From a718007f03760722a49be068c6c839a415ef1dfb Mon Sep 17 00:00:00 2001 From: Chaithanya Garrepalli Date: Wed, 12 Aug 2020 18:07:51 +0530 Subject: [PATCH] qcacmn: increment vdev refcount for search by id Add new API dp_vdev_get_ref_by_id() which will return vdev pointer by holding a reference. Caller of this API has to ensure that this reference is released by calling dp_vdev_unref_delete() API New lock soc->vdev_map_lock is introduced to protect vdev id to object array Change-Id: I883e328932e35ef31254125492dbae20cebe0e00 --- dp/wifi3.0/dp_htt.c | 16 +- dp/wifi3.0/dp_internal.h | 53 ++-- dp/wifi3.0/dp_ipa.c | 23 +- dp/wifi3.0/dp_main.c | 485 ++++++++++++++++++++++---------- dp/wifi3.0/dp_peer.c | 23 +- dp/wifi3.0/dp_rx.c | 63 +---- dp/wifi3.0/dp_stats.c | 16 +- dp/wifi3.0/dp_tx.c | 55 ++-- dp/wifi3.0/dp_tx_desc.h | 8 +- dp/wifi3.0/dp_tx_flow_control.c | 13 +- dp/wifi3.0/dp_types.h | 2 + 11 files changed, 468 insertions(+), 289 deletions(-) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 5651e4ef86..cfa359e3c4 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -2414,13 +2414,12 @@ static void dp_process_ppdu_stats_user_common_tlv( /* returning earlier causes other feilds unpopulated */ if (peer_id == DP_SCAN_PEER_ID) { - vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc, - ppdu_desc->vdev_id); + vdev = dp_vdev_get_ref_by_id(pdev->soc, ppdu_desc->vdev_id); if (!vdev) return; qdf_mem_copy(ppdu_user_desc->mac_addr, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE); + dp_vdev_unref_delete(pdev->soc, vdev); } else { peer = dp_peer_get_ref_by_id(pdev->soc, peer_id, DP_MOD_ID_TX_PPDU_STATS); @@ -2432,13 +2431,13 @@ static void dp_process_ppdu_stats_user_common_tlv( * with peer id equal to previously associated * peer's peer_id but it was removed */ - vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc, - ppdu_desc->vdev_id); + vdev = dp_vdev_get_ref_by_id(pdev->soc, + ppdu_desc->vdev_id); if (!vdev) return; qdf_mem_copy(ppdu_user_desc->mac_addr, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE); + dp_vdev_unref_delete(pdev->soc, vdev); return; } qdf_mem_copy(ppdu_user_desc->mac_addr, @@ -2478,11 +2477,10 @@ static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev, ppdu_user_desc = &ppdu_desc->user[curr_user_index]; ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); if (peer_id == DP_SCAN_PEER_ID) { - vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc, - ppdu_desc->vdev_id); + vdev = dp_vdev_get_ref_by_id(pdev->soc, ppdu_desc->vdev_id); if (!vdev) return; + dp_vdev_unref_delete(pdev->soc, vdev); } ppdu_user_desc->peer_id = peer_id; diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index b30b05a2a9..c23601c5c5 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2128,20 +2128,47 @@ void dp_rx_fst_detach(struct dp_soc *soc, struct dp_pdev *pdev) #endif /** - * dp_get_vdev_from_soc_vdev_id_wifi3() - Returns vdev object given the vdev id + * dp_vdev_get_ref() - API to take a reference for VDEV object + * + * @soc : core DP soc context + * @vdev : DP vdev + * + * Return: QDF_STATUS_SUCCESS if reference held successfully + * else QDF_STATUS_E_INVAL + */ +static inline +QDF_STATUS dp_vdev_get_ref(struct dp_soc *soc, struct dp_vdev *vdev) +{ + if (!qdf_atomic_inc_not_zero(&vdev->ref_cnt)) + return QDF_STATUS_E_INVAL; + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_vdev_get_ref_by_id() - Returns vdev object given the vdev id * @soc: core DP soc context * @vdev_id: vdev id from vdev object can be retrieved * * Return: struct dp_vdev*: Pointer to DP vdev object */ static inline struct dp_vdev * -dp_get_vdev_from_soc_vdev_id_wifi3(struct dp_soc *soc, - uint8_t vdev_id) +dp_vdev_get_ref_by_id(struct dp_soc *soc, uint8_t vdev_id) { + struct dp_vdev *vdev = NULL; if (qdf_unlikely(vdev_id >= MAX_VDEV_CNT)) return NULL; - return soc->vdev_id_map[vdev_id]; + qdf_spin_lock_bh(&soc->vdev_map_lock); + vdev = soc->vdev_id_map[vdev_id]; + + if (!vdev || dp_vdev_get_ref(soc, vdev) != QDF_STATUS_SUCCESS) { + qdf_spin_unlock_bh(&soc->vdev_map_lock); + return NULL; + } + qdf_spin_unlock_bh(&soc->vdev_map_lock); + + return vdev; } /** @@ -2278,22 +2305,4 @@ dp_hmwds_ast_add_notify(struct dp_peer *peer, { } #endif - -/** - * dp_vdev_get_ref() - API to take a reference for VDEV object - * - * @soc : core DP soc context - * @vdev : DP vdev - * - * Return: QDF_STATUS_SUCCESS if reference held successfully - * else QDF_STATUS_E_INVAL - */ -static inline -QDF_STATUS dp_vdev_get_ref(struct dp_soc *soc, struct dp_vdev *vdev) -{ - if (!qdf_atomic_inc_not_zero(&vdev->ref_cnt)) - return QDF_STATUS_E_INVAL; - - return QDF_STATUS_SUCCESS; -} #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c index 5aab69c5e1..b09ca243ca 100644 --- a/dp/wifi3.0/dp_ipa.c +++ b/dp/wifi3.0/dp_ipa.c @@ -1786,14 +1786,14 @@ bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, qdf_nbuf_t nbuf, bool *fwd_success) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); struct dp_pdev *pdev; struct dp_peer *da_peer; struct dp_peer *sa_peer; qdf_nbuf_t nbuf_copy; uint8_t da_is_bcmc; struct ethhdr *eh; + bool status = false; *fwd_success = false; /* set default as failure */ @@ -1809,16 +1809,16 @@ bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, pdev = vdev->pdev; if (qdf_unlikely(!pdev)) - return false; + goto out; /* no fwd for station mode and just pass up to stack */ if (vdev->opmode == wlan_op_mode_sta) - return false; + goto out; if (da_is_bcmc) { nbuf_copy = qdf_nbuf_copy(nbuf); if (!nbuf_copy) - return false; + goto out; if (dp_ipa_intrabss_send(pdev, vdev, nbuf_copy)) qdf_nbuf_free(nbuf_copy); @@ -1826,25 +1826,25 @@ bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, *fwd_success = true; /* return false to pass original pkt up to stack */ - return false; + goto out; } eh = (struct ethhdr *)qdf_nbuf_data(nbuf); if (!qdf_mem_cmp(eh->h_dest, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE)) - return false; + goto out; da_peer = dp_peer_find_hash_find(soc, eh->h_dest, 0, vdev->vdev_id, DP_MOD_ID_IPA); if (!da_peer) - return false; + goto out; dp_peer_unref_delete(da_peer, DP_MOD_ID_IPA); sa_peer = dp_peer_find_hash_find(soc, eh->h_source, 0, vdev->vdev_id, DP_MOD_ID_IPA); if (!sa_peer) - return false; + goto out; dp_peer_unref_delete(sa_peer, DP_MOD_ID_IPA); @@ -1860,7 +1860,10 @@ bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, else *fwd_success = true; - return true; + status = true; +out: + dp_vdev_unref_delete(soc, vdev); + return status; } #ifdef MDM_PLATFORM diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 39c077fdf7..6eef8d2d73 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -735,7 +735,7 @@ static QDF_STATUS dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, struct dp_ast_entry *ast_entry = NULL; struct dp_peer *peer; struct dp_pdev *pdev; - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return QDF_STATUS_E_FAILURE; @@ -747,6 +747,7 @@ static QDF_STATUS dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, 0, vdev->vdev_id, DP_MOD_ID_CDP); if (!peer) { + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_E_FAILURE; } @@ -754,8 +755,6 @@ static QDF_STATUS dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, dp_peer_reset_ast_entries(soc, peer, NULL); qdf_spin_unlock_bh(&soc->ast_lock); dp_peer_unref_delete(peer, DP_MOD_ID_CDP); - - return QDF_STATUS_SUCCESS; } else if (wds_macaddr) { qdf_spin_lock_bh(&soc->ast_lock); ast_entry = dp_peer_ast_hash_find_by_pdevid(soc, wds_macaddr, @@ -769,6 +768,7 @@ static QDF_STATUS dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, qdf_spin_unlock_bh(&soc->ast_lock); } + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -4378,6 +4378,8 @@ static void dp_soc_deinit(void *txrx_soc) qdf_spinlock_destroy(&soc->rx.defrag.defrag_lock); + qdf_spinlock_destroy(&soc->vdev_map_lock); + dp_reo_cmdlist_destroy(soc); qdf_spinlock_destroy(&soc->rx.reo_cmd_lock); @@ -4934,6 +4936,118 @@ dp_soc_config_full_mon_mode(struct dp_pdev *pdev, enum dp_full_mon_config val) } #endif +/* + * dp_vdev_id_map_tbl_add() - Add vdev into vdev_id table + * @soc: SoC handle + * @vdev: vdev handle + * @vdev_id: vdev_id + * + * Return: None + */ +static void dp_vdev_id_map_tbl_add(struct dp_soc *soc, + struct dp_vdev *vdev, + uint8_t vdev_id) +{ + QDF_ASSERT(vdev_id <= MAX_VDEV_CNT); + + qdf_spin_lock_bh(&soc->vdev_map_lock); + + if (dp_vdev_get_ref(soc, vdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "unable to get vdev reference at MAP vdev %pK vdev_id %u", + vdev, vdev_id); + qdf_spin_unlock_bh(&soc->vdev_map_lock); + return; + } + + if (!soc->vdev_id_map[vdev_id]) + soc->vdev_id_map[vdev_id] = vdev; + else + QDF_ASSERT(0); + + qdf_spin_unlock_bh(&soc->vdev_map_lock); +} + +/* + * dp_vdev_id_map_tbl_remove() - remove vdev from vdev_id table + * @soc: SoC handle + * @vdev: vdev handle + * + * Return: None + */ +static void dp_vdev_id_map_tbl_remove(struct dp_soc *soc, + struct dp_vdev *vdev) +{ + qdf_spin_lock_bh(&soc->vdev_map_lock); + QDF_ASSERT(soc->vdev_id_map[vdev->vdev_id] == vdev); + + soc->vdev_id_map[vdev->vdev_id] = NULL; + dp_vdev_unref_delete(soc, vdev); + qdf_spin_unlock_bh(&soc->vdev_map_lock); +} + +/* + * dp_vdev_pdev_list_add() - add vdev into pdev's list + * @soc: soc handle + * @pdev: pdev handle + * @vdev: vdev handle + * + * return: none + */ +static void dp_vdev_pdev_list_add(struct dp_soc *soc, + struct dp_pdev *pdev, + struct dp_vdev *vdev) +{ + qdf_spin_lock_bh(&pdev->vdev_list_lock); + if (dp_vdev_get_ref(soc, vdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "unable to get vdev reference at MAP vdev %pK", + vdev); + qdf_spin_unlock_bh(&pdev->vdev_list_lock); + return; + } + /* add this vdev into the pdev's list */ + TAILQ_INSERT_TAIL(&pdev->vdev_list, vdev, vdev_list_elem); + qdf_spin_unlock_bh(&pdev->vdev_list_lock); +} + +/* + * dp_vdev_pdev_list_remove() - remove vdev from pdev's list + * @soc: SoC handle + * @pdev: pdev handle + * @vdev: VDEV handle + * + * Return: none + */ +static void dp_vdev_pdev_list_remove(struct dp_soc *soc, + struct dp_pdev *pdev, + struct dp_vdev *vdev) +{ + uint8_t found = 0; + struct dp_vdev *tmpvdev = NULL; + + qdf_spin_lock_bh(&pdev->vdev_list_lock); + TAILQ_FOREACH(tmpvdev, &pdev->vdev_list, vdev_list_elem) { + if (tmpvdev == vdev) { + found = 1; + break; + } + } + + if (found) { + TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem); + dp_vdev_unref_delete(soc, vdev); + } else { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "vdev:%pK not found in pdev:%pK vdevlist:%pK", + vdev, pdev, &pdev->vdev_list); + QDF_ASSERT(0); + } + qdf_spin_unlock_bh(&pdev->vdev_list_lock); +} + /* * dp_vdev_attach_wifi3() - attach txrx vdev * @txrx_pdev: Datapath PDEV handle @@ -5018,7 +5132,7 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc, qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS); } - soc->vdev_id_map[vdev_id] = vdev; + dp_vdev_id_map_tbl_add(soc, vdev, vdev_id); if (wlan_op_mode_monitor == vdev->opmode) { pdev->monitor_vdev = vdev; @@ -5033,10 +5147,7 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc, vdev->prev_tx_enq_tstamp = 0; vdev->prev_rx_deliver_tstamp = 0; - qdf_spin_lock_bh(&pdev->vdev_list_lock); - /* add this vdev into the pdev's list */ - TAILQ_INSERT_TAIL(&pdev->vdev_list, vdev, vdev_list_elem); - qdf_spin_unlock_bh(&pdev->vdev_list_lock); + dp_vdev_pdev_list_add(soc, pdev, vdev); pdev->vdev_count++; if (wlan_op_mode_sta != vdev->opmode) @@ -5073,14 +5184,14 @@ fail0: * * Return: DP VDEV handle on success, NULL on failure */ -static QDF_STATUS dp_vdev_register_wifi3(struct cdp_soc_t *soc, +static QDF_STATUS dp_vdev_register_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, ol_osif_vdev_handle osif_vdev, struct ol_txrx_ops *txrx_ops) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return QDF_STATUS_E_FAILURE; @@ -5119,6 +5230,7 @@ static QDF_STATUS dp_vdev_register_wifi3(struct cdp_soc_t *soc, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, "DP Vdev Register success"); + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -5206,7 +5318,7 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, struct dp_neighbour_peer *peer = NULL; struct dp_neighbour_peer *temp_peer = NULL; struct dp_peer *vap_self_peer = NULL; - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return QDF_STATUS_E_FAILURE; @@ -5244,7 +5356,7 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, * as the call back done in dp_rx_vdev_detach() * still need to get vdev pointer by vdev_id. */ - soc->vdev_id_map[vdev->vdev_id] = NULL; + dp_vdev_id_map_tbl_remove(soc, vdev); qdf_spin_lock_bh(&pdev->neighbour_peer_mutex); if (!soc->hw_nac_monitor_support) { @@ -5273,6 +5385,13 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, vdev->delete.callback = callback; vdev->delete.context = cb_context; + if (vdev->opmode != wlan_op_mode_monitor) + dp_vdev_pdev_list_remove(soc, pdev, vdev); + + /* release reference taken at dp_vdev_create */ + dp_vdev_unref_delete(soc, vdev); + + /* release reference taken above for find */ dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -5391,9 +5510,14 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, struct dp_pdev *pdev; struct cdp_peer_cookie peer_cookie; enum cdp_txrx_ast_entry_type ast_type = CDP_TXRX_AST_TYPE_STATIC; - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = NULL; - if (!vdev || !peer_mac_addr) + if (!peer_mac_addr) + return QDF_STATUS_E_FAILURE; + + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + + if (!vdev) return QDF_STATUS_E_FAILURE; pdev = vdev->pdev; @@ -5442,6 +5566,8 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, qdf_spinlock_create(&peer->rx_tid[i].tid_lock); dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT); + + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } else { /* @@ -5464,8 +5590,10 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, sizeof(*peer), soc->ctrl_psoc, WLAN_MD_DP_PEER, "dp_peer"); - if (!peer) + if (!peer) { + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_E_FAILURE; /* failure */ + } qdf_mem_zero(peer, sizeof(struct dp_peer)); @@ -5579,6 +5707,8 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT); + dp_vdev_unref_delete(soc, vdev); + return QDF_STATUS_SUCCESS; } @@ -5717,8 +5847,7 @@ dp_peer_setup_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, bool hash_based = 0; enum cdp_host_reo_dest_ring reo_dest; QDF_STATUS status = QDF_STATUS_SUCCESS; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = NULL; struct dp_peer *peer = dp_peer_find_hash_find(soc, peer_mac, 0, vdev_id, DP_MOD_ID_CDP); @@ -5726,6 +5855,7 @@ dp_peer_setup_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, if (!peer) return QDF_STATUS_E_FAILURE; + vdev = peer->vdev; if (!vdev) { status = QDF_STATUS_E_FAILURE; goto fail; @@ -5787,10 +5917,6 @@ static QDF_STATUS dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, struct dp_ast_entry *ast_entry = NULL; txrx_ast_free_cb cb = NULL; void *cookie; - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); - - if (!vdev) - return QDF_STATUS_E_FAILURE; qdf_spin_lock_bh(&soc->ast_lock); @@ -5947,15 +6073,14 @@ static int dp_set_filter_neigh_peers(struct dp_pdev *pdev, * * Return: success/failure */ -static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, +static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, uint32_t cmd, uint8_t *macaddr) { + struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_pdev *pdev; struct dp_neighbour_peer *peer = NULL; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev || !macaddr) goto fail0; @@ -6004,7 +6129,6 @@ static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, pdev->neighbour_peers_added = false; } } - return 1; } else if (cmd == DP_NAC_PARAM_DEL) { qdf_spin_lock_bh(&pdev->neighbour_peer_mutex); @@ -6035,11 +6159,13 @@ static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, } qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); - return 1; - } + dp_vdev_unref_delete(soc, vdev); + return 1; fail0: + if (vdev) + dp_vdev_unref_delete(soc, vdev); return 0; } #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ @@ -6214,10 +6340,6 @@ void dp_vdev_unref_delete(struct dp_soc *soc, struct dp_vdev *vdev) FLOW_TYPE_VDEV, vdev_id); dp_tx_vdev_detach(vdev); - qdf_spin_lock_bh(&pdev->vdev_list_lock); - TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem); - qdf_spin_unlock_bh(&pdev->vdev_list_lock); - free_vdev: qdf_spinlock_destroy(&vdev->peer_list_lock); dp_info("deleting vdev object %pK (%pM)", @@ -6346,9 +6468,7 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, struct dp_peer *peer = dp_peer_find_hash_find(soc, peer_mac, 0, vdev_id, DP_MOD_ID_CDP); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); - if (!vdev) - return QDF_STATUS_E_FAILURE; + struct dp_vdev *vdev = NULL; /* Peer can be null for monitor vap mac address */ if (!peer) { @@ -6363,6 +6483,10 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, return QDF_STATUS_E_ALREADY; } + vdev = peer->vdev; + + if (!vdev) + return QDF_STATUS_E_FAILURE; peer->valid = 0; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, @@ -6410,12 +6534,16 @@ static uint8 *dp_get_vdev_mac_addr_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + uint8_t *mac = NULL; if (!vdev) return NULL; - return vdev->mac_addr.raw; + mac = vdev->mac_addr.raw; + dp_vdev_unref_delete(soc, vdev); + + return mac; } /* @@ -6426,16 +6554,19 @@ static uint8 *dp_get_vdev_mac_addr_wifi3(struct cdp_soc_t *soc_hdl, * * Return: none */ -static int dp_vdev_set_wds(struct cdp_soc_t *soc, uint8_t vdev_id, uint32_t val) +static int dp_vdev_set_wds(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint32_t val) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + dp_vdev_get_ref_by_id((struct dp_soc *)soc, vdev_id); if (!vdev) return QDF_STATUS_E_FAILURE; vdev->wds_enabled = val; + dp_vdev_unref_delete(soc, vdev); + return QDF_STATUS_SUCCESS; } @@ -6461,14 +6592,17 @@ static uint8_t dp_get_mon_vdev_from_pdev_wifi3(struct cdp_soc_t *soc_hdl, static int dp_get_opmode(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + int opmode; if (!vdev) { dp_err("vdev for id %d is NULL", vdev_id); return -EINVAL; } + opmode = vdev->opmode; + dp_vdev_unref_delete(soc, vdev); - return vdev->opmode; + return opmode; } /** @@ -6487,13 +6621,14 @@ void dp_get_os_rx_handles_from_vdev_wifi3(struct cdp_soc_t *soc_hdl, ol_osif_vdev_handle *osif_vdev_p) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return; *stack_fn_p = vdev->osif_rx_stack; *osif_vdev_p = vdev->osif_vdev; + dp_vdev_unref_delete(soc, vdev); } /** @@ -6508,14 +6643,15 @@ static struct cdp_cfg *dp_get_ctrl_pdev_from_vdev_wifi3( uint8_t vdev_id) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); struct dp_pdev *pdev; - if (!vdev || !vdev->pdev) + if (!vdev) return NULL; pdev = vdev->pdev; - return (struct cdp_cfg *)pdev->wlan_cfg_ctx; + dp_vdev_unref_delete(soc, vdev); + return pdev ? (struct cdp_cfg *)pdev->wlan_cfg_ctx : NULL; } /** @@ -6663,18 +6799,18 @@ static QDF_STATUS dp_get_peer_mac_from_peer_id(struct cdp_soc_t *soc, * * Return: 0 on success, not 0 on failure */ -static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc, +static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, uint8_t special_monitor) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); uint32_t mac_id; uint32_t mac_for_pdev; struct dp_pdev *pdev; uint32_t num_entries; struct dp_srng *mon_buf_ring; struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + dp_vdev_get_ref_by_id(soc, vdev_id); QDF_STATUS status = QDF_STATUS_SUCCESS; if (!vdev) @@ -6693,14 +6829,17 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc, * for lite monitor required configuration done through * dp_set_pdev_param */ - if (special_monitor) - return QDF_STATUS_SUCCESS; + if (special_monitor) { + status = QDF_STATUS_SUCCESS; + goto fail; + } /*Check if current pdev's monitor_vdev exists */ if (pdev->monitor_configured) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "monitor vap already created vdev=%pK\n", vdev); - return QDF_STATUS_E_RESOURCES; + status = QDF_STATUS_E_RESOURCES; + goto fail; } pdev->monitor_configured = true; @@ -6738,6 +6877,8 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc, pdev->monitor_vdev = NULL; } +fail: + dp_vdev_unref_delete(soc, vdev); return status; } @@ -6914,52 +7055,76 @@ void dp_peer_set_mesh_rx_filter(struct cdp_vdev *vdev_hdl, uint32_t val) #endif #ifdef VDEV_PEER_PROTOCOL_COUNT -static void dp_enable_vdev_peer_protocol_count(struct cdp_soc_t *soc, +static void dp_enable_vdev_peer_protocol_count(struct cdp_soc_t *soc_hdl, int8_t vdev_id, bool enable) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) + return; + dp_info("enable %d vdev_id %d", enable, vdev_id); vdev->peer_protocol_count_track = enable; + dp_vdev_unref_delete(soc, vdev); } -static void dp_enable_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc, +static void dp_enable_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc_hdl, int8_t vdev_id, int drop_mask) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) + return; + dp_info("drop_mask %d vdev_id %d", drop_mask, vdev_id); vdev->peer_protocol_count_dropmask = drop_mask; + dp_vdev_unref_delete(soc, vdev); } -static int dp_is_vdev_peer_protocol_count_enabled(struct cdp_soc_t *soc, +static int dp_is_vdev_peer_protocol_count_enabled(struct cdp_soc_t *soc_hdl, int8_t vdev_id) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev; + int peer_protocol_count_track; + + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) + return 0; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); dp_info("enable %d vdev_id %d", vdev->peer_protocol_count_track, vdev_id); - return vdev->peer_protocol_count_track; + peer_protocol_count_track = + vdev->peer_protocol_count_track; + + dp_vdev_unref_delete(soc, vdev); + return peer_protocol_count_track; } -static int dp_get_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc, +static int dp_get_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc_hdl, int8_t vdev_id) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev; + int peer_protocol_count_dropmask; + + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) + return 0; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); dp_info("drop_mask %d vdev_id %d", vdev->peer_protocol_count_dropmask, vdev_id); - return vdev->peer_protocol_count_dropmask; + peer_protocol_count_dropmask = + vdev->peer_protocol_count_dropmask; + + dp_vdev_unref_delete(soc, vdev); + return peer_protocol_count_dropmask; } #endif @@ -7179,15 +7344,24 @@ static void dp_pdev_getstats(struct cdp_pdev *pdev_handle, * * Return: QDF_STATUS */ -static QDF_STATUS dp_get_device_stats(struct cdp_soc_t *soc, uint8_t id, +static QDF_STATUS dp_get_device_stats(struct cdp_soc_t *soc_hdl, uint8_t id, struct cdp_dev_stats *stats, uint8_t type) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct dp_vdev *vdev; + switch (type) { case UPDATE_VDEV_STATS: - return dp_vdev_getstats( - (struct cdp_vdev *)dp_get_vdev_from_soc_vdev_id_wifi3( - (struct dp_soc *)soc, id), stats); + vdev = dp_vdev_get_ref_by_id(soc, id); + + if (vdev) { + status = dp_vdev_getstats((struct cdp_vdev *)vdev, + stats); + dp_vdev_unref_delete(soc, vdev); + } + return status; case UPDATE_PDEV_STATS: { struct dp_pdev *pdev = @@ -8165,23 +8339,23 @@ static QDF_STATUS dp_calculate_delay_stats(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, qdf_nbuf_t nbuf) { - struct dp_soc *soc = (struct dp_soc *)cdp_soc; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)cdp_soc, - vdev_id); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(cdp_soc); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return QDF_STATUS_SUCCESS; if (vdev->pdev->delay_stats_flag) { dp_rx_compute_delay(vdev, nbuf); - return QDF_STATUS_SUCCESS; + } else { + /* + * Update the per peer delay stats + */ + dp_rx_update_peer_delay_stats(soc, nbuf); + } - /* - * Update the per peer delay stats - */ - dp_rx_update_peer_delay_stats(soc, nbuf); + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -8198,9 +8372,9 @@ static QDF_STATUS dp_get_vdev_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, enum cdp_vdev_param_type param, cdp_config_param_type *val) { - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)cdp_soc, - vdev_id); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(cdp_soc); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) return QDF_STATUS_E_FAILURE; @@ -8218,9 +8392,11 @@ static QDF_STATUS dp_get_vdev_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "param value %d is wrong\n", param); + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_E_FAILURE; } + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -8239,7 +8415,7 @@ dp_set_vdev_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, { struct dp_soc *dsoc = (struct dp_soc *)cdp_soc; struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(dsoc, vdev_id); + dp_vdev_get_ref_by_id(dsoc, vdev_id); uint32_t var = 0; if (!vdev) @@ -8329,6 +8505,7 @@ dp_set_vdev_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, } dp_tx_vdev_update_search_flags((struct dp_vdev *)vdev); + dp_vdev_unref_delete(dsoc, vdev); return QDF_STATUS_SUCCESS; } @@ -8480,10 +8657,10 @@ static QDF_STATUS dp_set_vdev_dscp_tid_map_wifi3(ol_txrx_soc_handle soc, uint8_t map_id) { struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + dp_vdev_get_ref_by_id((struct dp_soc *)soc, vdev_id); if (vdev) { vdev->dscp_tid_map_id = map_id; + dp_vdev_unref_delete((struct dp_soc *)soc, vdev); return QDF_STATUS_SUCCESS; } @@ -8574,14 +8751,14 @@ static void dp_txrx_update_vdev_me_stats(struct dp_vdev *vdev, * * Returns: QDF_STATUS */ -static QDF_STATUS dp_txrx_update_vdev_host_stats(struct cdp_soc_t *soc, +static QDF_STATUS dp_txrx_update_vdev_host_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, void *buf, uint16_t stats_id) { - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "Invalid vdev handle"); @@ -8599,6 +8776,7 @@ static QDF_STATUS dp_txrx_update_vdev_host_stats(struct cdp_soc_t *soc, break; } + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -8744,22 +8922,16 @@ dp_txrx_reset_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, * * return : int */ -static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc, uint8_t vdev_id, - void *buf, bool is_aggregate) +static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + void *buf, bool is_aggregate) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct cdp_vdev_stats *vdev_stats; - struct dp_pdev *pdev; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return 1; - pdev = vdev->pdev; - if (!pdev) - return 1; - vdev_stats = (struct cdp_vdev_stats *)buf; if (is_aggregate) { @@ -8768,6 +8940,7 @@ static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_mem_copy(vdev_stats, &vdev->stats, sizeof(vdev->stats)); } + dp_vdev_unref_delete(soc, vdev); return 0; } @@ -8939,23 +9112,27 @@ QDF_STATUS dp_txrx_stats_request(struct cdp_soc_t *soc_handle, int fw_stats; enum cdp_stats stats; int num_stats; - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, - vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + QDF_STATUS status = QDF_STATUS_E_INVAL; if (!vdev || !req) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "Invalid vdev/req instance"); - return QDF_STATUS_E_INVAL; + status = QDF_STATUS_E_INVAL; + goto fail0; } if (req->mac_id >= WLAN_CFG_MAC_PER_TARGET) { dp_err("Invalid mac id request"); - return QDF_STATUS_E_INVAL; + status = QDF_STATUS_E_INVAL; + goto fail0; } stats = req->stats; - if (stats >= CDP_TXRX_MAX_STATS) - return QDF_STATUS_E_INVAL; + if (stats >= CDP_TXRX_MAX_STATS) { + status = QDF_STATUS_E_INVAL; + goto fail0; + } /* * DP_CURR_FW_STATS_AVAIL: no of FW stats currently available @@ -8969,7 +9146,8 @@ QDF_STATUS dp_txrx_stats_request(struct cdp_soc_t *soc_handle, if (stats >= num_stats) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s: Invalid stats option: %d", __func__, stats); - return QDF_STATUS_E_INVAL; + status = QDF_STATUS_E_INVAL; + goto fail0; } req->stats = stats; @@ -8982,17 +9160,17 @@ QDF_STATUS dp_txrx_stats_request(struct cdp_soc_t *soc_handle, if (fw_stats != TXRX_FW_STATS_INVALID) { /* update request with FW stats type */ req->stats = fw_stats; - return dp_fw_stats_process(vdev, req); - } - - if ((host_stats != TXRX_HOST_STATS_INVALID) && + status = dp_fw_stats_process(vdev, req); + } else if ((host_stats != TXRX_HOST_STATS_INVALID) && (host_stats <= TXRX_HOST_STATS_MAX)) - return dp_print_host_stats(vdev, req, soc); + status = dp_print_host_stats(vdev, req, soc); else QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, "Wrong Input for TxRx Stats"); - - return QDF_STATUS_SUCCESS; +fail0: + if (vdev) + dp_vdev_unref_delete(soc, vdev); + return status; } /* @@ -9215,13 +9393,15 @@ dp_txrx_data_tx_cb_set(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, ol_txrx_data_tx_cb callback, void *ctxt) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return; vdev->tx_non_std_data_callback.func = callback; vdev->tx_non_std_data_callback.ctxt = ctxt; + + dp_vdev_unref_delete(soc, vdev); } /** @@ -9274,13 +9454,14 @@ dp_pdev_set_dp_txrx_handle(struct cdp_soc_t *soc, uint8_t pdev_id, static void *dp_vdev_get_dp_ext_handle(ol_txrx_soc_handle soc, uint8_t vdev_id) { struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + dp_vdev_get_ref_by_id((struct dp_soc *)soc, vdev_id); + void *dp_ext_handle; if (!vdev) return NULL; + dp_ext_handle = vdev->vdev_dp_ext_handle; - return vdev->vdev_dp_ext_handle; + return dp_ext_handle; } /** @@ -9292,12 +9473,11 @@ static void *dp_vdev_get_dp_ext_handle(ol_txrx_soc_handle soc, uint8_t vdev_id) * Return: QDF_STATUS */ static QDF_STATUS -dp_vdev_set_dp_ext_handle(ol_txrx_soc_handle soc, uint8_t vdev_id, +dp_vdev_set_dp_ext_handle(ol_txrx_soc_handle soc_hdl, uint8_t vdev_id, uint16_t size) { - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); void *dp_ext_handle; if (!vdev) @@ -9305,10 +9485,14 @@ dp_vdev_set_dp_ext_handle(ol_txrx_soc_handle soc, uint8_t vdev_id, dp_ext_handle = qdf_mem_malloc(size); - if (!dp_ext_handle) + if (!dp_ext_handle) { + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_E_FAILURE; + } vdev->vdev_dp_ext_handle = dp_ext_handle; + + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -9508,14 +9692,13 @@ dp_peer_teardown_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, * * Return: 0 for success. nonzero for failure. */ -static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_soc_t *soc, +static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, char *mac_addr, uint8_t *rssi) { - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); struct dp_pdev *pdev; struct dp_neighbour_peer *peer = NULL; QDF_STATUS status = QDF_STATUS_E_FAILURE; @@ -9536,6 +9719,7 @@ static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_soc_t *soc, } } qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); + dp_vdev_unref_delete(soc, vdev); return status; } @@ -9548,8 +9732,7 @@ dp_config_for_nac_rssi(struct cdp_soc_t *cdp_soc, { struct dp_soc *soc = (struct dp_soc *)cdp_soc; struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(soc, - vdev_id); + dp_vdev_get_ref_by_id(soc, vdev_id); struct dp_pdev *pdev; if (!vdev) @@ -9576,6 +9759,7 @@ dp_config_for_nac_rssi(struct cdp_soc_t *cdp_soc, (soc->ctrl_psoc, pdev->pdev_id, vdev->vdev_id, cmd, bssid, client_macaddr); + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } #endif @@ -10006,19 +10190,19 @@ static QDF_STATUS dp_set_pdev_pcp_tid_map_wifi3(ol_txrx_soc_handle psoc, * * Return: QDF_STATUS_SUCCESS on success */ -static QDF_STATUS dp_set_vdev_pcp_tid_map_wifi3(struct cdp_soc_t *soc, +static QDF_STATUS dp_set_vdev_pcp_tid_map_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, uint8_t pcp, uint8_t tid) { - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) return QDF_STATUS_E_FAILURE; vdev->pcp_tid_map[pcp] = tid; + dp_vdev_unref_delete(soc, vdev); return QDF_STATUS_SUCCESS; } @@ -10353,8 +10537,7 @@ static uint32_t dp_tx_get_success_ack_stats(struct cdp_soc_t *soc_hdl, struct cdp_vdev_stats *vdev_stats = NULL; uint32_t tx_success; struct dp_vdev *vdev = - (struct dp_vdev *)dp_get_vdev_from_soc_vdev_id_wifi3(soc, - vdev_id); + (struct dp_vdev *)dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -10366,6 +10549,7 @@ static uint32_t dp_tx_get_success_ack_stats(struct cdp_soc_t *soc_hdl, if (!vdev_stats) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "DP alloc failure - unable to get alloc vdev stats"); + dp_vdev_unref_delete(soc, vdev); return 0; } @@ -10374,6 +10558,7 @@ static uint32_t dp_tx_get_success_ack_stats(struct cdp_soc_t *soc_hdl, tx_success = vdev_stats->tx.tx_success.num; qdf_mem_free(vdev_stats); + dp_vdev_unref_delete(soc, vdev); return tx_success; } @@ -10566,8 +10751,8 @@ static QDF_STATUS dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { struct dp_soc *soc = (struct dp_soc *)soc_hdl; - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); - struct dp_peer *peer; + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + struct dp_peer *peer = NULL; QDF_STATUS status; struct dp_req_rx_hw_stats_t *rx_hw_stats; int rx_stats_sent_cnt = 0; @@ -10576,22 +10761,24 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) if (!vdev) { dp_err("vdev is null for vdev_id: %u", vdev_id); - return QDF_STATUS_E_INVAL; + status = QDF_STATUS_E_INVAL; + goto out; } peer = dp_vdev_bss_peer_ref_n_get(soc, vdev, DP_MOD_ID_CDP); if (!peer) { dp_err("Peer is NULL"); - return QDF_STATUS_E_INVAL; + status = QDF_STATUS_E_INVAL; + goto out; } rx_hw_stats = qdf_mem_malloc(sizeof(*rx_hw_stats)); if (!rx_hw_stats) { dp_err("malloc failed for hw stats structure"); - dp_peer_unref_delete(peer, DP_MOD_ID_CDP); - return QDF_STATUS_E_NOMEM; + status = QDF_STATUS_E_INVAL; + goto out; } qdf_event_reset(&soc->rx_hw_stats_event); @@ -10608,8 +10795,8 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) dp_err("no tid stats sent successfully"); qdf_mem_free(rx_hw_stats); qdf_spin_unlock_bh(&soc->rx_hw_stats_lock); - dp_peer_unref_delete(peer, DP_MOD_ID_CDP); - return QDF_STATUS_E_INVAL; + status = QDF_STATUS_E_INVAL; + goto out; } qdf_atomic_set(&rx_hw_stats->pending_tid_stats_cnt, rx_stats_sent_cnt); @@ -10633,7 +10820,12 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) soc->ext_stats.rx_mpdu_missed = last_rx_mpdu_missed; } qdf_spin_unlock_bh(&soc->rx_hw_stats_lock); - dp_peer_unref_delete(peer, DP_MOD_ID_CDP); + +out: + if (peer) + dp_peer_unref_delete(peer, DP_MOD_ID_CDP); + if (vdev) + dp_vdev_unref_delete(soc, vdev); return status; } @@ -11136,6 +11328,7 @@ void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle, soc->cce_disable = false; qdf_mem_zero(&soc->vdev_id_map, sizeof(soc->vdev_id_map)); + qdf_spinlock_create(&soc->vdev_map_lock); qdf_atomic_init(&soc->num_tx_outstanding); qdf_atomic_init(&soc->num_tx_exception); soc->num_tx_allowed = @@ -11876,8 +12069,7 @@ uint16_t dp_get_peer_mac_list(ol_txrx_soc_handle soc, uint8_t vdev_id, { struct dp_soc *dp_soc = (struct dp_soc *)soc; struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(dp_soc, - vdev_id); + dp_vdev_get_ref_by_id(dp_soc, vdev_id); struct dp_peer *peer; uint16_t new_mac_cnt = 0; @@ -11894,6 +12086,7 @@ uint16_t dp_get_peer_mac_list(ol_txrx_soc_handle soc, uint8_t vdev_id, } } qdf_spin_unlock_bh(&vdev->peer_list_lock); + dp_vdev_unref_delete(dp_soc, vdev); return new_mac_cnt; } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 186da1abe3..c0af3f4eff 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -266,7 +266,7 @@ void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer) } /* - * dp_peer_vdev_list_add() - add peer into vdev list + * dp_peer_vdev_list_add() - add peer into vdev's peer list * @soc: soc handle * @vdev: vdev handle * @peer: peer handle @@ -297,7 +297,7 @@ void dp_peer_vdev_list_add(struct dp_soc *soc, struct dp_vdev *vdev, } /* - * dp_peer_vdev_list_remove() - remove peer from vdev list + * dp_peer_vdev_list_remove() - remove peer from vdev's peer list * @soc: SoC handle * @vdev: VDEV handle * @peer: peer handle @@ -3500,15 +3500,7 @@ dp_set_pn_check_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t pn_size; struct hal_reo_cmd_params params; struct dp_peer *peer = NULL; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); - - if (!vdev) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: VDEV is NULL!\n", __func__); - return QDF_STATUS_E_FAILURE; - } + struct dp_vdev *vdev = NULL; peer = dp_peer_find_hash_find((struct dp_soc *)soc, peer_mac, 0, vdev_id, @@ -3520,6 +3512,15 @@ dp_set_pn_check_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, return QDF_STATUS_E_FAILURE; } + vdev = peer->vdev; + + if (!vdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: VDEV is NULL!\n", __func__); + dp_peer_unref_delete(peer, DP_MOD_ID_CDP); + return QDF_STATUS_E_FAILURE; + } + pdev = vdev->pdev; qdf_mem_zero(¶ms, sizeof(params)); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 5bc4ca1682..c1b62f0df5 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -483,62 +483,6 @@ dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list, vdev->osif_rx(vdev->osif_vdev, deliver_list_head); } - -#ifdef DP_LFR -/* - * In case of LFR, data of a new peer might be sent up - * even before peer is added. - */ -static inline struct dp_vdev * -dp_get_vdev_from_peer(struct dp_soc *soc, - uint16_t peer_id, - struct dp_peer *peer, - struct hal_rx_mpdu_desc_info mpdu_desc_info) -{ - struct dp_vdev *vdev; - uint8_t vdev_id; - - if (unlikely(!peer)) { - if (peer_id != HTT_INVALID_PEER) { - vdev_id = DP_PEER_METADATA_VDEV_ID_GET( - mpdu_desc_info.peer_meta_data); - QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_DEBUG, - FL("PeerID %d not found use vdevID %d"), - peer_id, vdev_id); - vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, - vdev_id); - } else { - QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_DEBUG, - FL("Invalid PeerID %d"), - peer_id); - return NULL; - } - } else { - vdev = peer->vdev; - } - return vdev; -} -#else -static inline struct dp_vdev * -dp_get_vdev_from_peer(struct dp_soc *soc, - uint16_t peer_id, - struct dp_peer *peer, - struct hal_rx_mpdu_desc_info mpdu_desc_info) -{ - if (unlikely(!peer)) { - QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_DEBUG, - FL("Peer not found for peerID %d"), - peer_id); - return NULL; - } else { - return peer->vdev; - } -} -#endif - #ifndef FEATURE_WDS static void dp_rx_da_learn(struct dp_soc *soc, @@ -1919,7 +1863,7 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) { uint16_t peer_id; uint8_t vdev_id; - struct dp_vdev *vdev; + struct dp_vdev *vdev = NULL; uint32_t l2_hdr_offset = 0; uint16_t msdu_len = 0; uint32_t pkt_len = 0; @@ -1932,7 +1876,7 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) goto deliver_fail; vdev_id = QDF_NBUF_CB_RX_VDEV_ID(nbuf); - vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev || vdev->delete.pending || !vdev->osif_rx) goto deliver_fail; @@ -1958,6 +1902,7 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) vdev->osif_rx(vdev->osif_vdev, nbuf)) goto deliver_fail; DP_STATS_INC(soc, rx.err.pkt_delivered_no_peer, 1); + dp_vdev_unref_delete(soc, vdev); return; } @@ -1965,6 +1910,8 @@ deliver_fail: DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1, QDF_NBUF_CB_RX_PKT_LEN(nbuf)); qdf_nbuf_free(nbuf); + if (vdev) + dp_vdev_unref_delete(soc, vdev); } #else static inline diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index b70c22bc79..1cd885233e 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -4338,20 +4338,24 @@ dp_vdev_peer_stats_update_protocol_cnt_free_peer: dp_peer_unref_delete(peer, DP_MOD_ID_GENERIC_STATS); } -void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc, +void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc_hdl, int8_t vdev_id, qdf_nbuf_t nbuf, bool is_egress, bool is_rx) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_vdev *vdev; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); - if (qdf_likely(!vdev->peer_protocol_count_track)) + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); + if (!vdev) return; - dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, is_egress, - is_rx); + + if (qdf_likely(vdev->peer_protocol_count_track)) + dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, + is_egress, is_rx); + + dp_vdev_unref_delete(soc, vdev); } #endif diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index ea804795d2..5c261018cd 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -2172,14 +2172,14 @@ static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc) * nbuf when it fails to send */ qdf_nbuf_t -dp_tx_send_exception(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf, +dp_tx_send_exception(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf, struct cdp_tx_exception_metadata *tx_exc_metadata) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); qdf_ether_header_t *eh = NULL; struct dp_tx_msdu_info_s msdu_info; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (qdf_unlikely(!vdev)) goto fail; @@ -2270,9 +2270,12 @@ dp_tx_send_exception(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf, nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info, tx_exc_metadata->peer_id, tx_exc_metadata); + dp_vdev_unref_delete(soc, vdev); return nbuf; fail: + if (vdev) + dp_vdev_unref_delete(soc, vdev); dp_verbose_debug("pkt send failed"); return nbuf; } @@ -2290,9 +2293,10 @@ fail: * nbuf when it fails to send */ #ifdef MESH_MODE_SUPPORT -qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, +qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, qdf_nbuf_t nbuf) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct meta_hdr_s *mhdr; qdf_nbuf_t nbuf_mesh = NULL; qdf_nbuf_t nbuf_clone = NULL; @@ -2306,8 +2310,7 @@ qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, return nbuf; } - vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "vdev is NULL for vdev_id %d", vdev_id); @@ -2331,13 +2334,14 @@ qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, if (!nbuf_clone) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "qdf_nbuf_clone failed"); + dp_vdev_unref_delete(soc, vdev); return nbuf; } qdf_nbuf_set_tx_ftype(nbuf_clone, CB_FTYPE_MESH_TX_INFO); } if (nbuf_clone) { - if (!dp_tx_send(soc, vdev_id, nbuf_clone)) { + if (!dp_tx_send(soc_hdl, vdev_id, nbuf_clone)) { DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1); } else { qdf_nbuf_free(nbuf_clone); @@ -2349,11 +2353,12 @@ qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, else qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_INVALID); - nbuf = dp_tx_send(soc, vdev_id, nbuf); + nbuf = dp_tx_send(soc_hdl, vdev_id, nbuf); if ((!nbuf) && no_enc_frame) { DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1); } + dp_vdev_unref_delete(soc, vdev); return nbuf; } @@ -2382,28 +2387,27 @@ qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, */ static inline -void dp_tx_nawds_handler(struct cdp_soc_t *soc, struct dp_vdev *vdev, +void dp_tx_nawds_handler(struct dp_soc *soc, struct dp_vdev *vdev, struct dp_tx_msdu_info_s *msdu_info, qdf_nbuf_t nbuf) { struct dp_peer *peer = NULL; qdf_nbuf_t nbuf_clone = NULL; - struct dp_soc *dp_soc = (struct dp_soc *)soc; uint16_t peer_id = DP_INVALID_PEER; uint16_t sa_peer_id = DP_INVALID_PEER; struct dp_ast_entry *ast_entry = NULL; qdf_ether_header_t *eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); if (qdf_nbuf_get_tx_ftype(nbuf) == CB_FTYPE_INTRABSS_FWD) { - qdf_spin_lock_bh(&dp_soc->ast_lock); + qdf_spin_lock_bh(&soc->ast_lock); ast_entry = dp_peer_ast_hash_find_by_pdevid - (dp_soc, + (soc, (uint8_t *)(eh->ether_shost), vdev->pdev->pdev_id); if (ast_entry) sa_peer_id = ast_entry->peer_id; - qdf_spin_unlock_bh(&dp_soc->ast_lock); + qdf_spin_unlock_bh(&soc->ast_lock); } qdf_spin_lock_bh(&vdev->peer_list_lock); @@ -2462,17 +2466,29 @@ void dp_tx_nawds_handler(struct cdp_soc_t *soc, struct dp_vdev *vdev, * Return: NULL on success, * nbuf when it fails to send */ -qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf) +qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); uint16_t peer_id = HTT_INVALID_PEER; /* * doing a memzero is causing additional function call overhead * so doing static stack clearing */ struct dp_tx_msdu_info_s msdu_info = {0}; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, - vdev_id); + struct dp_vdev *vdev = NULL; + + if (qdf_unlikely(vdev_id >= MAX_VDEV_CNT)) + return nbuf; + + /* + * dp_vdev_get_ref_by_id does does a atomic operation avoid using + * this in per packet path. + * + * As in this path vdev memory is already protected with netdev + * tx lock + */ + vdev = soc->vdev_id_map[vdev_id]; if (qdf_unlikely(!vdev)) return nbuf; @@ -4123,7 +4139,7 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) { dp_err("vdev handle for id %d is NULL", vdev_id); @@ -4132,6 +4148,7 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, if (tx_spec & OL_TX_SPEC_NO_FREE) vdev->is_tdls_frame = true; + dp_vdev_unref_delete(soc, vdev); return dp_tx_send(soc_hdl, vdev_id, msdu_list); } diff --git a/dp/wifi3.0/dp_tx_desc.h b/dp/wifi3.0/dp_tx_desc.h index 39ddfd9727..3539a98f1e 100644 --- a/dp/wifi3.0/dp_tx_desc.h +++ b/dp/wifi3.0/dp_tx_desc.h @@ -526,16 +526,18 @@ static inline bool dp_tx_desc_thresh_reached(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, - vdev_id); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id); struct dp_tx_desc_pool_s *pool; + bool status; if (!vdev) return false; pool = vdev->pool; + status = dp_tx_is_threshold_reached(pool, pool->avail_desc); + dp_vdev_unref_delete(soc, vdev); - return dp_tx_is_threshold_reached(pool, pool->avail_desc); + return status; } #else /* QCA_LL_TX_FLOW_CONTROL_V2 */ diff --git a/dp/wifi3.0/dp_tx_flow_control.c b/dp/wifi3.0/dp_tx_flow_control.c index aecc68e174..66c608d9d5 100644 --- a/dp/wifi3.0/dp_tx_flow_control.c +++ b/dp/wifi3.0/dp_tx_flow_control.c @@ -342,10 +342,11 @@ int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool, pool->status = FLOW_POOL_INVALID; qdf_spin_unlock_bh(&pool->flow_pool_lock); /* Reset TX desc associated to this Vdev as NULL */ - vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, - pool->flow_pool_id); - if (vdev) + vdev = dp_vdev_get_ref_by_id(soc, pool->flow_pool_id); + if (vdev) { dp_tx_desc_flush(vdev->pdev, vdev, false); + dp_vdev_unref_delete(soc, vdev); + } dp_err("avail desc less than pool size"); return -EAGAIN; } @@ -371,7 +372,7 @@ static void dp_tx_flow_pool_vdev_map(struct dp_pdev *pdev, struct dp_vdev *vdev; struct dp_soc *soc = pdev->soc; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s: invalid vdev_id %d", @@ -384,6 +385,7 @@ static void dp_tx_flow_pool_vdev_map(struct dp_pdev *pdev, pool->pool_owner_ctx = soc; pool->flow_pool_id = vdev_id; qdf_spin_unlock_bh(&pool->flow_pool_lock); + dp_vdev_unref_delete(soc, vdev); } /** @@ -400,7 +402,7 @@ static void dp_tx_flow_pool_vdev_unmap(struct dp_pdev *pdev, struct dp_vdev *vdev; struct dp_soc *soc = pdev->soc; - vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + vdev = dp_vdev_get_ref_by_id(soc, vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s: invalid vdev_id %d", @@ -409,6 +411,7 @@ static void dp_tx_flow_pool_vdev_unmap(struct dp_pdev *pdev, } vdev->pool = NULL; + dp_vdev_unref_delete(soc, vdev); } /** diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index b2f624b6e9..e5752b2f85 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1508,6 +1508,8 @@ struct dp_soc { struct dp_last_op_info last_op_info; TAILQ_HEAD(, dp_peer) inactive_peer_list; qdf_spinlock_t inactive_peer_list_lock; + /* lock to protect vdev_id_map table*/ + qdf_spinlock_t vdev_map_lock; }; #ifdef IPA_OFFLOAD