diff options
| author | Visweswara Tanuku <vtanuku@codeaurora.org> | 2018-01-10 21:25:16 +0530 |
|---|---|---|
| committer | Visweswara Tanuku <vtanuku@codeaurora.org> | 2018-05-21 14:15:47 +0530 |
| commit | 50b489c3ecf7e7a8cbf0b6ce366c4e17b40f093c (patch) | |
| tree | 362733ba18836b97db0fa781c6cae0f84e7b4def | |
| parent | 23f27846af37710ec1c55e8f1029e1f52ac83e2f (diff) | |
qcacld-2.0: SDIO: TxRx Throughput Enhancement
Tx improvement achieved by increasing Tx buffers in FW
and by enabling 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,
Using HTC Connect Service messages find if FW supports bundling
of different sized Rx packets. Handle the Rx bundling in host,
based on support in FW and maintain backward compatibility.
Rx Bundling helped in improving Chariot TCP Rx throughput
Change-Id: I63118395bf148f53a25304c7fd90e126c1f29270
CRs-Fixed: 2170127
| -rw-r--r-- | CORE/SERVICES/COMMON/htc.h | 47 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/htc_packet.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/sdio/hif_sdio_dev.c | 102 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/sdio/hif_sdio_internal.h | 24 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/sdio/hif_sdio_recv.c | 654 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c | 15 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc.c | 8 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc_internal.h | 6 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc_send.c | 11 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc_services.c | 20 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_sched.c | 6 | ||||
| -rw-r--r-- | Kbuild | 5 |
12 files changed, 794 insertions, 107 deletions
diff --git a/CORE/SERVICES/COMMON/htc.h b/CORE/SERVICES/COMMON/htc.h index e61555ee6c45..91296a512246 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-2014,2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -82,6 +82,10 @@ * */ +#ifdef HIF_SDIO +#define HIF_BUNDLE_DIFF_BLK_FRAMES 1 +#endif + /* HTC frame header */ typedef PREPACK struct _HTC_FRAME_HDR{ /* do not remove or re-arrange these fields, these are minimally required @@ -266,7 +270,12 @@ typedef PREPACK struct { #define HTC_CONNECT_FLAGS_ENABLE_HTC_SCHEDULE (1 << 4) ServiceMetaLength : 8, /* length of meta data that follows */ +#ifdef HIF_SDIO + LookAheadV2 : 1, /* indicate host support bundle different SDIO block number frames */ + _Pad1 : 7; +#else _Pad1 : 8; +#endif /* service-specific meta data starts after the header */ @@ -284,6 +293,11 @@ typedef PREPACK struct { #define HTC_CONNECT_SERVICE_MSG_SERVICEMETALENGTH_LSB 16 #define HTC_CONNECT_SERVICE_MSG_SERVICEMETALENGTH_MASK 0x00ff0000 #define HTC_CONNECT_SERVICE_MSG_SERVICEMETALENGTH_OFFSET 0x00000004 +#ifdef HIF_SDIO +#define HTC_CONNECT_SERVICE_MSG_LOOKAHEADV2_LSB 24 +#define HTC_CONNECT_SERVICE_MSG_LOOKAHEADV2_MASK 0x01000000 +#define HTC_CONNECT_SERVICE_MSG_LOOKAHEADV2_OFFSET 0x00000004 +#endif #define HTC_SET_RECV_ALLOC_SHIFT 8 #define HTC_SET_RECV_ALLOC_MASK 0xFF00 @@ -299,7 +313,12 @@ typedef PREPACK struct { EndpointID : 8, /* assigned endpoint ID */ MaxMsgSize : 16; /* maximum expected message size on this endpoint */ A_UINT32 ServiceMetaLength : 8, /* length of meta data that follows */ +#ifdef HIF_SDIO + LookAheadV2 : 1, /* indicate firmware support bundle different SDIO block number frames */ + _Pad1 : 7, +#else _Pad1 : 8, +#endif reserved : 16; /* service-specific meta data starts after the header */ @@ -324,6 +343,11 @@ typedef PREPACK struct { #define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEMETALENGTH_LSB 0 #define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEMETALENGTH_MASK 0x000000ff #define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEMETALENGTH_OFFSET 0x00000008 +#ifdef HIF_SDIO +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_LOOKAHEADV2_LSB 8 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_LOOKAHEADV2_MASK 0x00000100 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_LOOKAHEADV2_OFFSET 0x00000008 +#endif typedef PREPACK struct { A_UINT32 MessageID : 16, @@ -425,6 +449,27 @@ typedef PREPACK struct { } POSTPACK HTC_LOOKAHEAD_REPORT; +#ifdef HIF_SDIO +typedef PREPACK struct { + A_UINT32 PreValid : 8, /* pre valid guard */ + reserved0 : 24; + A_UINT32 LookAhead0 : 8, /* 4 byte lookahead */ + LookAhead1 : 8, + LookAhead2 : 8, + LookAhead3 : 8; + A_UINT32 LookAhead4 : 8, /* 4 byte lookahead */ + LookAhead5 : 8, + LookAhead6 : 8, + LookAhead7 : 8; + A_UINT32 PostValid : 8, /* post valid guard */ + reserved1 : 24; + + /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes. + * The PreValid bytes must equal the inverse of the PostValid byte */ + +} POSTPACK HTC_LOOKAHEAD_REPORTV2; +#endif + #define HTC_LOOKAHEAD_REPORT_PREVALID_LSB 0 #define HTC_LOOKAHEAD_REPORT_PREVALID_MASK 0x000000ff #define HTC_LOOKAHEAD_REPORT_PREVALID_OFFSET 0x00000000 diff --git a/CORE/SERVICES/COMMON/htc_packet.h b/CORE/SERVICES/COMMON/htc_packet.h index ce4532fd071d..69b2bc8970c9 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-2015,2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -115,6 +115,7 @@ typedef struct _HTC_PACKET { 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 5d9b3b9a6d1a..8d215633d80d 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 @@ HTC_PACKET *HIFDevAllocRxBuffer(HIF_SDIO_DEVICE *pDev, size_t length) 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, ¶m); +#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 @@ HIF_SDIO_DEVICE* HIFDevCreate(HIF_DEVICE *hif_device, 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 @@ HIF_SDIO_DEVICE* HIFDevCreate(HIF_DEVICE *hif_device, 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 fd200d52f87e..842d9e8f2e91 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,8 +111,26 @@ struct TAG_HIF_SDIO_DEVICE { 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); diff --git a/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c b/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c index 36682b081120..0cf998fe5c18 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 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, int numMessages; int fullLength; A_BOOL noRecycle; - +#ifdef HIF_RX_THREAD + unsigned long flags; +#endif + HTC_TARGET *target = NULL; + target = (HTC_TARGET *)pDev->pTarget; /* lock RX while we assemble the packet buffers */ LOCK_HIF_DEV_RX(pDev); @@ -164,7 +168,14 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages)); } - fullLength = DEV_CALC_RECV_PADDED_LEN(pDev,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR)); + if(target->enable_b2b) { + 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)); /* all but the last packet have a length of payloadLen + sizeof(HTC_FRAME_HDR) @@ -174,6 +185,9 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, /* 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 +195,18 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, 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 +215,9 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, 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 +258,25 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */ } /* set the amount of data to fetch */ - pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; - if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK)) + if(target->enable_b2b) { + 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)) { 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 +305,136 @@ static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, return status; } +#ifdef HIF_RX_THREAD +static INLINE void HIFDevPreprocessTrailer(HIF_SDIO_DEVICE *pDev, HTC_PACKET* pPacket, + A_UINT32 LookAheads[], int *pNumLookAheads, + A_UINT32 lookAhead_part2[]) +{ + HTC_TARGET *target = NULL; + A_UINT8 *pRecordBuf; + HTC_RECORD_HDR *pRecord; + HTC_LOOKAHEAD_REPORT *pLookAhead; + HTC_LOOKAHEAD_REPORTV2 *pLookAheadV2; + A_UINT8 *pBuffer, *pLastPktBuffer, *pCur; + A_UINT8 lastPktFlag; + A_UINT16 lastPktPayloadLength; + A_UINT8 lastPktRecordID; + int numMessages; + A_UINT8 temp; + A_UINT32 i; + A_UINT16 curPayloadLen = 0; + A_UINT32 paddedLength = 0, lastPktOffset = 0; + + target = (HTC_TARGET *)pDev->pTarget; + pBuffer = pPacket->pBuffer; + pLastPktBuffer = pBuffer; + pCur = pBuffer; + numMessages = GET_RECV_BUNDLE_COUNT(pBuffer[1]); + + if(target->enable_b2b) { + 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; + } + + 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) { + if(target->enable_b2b) { + pLookAheadV2 = (HTC_LOOKAHEAD_REPORTV2 *) pRecordBuf; + if (pLookAheadV2->PreValid == ((~pLookAheadV2->PostValid) & 0xFF)) { + ((A_UINT8 *) (&LookAheads[0]))[0] = pLookAheadV2->LookAhead0; + ((A_UINT8 *) (&LookAheads[0]))[1] = pLookAheadV2->LookAhead1; + ((A_UINT8 *) (&LookAheads[0]))[2] = pLookAheadV2->LookAhead2; + ((A_UINT8 *) (&LookAheads[0]))[3] = pLookAheadV2->LookAhead3; + + ((A_UINT8 *) (&lookAhead_part2[0]))[0] = pLookAheadV2->LookAhead4; + ((A_UINT8 *) (&lookAhead_part2[0]))[1] = pLookAheadV2->LookAhead5; + ((A_UINT8 *) (&lookAhead_part2[0]))[2] = pLookAheadV2->LookAhead6; + ((A_UINT8 *) (&lookAhead_part2[0]))[3] = pLookAheadV2->LookAhead7; + if (pNumLookAheads != NULL) { + *pNumLookAheads = 1; + } + return; + } + } + else { + 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 (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,11 +508,14 @@ static INLINE A_STATUS HIFDevRecvPacket(HIF_SDIO_DEVICE *pDev, 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, + A_UINT32 lookAhead_part2[]) { + HTC_TARGET *target = NULL; HTC_RECORD_HDR *pRecord; A_UINT8 *pRecordBuf; HTC_LOOKAHEAD_REPORT *pLookAhead; + HTC_LOOKAHEAD_REPORTV2 *pLookAheadV2; A_UINT8 *pOrigBuffer; int origLength; A_STATUS status; @@ -359,6 +527,7 @@ static INLINE A_STATUS HIFDevProcessTrailer(HIF_SDIO_DEVICE *pDev, AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer"); } + target = (HTC_TARGET *)pDev->pTarget; pOrigBuffer = pBuffer; origLength = Length; status = A_OK; @@ -390,30 +559,63 @@ static INLINE A_STATUS HIFDevProcessTrailer(HIF_SDIO_DEVICE *pDev, break; case HTC_RECORD_LOOKAHEAD: AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT)); - pLookAhead = (HTC_LOOKAHEAD_REPORT *) pRecordBuf; - if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) - && (pNextLookAheads != NULL)) { - - AR_DEBUG_PRINTF( ATH_DEBUG_RECV, - (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) %d %d\n", - pLookAhead->PreValid, pLookAhead->PostValid, - FromEndpoint, - pLookAhead->LookAhead0 - )); - /* look ahead bytes are valid, copy them over */ - ((A_UINT8 *) (&pNextLookAheads[0]))[0] = pLookAhead->LookAhead0; - ((A_UINT8 *) (&pNextLookAheads[0]))[1] = pLookAhead->LookAhead1; - ((A_UINT8 *) (&pNextLookAheads[0]))[2] = pLookAhead->LookAhead2; - ((A_UINT8 *) (&pNextLookAheads[0]))[3] = pLookAhead->LookAhead3; - - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { - DebugDumpBytes((A_UINT8 *) pNextLookAheads, - 4, - "Next Look Ahead"); + if(target->enable_b2b) { + pLookAheadV2 = (HTC_LOOKAHEAD_REPORTV2 *) pRecordBuf; + if ((pLookAheadV2->PreValid == ((~pLookAheadV2->PostValid) & 0xFF)) + && (pNextLookAheads != NULL)) { + + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) %d %d\n", + pLookAheadV2->PreValid, pLookAheadV2->PostValid, + FromEndpoint, + pLookAheadV2->LookAhead0 + )); + /* look ahead bytes are valid, copy them over */ + ((A_UINT8 *) (&pNextLookAheads[0]))[0] = pLookAheadV2->LookAhead0; + ((A_UINT8 *) (&pNextLookAheads[0]))[1] = pLookAheadV2->LookAhead1; + ((A_UINT8 *) (&pNextLookAheads[0]))[2] = pLookAheadV2->LookAhead2; + ((A_UINT8 *) (&pNextLookAheads[0]))[3] = pLookAheadV2->LookAhead3; + + ((A_UINT8 *) (&lookAhead_part2[0]))[0] = pLookAheadV2->LookAhead4; + ((A_UINT8 *) (&lookAhead_part2[0]))[1] = pLookAheadV2->LookAhead5; + ((A_UINT8 *) (&lookAhead_part2[0]))[2] = pLookAheadV2->LookAhead6; + ((A_UINT8 *) (&lookAhead_part2[0]))[3] = pLookAheadV2->LookAhead7; + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes((A_UINT8 *) pNextLookAheads, + 4, + "Next Look Ahead"); + } + /* just one normal lookahead */ + if (pNumLookAheads != NULL) { + *pNumLookAheads = 1; + } } - /* just one normal lookahead */ - if (pNumLookAheads != NULL) { - *pNumLookAheads = 1; + } + else { + pLookAhead = (HTC_LOOKAHEAD_REPORT *) pRecordBuf; + if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) + && (pNextLookAheads != NULL)) { + + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) %d %d\n", + pLookAhead->PreValid, pLookAhead->PostValid, + FromEndpoint, + pLookAhead->LookAhead0 + )); + /* look ahead bytes are valid, copy them over */ + ((A_UINT8 *) (&pNextLookAheads[0]))[0] = pLookAhead->LookAhead0; + ((A_UINT8 *) (&pNextLookAheads[0]))[1] = pLookAhead->LookAhead1; + ((A_UINT8 *) (&pNextLookAheads[0]))[2] = pLookAhead->LookAhead2; + ((A_UINT8 *) (&pNextLookAheads[0]))[3] = pLookAhead->LookAhead3; + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes((A_UINT8 *) pNextLookAheads, + 4, + "Next Look Ahead"); + } + /* just one normal lookahead */ + if (pNumLookAheads != NULL) { + *pNumLookAheads = 1; + } } } break; @@ -479,14 +681,13 @@ static INLINE A_STATUS HIFDevProcessTrailer(HIF_SDIO_DEVICE *pDev, AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n")); return status; - } - /* 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, A_UINT32 lookAhead_part2[]) { A_UINT8 temp; A_UINT8 *pBuf; @@ -548,9 +749,9 @@ static A_STATUS HIFDevProcessRecvHeader(HIF_SDIO_DEVICE *pDev, /* 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 +768,49 @@ static A_STATUS HIFDevProcessRecvHeader(HIF_SDIO_DEVICE *pDev, 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; - } + 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); + /* process trailer data that follows HDR + application payload */ + status = HIFDevProcessTrailer(pDev, + (pBuf + HTC_HDR_LENGTH + payloadLen - temp), + temp, + pNextLookAheads, + pNumLookAheads, + pPacket->Endpoint, + lookAhead_part2); - if (A_FAILED(status)) { - break; + if (A_FAILED(status)) { + break; + } } +#ifdef HIF_RX_THREAD } +#endif }while (FALSE); if (A_FAILED(status)) { @@ -621,19 +829,234 @@ static A_STATUS HIFDevProcessRecvHeader(HIF_SDIO_DEVICE *pDev, 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]; + A_UINT32 lookAhead_part2[HTC_MAX_MSG_PER_BUNDLE_RX]; + A_STATUS status = A_OK; + + NumLookAheads = 0; + status = HIFDevProcessRecvHeader(device, pPacket, lookAheads, &NumLookAheads, + processTrailer, lookAhead_part2); + 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; + A_UINT16 curPayloadLen = 0; + 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(target->enable_b2b) { + 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; + } + } + 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[] +#endif + , A_UINT32 lookAhead_part2[] + ) { 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; + A_UINT16 curPayloadLen = 0; +#endif int bundleSpaceRemaining = 0; target = (HTC_TARGET *)pDev->pTarget; @@ -685,6 +1108,8 @@ static A_STATUS HIFDevIssueRecvPacketBundle(HIF_SDIO_DEVICE *pDev, totalLength += paddedLength; } + if(target->enable_b2b) + totalLength = (A_UINT16)((lookAhead_part2[0] & 0xffff0000) >> 16); #if DEBUG_BUNDLE adf_os_print("Recv bundle count %d, length %d.\n", HTC_PACKET_QUEUE_DEPTH(pSyncCompletionQueue), totalLength); @@ -715,37 +1140,67 @@ static A_STATUS HIFDevIssueRecvPacketBundle(HIF_SDIO_DEVICE *pDev, 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, lookAhead_part2); *pNumPacketsFetched = i; + pPacketRxBundle->BundlePktnum = i; + 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){ - 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; + if(target->enable_b2b) { + 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; + } } 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, + A_UINT32 LookAhead_Part2[]) { A_STATUS status = A_OK; HTC_PACKET *pPacket; A_BOOL asyncProc = FALSE; A_UINT32 lookAheads[HTC_MAX_MSG_PER_BUNDLE_RX]; + A_UINT32 lookAhead_part2[HTC_MAX_MSG_PER_BUNDLE_RX]; 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 +1227,7 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, return A_EPROTO; } A_MEMCPY(lookAheads, MsgLookAheads, (sizeof(A_UINT32)) * NumLookAheads); + A_MEMCPY(lookAhead_part2, LookAhead_Part2, (sizeof(A_UINT32)) * NumLookAheads); target = (HTC_TARGET *)pDev->pTarget; id = ((HTC_FRAME_HDR *) &lookAheads[0])->EndpointID; @@ -783,7 +1239,6 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, #endif - while (TRUE) { /* reset packets queues */ @@ -794,7 +1249,6 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, 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 +1276,21 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, /* 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 +#endif + , lookAhead_part2 + ); if (A_FAILED(status)) { while (!HTC_QUEUE_EMPTY(&recvPktQueue)) { adf_nbuf_t netbuf; @@ -901,7 +1360,17 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, break; } /* sent synchronously, queue this packet for synchronous completion */ +#ifdef HIF_RX_THREAD + NumLookAheads = 0; + HIFDevPreprocessTrailer(pDev, pPacket, lookAheads, + &NumLookAheads, lookAhead_part2); + 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 +1382,9 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, /* 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; @@ -925,7 +1396,7 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, NumLookAheads = 0; status = HIFDevProcessRecvHeader(pDev, pPacket, lookAheads, - &NumLookAheads); + &NumLookAheads, TRUE, lookAhead_part2); if (A_FAILED(status)) { HTC_PACKET_ENQUEUE_TO_HEAD(&syncCompletedPktsQueue, pPacket); break; @@ -942,7 +1413,7 @@ A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, pipeid); } } - +#endif if (A_FAILED(status)) { while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { adf_nbuf_t netbuf; @@ -1130,9 +1601,11 @@ static A_STATUS HIFDevProcessPendingIRQs(HIF_SDIO_DEVICE *pDev, A_BOOL *pDone, A_STATUS status = A_OK; A_UINT8 host_int_status = 0; A_UINT32 lookAhead[MAILBOX_USED_COUNT]; + A_UINT32 lookAhead_part2[MAILBOX_USED_COUNT]; int i; A_MEMZERO(&lookAhead, sizeof(lookAhead)); + A_MEMZERO(&lookAhead_part2, sizeof(lookAhead_part2)); AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev)); @@ -1150,7 +1623,6 @@ static A_STATUS HIFDevProcessPendingIRQs(HIF_SDIO_DEVICE *pDev, A_BOOL *pDone, break; } - #ifdef HIF_SYNC_READ status = HIFSyncRead(pDev->HIFDevice, HOST_INT_STATUS_ADDRESS, @@ -1193,9 +1665,16 @@ static A_STATUS HIFDevProcessPendingIRQs(HIF_SDIO_DEVICE *pDev, A_BOOL *pDone, 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]; + lookAhead_part2[i] = pDev->IrqProcRegisters.rx_lookahead[MAILBOX_LOOKAHEAD_SIZE_IN_WORD*i + 1]; } } } /*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 +1715,8 @@ static A_STATUS HIFDevProcessPendingIRQs(HIF_SDIO_DEVICE *pDev, A_BOOL *pDone, &lookAhead[i], 1, pASyncProcessing, - &fetched); + &fetched, + lookAhead_part2); 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 416a682fed3f..0174a606e93d 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 void hif_free_bus_request(HIF_DEVICE *device, */ 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, ¶m); +#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 hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func) 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 @@ static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func) device->async_task = kthread_create(async_task, (void *)device, "AR6K Async"); +#ifdef CONFIG_PERF_NON_QC_PLATFORM + sched_setscheduler(device->async_task, SCHED_FIFO, ¶m); +#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.c b/CORE/SERVICES/HTC/htc.c index 09120e5c6761..09936a01b5de 100644 --- a/CORE/SERVICES/HTC/htc.c +++ b/CORE/SERVICES/HTC/htc.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. * @@ -249,11 +249,13 @@ HTC_HANDLE HTCCreate(void *ol_sc, HTC_INIT_INFO *pInfo, adf_os_device_t osdev) adf_os_spinlock_init(&pEndpoint->htc_endpoint_rx_lock); } target->is_nodrop_pkt = FALSE; - +#ifdef HIF_SDIO + target->enable_b2b = FALSE; +#endif do { A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO)); target->host_handle = pInfo->pContext; - target->osdev = osdev; + target->osdev = osdev; ResetEndpointStates(target); diff --git a/CORE/SERVICES/HTC/htc_internal.h b/CORE/SERVICES/HTC/htc_internal.h index 36646891e6fa..f6bd7cdd10be 100644 --- a/CORE/SERVICES/HTC/htc_internal.h +++ b/CORE/SERVICES/HTC/htc_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016,2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -212,6 +212,10 @@ typedef struct _HTC_TARGET { * Besides, nodrop pkts have higher priority than normal pkts. */ A_BOOL is_nodrop_pkt; +#ifdef HIF_SDIO + /* RX: enable bundle different SDIO block frames */ + A_BOOL enable_b2b; +#endif } HTC_TARGET; #define HTC_ENABLE_BUNDLE(target) (target->MaxMsgsPerHTCBundle > 1) diff --git a/CORE/SERVICES/HTC/htc_send.c b/CORE/SERVICES/HTC/htc_send.c index ee5902c44286..21eb303e5157 100644 --- a/CORE/SERVICES/HTC/htc_send.c +++ b/CORE/SERVICES/HTC/htc_send.c @@ -412,8 +412,8 @@ static A_STATUS HTCSendBundledNetbuf(HTC_TARGET *target, 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,6 +526,9 @@ static A_STATUS HTCIssuePacketsBundle(HTC_TARGET *target, HTC_WRITE32((A_UINT32 *)pHtcHdr + 1, SM(pPacket->PktInfo.AsTx.SeqNo, HTC_FRAME_HDR_CONTROLBYTES1) | SM(creditPad, HTC_FRAME_HDR_RESERVED)); +#ifdef HIF_SDIO + if(target->enable_b2b) +#endif pHtcHdr->reserved = creditPad; #endif frag_count = adf_nbuf_get_num_frags(netbuf); @@ -668,7 +671,7 @@ static A_STATUS HTCIssuePackets(HTC_TARGET *target, 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) @@ -1541,7 +1544,7 @@ A_STATUS HTCSendDataPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, 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/SERVICES/HTC/htc_services.c b/CORE/SERVICES/HTC/htc_services.c index b72fedb4cba0..be07d3924183 100644 --- a/CORE/SERVICES/HTC/htc_services.c +++ b/CORE/SERVICES/HTC/htc_services.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. * @@ -58,6 +58,9 @@ A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, A_UINT16 conn_flags; A_UINT16 rsp_msg_id, rsp_msg_serv_id, rsp_msg_max_msg_size; A_UINT8 rsp_msg_status, rsp_msg_end_id, rsp_msg_serv_meta_len; +#ifdef HIF_SDIO + A_UINT8 rsp_msg_enable_b2b = 0; +#endif AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:%pK SvcID:0x%X \n", target, pConnectReq->ServiceID)); @@ -138,6 +141,12 @@ A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, SERVICEMETALENGTH, pConnectReq->MetaDataLength); } +#ifdef HIF_SDIO + HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, + LOOKAHEADV2, HIF_BUNDLE_DIFF_BLK_FRAMES); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCConnectService, host indicate %s b2b bundle\n", + (HIF_BUNDLE_DIFF_BLK_FRAMES == 1) ? "support" : "not support")); +#endif SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pConnectMsg, @@ -174,7 +183,6 @@ A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, rsp_msg_serv_meta_len = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, SERVICEMETALENGTH); - if ((rsp_msg_id != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || (target->CtrlResponseLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { /* this message is not valid */ @@ -202,6 +210,14 @@ A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, break; } +#ifdef HIF_SDIO + rsp_msg_enable_b2b = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, LOOKAHEADV2); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCConnectService, firmware decide to %s b2b bundle\n", + (rsp_msg_enable_b2b == 1) ? "enabled" : "disabled")); + target->enable_b2b = (rsp_msg_enable_b2b == 1) ? TRUE : FALSE; +#endif + assignedEndpoint = (HTC_ENDPOINT_ID)rsp_msg_end_id; maxMsgSize = rsp_msg_max_msg_size; diff --git a/CORE/VOSS/src/vos_sched.c b/CORE/VOSS/src/vos_sched.c index a0948b9f3a10..a131095a94af 100644 --- a/CORE/VOSS/src/vos_sched.c +++ b/CORE/VOSS/src/vos_sched.c @@ -501,6 +501,9 @@ vos_sched_open ) { 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 @@ vos_sched_open pSchedContext->TlshimRxThread = kthread_create(VosTlshimRxThread, pSchedContext, "VosTlshimRxThread"); +#ifdef CONFIG_PERF_NON_QC_PLATFORM + sched_setscheduler(pSchedContext->TlshimRxThread, SCHED_FIFO, ¶m); +#endif if (IS_ERR(pSchedContext->TlshimRxThread)) { @@ -1097,6 +1097,11 @@ CDEFINES += -DCONFIG_HL_SUPPORT \ ifneq ($(TARGET_BUILD_VARIANT),user) CDEFINES += -DCONFIG_ATH_PROCFS_DIAG_SUPPORT endif + +# Enable SDIO HIF Rx Thread +ifeq ($(CONFIG_HIF_RX_THREAD), y) +CDEFINES += -DHIF_RX_THREAD +endif endif ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) |
