[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;