qcacld-3.0: Call vdev resp and hold req queue cleanup from MC thread

Vdev resp and hold req queue cleanup is called in kernel thread context
and this may lead to race condition where it may free the wma's iface
structure while MC thread is using the iface.

In case FW down is received during interface delete, driver complete wait
events and thus the interface delete remove the adapter before del sta
self resp is received and thus del sta self resp uses adapter after its
freed.

To avoid this call the vdev resp and hold req queue cleanup from MC
thread. Also call del sta self resp only when driver unload is in
progress. For FW down case the resp is not required.

Change-Id: I711f83c54df29251de365a3137077b3b8d82b448
CRs-Fixed: 2234547
This commit is contained in:
Abhishek Singh 2018-05-02 21:07:57 +05:30 committed by nshrivas
parent cb312923a2
commit 0ac37445d5
2 changed files with 42 additions and 4 deletions

View File

@ -3490,16 +3490,27 @@ void wma_vdev_resp_timer(void *data)
params->status = QDF_STATUS_E_TIMEOUT;
WMA_LOGA("%s: WMA_DEL_STA_SELF_REQ timedout", __func__);
if (wma_crash_on_fw_timeout(wma->fw_timeout_crash) == true) {
wma_trigger_recovery_assert_on_fw_timeout(
WMA_DEL_STA_SELF_REQ);
} else if (!cds_is_driver_unloading() &&
(cds_is_fw_down() || cds_is_driver_recovering())) {
qdf_mem_free(iface->del_staself_req);
iface->del_staself_req = NULL;
} else {
wma_send_del_sta_self_resp(iface->del_staself_req);
}
if (iface->addBssStaContext)
if (iface->addBssStaContext) {
qdf_mem_free(iface->addBssStaContext);
if (iface->staKeyParams)
iface->addBssStaContext = NULL;
}
if (iface->staKeyParams) {
qdf_mem_free(iface->staKeyParams);
iface->staKeyParams = NULL;
}
wma_vdev_deinit(iface);
qdf_mem_zero(iface, sizeof(*iface));

View File

@ -2025,6 +2025,27 @@ static void wma_cleanup_hold_req(tp_wma_handle wma)
qdf_spin_unlock_bh(&wma->wma_hold_req_q_lock);
}
/**
* wma_cleanup_vdev_resp_and_hold_req() - cleaunup the vdev resp and hold req
* queue
* @msg :scheduler msg
*
* Return: QDF_STATUS
*/
static QDF_STATUS
wma_cleanup_vdev_resp_and_hold_req(struct scheduler_msg *msg)
{
if (!msg || !msg->bodyptr) {
WMA_LOGE(FL("msg or body pointer is NULL"));
return QDF_STATUS_E_INVAL;
}
wma_cleanup_vdev_resp_queue(msg->bodyptr);
wma_cleanup_hold_req(msg->bodyptr);
return QDF_STATUS_SUCCESS;
}
/**
* wma_shutdown_notifier_cb - Shutdown notifer call back
* @priv : WMA handle
@ -2040,11 +2061,17 @@ static void wma_cleanup_hold_req(tp_wma_handle wma)
static void wma_shutdown_notifier_cb(void *priv)
{
tp_wma_handle wma_handle = priv;
struct scheduler_msg msg = { 0 };
QDF_STATUS status;
qdf_event_set(&wma_handle->wma_resume_event);
wma_cleanup_vdev_resp_queue(wma_handle);
wma_cleanup_hold_req(wma_handle);
pmo_ucfg_psoc_wakeup_host_event_received(wma_handle->psoc);
msg.bodyptr = priv;
msg.callback = wma_cleanup_vdev_resp_and_hold_req;
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
if (QDF_IS_STATUS_ERROR(status))
WMA_LOGE(FL("Failed to post SYS_MSG_ID_CLEAN_VDEV_RSP_QUEUE"));
}
struct wma_version_info g_wmi_version_info;