From 46e10b36ef1f2e0dd33d2a23756e2ba894439efe Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Mon, 12 Nov 2018 16:23:02 +0530 Subject: [PATCH] qcacld-3.0: Fix error handling path of wma_remove_peer If the wma_remove_peer fails, the caller can still proceed to start vdev hold request timer for WMA_DELETE_STA_REQ. The Host driver doesnot stop the timer and this results in page fault when the timer is expired. Check the return status of wma_remove_peer and send failure to the caller of wma_remove_peer. Change-Id: I63d0dfefb183cf1a88b1f7abb2686b2dfdc6bd79 CRs-Fixed: 2348248 --- core/wma/src/wma_dev_if.c | 53 ++++++++++++++++++++++++++----------- core/wma/src/wma_features.c | 8 +++++- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 749db0d2fe2c..52d97b03e89b 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1881,6 +1881,7 @@ static int wma_remove_bss_peer(tp_wma_handle wma, void *pdev, uint8_t *mac_addr = NULL; struct wma_target_req *del_req; int ret_value = 0; + QDF_STATUS qdf_status; vdev = cdp_get_vdev_from_vdev_id(soc, pdev, vdev_id); if (!vdev) { @@ -1909,18 +1910,23 @@ static int wma_remove_bss_peer(tp_wma_handle wma, void *pdev, return -EINVAL; } - wma_remove_peer(wma, mac_addr, vdev_id, peer, false); - if (wmi_service_enabled( - wma->wmi_handle, - wmi_service_sync_delete_cmds)) { + qdf_status = wma_remove_peer(wma, mac_addr, vdev_id, peer, false); + + if (QDF_IS_STATUS_ERROR(qdf_status)) { + WMA_LOGE(FL("wma_remove_peer failed")); + wma_cleanup_target_req_param(req_msg); + return -EINVAL; + } + + if (wmi_service_enabled(wma->wmi_handle, + wmi_service_sync_delete_cmds)) { WMA_LOGD(FL("Wait for the peer delete. vdev_id %d"), - req_msg->vdev_id); - del_req = wma_fill_hold_req(wma, - req_msg->vdev_id, - WMA_DELETE_STA_REQ, - WMA_DELETE_PEER_RSP, - params, - WMA_DELETE_STA_TIMEOUT); + req_msg->vdev_id); + del_req = wma_fill_hold_req(wma, req_msg->vdev_id, + WMA_DELETE_STA_REQ, + WMA_DELETE_PEER_RSP, + params, + WMA_DELETE_STA_TIMEOUT); if (!del_req) { WMA_LOGE(FL("Failed to allocate request. vdev_id %d"), req_msg->vdev_id); @@ -2133,6 +2139,7 @@ __wma_vdev_stop_resp_handler(wmi_vdev_stopped_event_fixed_param *resp_event) struct wma_txrx_node *iface; int status = 0; void *soc = cds_get_context(QDF_MODULE_ID_SOC); + QDF_STATUS qdf_status; if (!wma) { WMA_LOGE("%s: wma is null", __func__); @@ -2221,8 +2228,15 @@ __wma_vdev_stop_resp_handler(wmi_vdev_stopped_event_fixed_param *resp_event) if (peer) { WMA_LOGP(FL("Deleting peer %pM vdev id %d"), params->bssid, req_msg->vdev_id); - wma_remove_peer(wma, params->bssid, req_msg->vdev_id, - peer, false); + qdf_status = wma_remove_peer(wma, params->bssid, + req_msg->vdev_id, + peer, false); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + WMA_LOGE(FL("wma_remove_peer failed")); + status = -EINVAL; + params->status = QDF_STATUS_E_FAILURE; + goto set_link_rsp; + } if (wmi_service_enabled(wma->wmi_handle, wmi_service_sync_delete_cmds)) { WMA_LOGI(FL("Wait for the peer delete. vdev_id %d"), @@ -2242,6 +2256,8 @@ __wma_vdev_stop_resp_handler(wmi_vdev_stopped_event_fixed_param *resp_event) } } } + +set_link_rsp: #ifdef CONFIG_VDEV_SM wlan_vdev_mlme_sm_deliver_evt(iface->vdev, WLAN_VDEV_SM_EV_MLME_DOWN_REQ, @@ -5309,6 +5325,7 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, struct wma_target_req *msg; uint8_t *peer_mac_addr; void *soc = cds_get_context(QDF_MODULE_ID_SOC); + QDF_STATUS qdf_status; pdev = cds_get_context(QDF_MODULE_ID_TXRX); @@ -5328,8 +5345,13 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, } peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer); - wma_remove_peer(wma, peer_mac_addr, del_sta->smesessionId, peer, - false); + qdf_status = wma_remove_peer(wma, peer_mac_addr, del_sta->smesessionId, + peer, false); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + WMA_LOGE(FL("wma_remove_peer failed")); + del_sta->status = QDF_STATUS_E_FAILURE; + goto send_del_rsp; + } del_sta->status = QDF_STATUS_SUCCESS; if (wmi_service_enabled(wma->wmi_handle, @@ -5403,6 +5425,7 @@ static void wma_del_tdls_sta(tp_wma_handle wma, tpDeleteStaParams del_sta) if (status < 0) { WMA_LOGE("%s: wma_update_tdls_peer_state returned failure", __func__); + del_sta->status = QDF_STATUS_E_FAILURE; goto send_del_rsp; } diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index ff01e67096f5..75e887a90acf 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4195,6 +4195,7 @@ int wma_update_tdls_peer_state(WMA_HANDLE handle, int ret = 0; uint32_t *ch_mhz = NULL; bool restore_last_peer = false; + QDF_STATUS qdf_status; if (!wma_handle || !wma_handle->wmi_handle) { WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); @@ -4281,8 +4282,13 @@ int wma_update_tdls_peer_state(WMA_HANDLE handle, " vdevId: %d", __func__, MAC_ADDR_ARRAY(peer_mac_addr), peerStateParams->vdevId); - wma_remove_peer(wma_handle, peer_mac_addr, + qdf_status = wma_remove_peer(wma_handle, peer_mac_addr, peerStateParams->vdevId, peer, false); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + WMA_LOGE(FL("wma_remove_peer failed")); + ret = -EINVAL; + goto end_tdls_peer_state; + } cdp_peer_update_last_real_peer(soc, pdev, peer, &peer_id, restore_last_peer);