summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar <rajekuma@qca.qualcomm.com>2014-03-09 09:57:14 -0700
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-03-10 16:07:57 -0700
commit28bc26ba761fbb9b3ea564204bc26b7e83cc903d (patch)
treecf39bd730de9810e685d1926e7c95f67ece0c31a
parent990c4d72fa3a210e9d6d2dc16ec039d676d5e010 (diff)
qcacld: Fix of kernel panic during modem power state indication
Fix of race condition between modem power state notification kernel worker thread and wlan driver load/unload kernel worker thread by adding module load/unload check and in addition serializing modem power state notification to MC thread to avoid sending this event to FW when host is expecting response of another event Change-Id: I176edb76cc5bfc9adc3679614073daba48d26ac3 CRs-Fixed: 628597
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c14
-rw-r--r--CORE/MAC/inc/sirApi.h6
-rw-r--r--CORE/MAC/src/include/sirParams.h2
-rw-r--r--CORE/SERVICES/WMA/wma.c41
-rw-r--r--CORE/SME/inc/sme_Api.h2
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c31
-rw-r--r--CORE/WDA/inc/wlan_qct_wda.h3
7 files changed, 72 insertions, 27 deletions
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 93a2fa6aa639..e94a34fc378d 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8671,6 +8671,7 @@ void __hdd_wlan_exit(void)
-------------------------------------------------------------------------*/
int hdd_wlan_notify_modem_power_state(int state)
{
+ int status;
VOS_STATUS vosStatus;
v_CONTEXT_t pVosContext = NULL;
hdd_context_t *pHddCtx = NULL;
@@ -8678,11 +8679,20 @@ int hdd_wlan_notify_modem_power_state(int state)
pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
if (!pVosContext)
return -1;
+
pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
- if (!pHddCtx)
+
+ status = wlan_hdd_validate_context(pHddCtx);
+ if (0 != status)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: HDD context is not valid", __func__);
+ return -1;
+ }
+ if (!pHddCtx->hHal)
return -1;
- vosStatus = sme_notify_modem_power_state(pHddCtx->pvosContext, state);
+ vosStatus = sme_notify_modem_power_state(pHddCtx->hHal, state);
if (VOS_STATUS_SUCCESS != vosStatus) {
hddLog(LOGE, "Fail to send notification with modem power state %d\n",
state);
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index a7860b14deb2..07b21d5439fd 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -4866,4 +4866,10 @@ typedef struct sSirTxPowerLimit
u_int32_t txPower5g;
} tSirTxPowerLimit;
+// Notify MODEM power state to FW
+typedef struct
+{
+ tANI_U32 param;
+} tSirModemPowerStateInd, *tpSirModemPowerStateInd;
+
#endif /* __SIR_API_H */
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index cfea61d3d6ba..9d41e7047ae7 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -659,6 +659,8 @@ typedef struct sSirMbMsgP2p
#define SIR_HAL_SET_SAP_INTRABSS_DIS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 252)
#define SIR_HAL_FW_STATS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 253)
+#define SIR_HAL_MODEM_POWER_STATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 254)
+
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
// CFG message types
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 481072cddf49..4b2c3a28459d 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -15058,6 +15058,26 @@ static void wma_set_vdev_intrabss_fwd(tp_wma_handle wma_handle,
wdi_in_vdev_rx_fwd_disabled(txrx_vdev, pdis_intra_fwd->disableintrabssfwd);
}
+VOS_STATUS wma_notify_modem_power_state(void *wda_handle,
+ tSirModemPowerStateInd *pReq)
+{
+ int32_t ret;
+ tp_wma_handle wma = (tp_wma_handle)wda_handle;
+
+ WMA_LOGD("%s: WMA Notify Modem Power State %d", __func__, pReq->param);
+
+ ret = wmi_unified_modem_power_state(wma->wmi_handle, pReq->param);
+ if (ret) {
+ WMA_LOGE("%s: Fail to notify Modem Power State %d",
+ __func__, pReq->param);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ WMA_LOGD("Successfully notify Modem Power State %d", pReq->param);
+ return VOS_STATUS_SUCCESS;
+}
+
+
/*
* function : wma_mc_process_msg
* Descriptin :
@@ -15451,6 +15471,10 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg)
wma_fw_stats_ind(wma_handle, msg->bodyptr);
vos_mem_free(msg->bodyptr);
break;
+ case WDA_MODEM_POWER_STATE_IND:
+ wma_notify_modem_power_state(wma_handle,
+ (tSirModemPowerStateInd *)msg->bodyptr);
+ vos_mem_free(msg->bodyptr);
default:
WMA_LOGD("unknow msg type %x", msg->type);
/* Do Nothing? MSG Body should be freed at here */
@@ -18460,23 +18484,6 @@ wma_process_ftm_command(tp_wma_handle wma_handle,
}
#endif
-VOS_STATUS WDA_notify_modem_power_state(void *wda_handle, tANI_U32 value)
-{
- int32_t ret;
- tp_wma_handle wma = (tp_wma_handle)wda_handle;
-
- WMA_LOGD("%s: WMA Notify Modem Power State %d", __func__, value);
-
- ret = wmi_unified_modem_power_state(wma->wmi_handle, value);
- if (ret) {
- WMA_LOGE("%s: Fail to notify Modem Power State %d", __func__, value);
- return VOS_STATUS_E_FAILURE;
- }
-
- WMA_LOGD("Successfully notify Modem Power State %d", value);
- return VOS_STATUS_SUCCESS;
-}
-
/* Function to enable/disble Low Power Support(Pdev Specific) */
VOS_STATUS WDA_SetIdlePsConfig(void *wda_handle, tANI_U32 idle_ps)
{
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index b518293c17ff..357f9b8d4946 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -3400,7 +3400,7 @@ sme_StopBatchScanInd
* is enabled
*/
VOS_STATUS sme_SetIdlePowersaveConfig(v_PVOID_t vosContext, tANI_U32 value);
-VOS_STATUS sme_notify_modem_power_state(v_PVOID_t vosContext, tANI_U32 value);
+VOS_STATUS sme_notify_modem_power_state(tHalHandle hHal, tANI_U32 value);
eHalStatus sme_ConfigEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode);
eHalStatus sme_ConfigDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode);
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 3eccc684e83b..3813718ddb6e 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -11085,23 +11085,40 @@ void activeListCmdTimeoutHandle(void *userData)
smeGetCommandQStatus((tHalHandle) userData);
}
-VOS_STATUS sme_notify_modem_power_state(v_PVOID_t vosContext, tANI_U32 value)
+VOS_STATUS sme_notify_modem_power_state(tHalHandle hHal, tANI_U32 value)
{
- v_PVOID_t wdaContext = vos_get_context(VOS_MODULE_ID_WDA, vosContext);
+ vos_msg_t msg;
+ tpSirModemPowerStateInd pRequestBuf;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
- if (NULL == wdaContext)
+ if (NULL == pMac)
{
- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
- "%s: wdaContext is NULL", __func__);
return VOS_STATUS_E_FAILURE;
}
- if (VOS_STATUS_SUCCESS != WDA_notify_modem_power_state(wdaContext, value))
+ pRequestBuf = vos_mem_malloc(sizeof(tSirModemPowerStateInd));
+ if (NULL == pRequestBuf)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
- "Failed to notify modem power state %d", value);
+ "%s: Not able to allocate memory for MODEM POWER STATE IND",
+ __func__);
return VOS_STATUS_E_FAILURE;
}
+
+ pRequestBuf->param = value;
+
+ msg.type = WDA_MODEM_POWER_STATE_IND;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: Not able to post WDA_MODEM_POWER_STATE_IND message"
+ " to WDA", __func__);
+ vos_mem_free(pRequestBuf);
+ return VOS_STATUS_E_FAILURE;
+ }
+
return VOS_STATUS_SUCCESS;
}
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index e2ae45bd7e0e..0afa9f604495 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1332,6 +1332,9 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb);
#define WDA_DFS_BEACON_TX_SUCCESS_IND SIR_HAL_BEACON_TX_SUCCESS_IND
#define WDA_FW_STATS_IND SIR_HAL_FW_STATS_IND
+#define WDA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND
+
+
tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg);
#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames