summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGovind Singh <govinds@codeaurora.org>2016-12-13 12:17:11 +0530
committerAshish kumar goswami <agoswa@codeaurora.org>2016-12-19 18:40:07 +0530
commitffd336ffd8174b88d12c76a43f1b3a8bee2abad4 (patch)
treed95a75fd6339f31786490afaab12fc849885c693
parent0b2a9ed425513ab16409424ea1e9c4cc604f6075 (diff)
qcacld-2.0: Move card reset sequence post async task cleanup
sdio bus is not claimed prior issuing target reset command, this can result in bus access by async task during card reset operation. Avoid the race condition by moving the reset sequence post async task cleanup. Change-Id: I6817a3ce4935571d103f1b6b5989b15e11049834 CRs-Fixed: 1100166
-rw-r--r--CORE/SERVICES/COMMON/hif_msg_based.h4
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h3
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c79
-rw-r--r--CORE/SERVICES/HTC/htc_recv.c5
4 files changed, 60 insertions, 31 deletions
diff --git a/CORE/SERVICES/COMMON/hif_msg_based.h b/CORE/SERVICES/COMMON/hif_msg_based.h
index af339aef1248..ae3332893730 100644
--- a/CORE/SERVICES/COMMON/hif_msg_based.h
+++ b/CORE/SERVICES/COMMON/hif_msg_based.h
@@ -149,9 +149,9 @@ void HIFSetBundleMode(HIF_DEVICE *hif_device, bool enabled, int rx_bundle_cnt);
#endif
#ifdef HIF_SDIO
-int hif_reset_target(HIF_DEVICE *hif_device);
+int hif_set_target_reset(HIF_DEVICE *hif_device);
#else
-static inline int hif_reset_target(HIF_DEVICE *hif_device)
+static inline int hif_set_target_reset(HIF_DEVICE *hif_device)
{
return 0;
}
diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h b/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h
index 6199746ac33f..19fb0afb19ff 100644
--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h
+++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h
@@ -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.
*
@@ -119,6 +119,7 @@ struct hif_device {
void *htcContext;
/* mailbox swapping for control and data svc*/
A_BOOL swap_mailbox;
+ bool ctrl_response_timeout;
};
#define HIF_DMA_BUFFER_SIZE (4 * 1024)
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 428b96e12f91..c1edb6c8d893 100644
--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
+++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
@@ -2584,9 +2584,59 @@ static void hif_flush_async_task(HIF_DEVICE *device)
}
}
+/**
+ * hif_reset_target() - Reset target device
+ * @hif_device: pointer to hif_device structure
+ *
+ * Reset the target by invoking power off and power on
+ * sequence to bring back target into active state.
+ * This API shall be called only when driver load/unload
+ * is in progress.
+ *
+ * Return: 0 on success, error for failure case.
+ */
+static int hif_reset_target(HIF_DEVICE *hif_device)
+{
+ int ret;
+
+ if (!hif_device || !hif_device->func|| !hif_device->func->card) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: %s invalid HIF DEVICE \n", __func__));
+ return -ENODEV;
+ }
+ /* Disable sdio func->pull down WLAN_EN-->pull down DAT_2 line */
+ ret = mmc_power_save_host(hif_device->func->card->host);
+ if(ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: %s Failed to save mmc Power host %d\n",
+ __func__, ret));
+ goto done;
+ }
+
+ /* pull up DAT_2 line->pull up WLAN_EN-->Enable sdio func */
+ ret = mmc_power_restore_host(hif_device->func->card->host);
+ if(ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: %s Failed to restore mmc Power host %d\n",
+ __func__, ret));
+ }
+
+done:
+ return ret;
+}
+
void HIFDetachHTC(HIF_DEVICE *device)
{
hif_flush_async_task(device);
+ if (device->ctrl_response_timeout) {
+ /* Reset the target by invoking power off and power on sequence to
+ * the card to bring back into active state.
+ */
+ if(hif_reset_target(device))
+ VOS_BUG(0);
+ device->ctrl_response_timeout = false;
+ }
+
A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
}
@@ -2762,42 +2812,23 @@ static int hif_sdio_device_resume(struct device *dev)
#endif
/**
- * hif_reset_target() - Reset target device
+ * hif_set_target_reset() - Reset target device
* @hif_device: pointer to hif_device structure
*
- * Reset the target by invoking power off and power on
- * sequence to bring back target into active state.
+ * Set the target reset flag.
* This API shall be called only when driver load/unload
* is in progress.
*
* Return: 0 on success, error for failure case.
*/
-int hif_reset_target(HIF_DEVICE *hif_device)
+int hif_set_target_reset(HIF_DEVICE *hif_device)
{
- int ret;
-
if (!hif_device || !hif_device->func|| !hif_device->func->card) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
("AR6000: %s invalid HIF DEVICE \n", __func__));
return -ENODEV;
}
- /* Disable sdio func->pull down WLAN_EN-->pull down DAT_2 line */
- ret = mmc_power_save_host(hif_device->func->card->host);
- if(ret) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: %s Failed to save mmc Power host %d\n",
- __func__, ret));
- goto done;
- }
-
- /* pull up DAT_2 line->pull up WLAN_EN-->Enable sdio func */
- ret = mmc_power_restore_host(hif_device->func->card->host);
- if(ret) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: %s Failed to restore mmc Power host %d\n",
- __func__, ret));
- }
+ hif_device->ctrl_response_timeout = true;
-done:
- return ret;
+ return 0;
}
diff --git a/CORE/SERVICES/HTC/htc_recv.c b/CORE/SERVICES/HTC/htc_recv.c
index b082a25941cf..e78121f0b2b5 100644
--- a/CORE/SERVICES/HTC/htc_recv.c
+++ b/CORE/SERVICES/HTC/htc_recv.c
@@ -585,10 +585,7 @@ A_STATUS HTCWaitRecvCtrlMessage(HTC_TARGET *target)
/* Wait for BMI request/response transaction to complete */
if(!adf_os_wait_for_completion_timeout(&target->CtrlResponseValid,
adf_os_msecs_to_ticks(HTC_CONTROL_RX_TIMEOUT))) {
- /* Reset the target by invoking power off and power on sequence to
- * the card to bring back into active state.
- */
- if(hif_reset_target(target->hif_dev))
+ if(hif_set_target_reset(target->hif_dev))
VOS_BUG(0);
return A_ERROR;
}