summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKabilan Kannan <kabilank@codeaurora.org>2018-02-02 16:42:04 -0800
committersnandini <snandini@codeaurora.org>2018-02-22 05:32:52 -0800
commit9cf3880813a70fa505b618b4f3da4dfcd9b69788 (patch)
tree5e8e6fb69005d229f3353cec9cfe9f0d2ad7e077
parentcb4726c202c741b186a4be61a01f19a76c5ebfdd (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.c125
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",