summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPoddar, Siddarth <siddpodd@codeaurora.org>2016-09-02 17:37:24 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-09-08 14:27:58 +0530
commit429604f6fc2bea44697b21618ef4fcadef8bffd8 (patch)
treea80d5db4a9ed3d9012fe3e785f8932edea09915b
parent3e81eee752bf75094fc9e40307431c246d71c722 (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.c8
-rw-r--r--CORE/CLD_TXRX/HTT/htt_internal.h10
-rw-r--r--CORE/SERVICES/COMMON/htc_api.h13
-rw-r--r--CORE/SERVICES/HTC/htc.c13
-rw-r--r--CORE/SERVICES/HTC/htc_internal.h3
-rw-r--r--CORE/SERVICES/HTC/htc_recv.c3
-rw-r--r--CORE/SERVICES/HTC/htc_services.c13
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,