diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c index cd09db62beb0..eaf4e3770b8d 100644 --- a/dp/wifi3.0/dp_ipa.c +++ b/dp/wifi3.0/dp_ipa.c @@ -1717,7 +1717,7 @@ static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev, struct dp_peer *vdev_peer; uint16_t len; - vdev_peer = vdev->vap_bss_peer; + vdev_peer = dp_vdev_bss_peer_ref_n_get(pdev->soc, vdev); if (qdf_unlikely(!vdev_peer)) return nbuf; @@ -1726,10 +1726,12 @@ static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev, if (dp_tx_send((struct cdp_soc_t *)pdev->soc, vdev->vdev_id, nbuf)) { DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.fail, 1, len); + dp_peer_unref_delete(vdev_peer); return nbuf; } DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.pkts, 1, len); + dp_peer_unref_delete(vdev_peer); return NULL; } diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index c003143a3167..b07b3893d52a 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5197,6 +5197,7 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, struct dp_pdev *pdev; 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); if (!vdev) @@ -5204,14 +5205,11 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, pdev = vdev->pdev; - if (wlan_op_mode_sta == vdev->opmode) { - if (vdev->vap_self_peer) - dp_peer_delete_wifi3((struct cdp_soc_t *)soc, - vdev->vdev_id, - vdev->vap_self_peer->mac_addr.raw, - 0); - else - dp_err("vdev self peer is NULL"); + vap_self_peer = dp_sta_vdev_self_peer_ref_n_get(soc, vdev); + if (vap_self_peer) { + dp_peer_delete_wifi3((struct cdp_soc_t *)soc, vdev->vdev_id, + vap_self_peer->mac_addr.raw, 0); + dp_peer_unref_delete(vap_self_peer); } /* @@ -5563,13 +5561,12 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, (wlan_op_mode_sta != vdev->opmode)) { dp_info("vdev bss_peer!!"); peer->bss_peer = 1; - vdev->vap_bss_peer = peer; } if (wlan_op_mode_sta == vdev->opmode && qdf_mem_cmp(peer->mac_addr.raw, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE) == 0) { - vdev->vap_self_peer = peer; + peer->sta_self_peer = 1; } for (i = 0; i < DP_MAX_TIDS; i++) @@ -6146,35 +6143,6 @@ dp_peer_authorize(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, return status; } -/* - * dp_vdev_reset_peer() - Update peer related member in vdev - as peer is going to free - * @vdev: datapath vdev handle - * @peer: dataptah peer handle - * - * Return: None - */ -static void dp_vdev_reset_peer(struct dp_vdev *vdev, - struct dp_peer *peer) -{ - struct dp_peer *bss_peer = NULL; - - if (!vdev) { - dp_err("vdev is NULL"); - } else { - if (vdev->vap_bss_peer == peer) { - vdev->vap_bss_peer = NULL; - qdf_mem_zero(vdev->vap_bss_peer_mac_addr, - QDF_MAC_ADDR_SIZE); - } - - if (vdev && vdev->vap_bss_peer) { - bss_peer = vdev->vap_bss_peer; - DP_UPDATE_STATS(vdev, peer); - } - } -} - /* * dp_peer_release_mem() - free dp peer handle memory * @soc: dataptah soc handle @@ -6345,8 +6313,8 @@ void dp_peer_unref_delete(struct dp_peer *peer) /* cleanup the peer data */ dp_peer_cleanup(vdev, peer, false); - /* reset this peer related info in vdev */ - dp_vdev_reset_peer(vdev, peer); + if (!peer->bss_peer) + DP_UPDATE_STATS(vdev, peer); /* save vdev related member in case vdev freed */ vdev_opmode = vdev->opmode; qdf_mem_copy(vdev_mac_addr, vdev->mac_addr.raw, @@ -10460,39 +10428,6 @@ dp_txrx_post_data_stall_event(struct cdp_soc_t *soc_hdl, } #endif /* WLAN_SUPPORT_DATA_STALL */ -#ifdef DP_PEER_EXTENDED_API -/** - * dp_peer_get_ref_find_by_addr - get peer with addr by ref count inc - * @dev: physical device instance - * @peer_mac_addr: peer mac address - * @debug_id: to track enum peer access - * - * Return: peer instance pointer - */ -static void * -dp_peer_get_ref_find_by_addr(struct cdp_pdev *dev, uint8_t *peer_mac_addr, - enum peer_debug_id_type debug_id) -{ - struct dp_pdev *pdev = (struct dp_pdev *)dev; - struct dp_peer *peer; - - peer = dp_peer_find_hash_find(pdev->soc, peer_mac_addr, 0, DP_VDEV_ALL); - - if (!peer) - return NULL; - - if (peer->delete_in_progress) { - dp_err("Peer deletion in progress"); - dp_peer_unref_delete(peer); - return NULL; - } - - dp_info_rl("peer %pK mac: %pM", peer, peer->mac_addr.raw); - - return peer; -} -#endif /* DP_PEER_EXTENDED_API */ - #ifdef WLAN_FEATURE_STATS_EXT /* rx hw stats event wait timeout in ms */ #define DP_REO_STATUS_STATS_TIMEOUT 1500 @@ -10594,8 +10529,7 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) return QDF_STATUS_E_INVAL; } - peer = dp_peer_get_ref_find_by_addr((struct cdp_pdev *)vdev->pdev, - vdev->vap_bss_peer_mac_addr, 0); + peer = dp_vdev_bss_peer_ref_n_get(soc, vdev); if (!peer) { dp_err("Peer is NULL"); diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 1e30f45cb819..9097371edfed 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -711,6 +711,7 @@ QDF_STATUS dp_peer_add_ast(struct dp_soc *soc, uint8_t next_node_mac[6]; txrx_ast_free_cb cb = NULL; void *cookie = NULL; + struct dp_peer *vap_bss_peer = NULL; bool is_peer_found = false; vdev = peer->vdev; @@ -916,7 +917,13 @@ add_ast_entry: ast_entry->type = CDP_TXRX_AST_TYPE_MEC; break; case CDP_TXRX_AST_TYPE_DA: - peer = peer->vdev->vap_bss_peer; + vap_bss_peer = dp_vdev_bss_peer_ref_n_get(soc, vdev); + if (!vap_bss_peer) { + qdf_spin_unlock_bh(&soc->ast_lock); + qdf_mem_free(ast_entry); + return QDF_STATUS_E_FAILURE; + } + peer = vap_bss_peer; ast_entry->next_hop = 1; ast_entry->type = CDP_TXRX_AST_TYPE_DA; break; @@ -953,11 +960,16 @@ add_ast_entry: next_node_mac, flags, ast_entry->type)) { + if (vap_bss_peer) + dp_peer_unref_delete(vap_bss_peer); qdf_spin_unlock_bh(&soc->ast_lock); return QDF_STATUS_SUCCESS; } } + if (vap_bss_peer) + dp_peer_unref_delete(vap_bss_peer); + qdf_spin_unlock_bh(&soc->ast_lock); return QDF_STATUS_E_FAILURE; } @@ -1781,10 +1793,6 @@ dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, QDF_MAC_ADDR_SIZE) != 0) { dp_info("STA vdev bss_peer!!!!"); peer->bss_peer = 1; - peer->vdev->vap_bss_peer = peer; - qdf_mem_copy(peer->vdev->vap_bss_peer_mac_addr, - peer->mac_addr.raw, - QDF_MAC_ADDR_SIZE); } if (peer->vdev->opmode == wlan_op_mode_sta) { @@ -4033,3 +4041,60 @@ bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id) return false; } + +/** + * dp_vdev_bss_peer_ref_n_get: Get bss peer of a vdev + * @soc: DP soc + * @vdev: vdev + * + * Return: VDEV BSS peer + */ +struct dp_peer *dp_vdev_bss_peer_ref_n_get(struct dp_soc *soc, + struct dp_vdev *vdev) +{ + struct dp_peer *peer; + + qdf_spin_lock_bh(&soc->peer_ref_mutex); + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + if (peer->bss_peer) + break; + } + + if (!peer || !qdf_atomic_inc_not_zero(&peer->ref_cnt)) { + qdf_spin_unlock_bh(&soc->peer_ref_mutex); + return NULL; + } + + qdf_spin_unlock_bh(&soc->peer_ref_mutex); + return peer; +} + +/** + * dp_sta_vdev_self_peer_ref_n_get: Get self peer of sta vdev + * @soc: DP soc + * @vdev: vdev + * + * Return: VDEV self peer + */ +struct dp_peer *dp_sta_vdev_self_peer_ref_n_get(struct dp_soc *soc, + struct dp_vdev *vdev) +{ + struct dp_peer *peer; + + if (vdev->opmode != wlan_op_mode_sta) + return NULL; + + qdf_spin_lock_bh(&soc->peer_ref_mutex); + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + if (peer->sta_self_peer) + break; + } + + if (!peer || !qdf_atomic_inc_not_zero(&peer->ref_cnt)) { + qdf_spin_unlock_bh(&soc->peer_ref_mutex); + return NULL; + } + + qdf_spin_unlock_bh(&soc->peer_ref_mutex); + return peer; +} diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 2c774c6b59e8..a83e36feb382 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -401,4 +401,8 @@ static inline void dp_peer_ext_stats_ctx_dealloc(struct dp_soc *soc, } #endif +struct dp_peer *dp_vdev_bss_peer_ref_n_get(struct dp_soc *soc, + struct dp_vdev *vdev); +struct dp_peer *dp_sta_vdev_self_peer_ref_n_get(struct dp_soc *soc, + struct dp_vdev *vdev); #endif /* _DP_PEER_H_ */ diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index ed2f1f809783..5a5fbf174c7c 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -2203,8 +2203,6 @@ struct dp_vdev { /* TIDmap priority */ uint8_t tidmap_prty; - /* Self Peer in STA mode */ - struct dp_peer *vap_self_peer; #ifdef QCA_MULTIPASS_SUPPORT uint16_t *iv_vlan_map; @@ -2230,10 +2228,6 @@ struct dp_vdev { bool peer_protocol_count_track; int peer_protocol_count_dropmask; #endif - - /* vap bss peer mac addr */ - uint8_t vap_bss_peer_mac_addr[QDF_MAC_ADDR_SIZE]; - /* callback to collect connectivity stats */ ol_txrx_stats_rx_fp stats_cb; @@ -2364,7 +2358,9 @@ struct dp_peer { tx_cap_enabled:1, /* Peer's tx-capture is enabled */ rx_cap_enabled:1, /* Peer's rx-capture is enabled */ valid:1, /* valid bit */ - in_twt:1; /* in TWT session */ + in_twt:1, /* in TWT session */ + delete_in_progress:1, /*delete_in_progress bit*/ + sta_self_peer:1; /* Indicate STA self peer */ #ifdef QCA_SUPPORT_PEER_ISOLATION bool isolation; /* enable peer isolation for this peer */ @@ -2387,7 +2383,6 @@ struct dp_peer { #ifdef WDS_VENDOR_EXTENSION dp_ecm_policy wds_ecm; #endif - bool delete_in_progress; /* Active Block ack sessions */ uint16_t active_ba_session_cnt;