diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index c276f4d4d0f7..63d4eb3b029c 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1110,6 +1110,8 @@ struct wma_txrx_node { void *staKeyParams; bool restore_dtim_setting; uint32_t peer_count; + qdf_atomic_t fw_peer_count; + qdf_event_t fw_peer_delete; bool roam_synch_in_progress; void *plink_status_req; void *psnr_req; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 3326f6de0725..876cb8450138 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -573,6 +573,8 @@ wma_cdp_vdev_detach(ol_txrx_soc_handle soc, iface->is_vdev_valid = false; } +#define WAIT_FW_PEER_DELETE_TIMEOUT (5*1000) + static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle, struct del_sta_self_params *del_sta_self_req_param, uint8_t generate_rsp) @@ -589,12 +591,20 @@ static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle, goto out; } + while (qdf_atomic_read(&iface->fw_peer_count)) { + qdf_wait_for_event_completion(&iface->fw_peer_delete, + WAIT_FW_PEER_DELETE_TIMEOUT); + qdf_event_reset(&iface->fw_peer_delete); + } + status = wmi_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id); if (QDF_IS_STATUS_ERROR(status)) { WMA_LOGE("Unable to remove an interface"); goto out; } + qdf_event_destroy(&iface->fw_peer_delete); + WMA_LOGD("vdev_id:%hu vdev_hdl:%pK", vdev_id, iface->handle); if (!generate_rsp) { WMA_LOGE("Call txrx detach w/o callback for vdev %d", vdev_id); @@ -1414,6 +1424,11 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid, __func__, qdf_status); /* Clear default bit and set to NOT_START_UNMAP */ bitmap = 1 << CDP_PEER_DO_NOT_START_UNMAP_TIMER; + } else { + qdf_atomic_dec(&wma->interfaces[vdev_id].fw_peer_count); + qdf_event_set(&wma->interfaces[vdev_id].fw_peer_delete); + WMA_LOGD("%s: vdev-%d fw_peer_count %d", __func__, vdev_id, + qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count)); } peer_detach: @@ -1551,6 +1566,10 @@ QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev, cdp_peer_delete(dp_soc, peer, 1 << CDP_PEER_DO_NOT_START_UNMAP_TIMER); goto err; + } else { + qdf_atomic_inc(&wma->interfaces[vdev_id].fw_peer_count); + WMA_LOGD("%s: vdev-%d fw_peer_count %d", __func__, vdev_id, + qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count)); } WMA_LOGD("%s: Created peer %pK with peer_addr %pM vdev_id %d, peer_count - %d", @@ -2213,6 +2232,12 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle, self_sta_req->sub_type; qdf_atomic_init(&wma_handle->interfaces [self_sta_req->session_id].bss_status); + qdf_atomic_init(&wma_handle->interfaces + [self_sta_req->session_id].fw_peer_count); + status = qdf_event_create(&wma_handle->interfaces + [self_sta_req->session_id].fw_peer_delete); + if (status != QDF_STATUS_SUCCESS) + WMA_LOGE("%s: Failed to create fw_peer_delete event", __func__); if (((self_sta_req->type == WMI_VDEV_TYPE_AP) && (self_sta_req->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) ||