diff options
| author | Poddar, Siddarth <siddpodd@codeaurora.org> | 2016-09-02 17:37:24 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-09-08 14:27:58 +0530 |
| commit | 429604f6fc2bea44697b21618ef4fcadef8bffd8 (patch) | |
| tree | a80d5db4a9ed3d9012fe3e785f8932edea09915b | |
| parent | 3e81eee752bf75094fc9e40307431c246d71c722 (diff) | |
qcacld-2.0: Disconnect Service before detaching HTT to avoid invalid access
HIFDevDsrHandler is deregistered much later than ol_txrx_pdev_detach and
as a result Htt_t2h_msg_handler() has context which is freed/stale pointer.
In order to avoid invalid access to the context added htt disconnect
service to clear the endpoint receive callback for the htt.
CRs-Fixed: 1063430
Change-Id: I40d99b51726c0e206b895a9a40caffd059f0424d
| -rw-r--r-- | CORE/CLD_TXRX/HTT/htt.c | 8 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/HTT/htt_internal.h | 10 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/htc_api.h | 13 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc.c | 13 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc_internal.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc_recv.c | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/HTC/htc_services.c | 13 |
7 files changed, 61 insertions, 2 deletions
diff --git a/CORE/CLD_TXRX/HTT/htt.c b/CORE/CLD_TXRX/HTT/htt.c index 40fadc4e91d3..e986cd48e1aa 100644 --- a/CORE/CLD_TXRX/HTT/htt.c +++ b/CORE/CLD_TXRX/HTT/htt.c @@ -389,9 +389,17 @@ htt_attach_target(htt_pdev_handle pdev) return status; } +void htt_htc_detach(struct htt_pdev_t *pdev) +{ + htc_disconnect_service(pdev->htc_pdev, pdev->htc_endpoint); + return; +} + + void htt_detach(htt_pdev_handle pdev) { + htt_htc_detach(pdev); htt_rx_detach(pdev); htt_tx_detach(pdev); htt_htc_pkt_pool_free(pdev); diff --git a/CORE/CLD_TXRX/HTT/htt_internal.h b/CORE/CLD_TXRX/HTT/htt_internal.h index 443a131398d5..947444cfe22f 100644 --- a/CORE/CLD_TXRX/HTT/htt_internal.h +++ b/CORE/CLD_TXRX/HTT/htt_internal.h @@ -361,6 +361,16 @@ htt_rx_detach(struct htt_pdev_t *pdev); int htt_htc_attach(struct htt_pdev_t *pdev); +/** + * htt_htc_detach() - Detach htc service from htt + * @pdev: htt pdev handle + * + * + * Return: None + */ +void +htt_htc_detach(struct htt_pdev_t *pdev); + void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt); diff --git a/CORE/SERVICES/COMMON/htc_api.h b/CORE/SERVICES/COMMON/htc_api.h index 8fffe5381e58..351d485af0f3 100644 --- a/CORE/SERVICES/COMMON/htc_api.h +++ b/CORE/SERVICES/COMMON/htc_api.h @@ -391,6 +391,19 @@ A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, HTC_SERVICE_CONNECT_REQ *pReq, HTC_SERVICE_CONNECT_RESP *pResp); + +/** + * htc_disconnect_service() - Disconnect to an HTC service + * @htc_handle: HTC handle + * @endpoint_id: endpoint id + * + * Service disconnection must be performed during htt_detach. + * + * Return: None + */ +void htc_disconnect_service(HTC_HANDLE htc_handle, + HTC_ENDPOINT_ID endpoint_id); + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @desc: HTC register log dump @function name: HTCDump diff --git a/CORE/SERVICES/HTC/htc.c b/CORE/SERVICES/HTC/htc.c index 80f9f3ab953f..0600149dc55a 100644 --- a/CORE/SERVICES/HTC/htc.c +++ b/CORE/SERVICES/HTC/htc.c @@ -144,6 +144,7 @@ static void HTCCleanup(HTC_TARGET *target) { HTC_PACKET *pPacket; adf_nbuf_t netbuf; + int j; if (target->hif_dev != NULL) { HIFDetachHTC(target->hif_dev); @@ -207,6 +208,11 @@ static void HTCCleanup(HTC_TARGET *target) adf_os_spinlock_destroy(&target->HTCTxLock); adf_os_spinlock_destroy(&target->HTCCreditLock); + for (j = 0; j < ENDPOINT_MAX; j++) { + HTC_ENDPOINT *endpoint = &target->EndPoint[j]; + adf_os_spinlock_destroy(&endpoint->htc_endpoint_rx_lock); + } + /* free our instance */ A_FREE(target); } @@ -218,7 +224,7 @@ HTC_HANDLE HTCCreate(void *ol_sc, HTC_INIT_INFO *pInfo, adf_os_device_t osdev) MSG_BASED_HIF_CALLBACKS htcCallbacks; HTC_ENDPOINT *pEndpoint=NULL; HTC_TARGET *target = NULL; - int i; + int i, j; AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("+HTCCreate .. HIF :%p \n",hHIF)); @@ -235,6 +241,11 @@ HTC_HANDLE HTCCreate(void *ol_sc, HTC_INIT_INFO *pInfo, adf_os_device_t osdev) adf_os_spinlock_init(&target->HTCRxLock); adf_os_spinlock_init(&target->HTCTxLock); adf_os_spinlock_init(&target->HTCCreditLock); + + for (j = 0; j < ENDPOINT_MAX; j++) { + pEndpoint = &target->EndPoint[j]; + adf_os_spinlock_init(&pEndpoint->htc_endpoint_rx_lock); + } target->is_nodrop_pkt = FALSE; do { diff --git a/CORE/SERVICES/HTC/htc_internal.h b/CORE/SERVICES/HTC/htc_internal.h index 870046d1c618..36646891e6fa 100644 --- a/CORE/SERVICES/HTC/htc_internal.h +++ b/CORE/SERVICES/HTC/htc_internal.h @@ -147,6 +147,7 @@ typedef struct _HTC_ENDPOINT { HTC_ENDPOINT_STATS EndPointStats; /* endpoint statistics */ #endif A_BOOL TxCreditFlowEnabled; + adf_os_spinlock_t htc_endpoint_rx_lock; } HTC_ENDPOINT; #ifdef HTC_EP_STAT_PROFILING @@ -231,6 +232,8 @@ typedef struct _HTC_TARGET { #define UNLOCK_HTC_TX(t) adf_os_spin_unlock_bh(&(t)->HTCTxLock); #define LOCK_HTC_CREDIT(t) adf_os_spin_lock_bh(&(t)->HTCCreditLock); #define UNLOCK_HTC_CREDIT(t) adf_os_spin_unlock_bh(&(t)->HTCCreditLock); +#define LOCK_HTC_ENDPOINT_RX(t) adf_os_spin_lock_bh(&(t)->htc_endpoint_rx_lock); +#define UNLOCK_HTC_ENDPOINT_RX(t) adf_os_spin_unlock_bh(&(t)->htc_endpoint_rx_lock); #define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd)) diff --git a/CORE/SERVICES/HTC/htc_recv.c b/CORE/SERVICES/HTC/htc_recv.c index e4c1ffcdb6d5..b082a25941cf 100644 --- a/CORE/SERVICES/HTC/htc_recv.c +++ b/CORE/SERVICES/HTC/htc_recv.c @@ -104,14 +104,17 @@ static void DoRecvCompletion(HTC_ENDPOINT *pEndpoint, /* using legacy EpRecv */ while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) { pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + LOCK_HTC_ENDPOINT_RX(pEndpoint); if (pEndpoint->EpCallBacks.EpRecv == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTC ep %d has NULL recv callback on packet %p\n", pEndpoint->Id, pPacket)); + UNLOCK_HTC_ENDPOINT_RX(pEndpoint); continue; } AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTC calling ep %d recv callback on packet %p\n", pEndpoint->Id, pPacket)); pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket); + UNLOCK_HTC_ENDPOINT_RX(pEndpoint); } } diff --git a/CORE/SERVICES/HTC/htc_services.c b/CORE/SERVICES/HTC/htc_services.c index 0ce50c4a5d83..36d45557a70f 100644 --- a/CORE/SERVICES/HTC/htc_services.c +++ b/CORE/SERVICES/HTC/htc_services.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -328,6 +328,17 @@ A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, return status; } +void htc_disconnect_service(HTC_HANDLE htc_handle, HTC_ENDPOINT_ID endpoint_id) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + HTC_ENDPOINT *endpoint = &target->EndPoint[endpoint_id]; + + LOCK_HTC_ENDPOINT_RX(endpoint); + endpoint->EpCallBacks.EpRecv = NULL; + UNLOCK_HTC_ENDPOINT_RX(endpoint); + return; +} + void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, void *pCreditDistContext, |
