diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index cb38ed552e..11413e8fa4 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5589,43 +5589,35 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, return QDF_STATUS_SUCCESS; } -#if ATH_SUPPORT_WRAP static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev, uint8_t *peer_mac_addr) { struct dp_peer *peer; + struct dp_soc *soc = vdev->pdev->soc; - peer = dp_peer_find_hash_find(vdev->pdev->soc, peer_mac_addr, - 0, vdev->vdev_id, - DP_MOD_ID_CONFIG); - if (!peer) - return NULL; + qdf_spin_lock_bh(&soc->inactive_peer_list_lock); + TAILQ_FOREACH(peer, &soc->inactive_peer_list, + inactive_list_elem) { - if (peer->bss_peer) - return peer; + /* reuse bss peer only when vdev matches*/ + if (peer->bss_peer && (peer->vdev == vdev) && + qdf_mem_cmp(peer_mac_addr, peer->mac_addr.raw, + QDF_MAC_ADDR_SIZE) == 0) { + /* increment ref count for cdp_peer_create*/ + if (dp_peer_get_ref(soc, peer, DP_MOD_ID_CONFIG) == + QDF_STATUS_SUCCESS) { + TAILQ_REMOVE(&soc->inactive_peer_list, peer, + inactive_list_elem); + qdf_spin_unlock_bh + (&soc->inactive_peer_list_lock); + return peer; + } + } + } - dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG); + qdf_spin_unlock_bh(&soc->inactive_peer_list_lock); return NULL; } -#else -static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev, - uint8_t *peer_mac_addr) -{ - struct dp_peer *peer; - - peer = dp_peer_find_hash_find(vdev->pdev->soc, peer_mac_addr, - 0, vdev->vdev_id, - DP_MOD_ID_CONFIG); - if (!peer) - return NULL; - - if (peer->bss_peer && (peer->vdev->vdev_id == vdev->vdev_id)) - return peer; - - dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG); - return NULL; -} -#endif #ifdef FEATURE_AST static inline void dp_peer_ast_handle_roam_del(struct dp_soc *soc, @@ -5699,9 +5691,15 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, peer = dp_peer_can_reuse(vdev, peer_mac_addr); if (peer) { + dp_peer_vdev_list_add(soc, vdev, peer); + + dp_peer_find_hash_add(soc, peer); qdf_atomic_init(&peer->is_default_route_set); dp_peer_cleanup(vdev, peer); + for (i = 0; i < DP_MAX_TIDS; i++) + qdf_spinlock_create(&peer->rx_tid[i].tid_lock); + qdf_spin_lock_bh(&soc->ast_lock); dp_peer_delete_ast_entries(soc, peer); qdf_spin_unlock_bh(&soc->ast_lock); @@ -5871,6 +5869,7 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, dp_set_peer_isolation(peer, false); + qdf_spinlock_create(&peer->peer_state_lock); dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT); dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); @@ -6557,7 +6556,7 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id) struct cdp_peer_cookie peer_cookie; struct dp_peer *tmp_peer; bool found = false; - int tid; + int tid = 0; if (mod_id > DP_MOD_ID_RX) QDF_ASSERT(qdf_atomic_dec_return(&peer->mod_refs[mod_id]) >= 0); @@ -6623,9 +6622,12 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id) DP_AST_ASSERT(TAILQ_EMPTY(&peer->ast_entry_list)); dp_peer_update_state(soc, peer, DP_PEER_STATE_FREED); + /* cleanup the peer data */ + dp_peer_cleanup(vdev, peer); for (tid = 0; tid < DP_MAX_TIDS; tid++) qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock); + qdf_spinlock_destroy(&peer->peer_state_lock); qdf_mem_free(peer); /* @@ -6704,6 +6706,11 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, dp_peer_vdev_list_remove(soc, vdev, peer); + qdf_spin_lock_bh(&soc->inactive_peer_list_lock); + TAILQ_INSERT_TAIL(&soc->inactive_peer_list, peer, + inactive_list_elem); + qdf_spin_unlock_bh(&soc->inactive_peer_list_lock); + /* * Remove the reference added during peer_attach. * The peer will still be left allocated until the @@ -10064,9 +10071,6 @@ dp_peer_teardown_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, return QDF_STATUS_E_FAILURE; } - if (peer->peer_state == DP_PEER_STATE_INIT) - dp_peer_cleanup(peer->vdev, peer); - qdf_spin_lock_bh(&soc->ast_lock); dp_peer_delete_ast_entries(soc, peer); diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 42e0c8a829..e8fccd7606 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -890,7 +890,7 @@ QDF_STATUS dp_peer_add_ast(struct dp_soc *soc, qdf_spin_lock_bh(&soc->ast_lock); - if (peer->peer_state != DP_PEER_STATE_ACTIVE) { + if (!dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE)) { if ((type != CDP_TXRX_AST_TYPE_STATIC) && (type != CDP_TXRX_AST_TYPE_SELF)) { qdf_spin_unlock_bh(&soc->ast_lock); @@ -1319,7 +1319,7 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, * 3) We did not get the HTT map for create event */ if (ast_entry->delete_in_progress || - (peer->peer_state != DP_PEER_STATE_ACTIVE) || + !dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE) || !ast_entry->is_mapped) return ret; @@ -1983,7 +1983,7 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, * if peer is in logical delete CP triggered delete before map * is received ignore this event */ - if (peer->peer_state == DP_PEER_STATE_LOGICAL_DELETE) { + if (dp_peer_state_cmp(peer, DP_PEER_STATE_LOGICAL_DELETE)) { dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG); dp_alert("Peer %pK["QDF_MAC_ADDR_FMT"] logical delete state vid %d", peer, QDF_MAC_ADDR_REF(peer_mac_addr), @@ -2171,14 +2171,8 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id, } vdev = peer->vdev; - /* cleanup the peer data */ - dp_peer_cleanup(vdev, peer); DP_UPDATE_STATS(vdev, peer); - qdf_spin_lock_bh(&soc->inactive_peer_list_lock); - TAILQ_INSERT_TAIL(&soc->inactive_peer_list, peer, inactive_list_elem); - qdf_spin_unlock_bh(&soc->inactive_peer_list_lock); - dp_peer_update_state(soc, peer, DP_PEER_STATE_INACTIVE); dp_peer_unref_delete(peer, DP_MOD_ID_HTT); /* diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 2530972731..0920af0586 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -434,6 +434,28 @@ dp_soc_iterate_peer_lock_safe(struct dp_soc *soc, } while (0) #endif +/** + * dp_peer_state_cmp() - compare dp peer state + * + * @peer : DP peer + * @state : state + * + * Return: true if state matches with peer state + * false if it does not match + */ +static inline bool +dp_peer_state_cmp(struct dp_peer *peer, + enum dp_peer_state state) +{ + bool is_status_equal = false; + + qdf_spin_lock_bh(&peer->peer_state_lock); + is_status_equal = (peer->peer_state == state); + qdf_spin_unlock_bh(&peer->peer_state_lock); + + return is_status_equal; +} + /** * dp_peer_update_state() - update dp peer state * @@ -448,7 +470,10 @@ dp_peer_update_state(struct dp_soc *soc, struct dp_peer *peer, enum dp_peer_state state) { - uint8_t peer_state = peer->peer_state; + uint8_t peer_state; + + qdf_spin_lock_bh(&peer->peer_state_lock); + peer_state = peer->peer_state; switch (state) { case DP_PEER_STATE_INIT: @@ -488,12 +513,14 @@ dp_peer_update_state(struct dp_soc *soc, default: dp_alert("Invalid peer state %u for peer "QDF_MAC_ADDR_FMT, state, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); + qdf_spin_unlock_bh(&peer->peer_state_lock); return; } dp_info("Updating peer state from %u to %u mac "QDF_MAC_ADDR_FMT"\n", peer_state, state, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); peer->peer_state = state; + qdf_spin_unlock_bh(&peer->peer_state_lock); } void dp_print_ast_stats(struct dp_soc *soc); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 1c44309edd..474c81ade5 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -177,29 +177,29 @@ enum dp_peer_state { * enum for modules ids of */ enum dp_mod_id { - DP_MOD_ID_TX_COMP, - DP_MOD_ID_RX, - DP_MOD_ID_HTT_COMP, - DP_MOD_ID_RX_ERR, - DP_MOD_ID_TX_PPDU_STATS, - DP_MOD_ID_RX_PPDU_STATS, - DP_MOD_ID_CDP, - DP_MOD_ID_GENERIC_STATS, - DP_MOD_ID_TX_MULTIPASS, - DP_MOD_ID_TX_CAPTURE, - DP_MOD_ID_NSS_OFFLOAD, - DP_MOD_ID_CONFIG, - DP_MOD_ID_HTT, - DP_MOD_ID_IPA, - DP_MOD_ID_AST, - DP_MOD_ID_MCAST2UCAST, - DP_MOD_ID_CHILD, - DP_MOD_ID_MESH, - DP_MOD_ID_TX_EXCEPTION, - DP_MOD_ID_TDLS, - DP_MOD_ID_MISC, - DP_MOD_ID_MSCS, - DP_MOD_ID_MAX, + DP_MOD_ID_TX_COMP = 0, + DP_MOD_ID_RX = 1, + DP_MOD_ID_HTT_COMP = 2, + DP_MOD_ID_RX_ERR = 3, + DP_MOD_ID_TX_PPDU_STATS = 4, + DP_MOD_ID_RX_PPDU_STATS = 5, + DP_MOD_ID_CDP = 6, + DP_MOD_ID_GENERIC_STATS = 7, + DP_MOD_ID_TX_MULTIPASS = 8, + DP_MOD_ID_TX_CAPTURE = 9, + DP_MOD_ID_NSS_OFFLOAD = 10, + DP_MOD_ID_CONFIG = 11, + DP_MOD_ID_HTT = 12, + DP_MOD_ID_IPA = 13, + DP_MOD_ID_AST = 14, + DP_MOD_ID_MCAST2UCAST = 15, + DP_MOD_ID_CHILD = 16, + DP_MOD_ID_MESH = 17, + DP_MOD_ID_TX_EXCEPTION = 18, + DP_MOD_ID_TDLS = 19, + DP_MOD_ID_MISC = 20, + DP_MOD_ID_MSCS = 21, + DP_MOD_ID_MAX = 22, }; #define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \ @@ -2291,9 +2291,6 @@ struct dp_vdev { /* Rx Decapsulation type for this VAP */ enum htt_cmn_pkt_type rx_decap_type; - /* BSS peer */ - struct dp_peer *vap_bss_peer; - /* WDS enabled */ bool wds_enabled; @@ -2736,6 +2733,7 @@ struct dp_peer { qdf_atomic_t mod_refs[DP_MOD_ID_MAX]; uint8_t peer_state; + qdf_spinlock_t peer_state_lock; #ifdef WLAN_SUPPORT_MSCS struct dp_peer_mscs_parameter mscs_ipv4_parameter, mscs_ipv6_parameter; bool mscs_active;