qcacld-2.0: SDIO: Throughput Enhancement

Tx improvement achieved by increasing Tx buffers in FW, enable Tx bundling
feature in host.
Rx improvement achieved by introducing Rx completion task/thread which helps
in reducing DSR Handler workload.
Used FW feature which bundles variable size rx packets which helps in
increasing TCP chariot numbers for multiple streams, under define
HIF_BUNDLE_DIFF_BLK_FRAMES

Change-Id: I63118395bf148f53a25304c7fd90e126c1f29270
CRs-Fixed: 2170127
diff --git a/CORE/SERVICES/COMMON/htc.h b/CORE/SERVICES/COMMON/htc.h
index e61555e..bcc980d 100644
--- a/CORE/SERVICES/COMMON/htc.h
+++ b/CORE/SERVICES/COMMON/htc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -82,6 +82,9 @@
  *
  */
 
+#define HIF_RX_THREAD
+#define HIF_BUNDLE_DIFF_BLK_FRAMES 0
+
 /* HTC frame header */
 typedef PREPACK struct _HTC_FRAME_HDR{
         /* do not remove or re-arrange these fields, these are minimally required
@@ -94,7 +97,11 @@
 
     A_UINT32   ControlBytes0 : 8, /* used for CRC check if CRC_CHECK flag set */
                ControlBytes1 : 8, /* used for seq check if SEQ_CHECK flag set */
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+               TotalLen : 16;
+#else
                reserved : 16; /* used by bundle processing in SDIO systems */
+#endif
 
     /* message payload starts after the header */
 
@@ -417,6 +424,12 @@
              LookAhead1 : 8,
              LookAhead2 : 8,
              LookAhead3 : 8;
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_UINT32 LookAhead4 : 8,    /* 4 byte lookahead */
+             LookAhead5 : 8,
+             LookAhead6 : 8,
+             LookAhead7 : 8;
+#endif
     A_UINT32 PostValid : 8,     /* post valid guard */
              reserved1 : 24;
 
diff --git a/CORE/SERVICES/COMMON/htc_packet.h b/CORE/SERVICES/COMMON/htc_packet.h
index ce4532f..1be4fb8 100644
--- a/CORE/SERVICES/COMMON/htc_packet.h
+++ b/CORE/SERVICES/COMMON/htc_packet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -115,6 +115,7 @@
                                               can pass the network buffer corresponding to the HTC packet
                                               lower layers may optimized the transfer knowing this is
                                               a network buffer */
+    A_UINT8                BundlePktnum;
 } HTC_PACKET;
 
 
diff --git a/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c b/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c
index 5d9b3b9..fcbad8d 100644
--- a/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c
+++ b/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014,2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014,2016-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -26,6 +26,7 @@
  */
 
 #define ATH_MODULE_NAME hif
+#include <linux/kthread.h>
 #include "a_debug.h"
 
 #include <adf_os_types.h>
@@ -48,9 +49,11 @@
 #include <a_osapi.h>
 #include <hif.h>
 #include <htc_services.h>
+#include <htc_internal.h>
 #include "hif_sdio_internal.h"
 #include "if_ath_sdio.h"
 #include "regtable.h"
+#include "vos_sched.h"
 
 /* under HL SDIO, with Interface Memory support, we have the following
  * reasons to support 2 mboxs: a) we need place different buffers in different
@@ -162,11 +165,91 @@
     return pPacket;
 }
 
+#ifdef HIF_RX_THREAD
+/**
+ * rx_completion_sem_init() - initialize rx completion semaphore
+ * @device:  device handle.
+ *
+ * Initialize semaphore for RX completion thread's synchronization.
+ *
+ * Return: None.
+ */
+static inline void rx_completion_sem_init(HIF_SDIO_DEVICE *pDev)
+{
+	spin_lock_init(&pDev->pRecvTask->rx_bundle_lock);
+	spin_lock_init(&pDev->pRecvTask->rx_sync_completion_lock);
+	sema_init(&pDev->pRecvTask->sem_rx_completion, 0);
+}
+extern int rx_completion_task(void *param);
+
+/**
+ * hif_start_tx_completion_thread() - Create and start the RX compl thread
+ * @pDev:   pDev handle.
+ *
+ * This function will create the rx completion thread.
+ *
+ * Return: A_OK     thread created.
+ *         A_ERROR  thread not created.
+ */
+static inline int hif_start_rx_completion_thread(HIF_SDIO_DEVICE *pDev)
+{
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+    struct sched_param param = {.sched_priority = 99};
+#endif
+	if (!pDev->pRecvTask->rx_completion_task) {
+		pDev->pRecvTask->rx_completion_shutdown = 0;
+		pDev->pRecvTask->rx_completion_task = kthread_create(rx_completion_task,
+			(void *)pDev,	"AR6K RxCompletion");
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+                sched_setscheduler(pDev->pRecvTask->rx_completion_task, SCHED_FIFO, &param);
+#endif
+		if (IS_ERR(pDev->pRecvTask->rx_completion_task)) {
+			pDev->pRecvTask->rx_completion_shutdown = 1;
+			AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+			("AR6000: fail to create rx_comple task\n"));
+			pDev->pRecvTask->rx_completion_task = NULL;
+			return A_ERROR;
+		}
+		AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
+			("AR6000: start rx_comple task\n"));
+		wake_up_process(pDev->pRecvTask->rx_completion_task);
+	}
+	return A_OK;
+}
+
+/*
+ * hif_stop_rx_completion_thread() - Destroy the rx compl thread
+ * @pDev: pDev handle.
+ *
+ * This function will destroy the RX completion thread.
+ *
+ * Return: None.
+ */
+static inline void hif_stop_rx_completion_thread(HIF_SDIO_DEVICE *pDev)
+{
+    HTC_PACKET *pPacket;
+    if (pDev->pRecvTask->rx_completion_task) {
+        init_completion(&pDev->pRecvTask->rx_completion_exit);
+        pDev->pRecvTask->rx_completion_shutdown = 1;
+        up(&pDev->pRecvTask->sem_rx_completion);
+        wait_for_completion(&pDev->pRecvTask->rx_completion_exit);
+        pDev->pRecvTask->rx_completion_task = NULL;
+        sema_init(&pDev->pRecvTask->sem_rx_completion, 0);
+    }
+    while(!HTC_QUEUE_EMPTY(&pDev->pRecvTask->rxAllocQueue)) {
+        pPacket = HTC_PACKET_DEQUEUE(&pDev->pRecvTask->rxAllocQueue);
+        if(pPacket == NULL)
+            break;
+        adf_nbuf_free(pPacket->pNetBufContext);
+    }
+}
+struct hif_recv_task gRecvTask;
+#endif
+
 HIF_SDIO_DEVICE* HIFDevCreate(HIF_DEVICE *hif_device,
         MSG_BASED_HIF_CALLBACKS *callbacks,
         void *target)
 {
-
     A_STATUS status;
     HIF_SDIO_DEVICE *pDev;
 
@@ -183,6 +266,17 @@
 
     pDev->HIFDevice = hif_device;
     pDev->pTarget = target;
+#ifdef HIF_RX_THREAD
+    pDev->pRecvTask = &gRecvTask;
+    pDev->pRecvTask->rx_completion_task = NULL;
+    rx_completion_sem_init(pDev);
+    INIT_HTC_PACKET_QUEUE(&pDev->pRecvTask->rxBundleQueue);
+    INIT_HTC_PACKET_QUEUE(&pDev->pRecvTask->rxSyncCompletionQueue);
+    hif_start_rx_completion_thread(pDev);
+    spin_lock_init(&pDev->pRecvTask->rx_alloc_lock);
+    INIT_HTC_PACKET_QUEUE(&pDev->pRecvTask->rxAllocQueue);
+#endif
+
     status = HIFConfigureDevice(hif_device,
             HIF_DEVICE_SET_HTC_CONTEXT,
             (void*) pDev,
@@ -200,7 +294,9 @@
 void HIFDevDestroy(HIF_SDIO_DEVICE *pDev)
 {
     A_STATUS status;
-
+#ifdef HIF_RX_THREAD
+    hif_stop_rx_completion_thread(pDev);
+#endif
     status = HIFConfigureDevice(pDev->HIFDevice,
             HIF_DEVICE_SET_HTC_CONTEXT,
             (void*) NULL,
diff --git a/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h b/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h
index fd200d5..3576db6 100644
--- a/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h
+++ b/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014,2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014,2016-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -55,7 +55,7 @@
 #define INVALID_MAILBOX_NUMBER 0xFF
 #define MAILBOX_COUNT 4
 #define MAILBOX_FOR_BLOCK_SIZE 1
-#define MAILBOX_USED_COUNT 2
+#define MAILBOX_USED_COUNT 1
 #if defined(SDIO_3_0)
 #define MAILBOX_LOOKAHEAD_SIZE_IN_WORD 2
 #else
@@ -111,9 +111,27 @@
     int CurrentDSRRecvCount;
     int RecheckIRQStatusCnt;
     A_UINT32 RecvStateFlags;
-	void *pTarget;
+    void *pTarget;
+#ifdef HIF_RX_THREAD
+    struct hif_recv_task* pRecvTask;
+#endif
 };
 
+#ifdef HIF_RX_THREAD
+struct hif_recv_task {
+    struct task_struct *rx_completion_task;
+    struct semaphore sem_rx_completion;
+    int    rx_completion_shutdown;
+    struct completion rx_completion_exit;
+    spinlock_t rx_bundle_lock;
+    spinlock_t rx_sync_completion_lock;
+    HTC_PACKET_QUEUE rxBundleQueue;
+    HTC_PACKET_QUEUE rxSyncCompletionQueue;
+    spinlock_t rx_alloc_lock;
+    HTC_PACKET_QUEUE rxAllocQueue;
+};
+#endif
+
 #define LOCK_HIF_DEV(device)    A_MUTEX_LOCK(&(device)->Lock);
 #define UNLOCK_HIF_DEV(device)  A_MUTEX_UNLOCK(&(device)->Lock);
 #define LOCK_HIF_DEV_RX(t)      A_MUTEX_LOCK(&(t)->RxLock);
diff --git a/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c b/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c
index 36682b0..9097859 100644
--- a/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c
+++ b/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014,2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014,2016-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -125,7 +125,11 @@
     int numMessages;
     int fullLength;
     A_BOOL noRecycle;
-
+#ifdef HIF_RX_THREAD
+    unsigned long flags;
+    HTC_TARGET *target = NULL;
+    target = (HTC_TARGET *)pDev->pTarget;
+#endif
     /* lock RX while we assemble the packet buffers */
     LOCK_HIF_DEV_RX(pDev);
 
@@ -164,8 +168,14 @@
                     ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages));
         }
 
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        if(numMessages > 1)
+            fullLength = target->TargetCreditSize;
+        else
+            fullLength = DEV_CALC_RECV_PADDED_LEN(pDev,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR));
+#else
         fullLength = DEV_CALC_RECV_PADDED_LEN(pDev,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR));
-
+#endif
         /*
             all but the last packet have a length of payloadLen + sizeof(HTC_FRAME_HDR)
             The last packet in the bundle has an additional 16 byte lookahead information.
@@ -174,6 +184,9 @@
 
         /* get packet buffers for each message, if there was a bundle detected in the header,
          * use pHdr as a template to fetch all packets in the bundle */
+#ifdef HIF_RX_THREAD
+        spin_lock_irqsave(&pDev->pRecvTask->rx_alloc_lock, flags);
+#endif
         for (j = 0; j < numMessages; j++) {
 
             /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup,
@@ -181,11 +194,18 @@
             noRecycle = FALSE;
 
             /*allocate memory for the last packet*/
-            if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK))
+            if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK)) {
                 fullLength += HIF_MBOX_BLOCK_SIZE;
+            }
 
+#ifdef HIF_RX_THREAD
+            pPacket = HTC_PACKET_DEQUEUE(&pDev->pRecvTask->rxAllocQueue);
+            if(pPacket == NULL) {
+                pPacket = HIFDevAllocRxBuffer(pDev, fullLength);
+            }
+#else
             pPacket = HIFDevAllocRxBuffer(pDev, fullLength);
-
+#endif
 
             if (pPacket == NULL) {
                 /* this is not an error, we simply need to mark that we are waiting for buffers.*/
@@ -194,7 +214,9 @@
                 status = A_NO_RESOURCE;
                 break;
             }
-
+#ifdef HIF_RX_THREAD
+            pPacket->BundlePktnum = 0;
+#endif
             //AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id);
             /* clear flags */
             pPacket->PktInfo.AsRx.HTCRxFlags = 0;
@@ -235,13 +257,24 @@
                 pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */
             }
             /* set the amount of data to fetch */
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+            if(numMessages > 1)
+                pPacket->ActualLength = target->TargetCreditSize;
+            else
+                pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
+#else
             pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
-            if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK))
+#endif
+            if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK)) {
                 pPacket->PktInfo.AsRx.HTCRxFlags |=
                 HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK;
+            }
             pPacket->Endpoint = pHdr->EndpointID;
             pPacket->Completion = NULL;
         }
+#ifdef HIF_RX_THREAD
+        spin_unlock_irqrestore(&pDev->pRecvTask->rx_alloc_lock, flags);
+#endif
 
         if (A_FAILED(status)) {
             if (A_NO_RESOURCE == status) {
@@ -270,6 +303,121 @@
     return status;
 }
 
+#ifdef HIF_RX_THREAD
+static INLINE void HIFDevPreprocessTrailer(HIF_SDIO_DEVICE *pDev, HTC_PACKET* pPacket, A_UINT32 LookAheads[], int *pNumLookAheads
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        , A_UINT32 lookAhead_part2[])
+#else
+        )
+#endif
+{
+    A_UINT8 *pRecordBuf;
+    HTC_RECORD_HDR *pRecord;
+    HTC_LOOKAHEAD_REPORT *pLookAhead;
+    A_UINT8 *pBuffer, *pLastPktBuffer, *pCur;
+    A_UINT8 lastPktFlag;
+    A_UINT16 lastPktPayloadLength;
+    A_UINT8 lastPktRecordID;
+    int numMessages;
+    A_UINT8 temp;
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_UINT32 i;
+#endif
+    A_UINT16 curPayloadLen = 0;
+    A_UINT32 paddedLength, lastPktOffset = 0;
+
+    pBuffer = pPacket->pBuffer;
+    pLastPktBuffer = pBuffer;
+    pCur = pBuffer;
+    numMessages = GET_RECV_BUNDLE_COUNT(pBuffer[1]);
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    for(i = 0; i < numMessages; i++) {
+        curPayloadLen = *((A_UINT16*)(&pCur[2]));
+        paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, curPayloadLen + HTC_HDR_LENGTH);
+        lastPktOffset += paddedLength;
+        pCur += paddedLength;
+    }
+#else
+    curPayloadLen = *((A_UINT16*)(pBuffer + 2));
+    paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, curPayloadLen + HTC_HDR_LENGTH);
+    lastPktOffset = numMessages * paddedLength;
+#endif
+    pLastPktBuffer = pBuffer + lastPktOffset;
+    lastPktFlag = pLastPktBuffer[1];
+    lastPktPayloadLength = ((A_UINT16)(*(A_UINT16*)(pLastPktBuffer + 2)));
+
+    if(lastPktFlag & HTC_FLAGS_RECV_TRAILER) {
+        temp = HTC_GET_FIELD(pLastPktBuffer, HTC_FRAME_HDR, CONTROLBYTES0);
+        if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > lastPktPayloadLength)) {
+            AR_DEBUG_PRINTF( ATH_DEBUG_ERR,
+                ("%s: invalid header (payloadlength should be :%d, CB[0] is:%d) \n", __func__, lastPktPayloadLength, temp));
+            return;
+        }
+        lastPktRecordID = *(A_UINT8*)(pLastPktBuffer + lastPktPayloadLength + 8 - temp);
+        pRecord = (HTC_RECORD_HDR *)(pLastPktBuffer + lastPktPayloadLength + 8 - temp);
+        pRecordBuf = (A_UINT8*)(pLastPktBuffer + lastPktPayloadLength - temp + 12);
+        if(lastPktRecordID == HTC_RECORD_LOOKAHEAD) {
+            pLookAhead = (HTC_LOOKAHEAD_REPORT *) pRecordBuf;
+            if (pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) {
+                ((A_UINT8 *) (&LookAheads[0]))[0] = pLookAhead->LookAhead0;
+                ((A_UINT8 *) (&LookAheads[0]))[1] = pLookAhead->LookAhead1;
+                ((A_UINT8 *) (&LookAheads[0]))[2] = pLookAhead->LookAhead2;
+                ((A_UINT8 *) (&LookAheads[0]))[3] = pLookAhead->LookAhead3;
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                ((A_UINT8 *) (&lookAhead_part2[0]))[0] = pLookAhead->LookAhead4;
+                ((A_UINT8 *) (&lookAhead_part2[0]))[1] = pLookAhead->LookAhead5;
+                ((A_UINT8 *) (&lookAhead_part2[0]))[2] = pLookAhead->LookAhead6;
+                ((A_UINT8 *) (&lookAhead_part2[0]))[3] = pLookAhead->LookAhead7;
+#endif
+                if (pNumLookAheads != NULL) {
+                    *pNumLookAheads = 1;
+                }
+                return;
+            }
+        }
+        else if (lastPktRecordID == HTC_RECORD_LOOKAHEAD_BUNDLE) {
+            if(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)) {
+                HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt;
+                int i;
+
+                pBundledLookAheadRpt =
+                        (HTC_BUNDLED_LOOKAHEAD_REPORT *) pRecordBuf;
+
+                if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+                    DebugDumpBytes(pRecordBuf,
+                            pRecord->Length,
+                            "Bundle LookAhead");
+                }
+
+                if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)))
+                        > HTC_MAX_MSG_PER_BUNDLE_RX) {
+                    /* this should never happen, the target restricts the number
+                     * of messages per bundle configured by the host */
+                    A_ASSERT(FALSE);
+                    return ;
+                }
+                for (i = 0; i< (int) (pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) {
+                    ((A_UINT8 *) (&LookAheads[i]))[0] =
+                            pBundledLookAheadRpt->LookAhead0;
+                    ((A_UINT8 *) (&LookAheads[i]))[1] =
+                            pBundledLookAheadRpt->LookAhead1;
+                    ((A_UINT8 *) (&LookAheads[i]))[2] =
+                            pBundledLookAheadRpt->LookAhead2;
+                    ((A_UINT8 *) (&LookAheads[i]))[3] =
+                            pBundledLookAheadRpt->LookAhead3;
+                    pBundledLookAheadRpt++;
+                }
+
+                if (pNumLookAheads != NULL) {
+                    *pNumLookAheads = i;
+                }
+
+            }
+        }
+    }
+}
+#endif
+
 static INLINE A_STATUS HIFDevRecvPacket(HIF_SDIO_DEVICE *pDev,
     HTC_PACKET *pPacket,
     A_UINT32 RecvLength,
@@ -343,7 +491,12 @@
 
 static INLINE A_STATUS HIFDevProcessTrailer(HIF_SDIO_DEVICE *pDev,
         A_UINT8 *pBuffer, int Length, A_UINT32 *pNextLookAheads,
-        int *pNumLookAheads, HTC_ENDPOINT_ID FromEndpoint)
+        int *pNumLookAheads, HTC_ENDPOINT_ID FromEndpoint
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        , A_UINT32 lookAhead_part2[])
+#else
+        )
+#endif
 {
     HTC_RECORD_HDR *pRecord;
     A_UINT8 *pRecordBuf;
@@ -406,6 +559,13 @@
                 ((A_UINT8 *) (&pNextLookAheads[0]))[2] = pLookAhead->LookAhead2;
                 ((A_UINT8 *) (&pNextLookAheads[0]))[3] = pLookAhead->LookAhead3;
 
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                ((A_UINT8 *) (&lookAhead_part2[0]))[0] = pLookAhead->LookAhead4;
+                ((A_UINT8 *) (&lookAhead_part2[0]))[1] = pLookAhead->LookAhead5;
+                ((A_UINT8 *) (&lookAhead_part2[0]))[2] = pLookAhead->LookAhead6;
+                ((A_UINT8 *) (&lookAhead_part2[0]))[3] = pLookAhead->LookAhead7;
+#endif
+
                 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
                     DebugDumpBytes((A_UINT8 *) pNextLookAheads,
                             4,
@@ -482,11 +642,15 @@
 
 }
 
-
 /* process a received message (i.e. strip off header, process any trailer data)
  * note : locks must be released when this function is called */
 static A_STATUS HIFDevProcessRecvHeader(HIF_SDIO_DEVICE *pDev,
-        HTC_PACKET *pPacket, A_UINT32 *pNextLookAheads, int *pNumLookAheads)
+        HTC_PACKET *pPacket, A_UINT32 *pNextLookAheads, int *pNumLookAheads, bool processTrailer
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        , A_UINT32 lookAhead_part2[])
+#else
+        )
+#endif
 {
     A_UINT8 temp;
     A_UINT8 *pBuf;
@@ -548,9 +712,9 @@
             /* somehow the lookahead that gave us the full read length did not
              * reflect the actual header in the pending message */
             AR_DEBUG_PRINTF( ATH_DEBUG_ERR,
-                ("HIFDevProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X), 0x%08X != 0x%08X\n",
-                           (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags,
-                           lookAhead, pPacket->PktInfo.AsRx.ExpectedHdr));
+                ("HIFDevProcessRecvHeader, lookahead mismatch! (pPkt:%p flags:0x%X), 0x%08X != 0x%08X len %d\n",
+                           pPacket, pPacket->PktInfo.AsRx.HTCRxFlags,
+                           lookAhead, pPacket->PktInfo.AsRx.ExpectedHdr, payloadLen));
 #ifdef ATH_DEBUG_MODULE
             DebugDumpBytes((A_UINT8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
             DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header");
@@ -567,42 +731,53 @@
             break;
         }
 
-        /* get flags */
-        temp = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, FLAGS);
+#ifdef HIF_RX_THREAD
+        if(processTrailer == TRUE) {
+#endif
+            /* get flags */
+            temp = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, FLAGS);
 
-        if (temp & HTC_FLAGS_RECV_TRAILER) {
-            /* this packet has a trailer */
+            if (temp & HTC_FLAGS_RECV_TRAILER) {
+                /* this packet has a trailer */
 
-            /* extract the trailer length in control byte 0 */
-            temp = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, CONTROLBYTES0);
+                /* extract the trailer length in control byte 0 */
+                temp = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, CONTROLBYTES0);
 
-            if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
-                AR_DEBUG_PRINTF( ATH_DEBUG_ERR,
-                    ("HIFDevProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", payloadLen, temp));
-                status = A_EPROTO;
-                break;
+                if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
+                    AR_DEBUG_PRINTF( ATH_DEBUG_ERR,
+                        ("HIFDevProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", payloadLen, temp));
+                    status = A_EPROTO;
+                    break;
+                }
+
+                if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
+                    /* this packet was fetched as part of an HTC bundle, the embedded lookahead is
+                     * not valid since the next packet may have already been fetched as part of the
+                     * bundle */
+                    pNextLookAheads = NULL;
+                    pNumLookAheads = NULL;
+                }
+
+                /* process trailer data that follows HDR + application payload */
+                status = HIFDevProcessTrailer(pDev,
+                        (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
+                        temp,
+                        pNextLookAheads,
+                        pNumLookAheads,
+                        pPacket->Endpoint
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                        , lookAhead_part2);
+#else
+                        );
+#endif
+
+                if (A_FAILED(status)) {
+                    break;
+                }
             }
-
-            if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
-                /* this packet was fetched as part of an HTC bundle, the embedded lookahead is
-                 * not valid since the next packet may have already been fetched as part of the
-                 * bundle */
-                pNextLookAheads = NULL;
-                pNumLookAheads = NULL;
-            }
-
-            /* process trailer data that follows HDR + application payload */
-            status = HIFDevProcessTrailer(pDev,
-                    (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
-                    temp,
-                    pNextLookAheads,
-                    pNumLookAheads,
-                    pPacket->Endpoint);
-
-            if (A_FAILED(status)) {
-                break;
-            }
+#ifdef HIF_RX_THREAD
         }
+#endif
     }while (FALSE);
 
     if (A_FAILED(status)) {
@@ -621,19 +796,242 @@
     return status;
 }
 
+#ifdef HIF_RX_THREAD
+static A_STATUS processHdrAndRxComp(HIF_SDIO_DEVICE *device, HTC_PACKET *pPacket, bool processTrailer)
+{
+    A_UINT8 pipeid;
+    adf_nbuf_t netbuf;
+    int NumLookAheads;
+    A_UINT32 lookAheads[HTC_MAX_MSG_PER_BUNDLE_RX];
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_UINT32 lookAhead_part2[HTC_MAX_MSG_PER_BUNDLE_RX];
+#endif
+    A_STATUS status = A_OK;
+
+    NumLookAheads = 0;
+    status = HIFDevProcessRecvHeader(device, pPacket, lookAheads, &NumLookAheads, processTrailer
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        , lookAhead_part2);
+#else
+            );
+#endif
+    if (A_FAILED(status)) {
+        return status;
+    }
+
+    netbuf = (adf_nbuf_t) pPacket->pNetBufContext;
+    /* set data length */
+    adf_nbuf_put_tail(netbuf, pPacket->ActualLength);
+
+    if (device->hif_callbacks.rxCompletionHandler) {
+        pipeid = HIFDevMapMailBoxToPipe(device, 0, TRUE);
+        device->hif_callbacks.rxCompletionHandler(device->hif_callbacks.Context,
+            netbuf,
+            pipeid);
+    }
+    return status;
+}
+
+int rx_completion_task(void *param)
+{
+    HIF_SDIO_DEVICE *device;
+    HTC_PACKET *pPacket = NULL;
+    unsigned long flags;
+    HTC_PACKET *pPacketRxBundle;
+    A_UINT32 paddedLength;
+    unsigned char    *pBundleBuffer = NULL;
+    unsigned char *pBuffer;
+    HTC_TARGET *target = NULL;
+    A_UINT8 syncQDepth = 0;
+    A_UINT8 nextIsSingle = 0;
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_UINT16 curPayloadLen = 0;
+#endif
+    A_STATUS status = A_OK;
+
+    device = (HIF_SDIO_DEVICE *)param;
+    target = (HTC_TARGET *)device->pTarget;
+    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: rx completion task\n"));
+
+    set_current_state(TASK_INTERRUPTIBLE);
+    vos_set_cpus_allowed_ptr(current, 1);
+
+    while (!device->pRecvTask->rx_completion_shutdown) {
+        if (down_interruptible(&device->pRecvTask->sem_rx_completion) != 0) {
+                AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+                        ("%s: rx completion task interrupted\n",
+                         __func__));
+                break;
+        }
+
+        if (device->pRecvTask->rx_completion_shutdown) {
+                AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+                        ("%s: rx completion task stopping\n",
+                         __func__));
+                break;
+        }
+
+        //process single packet
+        spin_lock_irqsave(&device->pRecvTask->rx_bundle_lock, flags);
+        if(HTC_QUEUE_EMPTY(&device->pRecvTask->rxBundleQueue)) {
+            spin_lock_irqsave(&device->pRecvTask->rx_sync_completion_lock, flags);
+            while(!HTC_QUEUE_EMPTY(&device->pRecvTask->rxSyncCompletionQueue)) {
+                pPacket = HTC_PACKET_DEQUEUE(&device->pRecvTask->rxSyncCompletionQueue);
+                if(pPacket == NULL) {
+                    break;
+                }
+                status = processHdrAndRxComp(device, pPacket, FALSE);
+
+                if (A_FAILED(status)) {
+                    break;
+                }
+            }
+            spin_unlock_irqrestore(&device->pRecvTask->rx_sync_completion_lock, flags);
+        }
+        else {
+            //1. Dequeue from bundle buffer queue, scatter data to sync completion queue
+            while(!HTC_QUEUE_EMPTY(&device->pRecvTask->rxBundleQueue)) {
+                pPacketRxBundle = HTC_PACKET_DEQUEUE(&device->pRecvTask->rxBundleQueue);
+                if(pPacketRxBundle == NULL) {
+                    break;
+                }
+                if(pPacketRxBundle->BundlePktnum < 1) {
+                    AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Packets in bundle buffer is < 1"));
+                    break;
+                }
+                spin_lock_irqsave(&device->pRecvTask->rx_sync_completion_lock, flags);
+                if(HTC_PACKET_QUEUE_DEPTH(&device->pRecvTask->rxSyncCompletionQueue) < pPacketRxBundle->BundlePktnum) {
+                    // corner case: the sync queue depth is not enough for processing this bundle pkt, push it back
+                    HTC_PACKET_ENQUEUE_TO_HEAD(&device->pRecvTask->rxBundleQueue, pPacketRxBundle);
+                    spin_unlock_irqrestore(&device->pRecvTask->rx_sync_completion_lock, flags);
+                    break;
+                }
+                spin_unlock_irqrestore(&device->pRecvTask->rx_sync_completion_lock, flags);
+                pBundleBuffer = pPacketRxBundle->pBuffer;
+                pBuffer = pBundleBuffer;
+                if(pPacketRxBundle == NULL)
+                    break;
+
+                spin_lock_irqsave(&device->pRecvTask->rx_sync_completion_lock, flags);
+                //if the next pkt is single, dequeue it and process it, until the bundle pkts
+                while(TRUE) {
+                    nextIsSingle = 0;
+                    pPacket = HTC_GET_PKT_AT_HEAD(&device->pRecvTask->rxSyncCompletionQueue);
+                    if(pPacket == NULL)
+                        break;
+                    if(pPacket->BundlePktnum == 1) {
+                        nextIsSingle = 1;
+                    }
+                    if(nextIsSingle == 1) {
+                        pPacket = HTC_PACKET_DEQUEUE(&device->pRecvTask->rxSyncCompletionQueue);
+                        if(pPacket == NULL)
+                            break;
+
+                        status = processHdrAndRxComp(device, pPacket, FALSE);
+
+                        if (A_FAILED(status)) {
+                            break;
+                        }
+                    }
+                    else
+                        break;
+                }
+
+                //2. Dequeue from sync completion queue for processing header, the trialer info at this point is useless.
+                syncQDepth = 0;
+                while(!HTC_QUEUE_EMPTY(&device->pRecvTask->rxSyncCompletionQueue)) {
+                    pPacket = HTC_PACKET_DEQUEUE(&device->pRecvTask->rxSyncCompletionQueue);
+                    if(pPacket == NULL)
+                        break;
+                    syncQDepth++;
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                    curPayloadLen = *(A_UINT16*)(&pBuffer[2]);
+                    pPacket->ActualLength = curPayloadLen + HTC_HDR_LENGTH;
+                    paddedLength = DEV_CALC_RECV_PADDED_LEN(device, pPacket->ActualLength);
+#else
+                    paddedLength = DEV_CALC_RECV_PADDED_LEN(device, pPacket->ActualLength);
+                    if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK){
+                            paddedLength += HIF_MBOX_BLOCK_SIZE;
+                    }
+#endif
+                    A_MEMCPY(pPacket->pBuffer, pBuffer, paddedLength);
+                    pBuffer += paddedLength;
+                    status = processHdrAndRxComp(device, pPacket, FALSE);
+                    if (A_FAILED(status)) {
+                        break;
+                    }
+
+                    if(syncQDepth > (pPacketRxBundle->BundlePktnum - 1))
+                        break;
+                }
+                //if the next pkt is single, dequeue it and process it, until the bundle pkts
+                while(TRUE) {
+                    nextIsSingle = 0;
+                    pPacket = HTC_GET_PKT_AT_HEAD(&device->pRecvTask->rxSyncCompletionQueue);
+                    if(pPacket == NULL)
+                        break;
+                    if(pPacket->BundlePktnum == 1) {
+                        nextIsSingle = 1;
+                    }
+                    if(nextIsSingle == 1) {
+                        pPacket = HTC_PACKET_DEQUEUE(&device->pRecvTask->rxSyncCompletionQueue);
+                        if(pPacket == NULL)
+                            break;
+                        status = processHdrAndRxComp(device, pPacket, FALSE);
+                        if (A_FAILED(status)) {
+                            break;
+                        }
+                    }
+                    else
+                        break;
+                }
+                spin_unlock_irqrestore(&device->pRecvTask->rx_sync_completion_lock, flags);
+                FreeHTCBundleRxPacket(target, pPacketRxBundle);
+            }
+        }
+        spin_unlock_irqrestore(&device->pRecvTask->rx_bundle_lock, flags);
+        //alloc skb for next bundle
+        spin_lock_irqsave(&device->pRecvTask->rx_alloc_lock, flags);
+        while(HTC_PACKET_QUEUE_DEPTH(&device->pRecvTask->rxAllocQueue) < 64) {
+            pPacket = HIFDevAllocRxBuffer(device, 2048);
+            if(pPacket == NULL) {
+                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Short of mem, alloc failed"));
+                break;
+            }
+            HTC_PACKET_ENQUEUE(&device->pRecvTask->rxAllocQueue, pPacket);
+        }
+        spin_unlock_irqrestore(&device->pRecvTask->rx_alloc_lock, flags);
+    }
+    complete_and_exit(&device->pRecvTask->rx_completion_exit, 0);
+    return 0;
+}
+#endif
+
 static A_STATUS HIFDevIssueRecvPacketBundle(HIF_SDIO_DEVICE *pDev,
         HTC_PACKET_QUEUE *pRecvPktQueue,
         HTC_PACKET_QUEUE *pSyncCompletionQueue,
         A_UINT8 MailBoxIndex,
         int *pNumPacketsFetched,
-        A_BOOL  PartialBundle)
+        A_BOOL  PartialBundle
+#ifdef HIF_RX_THREAD
+        , int *pNumLookAheads
+        , A_UINT32 LookAheads[]
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        , A_UINT32 lookAhead_part2[]
+#endif
+#endif
+        )
 { A_STATUS status = A_OK;
     int i, totalLength = 0;
     unsigned char    *pBundleBuffer = NULL;
     HTC_PACKET *pPacket, *pPacketRxBundle;
     HTC_TARGET *target = NULL;
     A_UINT32 paddedLength;
-
+#ifdef HIF_RX_THREAD
+    unsigned long flags;
+#else
+    unsigned char *pBuffer = NULL;
+#endif
     int bundleSpaceRemaining = 0;
     target = (HTC_TARGET *)pDev->pTarget;
 
@@ -685,6 +1083,9 @@
 
         totalLength += paddedLength;
     }
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    totalLength = (A_UINT16)((lookAhead_part2[0] & 0xffff0000) >> 16);
+#endif
 #if DEBUG_BUNDLE
     adf_os_print("Recv bundle count %d, length %d.\n",
        HTC_PACKET_QUEUE_DEPTH(pSyncCompletionQueue), totalLength);
@@ -715,37 +1116,77 @@
     if(status != A_OK){
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s, HIFSend Failed status:%d \n",__FUNCTION__, status));
     }else{
-        unsigned char *pBuffer = pBundleBuffer;
+#ifdef HIF_RX_THREAD
+        HIFDevPreprocessTrailer(pDev, pPacketRxBundle, LookAheads, pNumLookAheads
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                    , lookAhead_part2);
+#else
+                );
+#endif
         *pNumPacketsFetched = i;
+#ifdef HIF_RX_THREAD
+        pPacketRxBundle->BundlePktnum = i;
+#endif
+        spin_lock_irqsave(&pDev->pRecvTask->rx_bundle_lock, flags);
+        HTC_PACKET_ENQUEUE(&pDev->pRecvTask->rxBundleQueue, pPacketRxBundle);
+        spin_unlock_irqrestore(&pDev->pRecvTask->rx_bundle_lock, flags);
+
+        spin_lock_irqsave(&pDev->pRecvTask->rx_sync_completion_lock, flags);
+        HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pDev->pRecvTask->rxSyncCompletionQueue, pSyncCompletionQueue);
+        spin_unlock_irqrestore(&pDev->pRecvTask->rx_sync_completion_lock, flags);
+#else
+        *pNumPacketsFetched = i;
+        pBuffer = pBundleBuffer;
         HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pSyncCompletionQueue, pPacket){
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+            curPayloadLen = *(A_UINT16*)(&pBuffer[2]);
+            pPacket->ActualLength = curPayloadLen + HTC_HDR_LENGTH;
+            paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, pPacket->ActualLength);
+#else
             paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, pPacket->ActualLength);
             if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK){
                     paddedLength += HIF_MBOX_BLOCK_SIZE;
             }
+#endif
             A_MEMCPY(pPacket->pBuffer, pBuffer, paddedLength);
             pBuffer += paddedLength;
         }HTC_PACKET_QUEUE_ITERATE_END;
+#endif
     }
+#ifndef HIF_RX_THREAD
     /* free bundle space under Sync mode */
     FreeHTCBundleRxPacket(target, pPacketRxBundle);
+#endif
     return status;
 }
+
 A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev,
         A_UINT8 MailBoxIndex,
         A_UINT32 MsgLookAheads[],
         int NumLookAheads,
         A_BOOL *pAsyncProc,
-        int *pNumPktsFetched)
+        int *pNumPktsFetched
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+        , A_UINT32 LookAhead_Part2[])
+#else
+        )
+#endif
 {
     A_STATUS status = A_OK;
     HTC_PACKET *pPacket;
     A_BOOL asyncProc = FALSE;
     A_UINT32 lookAheads[HTC_MAX_MSG_PER_BUNDLE_RX];
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_UINT32 lookAhead_part2[HTC_MAX_MSG_PER_BUNDLE_RX];
+#endif
     int pktsFetched;
     HTC_PACKET_QUEUE recvPktQueue, syncCompletedPktsQueue;
     A_BOOL partialBundle;
     HTC_ENDPOINT_ID id;
     int totalFetched = 0;
+#ifdef HIF_RX_THREAD
+    unsigned long flags;
+#endif
 
     HTC_TARGET *target = NULL;
 
@@ -772,6 +1213,9 @@
         return A_EPROTO;
     }
     A_MEMCPY(lookAheads, MsgLookAheads, (sizeof(A_UINT32)) * NumLookAheads);
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_MEMCPY(lookAhead_part2, LookAhead_Part2, (sizeof(A_UINT32)) * NumLookAheads);
+#endif
 
     target = (HTC_TARGET *)pDev->pTarget;
     id = ((HTC_FRAME_HDR *) &lookAheads[0])->EndpointID;
@@ -783,7 +1227,6 @@
 #endif
 
 
-
     while (TRUE) {
 
         /* reset packets queues */
@@ -794,7 +1237,6 @@
             A_ASSERT(FALSE);
             break;
         }
-
         /* first lookahead sets the expected endpoint IDs for all packets in a bundle */
         id = ((HTC_FRAME_HDR *) &lookAheads[0])->EndpointID;
 
@@ -822,16 +1264,23 @@
 
         /* now go fetch the list of HTC packets */
         while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
-
             pktsFetched = 0;
             if ((HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) {
                 /* there are enough packets to attempt a bundle transfer and recv bundling is allowed  */
-                status = HIFDevIssueRecvPacketBundle(pDev,
-                        &recvPktQueue,
-                        asyncProc ? NULL : &syncCompletedPktsQueue,
-                        MailBoxIndex,
-                        &pktsFetched,
-                        partialBundle);
+                    status = HIFDevIssueRecvPacketBundle(pDev,
+                            &recvPktQueue,
+                            asyncProc ? NULL : &syncCompletedPktsQueue,
+                            MailBoxIndex,
+                            &pktsFetched,
+                            partialBundle
+#ifdef HIF_RX_THREAD
+                            , &NumLookAheads
+                            , lookAheads
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                            , lookAhead_part2
+#endif
+#endif
+                            );
                 if (A_FAILED(status)) {
                     while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
                         adf_nbuf_t netbuf;
@@ -901,7 +1350,21 @@
                     break;
                 }
                 /* sent synchronously, queue this packet for synchronous completion */
+#ifdef HIF_RX_THREAD
+                NumLookAheads = 0;
+                HIFDevPreprocessTrailer(pDev, pPacket, lookAheads, &NumLookAheads
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                    , lookAhead_part2);
+#else
+                        );
+#endif
+                pPacket->BundlePktnum = 1;
+                spin_lock_irqsave(&pDev->pRecvTask->rx_sync_completion_lock, flags);
+                HTC_PACKET_ENQUEUE(&pDev->pRecvTask->rxSyncCompletionQueue, pPacket);
+                spin_unlock_irqrestore(&pDev->pRecvTask->rx_sync_completion_lock, flags);
+#else
                 HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue, pPacket);
+#endif
             }
         }
 
@@ -913,7 +1376,9 @@
 
         /* in the sync case, all packet buffers are now filled,
          * we can process each packet, check lookaheads and then repeat */
-
+#ifdef HIF_RX_THREAD
+        up(&pDev->pRecvTask->sem_rx_completion);
+#else
         /* unload sync completion queue */
         while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
             A_UINT8 pipeid;
@@ -924,8 +1389,12 @@
                 break;
 
             NumLookAheads = 0;
-            status = HIFDevProcessRecvHeader(pDev, pPacket, lookAheads,
-                    &NumLookAheads);
+            status = HIFDevProcessRecvHeader(pDev, pPacket, lookAheads, &NumLookAheads, TRUE
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                    , lookAhead_part2);
+#else
+                    );
+#endif
             if (A_FAILED(status)) {
                 HTC_PACKET_ENQUEUE_TO_HEAD(&syncCompletedPktsQueue, pPacket);
                 break;
@@ -942,7 +1411,7 @@
                         pipeid);
             }
         }
-
+#endif
         if (A_FAILED(status)) {
             while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
                 adf_nbuf_t netbuf;
@@ -1130,6 +1599,9 @@
     A_STATUS status = A_OK;
     A_UINT8 host_int_status = 0;
     A_UINT32 lookAhead[MAILBOX_USED_COUNT];
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+    A_UINT32 lookAhead_part2[MAILBOX_USED_COUNT];
+#endif
     int i;
 
     A_MEMZERO(&lookAhead, sizeof(lookAhead));
@@ -1150,7 +1622,6 @@
             break;
         }
 
-
 #ifdef HIF_SYNC_READ
         status = HIFSyncRead(pDev->HIFDevice,
                     HOST_INT_STATUS_ADDRESS,
@@ -1193,9 +1664,18 @@
                 if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << i)) {
                     /* mailbox has a message and the look ahead is valid */
                     lookAhead[i] = pDev->IrqProcRegisters.rx_lookahead[MAILBOX_LOOKAHEAD_SIZE_IN_WORD*i];
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                    lookAhead_part2[i] = pDev->IrqProcRegisters.rx_lookahead[MAILBOX_LOOKAHEAD_SIZE_IN_WORD*i + 1];
+#endif
                 }
             }
         } /*end of for loop*/
+#ifdef HIF_RX_THREAD
+        if (((HTC_FRAME_HDR *) &lookAhead[0])->EndpointID >= ENDPOINT_MAX) {
+            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Endpoint id in register invalid"
+                            " %d\n", ((HTC_FRAME_HDR *) &lookAhead[0])->EndpointID));
+        }
+#endif
     } while (FALSE);
 
     do {
@@ -1236,7 +1716,12 @@
                         &lookAhead[i],
                         1,
                         pASyncProcessing,
-                        &fetched);
+                        &fetched
+#if HIF_BUNDLE_DIFF_BLK_FRAMES
+                        , lookAhead_part2);
+#else
+                        );
+#endif
                 if (A_FAILED(status)) {
                     break;
                 }
diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
index 416a682..0174a60 100644
--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
+++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -882,12 +882,18 @@
  */
 static inline int hif_start_tx_completion_thread(HIF_DEVICE *device)
 {
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+	struct sched_param param = {.sched_priority = 99};
+#endif
 	if (!device->tx_completion_task) {
 		device->tx_completion_req = NULL;
 		device->last_tx_completion = &device->tx_completion_req;
 		device->tx_completion_shutdown = 0;
 		device->tx_completion_task = kthread_create(tx_completion_task,
 			(void *)device,	"AR6K TxCompletion");
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+		sched_setscheduler(device->tx_completion_task, SCHED_FIFO, &param);
+#endif
 		if (IS_ERR(device->tx_completion_task)) {
 			device->tx_completion_shutdown = 1;
 			AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
@@ -2030,7 +2036,9 @@
 static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
 {
     int ret = A_OK;
-
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+    struct sched_param param = {.sched_priority = 99};
+#endif
     ENTER("sdio_func 0x%pK", func);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n"));
@@ -2142,6 +2150,9 @@
             device->async_task = kthread_create(async_task,
                                            (void *)device,
                                            "AR6K Async");
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+           sched_setscheduler(device->async_task, SCHED_FIFO, &param);
+#endif
            if (IS_ERR(device->async_task)) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
                device->async_task = NULL;
diff --git a/CORE/SERVICES/HTC/htc_send.c b/CORE/SERVICES/HTC/htc_send.c
index ad47adc..bc26d7e 100644
--- a/CORE/SERVICES/HTC/htc_send.c
+++ b/CORE/SERVICES/HTC/htc_send.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -412,8 +412,8 @@
     adf_os_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.\n",
             pEndpoint->Id,
             pEndpoint->TxCreditSize,
-            data_len,
-            data_len / pEndpoint->TxCreditSize);
+            (int)data_len,
+            (int)data_len / pEndpoint->TxCreditSize);
 #endif
 
 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
@@ -526,8 +526,10 @@
        HTC_WRITE32((A_UINT32 *)pHtcHdr + 1,
                  SM(pPacket->PktInfo.AsTx.SeqNo, HTC_FRAME_HDR_CONTROLBYTES1) |
                  SM(creditPad, HTC_FRAME_HDR_RESERVED));
+#if !HIF_BUNDLE_DIFF_BLK_FRAMES
        pHtcHdr->reserved = creditPad;
 #endif
+#endif
        frag_count = adf_nbuf_get_num_frags(netbuf);
        nbytes = pPacket->ActualLength + HTC_HDR_LENGTH;
        for (i = 0; i < frag_count && nbytes > 0; i ++){
@@ -668,7 +670,7 @@
         adf_os_print(" Send single EP%d buffer size:0x%x, total:0x%x.\n",
             pEndpoint->Id,
             pEndpoint->TxCreditSize,
-            HTC_HDR_LENGTH + pPacket->ActualLength);
+            (int)HTC_HDR_LENGTH + pPacket->ActualLength);
 #endif
 
 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
@@ -1538,7 +1540,7 @@
         adf_os_print(" Send single EP%d buffer size:0x%x, total:0x%x.\n",
             pEndpoint->Id,
             pEndpoint->TxCreditSize,
-            HTC_HDR_LENGTH + pPacket->ActualLength);
+            (int)HTC_HDR_LENGTH + pPacket->ActualLength);
 #endif
 
 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
diff --git a/CORE/VOSS/src/vos_sched.c b/CORE/VOSS/src/vos_sched.c
index 3f24b92..cb5787e 100644
--- a/CORE/VOSS/src/vos_sched.c
+++ b/CORE/VOSS/src/vos_sched.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -501,6 +501,9 @@
 )
 {
   VOS_STATUS  vStatus = VOS_STATUS_SUCCESS;
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+  struct sched_param param = {.sched_priority = 99};
+#endif
 /*-------------------------------------------------------------------------*/
   VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
              "%s: Opening the VOSS Scheduler",__func__);
@@ -589,6 +592,9 @@
   pSchedContext->TlshimRxThread = kthread_create(VosTlshimRxThread,
                                                  pSchedContext,
                                                  "VosTlshimRxThread");
+#ifdef CONFIG_PERF_NON_QC_PLATFORM
+  sched_setscheduler(pSchedContext->TlshimRxThread, SCHED_FIFO, &param);
+#endif
   if (IS_ERR(pSchedContext->TlshimRxThread))
   {