summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar <rajekuma@qca.qualcomm.com>2014-04-23 16:58:51 -0700
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-04-26 00:48:15 -0700
commitecc2eb4e135737e0f4633adc3c235b75c95ffbae (patch)
tree1215774045de768c6bbefbc174a3185836ad8838
parent4b94121999b5bfddb4dc8d5d7eda8c65dee2dfa7 (diff)
qcacld: Fix race condition while deleting SAP peers
Fix race condition while accessing vdev->peer_list from multiple contexts. Follwing is race condition in detail: a. Kernel worker thread/MC thread which is processing VDEV stop response from FW/VDEV response timeout calls wma_delete_all_ap_remote_peers and try to delete all remote peers. b. wma_delete_all_ap_remote_peers access vdev->peer_list and sends WMI peer delete command and after that FW sends HTT_T2H_MSG_TYPE_PEER_UNMAP message to host. This message is handled in wlan_tasklet context. c. TXRX module while processing HTT_T2H_MSG_TYPE_PEER_UNMAP also calls ol_txrx_peer_unref_delete to delete the peer from vdev->peer_list. d. Race condition is between b) and c) which can cause b) to break from the FOR loop for peer_list even though it has a pending peer. Change-Id: I57a500dbac9018ab7641318714e219f1852f0bab CRs-Fixed: 653359
-rw-r--r--CORE/SERVICES/WMA/wma.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 6d9b64829a92..9d3bed430897 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -1003,14 +1003,18 @@ static void wma_delete_all_ibss_peers(tp_wma_handle wma, A_UINT32 vdev_id)
return;
/* remove all IBSS remote peers first */
+ adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex);
TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
if (peer != TAILQ_FIRST(&vdev->peer_list)) {
+ adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex);
adf_os_atomic_init(&peer->ref_cnt);
adf_os_atomic_inc(&peer->ref_cnt);
wma_remove_peer(wma, wma->interfaces[vdev_id].bssid,
vdev_id, peer);
+ adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex);
}
}
+ adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex);
/* remove IBSS bss peer last */
peer = TAILQ_FIRST(&vdev->peer_list);
@@ -1020,26 +1024,31 @@ static void wma_delete_all_ibss_peers(tp_wma_handle wma, A_UINT32 vdev_id)
static void wma_delete_all_ap_remote_peers(tp_wma_handle wma, A_UINT32 vdev_id)
{
- ol_txrx_vdev_handle vdev;
- ol_txrx_peer_handle peer;
+ ol_txrx_vdev_handle vdev;
+ ol_txrx_peer_handle peer;
- if (!wma || vdev_id > wma->max_bssid)
- return;
+ if (!wma || vdev_id > wma->max_bssid)
+ return;
- vdev = wma->interfaces[vdev_id].handle;
- if (!vdev)
- return;
+ vdev = wma->interfaces[vdev_id].handle;
+ if (!vdev)
+ return;
- /* remove all remote peers of SAP */
- TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
+ /* remove all remote peers of SAP */
+ adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex);
+ TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
if (peer != TAILQ_FIRST(&vdev->peer_list)) {
+ adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex);
adf_os_atomic_init(&peer->ref_cnt);
adf_os_atomic_inc(&peer->ref_cnt);
wma_remove_peer(wma, peer->mac_addr.raw,
vdev_id, peer);
+ adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex);
}
}
+ adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex);
}
+
#ifdef QCA_IBSS_SUPPORT
static void wma_recreate_ibss_vdev_and_bss_peer(tp_wma_handle wma, u_int8_t vdev_id)
{