diff options
| author | Kabilan Kannan <kabilank@codeaurora.org> | 2018-02-02 16:42:04 -0800 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2018-02-22 05:32:52 -0800 |
| commit | 9cf3880813a70fa505b618b4f3da4dfcd9b69788 (patch) | |
| tree | 5e8e6fb69005d229f3353cec9cfe9f0d2ad7e077 | |
| parent | cb4726c202c741b186a4be61a01f19a76c5ebfdd (diff) | |
qcacld-3.0: Fix synchronization problem in wma remove peer
Peer removal happens in MC thread context and the corrresponding
unmap events processed in soft IRQ context. But both the events
are not synchronized correctly and causes race condition
in the system.
Apply reference count for the peer to avoid this
problem.
Change-Id: If1ca656a4dc0325032069af926697784cdec9b2d
CRs-Fixed: 2183468
| -rw-r--r-- | core/wma/src/wma_dev_if.c | 125 |
1 files changed, 72 insertions, 53 deletions
diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 322432e3c4cb..42e8e5733abe 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1786,6 +1786,57 @@ wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req, } } +static QDF_STATUS +wma_remove_peer_by_reference(ol_txrx_pdev_handle pdev, + tp_wma_handle wma, + void *params, + uint8_t *peer_id, + uint8_t *bssid, + uint8_t vdev_id, + uint8_t peer_rsp_type) +{ + ol_txrx_peer_handle peer; + struct wma_target_req *del_req; + QDF_STATUS status; + + status = QDF_STATUS_SUCCESS; + peer = ol_txrx_find_peer_by_addr_inc_ref(pdev, + bssid, + peer_id); + if (!peer) { + WMA_LOGD("%s Failed to find peer %pM", + __func__, bssid); + status = QDF_STATUS_E_FAULT; + return status; + } + + WMA_LOGI(FL("Deleting peer %pM vdev id %d"), + bssid, vdev_id); + + wma_remove_peer(wma, bssid, vdev_id, + peer, false); + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + WMA_LOGD(FL("Wait for the peer delete. vdev_id %d"), + vdev_id); + del_req = wma_fill_hold_req(wma, + vdev_id, + WMA_DELETE_STA_REQ, + peer_rsp_type, + params, + WMA_DELETE_STA_TIMEOUT); + if (!del_req) { + WMA_LOGE(FL("Failed to allocate request. vdev_id %d"), + vdev_id); + status = QDF_STATUS_E_NOMEM; + } + } + + OL_TXRX_PEER_UNREF_DELETE(peer); + + return status; +} /** * wma_vdev_stop_resp_handler() - vdev stop response handler @@ -1801,12 +1852,12 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, tp_wma_handle wma = (tp_wma_handle) handle; WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf; wmi_vdev_stopped_event_fixed_param *resp_event; - struct wma_target_req *req_msg, *del_req, *new_req_msg; - ol_txrx_peer_handle peer; + struct wma_target_req *req_msg, *new_req_msg; ol_txrx_pdev_handle pdev; uint8_t peer_id; struct wma_txrx_node *iface; int32_t status = 0; + QDF_STATUS result; WMA_LOGD("%s: Enter", __func__); param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info; @@ -1902,32 +1953,16 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, wma_delete_all_ap_remote_peers(wma, resp_event->vdev_id); } - peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, - &peer_id); - if (!peer) - WMA_LOGD("%s Failed to find peer %pM", - __func__, params->bssid); - wma_remove_peer(wma, params->bssid, resp_event->vdev_id, - peer, false); - if (peer && WMI_SERVICE_IS_ENABLED( - wma->wmi_service_bitmap, - 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); - if (!del_req) { - WMA_LOGE(FL("Failed to allocate request. vdev_id %d"), - req_msg->vdev_id); - params->status = QDF_STATUS_E_NOMEM; - } else { - goto free_req_msg; - } - } + result = wma_remove_peer_by_reference(pdev, + wma, params, + &peer_id, + params->bssid, + resp_event->vdev_id, + WMA_DELETE_PEER_RSP); + + if (result == QDF_STATUS_SUCCESS) + goto free_req_msg; + } wma_send_del_bss_response(wma, req_msg, resp_event->vdev_id); @@ -1935,31 +1970,15 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, tpLinkStateParams params = (tpLinkStateParams) req_msg->user_data; - peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, &peer_id); - if (peer) { - WMA_LOGE(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); - if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, - 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_SET_LINK_PEER_RSP, - params, - WMA_DELETE_STA_TIMEOUT); - if (!del_req) { - WMA_LOGE(FL("Failed to allocate request. vdev_id %d"), - req_msg->vdev_id); - params->status = QDF_STATUS_E_NOMEM; - } else { - goto free_req_msg; - } - } - } + result = wma_remove_peer_by_reference(pdev, wma, params, + &peer_id, + params->bssid, + req_msg->vdev_id, + WMA_SET_LINK_PEER_RSP); + + if (result == QDF_STATUS_SUCCESS) + goto free_req_msg; + if (wma_send_vdev_down_to_fw(wma, req_msg->vdev_id) != QDF_STATUS_SUCCESS) { WMA_LOGE("Failed to send vdev down cmd: vdev %d", |
