[WCNCR00151687] perf: Improve USB 2.0 peak throughput on TV platform
[Description]
Change to improve USB 2.0 peak throughput on TV platform
- Tune RX aggregation buffer size/number
- Use tasklet for urb complete handling instead of interrupt handler
- Use different spinlocks for different UsbReq queues
- Use usb_anchor_urb related API
Change-Id: I2aa6aa04785efff2465b415baf6558cb111d89d4
Feature: perf
Signed-off-by: Desmond Lin <desmond.lin@mediatek.com>
CR-Id: WCNCR00151687
diff --git a/Makefile.ce b/Makefile.ce
index 633c754..d6054bf 100644
--- a/Makefile.ce
+++ b/Makefile.ce
@@ -138,7 +138,7 @@
CFG_USB_REQ_TX_DATA_CNT=4
-CFG_USB_REQ_RX_DATA_CNT=2
+CFG_USB_REQ_RX_DATA_CNT=4
CFG_ENABLE_EFUSE_MAC_ADDR=1
diff --git a/include/nic/hal.h b/include/nic/hal.h
index 7d529d1..8f299d2 100644
--- a/include/nic/hal.h
+++ b/include/nic/hal.h
@@ -1048,6 +1048,8 @@
WLAN_STATUS halAllocateIOBuffer(IN P_ADAPTER_T prAdapter);
WLAN_STATUS halReleaseIOBuffer(IN P_ADAPTER_T prAdapter);
VOID halDeAggRxPktWorker(struct work_struct *work);
+VOID halRxTasklet(unsigned long data);
+VOID halTxCompleteTasklet(unsigned long data);
VOID halPrintHifDbgInfo(IN P_ADAPTER_T prAdapter);
BOOLEAN halIsTxResourceControlEn(IN P_ADAPTER_T prAdapter);
#endif /* _HAL_H */
diff --git a/include/queue.h b/include/queue.h
index 0114b3e..cd5fc29 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -185,7 +185,7 @@
{ \
ASSERT(prDestQueue); \
ASSERT(prSrcQueue); \
- if (prSrcQueue->u4NumElem > 0) { \
+ if ((prSrcQueue)->u4NumElem > 0) { \
if ((prDestQueue)->prTail) { \
((prDestQueue)->prTail)->prNext = (prSrcQueue)->prHead; \
} else { \
@@ -201,7 +201,7 @@
{ \
ASSERT(prDestQueue); \
ASSERT(prSrcQueue); \
- if (prSrcQueue->u4NumElem > 0) { \
+ if ((prSrcQueue)->u4NumElem > 0) { \
((prSrcQueue)->prTail)->prNext = (prDestQueue)->prHead; \
(prDestQueue)->prHead = (prSrcQueue)->prHead; \
((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \
diff --git a/nic/nic_rx.c b/nic/nic_rx.c
index 08f7503..aed75a9 100644
--- a/nic/nic_rx.c
+++ b/nic/nic_rx.c
@@ -2883,9 +2883,11 @@
}
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE);
+#if CFG_USB_RX_HANDLE_IN_HIF_THREAD
/* Trigger Rx if there are free SwRfb */
if (halIsPendingRx(prAdapter) && (prRxCtrl->rFreeSwRfbList.u4NumElem > 0))
kalSetIntEvent(prAdapter->prGlueInfo);
+#endif
} /* end of nicRxReturnRFB() */
/*----------------------------------------------------------------------------*/
diff --git a/os/linux/gl_init.c b/os/linux/gl_init.c
index 4732e7b..7bb4d7f 100644
--- a/os/linux/gl_init.c
+++ b/os/linux/gl_init.c
@@ -2236,6 +2236,9 @@
prRegInfo->fgEnArpFilter = TRUE;
#endif
+ tasklet_init(&prGlueInfo->rRxTask, halRxTasklet, (unsigned long)prGlueInfo);
+ tasklet_init(&prGlueInfo->rTxCompleteTask, halTxCompleteTasklet, (unsigned long)prGlueInfo);
+
if (wlanAdapterStart(prAdapter, prRegInfo) != WLAN_STATUS_SUCCESS)
i4Status = -EIO;
@@ -2622,6 +2625,9 @@
wlanNetDestroy(prDev->ieee80211_ptr);
prDev = NULL;
+ tasklet_kill(&prGlueInfo->rTxCompleteTask);
+ tasklet_kill(&prGlueInfo->rRxTask);
+
/* 4 <8> Unregister early suspend callback */
#if CFG_ENABLE_EARLY_SUSPEND
glUnregisterEarlySuspend(&wlan_early_suspend_desc);
diff --git a/os/linux/hif/pcie/hal_api.c b/os/linux/hif/pcie/hal_api.c
index 7fc06a3..b42b026 100644
--- a/os/linux/hif/pcie/hal_api.c
+++ b/os/linux/hif/pcie/hal_api.c
@@ -1651,6 +1651,16 @@
}
+VOID halRxTasklet(unsigned long data)
+{
+
+}
+
+VOID halTxCompleteTasklet(unsigned long data)
+{
+
+}
+
/* Hif power off wifi */
WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter)
{
diff --git a/os/linux/hif/sdio/hal_api.c b/os/linux/hif/sdio/hal_api.c
index e578465..dfde0ea 100644
--- a/os/linux/hif/sdio/hal_api.c
+++ b/os/linux/hif/sdio/hal_api.c
@@ -2017,6 +2017,16 @@
schedule_delayed_work(&prAdapter->prGlueInfo->rRxPktDeAggWork, 0);
}
+VOID halRxTasklet(unsigned long data)
+{
+
+}
+
+VOID halTxCompleteTasklet(unsigned long data)
+{
+
+}
+
/* Hif power off wifi */
WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter)
{
diff --git a/os/linux/hif/usb/hal_api.c b/os/linux/hif/usb/hal_api.c
index 1eff320..1b527b2 100644
--- a/os/linux/hif/usb/hal_api.c
+++ b/os/linux/hif/usb/hal_api.c
@@ -254,7 +254,7 @@
!(prHifInfo->state == USB_STATE_PRE_RESUME && prCmdInfo->ucCID == 0))
return WLAN_STATUS_FAILURE;
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock);
if (prUsbReq == NULL)
return WLAN_STATUS_RESOURCES;
@@ -300,19 +300,19 @@
#if CFG_USB_CONSISTENT_DMA
prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
#endif
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags);
u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC);
if (u4Status) {
DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d)\n", u4Status);
- /* glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq); */
+ /* glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock, prUsbReq); */
list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdFreeQ);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags);
return WLAN_STATUS_FAILURE;
}
- /* glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdSendingQ, prUsbReq); */
+ /* glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdSendingQ, &prHifInfo->rTxCmdQLock, prUsbReq); */
list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdSendingQ);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags);
if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter)
&& wlanIsChipNoAck(prGlueInfo->prAdapter)) {
@@ -331,16 +331,16 @@
unsigned long flags;
#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags);
list_del_init(&prUsbReq->list);
list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdCompleteQ);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags);
kalSetIntEvent(prGlueInfo);
#else
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags);
list_del_init(&prUsbReq->list);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags);
halTxUSBProcessCmdComplete(prGlueInfo->prAdapter, prUsbReq);
#endif
@@ -359,7 +359,7 @@
DBGLOG(HAL, INFO, "TX CMD DONE: URB[0x%p]\n", urb);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, &prHifInfo->rTxCmdQLock, FALSE);
u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR;
nicTxReleaseResource(prAdapter, TC4_INDEX, nicTxGetPageCount(u4SentDataSize, TRUE), TRUE);
@@ -372,7 +372,7 @@
struct urb *urb = NULL;
P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags);
list_for_each_entry_safe(prUsbReq, prNext, &prHifInfo->rTxCmdSendingQ, list) {
if (prUsbReq->prPriv == (PVOID) prCmdInfo) {
list_del_init(&prUsbReq->list);
@@ -380,7 +380,7 @@
break;
}
}
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags);
if (urb) {
prCmdInfo->pfHifTxCmdDoneCb = NULL;
@@ -407,20 +407,17 @@
#if CFG_USB_TX_AGG
for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) {
- list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataSendingQ[ucTc], list) {
- usb_kill_urb(prUsbReq->prUrb);
- }
+ usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor[ucTc]);
}
#else
- list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataSendingQ, list) {
- usb_kill_urb(prUsbReq->prUrb);
- }
+ usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor);
#endif
}
#if CFG_USB_TX_AGG
WLAN_STATUS halTxUSBSendAggData(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_8 ucTc, IN P_USB_REQ_T prUsbReq)
{
+ P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo;
P_BUF_CTRL_T prBufCtrl = prUsbReq->prBufCtrl;
WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
@@ -428,14 +425,14 @@
prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR;
if (prHifInfo->state != USB_STATE_LINK_UP) {
-#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
list_del_init(&prUsbReq->list);
list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataCompleteQ);
- kalSetIntEvent(prHifInfo->prGlueInfo);
+#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
+ kalSetIntEvent(prGlueInfo);
#else
- halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq);
- prBufCtrl->u4WrIdx = 0;
+ /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/
+ tasklet_schedule(&prGlueInfo->rTxCompleteTask);
#endif
return WLAN_STATUS_FAILURE;
}
@@ -450,15 +447,17 @@
prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
#endif
+ usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor[ucTc]);
u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC);
if (u4Status) {
DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__);
+ halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq);
+ prBufCtrl->u4WrIdx = 0;
+ usb_unanchor_urb(prUsbReq->prUrb);
list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]);
return WLAN_STATUS_FAILURE;
}
- list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataSendingQ[ucTc]);
-
return u4Status;
}
#endif
@@ -483,22 +482,28 @@
u4Length = skb->len;
ucTc = USB_TRANS_MSDU_TC(prMsduInfo);
#if CFG_USB_TX_AGG
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags);
if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) {
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
- DBGLOG(HAL, ERROR, "overflow BUG!!\n");
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
+ DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #1!!\n");
+ wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo);
return WLAN_STATUS_RESOURCES;
}
prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list);
prBufCtrl = prUsbReq->prBufCtrl;
+ if (prHifInfo->u4AggRsvSize < ALIGN_4(u4Length))
+ DBGLOG(HAL, ERROR, "u4AggRsvSize count FAIL (%u, %u)\n", prHifInfo->u4AggRsvSize, u4Length);
+ prHifInfo->u4AggRsvSize -= ALIGN_4(u4Length);
+
if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) + LEN_USB_UDMA_TX_TERMINATOR > prBufCtrl->u4BufSize) {
halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq);
if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) {
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
- DBGLOG(HAL, ERROR, "overflow BUG!!\n");
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
+ DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #2!!\n");
+ wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo);
return WLAN_STATUS_FAILURE;
}
@@ -518,14 +523,17 @@
if (!prMsduInfo->pfTxDoneHandler)
QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo);
- if (list_empty(&prHifInfo->rTxDataSendingQ[ucTc]))
+ if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc]))
halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
#else
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataFreeQ);
- if (prUsbReq == NULL)
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, &prHifInfo->rTxDataFreeQLock);
+ if (prUsbReq == NULL) {
+ DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ!!\n");
+ wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo);
return WLAN_STATUS_RESOURCES;
+ }
prBufCtrl = prUsbReq->prBufCtrl;
prBufCtrl->u4WrIdx = 0;
@@ -555,13 +563,16 @@
prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
#endif
+ usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor);
u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC);
if (u4Status) {
DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, prUsbReq, FALSE);
+ halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq);
+ prBufCtrl->u4WrIdx = 0;
+ usb_unanchor_urb(prUsbReq->prUrb);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, prUsbReq, &prHifInfo->rTxDataFreeQLock, FALSE);
return WLAN_STATUS_FAILURE;
}
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataSendingQ, prUsbReq, FALSE);
#endif
if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter)
@@ -582,7 +593,7 @@
UINT_8 ucTc;
unsigned long flags;
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags);
for (ucTc = TC0_INDEX; ucTc < USB_TC_NUM; ucTc++) {
if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc]))
@@ -595,7 +606,7 @@
halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq);
}
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
#endif
return WLAN_STATUS_SUCCESS;
@@ -607,17 +618,13 @@
P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo;
P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo;
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, prUsbReq, &prHifInfo->rTxDataQLock, FALSE);
+
#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
- unsigned long flags;
-
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
- list_del_init(&prUsbReq->list);
- list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataCompleteQ);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
-
kalSetIntEvent(prGlueInfo);
#else
- halTxUSBProcessDataComplete(prGlueInfo->prAdapter, prUsbReq);
+ /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/
+ tasklet_schedule(&prGlueInfo->rTxCompleteTask);
#endif
}
@@ -660,14 +667,13 @@
halTxUSBProcessMsduDone(prAdapter->prGlueInfo, prUsbReq);
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags);
#if CFG_USB_TX_AGG
prBufCtrl->u4WrIdx = 0;
- list_del_init(&prUsbReq->list);
list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]);
- if (list_empty(&prHifInfo->rTxDataSendingQ[ucTc])) {
+ if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) {
prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list);
prBufCtrl = prUsbReq->prBufCtrl;
@@ -675,10 +681,9 @@
halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); /* TODO */
}
#else
- list_del_init(&prUsbReq->list);
list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ);
#endif
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0)
kalSetEvent(prAdapter->prGlueInfo);
@@ -688,12 +693,14 @@
UINT_32 halRxUSBEnqueueRFB(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Length,
IN UINT_32 u4MinRfbCnt)
{
+ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo;
P_RX_CTRL_T prRxCtrl = &prAdapter->rRxCtrl;
P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL;
P_HW_MAC_RX_DESC_T prRxStatus;
UINT_32 u4RemainCount;
UINT_16 u2RxByteCount;
UINT_8 *pucRxFrame;
+ UINT_32 u4EnqCnt = 0;
KAL_SPIN_LOCK_DECLARATION();
@@ -711,7 +718,6 @@
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE);
if (!prSwRfb) {
- DBGLOG(RX, WARN, "Out of SwRfb!\n");
return (u4Length - u4RemainCount);
}
@@ -726,11 +732,12 @@
DBGLOG(RX, TRACE, "Rx status flag = %x wlan index = %d SecMode = %d\n",
prRxStatus->u2StatusFlag, prRxStatus->ucWlanIdx, HAL_RX_STATUS_GET_SEC_MODE(prRxStatus));
#endif
-
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE);
QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry);
- RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE);
+ u4EnqCnt++;
+
+ RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT);
} else {
DBGLOG(RX, WARN, "Rx byte count:%u exceeds SW_RFB max length:%u\n!",
u2RxByteCount, CFG_RX_MAX_PKT_SIZE);
@@ -742,8 +749,10 @@
pucRxFrame += u2RxByteCount;
}
- set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag));
- wake_up_interruptible(&(prAdapter->prGlueInfo->waitq));
+ if (u4EnqCnt) {
+ set_bit(GLUE_FLAG_RX_BIT, &(prGlueInfo->ulFlag));
+ wake_up_interruptible(&(prGlueInfo->waitq));
+ }
return u4Length;
}
@@ -754,16 +763,16 @@
P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo;
P_USB_REQ_T prUsbReq;
WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
- unsigned long flags;
if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP)
return WLAN_STATUS_FAILURE;
while (1) {
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxEventFreeQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, &prHifInfo->rRxEventQLock);
if (prUsbReq == NULL)
return WLAN_STATUS_RESOURCES;
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventRunningQ, prUsbReq, FALSE);
+
+ usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxEventAnchor);
prUsbReq->prPriv = NULL;
prUsbReq->prBufCtrl->u4ReadSize = 0;
@@ -784,10 +793,9 @@
if (u4Status) {
DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__);
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
- list_del_init(&prUsbReq->list);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, FALSE);
+ usb_unanchor_urb(prUsbReq->prUrb);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq,
+ &prHifInfo->rRxEventQLock, FALSE);
break;
}
}
@@ -800,26 +808,21 @@
P_USB_REQ_T prUsbReq = urb->context;
P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo;
P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo;
- unsigned long flags;
-
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
- list_del_init(&prUsbReq->list);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP) {
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
return;
}
/* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */
if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) {
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE);
return;
}
if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) {
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__);
return;
}
@@ -827,19 +830,21 @@
#if CFG_USB_RX_HANDLE_IN_HIF_THREAD
DBGLOG(RX, TRACE, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, urb, urb->actual_length, urb->status);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
kalSetIntEvent(prGlueInfo);
#else
- if (urb->status == 0)
- halRxUSBEnqueueRFB(prGlueInfo->prAdapter, prUsbReq->prBufCtrl->pucBuf,
- urb->actual_length, USB_RX_EVENT_RFB_RSV_CNT);
- else
+ if (urb->status == 0) {
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
+
+ /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/
+ tasklet_schedule(&prGlueInfo->rRxTask);
+ } else {
DBGLOG(RX, ERROR, "[%s] receive EVENT fail (status = %d)\n", __func__, urb->status);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, FALSE);
-
- halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE);
+ halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE);
+ }
#endif
}
@@ -849,16 +854,16 @@
P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo;
P_USB_REQ_T prUsbReq;
WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
- unsigned long flags;
if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP)
return WLAN_STATUS_FAILURE;
while (1) {
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxDataFreeQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, &prHifInfo->rRxDataQLock);
if (prUsbReq == NULL)
return WLAN_STATUS_RESOURCES;
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataRunningQ, prUsbReq, FALSE);
+
+ usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxDataAnchor);
prUsbReq->prPriv = NULL;
prUsbReq->prBufCtrl->u4ReadSize = 0;
@@ -870,10 +875,8 @@
u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC);
if (u4Status) {
DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__);
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
- list_del_init(&prUsbReq->list);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, FALSE);
+ usb_unanchor_urb(prUsbReq->prUrb);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE);
break;
}
}
@@ -886,26 +889,21 @@
P_USB_REQ_T prUsbReq = urb->context;
P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo;
P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo;
- unsigned long flags;
-
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
- list_del_init(&prUsbReq->list);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP) {
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE);
return;
}
/* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */
if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) {
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE);
halRxUSBReceiveData(prGlueInfo->prAdapter);
return;
}
if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) {
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE);
DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__);
return;
}
@@ -915,15 +913,17 @@
kalSetIntEvent(prGlueInfo);
#else
- if (urb->status == 0)
- halRxUSBEnqueueRFB(prGlueInfo->prAdapter, prUsbReq->prBufCtrl->pucBuf,
- urb->actual_length, USB_RX_DATA_RFB_RSV_CNT);
- else
+ if (urb->status == 0) {
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE);
+
+ /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/
+ tasklet_schedule(&prGlueInfo->rRxTask);
+ } else {
DBGLOG(RX, ERROR, "[%s] receive DATA fail (status = %d)\n", __func__, urb->status);
+ glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE);
- glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, FALSE);
-
- halRxUSBReceiveData(prGlueInfo->prAdapter);
+ halRxUSBReceiveData(prGlueInfo->prAdapter);
+ }
#endif
}
@@ -933,12 +933,15 @@
P_USB_REQ_T prUsbReq;
struct urb *prUrb;
P_BUF_CTRL_T prBufCtrl;
- P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
+ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo;
+ P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo;
PUINT_8 pucBufAddr;
UINT_32 u4BufLen;
+ static BOOL s_fgOutOfSwRfb = FALSE;
+ static UINT_32 s_u4OutOfSwRfbPrintLimit;
/* Process complete event/data */
- prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock);
while (prUsbReq) {
prUrb = prUsbReq->prUrb;
prBufCtrl = prUsbReq->prBufCtrl;
@@ -946,22 +949,41 @@
DBGLOG(RX, LOUD, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__,
prUrb, prUrb->actual_length, prUrb->status);
- if (prUrb->status == 0) {
- pucBufAddr = prBufCtrl->pucBuf + prBufCtrl->u4ReadSize;
- u4BufLen = prUrb->actual_length - prBufCtrl->u4ReadSize;
-
- prBufCtrl->u4ReadSize += halRxUSBEnqueueRFB(prAdapter, pucBufAddr, u4BufLen, u4MinRfbCnt);
-
- if (prUrb->actual_length - prBufCtrl->u4ReadSize > 4) {
- glUsbEnqueueReq(prHifInfo, prCompleteQ, prUsbReq, TRUE);
- break;
- }
- } else
+ if (prUrb->status != 0) {
DBGLOG(RX, ERROR, "[%s] receive EVENT/DATA fail (status = %d)\n", __func__, prUrb->status);
- glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, FALSE);
+ glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
+ prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock);
+ continue;
+ }
- prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ);
+ pucBufAddr = prBufCtrl->pucBuf + prBufCtrl->u4ReadSize;
+ u4BufLen = prUrb->actual_length - prBufCtrl->u4ReadSize;
+
+ prBufCtrl->u4ReadSize += halRxUSBEnqueueRFB(prAdapter, pucBufAddr, u4BufLen, u4MinRfbCnt);
+
+ if (unlikely(prUrb->actual_length - prBufCtrl->u4ReadSize > 4)) {
+ if (s_fgOutOfSwRfb == FALSE) {
+ if ((long)jiffies - (long)s_u4OutOfSwRfbPrintLimit > 0) {
+ DBGLOG(RX, WARN, "Out of SwRfb!\n");
+ s_u4OutOfSwRfbPrintLimit = jiffies + MSEC_TO_JIFFIES(SW_RFB_LOG_LIMIT_MS);
+ }
+ s_fgOutOfSwRfb = TRUE;
+ }
+ glUsbEnqueueReq(prHifInfo, prCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, TRUE);
+
+ set_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag);
+ wake_up_interruptible(&prGlueInfo->waitq);
+
+ schedule_delayed_work(&prGlueInfo->rRxPktDeAggWork, MSEC_TO_JIFFIES(SW_RFB_RECHECK_MS));
+ break;
+ }
+
+ if (unlikely(s_fgOutOfSwRfb == TRUE))
+ s_fgOutOfSwRfb = FALSE;
+
+ glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE);
+ prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock);
}
}
@@ -1003,20 +1025,14 @@
VOID halDisableInterrupt(IN P_ADAPTER_T prAdapter)
{
P_GLUE_INFO_T prGlueInfo;
- P_USB_REQ_T prUsbReq, prUsbReqNext;
P_GL_HIF_INFO_T prHifInfo;
ASSERT(prAdapter);
prGlueInfo = prAdapter->prGlueInfo;
prHifInfo = &prGlueInfo->rHifInfo;
- list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataRunningQ, list) {
- usb_kill_urb(prUsbReq->prUrb);
- }
-
- list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventRunningQ, list) {
- usb_kill_urb(prUsbReq->prUrb);
- }
+ usb_kill_anchored_urbs(&prHifInfo->rRxDataAnchor);
+ usb_kill_anchored_urbs(&prHifInfo->rRxEventAnchor);
glUdmaRxAggEnable(prGlueInfo, FALSE);
prAdapter->fgIsIntEnable = FALSE;
@@ -1136,11 +1152,11 @@
u4Length = skb->len;
ucTc = USB_TRANS_MSDU_TC(prMsduInfo);
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags);
#if CFG_USB_TX_AGG
if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) {
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
return FALSE;
}
@@ -1148,24 +1164,25 @@
prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list);
prBufCtrl = prUsbReq->prBufCtrl;
- if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) + LEN_USB_UDMA_TX_TERMINATOR > prBufCtrl->u4BufSize) {
- /* USB request count check */
- if (prUsbReq->list.next == &prHifInfo->rTxDataFreeQ[ucTc]) {
- /* Buffer is not enough if there is only one USB request left */
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
-
+ if (prHifInfo->rTxDataFreeQ[ucTc].next->next == &prHifInfo->rTxDataFreeQ[ucTc]) {
+ /* length of rTxDataFreeQ equals 1 */
+ if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) >
+ prBufCtrl->u4BufSize - prHifInfo->u4AggRsvSize - LEN_USB_UDMA_TX_TERMINATOR) {
+ /* Buffer is not enough */
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
return FALSE;
}
}
+ prHifInfo->u4AggRsvSize += ALIGN_4(u4Length);
#else
if (list_empty(&prHifInfo->rTxDataFreeQ)) {
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
return FALSE;
}
#endif
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags);
return TRUE;
}
@@ -1176,17 +1193,17 @@
P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
/* Process complete Tx cmd */
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock);
while (prUsbReq) {
halTxUSBProcessCmdComplete(prAdapter, prUsbReq);
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock);
}
/* Process complete Tx data */
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxCmdQLock);
while (prUsbReq) {
halTxUSBProcessDataComplete(prAdapter, prUsbReq);
- prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxCmdQLock);
}
#endif
}
@@ -1241,19 +1258,19 @@
VOID halProcessRxInterrupt(IN P_ADAPTER_T prAdapter)
{
-#if CFG_USB_RX_HANDLE_IN_HIF_THREAD
P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
- /* Process complete event */
- halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxEventCompleteQ,
- &prHifInfo->rRxEventFreeQ, USB_RX_EVENT_RFB_RSV_CNT);
- halRxUSBReceiveEvent(prAdapter, FALSE);
-
/* Process complete data */
halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxDataCompleteQ,
&prHifInfo->rRxDataFreeQ, USB_RX_DATA_RFB_RSV_CNT);
halRxUSBReceiveData(prAdapter);
-#endif
+
+ if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) {
+ /* Process complete event */
+ halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxEventCompleteQ,
+ &prHifInfo->rRxEventFreeQ, USB_RX_EVENT_RFB_RSV_CNT);
+ halRxUSBReceiveEvent(prAdapter, FALSE);
+ }
}
UINT_32 halDumpHifStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max)
@@ -1402,7 +1419,31 @@
VOID halDeAggRxPktWorker(struct work_struct *work)
{
+ P_GLUE_INFO_T prGlueInfo = ENTRY_OF(work, GLUE_INFO_T, rRxPktDeAggWork);
+ /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/
+ tasklet_schedule(&prGlueInfo->rRxTask);
+}
+
+VOID halRxTasklet(unsigned long data)
+{
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data;
+
+ halProcessRxInterrupt(prGlueInfo->prAdapter);
+}
+
+VOID halTxCompleteTasklet(unsigned long data)
+{
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data;
+ P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo;
+ P_USB_REQ_T prUsbReq;
+
+ /* Process complete Tx data */
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock);
+ while (prUsbReq) {
+ halTxUSBProcessDataComplete(prGlueInfo->prAdapter, prUsbReq);
+ prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock);
+ }
}
/* Hif power off wifi */
diff --git a/os/linux/hif/usb/include/hif.h b/os/linux/hif/usb/include/hif.h
index 8ee48e1..7f297db 100644
--- a/os/linux/hif/usb/include/hif.h
+++ b/os/linux/hif/usb/include/hif.h
@@ -142,9 +142,9 @@
#define USB_REQ_RX_DATA_CNT (32)
#endif
-#define USB_RX_AGGREGTAION_LIMIT (15) /* Unit: K-bytes */
+#define USB_RX_AGGREGTAION_LIMIT (32) /* Unit: K-bytes */
#define USB_RX_AGGREGTAION_TIMEOUT (100) /* Unit: us */
-#define USB_RX_AGGREGTAION_PKT_LIMIT (10)
+#define USB_RX_AGGREGTAION_PKT_LIMIT (30)
#define USB_TX_CMD_BUF_SIZE (1600)
#if CFG_USB_TX_AGG
@@ -154,9 +154,10 @@
NIC_TX_MAX_SIZE_PER_FRAME + LEN_USB_UDMA_TX_TERMINATOR)
#endif
#define USB_RX_EVENT_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO + 4)
-#define USB_RX_DATA_BUF_SIZE max(USB_RX_AGGREGTAION_LIMIT * 1024, \
- USB_RX_AGGREGTAION_PKT_LIMIT * \
- (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO) + 4)
+#define USB_RX_DATA_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + \
+ min(USB_RX_AGGREGTAION_LIMIT * 1024, \
+ (USB_RX_AGGREGTAION_PKT_LIMIT * \
+ (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO) + 4)))
#define LEN_USB_UDMA_TX_TERMINATOR (4) /*HW design spec */
#define LEN_USB_RX_PADDING_CSO (4) /*HW design spec */
@@ -169,7 +170,8 @@
#define VENDOR_TIMEOUT_MS (1000)
#define BULK_TIMEOUT_MS (1500)
#define INTERRUPT_TIMEOUT_MS (1000)
-#define SW_RFB_TIMEOUT_MS (3000)
+#define SW_RFB_RECHECK_MS (10)
+#define SW_RFB_LOG_LIMIT_MS (5000)
/* Vendor Request */
#define VND_REQ_POWER_ON_WIFI (0x4)
@@ -228,32 +230,40 @@
P_GLUE_INFO_T prGlueInfo;
enum usb_state state;
- spinlock_t rQLock;
+ spinlock_t rTxDataQLock;
+ spinlock_t rTxCmdQLock;
+ spinlock_t rRxEventQLock;
+ spinlock_t rRxDataQLock;
+
PVOID prTxCmdReqHead;
PVOID arTxDataReqHead[USB_TC_NUM];
PVOID prRxEventReqHead;
PVOID prRxDataReqHead;
struct list_head rTxCmdFreeQ;
+ spinlock_t rTxCmdFreeQLock;
struct list_head rTxCmdSendingQ;
+ spinlock_t rTxCmdSendingQLock;
#if CFG_USB_TX_AGG
+ UINT_32 u4AggRsvSize;
struct list_head rTxDataFreeQ[USB_TC_NUM];
- struct list_head rTxDataSendingQ[USB_TC_NUM];
+ struct usb_anchor rTxDataAnchor[USB_TC_NUM];
#else
struct list_head rTxDataFreeQ;
- struct list_head rTxDataSendingQ;
+ struct usb_anchor rTxDataAnchor;
#endif
+ spinlock_t rTxDataFreeQLock;
struct list_head rRxEventFreeQ;
- struct list_head rRxEventRunningQ;
+ spinlock_t rRxEventFreeQLock;
+ struct usb_anchor rRxEventAnchor;
struct list_head rRxDataFreeQ;
- struct list_head rRxDataRunningQ;
-#if CFG_USB_RX_HANDLE_IN_HIF_THREAD
+ spinlock_t rRxDataFreeQLock;
+ struct usb_anchor rRxDataAnchor;
struct list_head rRxEventCompleteQ;
+ spinlock_t rRxEventCompleteQLock;
struct list_head rRxDataCompleteQ;
-#endif
-#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
+ spinlock_t rRxDataCompleteQLock;
struct list_head rTxCmdCompleteQ;
struct list_head rTxDataCompleteQ;
-#endif
BUF_CTRL_T rTxCmdBufCtrl[USB_REQ_TX_CMD_CNT];
#if CFG_USB_TX_AGG
@@ -328,8 +338,9 @@
IN UCHAR Request, IN UINT_16 Value, IN UINT_16 Index, IN PVOID TransferBuffer,
IN UINT_32 TransferBufferLength);
-VOID glUsbEnqueueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, P_USB_REQ_T prUsbReq, BOOLEAN fgHead);
-P_USB_REQ_T glUsbDequeueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead);
+VOID glUsbEnqueueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, P_USB_REQ_T prUsbReq,
+ spinlock_t *prLock, BOOLEAN fgHead);
+P_USB_REQ_T glUsbDequeueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, spinlock_t *prLock);
WLAN_STATUS halTxUSBSendCmd(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucTc, IN P_CMD_INFO_T prCmdInfo);
VOID halTxUSBSendCmdComplete(struct urb *urb);
@@ -347,6 +358,8 @@
VOID halRxUSBReceiveEventComplete(struct urb *urb);
WLAN_STATUS halRxUSBReceiveData(IN P_ADAPTER_T prAdapter);
VOID halRxUSBReceiveDataComplete(struct urb *urb);
+VOID halRxUSBProcessEventDataComplete(IN P_ADAPTER_T prAdapter,
+ struct list_head *prCompleteQ, struct list_head *prFreeQ, UINT_32 u4MinRfbCnt);
VOID halUSBPreSuspendCmd(IN P_ADAPTER_T prAdapter);
VOID halUSBPreSuspendDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf);
diff --git a/os/linux/hif/usb/usb.c b/os/linux/hif/usb/usb.c
index 5060f35..3ee4403 100644
--- a/os/linux/hif/usb/usb.c
+++ b/os/linux/hif/usb/usb.c
@@ -50,12 +50,12 @@
*
*****************************************************************************/
/******************************************************************************
-*[File] sdio.c
+*[File] usb.c
*[Version] v1.0
*[Revision Date] 2010-03-01
*[Author]
*[Description]
-* The program provides SDIO HIF driver
+* The program provides USB HIF driver
*[Copyright]
* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved.
******************************************************************************/
@@ -196,36 +196,6 @@
dev = interface_to_usbdev(intf);
dev = usb_get_dev(dev);
- /* printk(KERN_INFO DRV_NAME "Basic struct size checking...\n"); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct device) = %d\n", sizeof(struct device)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct mmc_host) = %d\n", sizeof(struct mmc_host)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct mmc_card) = %d\n", sizeof(struct mmc_card)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct mmc_driver) = %d\n", sizeof(struct mmc_driver)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct mmc_data) = %d\n", sizeof(struct mmc_data)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct mmc_command) = %d\n", sizeof(struct mmc_command)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct mmc_request) = %d\n", sizeof(struct mmc_request)); */
- /* printk(KERN_INFO DRV_NAME "sizeof(struct sdio_func) = %d\n", sizeof(struct sdio_func)); */
-
- /* printk(KERN_INFO DRV_NAME "Card information checking...\n"); */
- /* printk(KERN_INFO DRV_NAME "intf = 0x%p\n", intf); */
- /* printk(KERN_INFO DRV_NAME "Number of info = %d:\n", intf->card->num_info); */
-
-#if 0
- for (i = 0; i < intf->card->num_info; i++)
- /* printk(KERN_INFO DRV_NAME "info[%d]: %s\n", i, intf->card->info[i]); */
-
- sdio_claim_host(intf);
- ret = sdio_enable_func(intf);
- sdio_release_host(intf);
-
- if (ret) {
- /* printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n"); */
- goto out;
- }
- /* printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n"); */
-#endif
-
-#if 1
DBGLOG(HAL, EVENT, "wlan_probe()\n");
if (pfWlanProbe((PVOID) intf, (PVOID) id->driver_info) != WLAN_STATUS_SUCCESS) {
/* printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); */
@@ -235,7 +205,6 @@
} else {
g_fgDriverProbed = TRUE;
}
-#endif
return ret;
}
@@ -538,12 +507,12 @@
/*----------------------------------------------------------------------------*/
/*!
-* \brief This function will register sdio bus to the os
+* \brief This function will register USB bus to the os
*
* \param[in] pfProbe Function pointer to detect card
* \param[in] pfRemove Function pointer to remove card
*
-* \return The result of registering sdio bus
+* \return The result of registering USB bus
*/
/*----------------------------------------------------------------------------*/
WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove)
@@ -570,7 +539,7 @@
/*----------------------------------------------------------------------------*/
/*!
-* \brief This function will unregister sdio bus to the os
+* \brief This function will unregister USB bus to the os
*
* \param[in] pfRemove Function pointer to remove card
*
@@ -665,31 +634,32 @@
}
}
-VOID glUsbEnqueueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, P_USB_REQ_T prUsbReq, BOOLEAN fgHead)
+VOID glUsbEnqueueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, P_USB_REQ_T prUsbReq, spinlock_t *prLock,
+ BOOLEAN fgHead)
{
unsigned long flags;
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(prLock, flags);
if (fgHead)
list_add(&prUsbReq->list, prHead);
else
list_add_tail(&prUsbReq->list, prHead);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(prLock, flags);
}
-P_USB_REQ_T glUsbDequeueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead)
+P_USB_REQ_T glUsbDequeueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, spinlock_t *prLock)
{
P_USB_REQ_T prUsbReq;
unsigned long flags;
- spin_lock_irqsave(&prHifInfo->rQLock, flags);
+ spin_lock_irqsave(prLock, flags);
if (list_empty(prHead)) {
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(prLock, flags);
return NULL;
}
prUsbReq = list_entry(prHead->next, struct _USB_REQ_T, list);
list_del_init(prHead->next);
- spin_unlock_irqrestore(&prHifInfo->rQLock, flags);
+ spin_unlock_irqrestore(prLock, flags);
return prUsbReq;
}
@@ -751,26 +721,42 @@
SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHifInfo->udev->dev);
+ spin_lock_init(&prHifInfo->rTxCmdQLock);
+ spin_lock_init(&prHifInfo->rTxDataQLock);
+ spin_lock_init(&prHifInfo->rTxDataFreeQLock);
+ spin_lock_init(&prHifInfo->rRxEventQLock);
+ spin_lock_init(&prHifInfo->rRxDataQLock);
+
mutex_init(&prHifInfo->vendor_req_sem);
+#if CFG_USB_TX_AGG
+ prHifInfo->u4AggRsvSize = 0;
+
+ for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc)
+ init_usb_anchor(&prHifInfo->rTxDataAnchor[ucTc]);
+#else
+ init_usb_anchor(&prHifInfo->rTxDataAnchor);
+#endif
+ init_usb_anchor(&prHifInfo->rRxDataAnchor);
+ init_usb_anchor(&prHifInfo->rRxEventAnchor);
+
/* TX CMD */
prHifInfo->prTxCmdReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdFreeQ, USB_REQ_TX_CMD_CNT);
prUsbReq = list_entry(prHifInfo->rTxCmdFreeQ.next, struct _USB_REQ_T, list);
i = 0;
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) {
+ prUsbReq->prBufCtrl = &prHifInfo->rTxCmdBufCtrl[i];
#if CFG_USB_CONSISTENT_DMA
- prHifInfo->rTxCmdBufCtrl[i].pucBuf =
- usb_alloc_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, GFP_ATOMIC,
- &prUsbReq->prUrb->transfer_dma);
+ prUsbReq->prBufCtrl->pucBuf = usb_alloc_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, GFP_ATOMIC,
+ &prUsbReq->prUrb->transfer_dma);
#else
- prHifInfo->rTxCmdBufCtrl[i].pucBuf = kmalloc(USB_TX_CMD_BUF_SIZE, GFP_ATOMIC);
+ prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_CMD_BUF_SIZE, GFP_ATOMIC | GFP_DMA);
#endif
- prHifInfo->rTxCmdBufCtrl[i].u4BufSize = USB_TX_CMD_BUF_SIZE;
- if (prHifInfo->rTxCmdBufCtrl[i].pucBuf == NULL) {
+ if (prUsbReq->prBufCtrl->pucBuf == NULL) {
DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
goto error;
}
- prUsbReq->prBufCtrl = &prHifInfo->rTxCmdBufCtrl[i];
+ prUsbReq->prBufCtrl->u4BufSize = USB_TX_CMD_BUF_SIZE;
++i;
}
@@ -786,23 +772,25 @@
QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList);
/* TODO: every endpoint should has an unique and only TC */
*((PUINT_8)&prUsbReq->prPriv) = ucTc;
+ prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[ucTc][i];
#if CFG_USB_CONSISTENT_DMA
- prHifInfo->rTxDataBufCtrl[ucTc][i].pucBuf =
+ prUsbReq->prBufCtrl->pucBuf =
usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC,
&prUsbReq->prUrb->transfer_dma);
#else
- prHifInfo->rTxDataBufCtrl[ucTc][i].pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC);
+ prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC | GFP_DMA);
#endif
- prHifInfo->rTxDataBufCtrl[ucTc][i].u4BufSize = USB_TX_DATA_BUFF_SIZE;
- prHifInfo->rTxDataBufCtrl[ucTc][i].u4WrIdx = 0;
- prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[ucTc][i];
+ if (prUsbReq->prBufCtrl->pucBuf == NULL) {
+ DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
+ goto error;
+ }
+ prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE;
+ prUsbReq->prBufCtrl->u4WrIdx = 0;
++i;
}
DBGLOG(INIT, INFO, "USB Tx URB INIT Tc[%u] cnt[%u] len[%u]\n", ucTc, i,
prHifInfo->rTxDataBufCtrl[ucTc][0].u4BufSize);
-
- glUsbInitQ(prHifInfo, &prHifInfo->rTxDataSendingQ[ucTc], 0);
}
#else
glUsbInitQ(prHifInfo, &prHifInfo->rTxDataFreeQ, USB_REQ_TX_DATA_CNT);
@@ -810,64 +798,58 @@
i = 0;
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) {
QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList);
+ prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[i];
#if CFG_USB_CONSISTENT_DMA
- prHifInfo->rTxDataBufCtrl[i].pucBuf =
+ prUsbReq->prBufCtrl->pucBuf =
usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUF_SIZE, GFP_ATOMIC,
&prUsbReq->prUrb->transfer_dma);
#else
- prHifInfo->rTxDataBufCtrl[i].pucBuf = kmalloc(USB_TX_DATA_BUF_SIZE, GFP_ATOMIC);
+ prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUF_SIZE, GFP_ATOMIC | GFP_DMA);
#endif
- prHifInfo->rTxDataBufCtrl[i].u4BufSize = USB_TX_DATA_BUF_SIZE;
- if (prHifInfo->rTxDataBufCtrl[i].pucBuf == NULL) {
+ if (prUsbReq->prBufCtrl->pucBuf == NULL) {
DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
goto error;
}
- prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[i];
+ prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUF_SIZE;
++i;
}
#endif
-#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdCompleteQ, 0);
glUsbInitQ(prHifInfo, &prHifInfo->rTxDataCompleteQ, 0);
-#endif
/* RX EVENT */
prHifInfo->prRxEventReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxEventFreeQ, USB_REQ_RX_EVENT_CNT);
i = 0;
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) {
- prHifInfo->rRxEventBufCtrl[i].pucBuf = kmalloc(USB_RX_EVENT_BUF_SIZE, GFP_ATOMIC);
- prHifInfo->rRxEventBufCtrl[i].u4BufSize = USB_RX_EVENT_BUF_SIZE;
- if (prHifInfo->rRxEventBufCtrl[i].pucBuf == NULL) {
+ prUsbReq->prBufCtrl = &prHifInfo->rRxEventBufCtrl[i];
+ prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_EVENT_BUF_SIZE, GFP_ATOMIC | GFP_DMA);
+ if (prUsbReq->prBufCtrl->pucBuf == NULL) {
DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
goto error;
}
- prUsbReq->prBufCtrl = &prHifInfo->rRxEventBufCtrl[i];
+ prUsbReq->prBufCtrl->u4BufSize = USB_RX_EVENT_BUF_SIZE;
+ prUsbReq->prBufCtrl->u4ReadSize = 0;
++i;
}
- glUsbInitQ(prHifInfo, &prHifInfo->rRxEventRunningQ, 0);
-
/* RX Data */
prHifInfo->prRxDataReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxDataFreeQ, USB_REQ_RX_DATA_CNT);
i = 0;
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) {
- prHifInfo->rRxDataBufCtrl[i].pucBuf = kmalloc(USB_RX_DATA_BUF_SIZE, GFP_ATOMIC);
- prHifInfo->rRxDataBufCtrl[i].u4BufSize = USB_RX_DATA_BUF_SIZE;
- if (prHifInfo->rRxDataBufCtrl[i].pucBuf == NULL) {
+ prUsbReq->prBufCtrl = &prHifInfo->rRxDataBufCtrl[i];
+ prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_DATA_BUF_SIZE, GFP_ATOMIC);
+ if (prUsbReq->prBufCtrl->pucBuf == NULL) {
DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
goto error;
}
- prUsbReq->prBufCtrl = &prHifInfo->rRxDataBufCtrl[i];
+ prUsbReq->prBufCtrl->u4BufSize = USB_RX_DATA_BUF_SIZE;
+ prUsbReq->prBufCtrl->u4ReadSize = 0;
++i;
}
- glUsbInitQ(prHifInfo, &prHifInfo->rRxDataRunningQ, 0);
-
-#if CFG_USB_RX_HANDLE_IN_HIF_THREAD
glUsbInitQ(prHifInfo, &prHifInfo->rRxEventCompleteQ, 0);
glUsbInitQ(prHifInfo, &prHifInfo->rRxDataCompleteQ, 0);
-#endif
prHifInfo->state = USB_STATE_LINK_UP;
@@ -933,7 +915,6 @@
usb_free_urb(prUsbReq->prUrb);
}
-#if CFG_USB_TX_HANDLE_IN_HIF_THREAD
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdCompleteQ, list) {
#if CFG_USB_CONSISTENT_DMA
usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE,
@@ -953,7 +934,6 @@
#endif
usb_free_urb(prUsbReq->prUrb);
}
-#endif
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) {
kfree(prUsbReq->prBufCtrl->pucBuf);
@@ -965,7 +945,6 @@
usb_free_urb(prUsbReq->prUrb);
}
-#if CFG_USB_RX_HANDLE_IN_HIF_THREAD
list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataCompleteQ, list) {
kfree(prUsbReq->prBufCtrl->pucBuf);
usb_free_urb(prUsbReq->prUrb);
@@ -975,11 +954,12 @@
kfree(prUsbReq->prBufCtrl->pucBuf);
usb_free_urb(prUsbReq->prUrb);
}
-#endif
kfree(prHifInfo->prTxCmdReqHead);
kfree(prHifInfo->prRxEventReqHead);
kfree(prHifInfo->prRxDataReqHead);
+
+ mutex_destroy(&prHifInfo->vendor_req_sem);
} /* end of glClearHifInfo() */
/*----------------------------------------------------------------------------*/
diff --git a/os/linux/include/gl_os.h b/os/linux/include/gl_os.h
index 690b515..0f46b0e 100644
--- a/os/linux/include/gl_os.h
+++ b/os/linux/include/gl_os.h
@@ -505,6 +505,8 @@
struct task_struct *rx_thread;
#endif
+ struct tasklet_struct rRxTask;
+ struct tasklet_struct rTxCompleteTask;
struct work_struct rTxMsduFreeWork;
struct delayed_work rRxPktDeAggWork;