diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 86cb09792e..3ca2598682 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -1313,7 +1313,6 @@ static void dp_print_peer_table(struct dp_vdev *vdev) " wds_enabled = %d" " tx_cap_enabled = %d" " rx_cap_enabled = %d" - " delete in progress = %d" " peer id = %d", peer->mac_addr.raw, peer->nawds_enabled, @@ -1321,7 +1320,6 @@ static void dp_print_peer_table(struct dp_vdev *vdev) peer->wds_enabled, peer->tx_cap_enabled, peer->rx_cap_enabled, - peer->delete_in_progress, peer->peer_id); } qdf_spin_unlock_bh(&vdev->peer_list_lock); @@ -5423,7 +5421,6 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, qdf_spin_lock_bh(&soc->ast_lock); dp_peer_delete_ast_entries(soc, peer); - peer->delete_in_progress = false; qdf_spin_unlock_bh(&soc->ast_lock); if ((vdev->opmode == wlan_op_mode_sta) && @@ -5453,6 +5450,8 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, for (i = 0; i < DP_MAX_TIDS; i++) qdf_spinlock_create(&peer->rx_tid[i].tid_lock); + + dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT); return QDF_STATUS_SUCCESS; } else { /* @@ -5587,6 +5586,9 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, dp_peer_tx_capture_filter_check(pdev, peer); dp_set_peer_isolation(peer, false); + + dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT); + return QDF_STATUS_SUCCESS; } @@ -6245,10 +6247,8 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_peer_mod_id mod_id) inactive_list_elem); /* delete this peer from the list */ qdf_spin_unlock_bh(&soc->inactive_peer_list_lock); - /* - * Peer AST list hast to be empty here - */ DP_AST_ASSERT(TAILQ_EMPTY(&peer->ast_entry_list)); + dp_peer_update_state(soc, peer, DP_PEER_STATE_FREED); qdf_mem_free(peer); @@ -6288,7 +6288,6 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, 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; @@ -9418,9 +9417,13 @@ 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); - peer->delete_in_progress = true; dp_peer_delete_ast_entries(soc, peer); + + dp_peer_update_state(soc, peer, DP_PEER_STATE_LOGICAL_DELETE); qdf_spin_unlock_bh(&soc->ast_lock); dp_peer_unref_delete(peer, DP_MOD_ID_CDP); diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 068b8a9379..8f97689396 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -885,9 +885,13 @@ QDF_STATUS dp_peer_add_ast(struct dp_soc *soc, is_peer_found = dp_peer_exist_on_pdev(soc, mac_addr, 0, pdev); qdf_spin_lock_bh(&soc->ast_lock); - if (peer->delete_in_progress) { - qdf_spin_unlock_bh(&soc->ast_lock); - return QDF_STATUS_E_BUSY; + + if (peer->peer_state != DP_PEER_STATE_ACTIVE) { + if ((type != CDP_TXRX_AST_TYPE_STATIC) && + (type != CDP_TXRX_AST_TYPE_SELF)) { + qdf_spin_unlock_bh(&soc->ast_lock); + return QDF_STATUS_E_BUSY; + } } QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -1296,7 +1300,8 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, * 2) Peer delete is already triggered * 3) We did not get the HTT map for create event */ - if (ast_entry->delete_in_progress || peer->delete_in_progress || + if (ast_entry->delete_in_progress || + (peer->peer_state != DP_PEER_STATE_ACTIVE) || !ast_entry->is_mapped) return ret; @@ -1936,6 +1941,16 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, "%s: ref_cnt: %d", __func__, qdf_atomic_read(&peer->ref_cnt)); + /* + * 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) { + dp_peer_unref_delete(peer, DP_MOD_ID_PEER_CONFIG); + dp_alert("Peer %pK[%pM] logical delete state vid %d", + peer, peer_mac_addr, vdev_id); + return NULL; + } dp_peer_find_id_to_obj_add(soc, peer, peer_id); if (peer->peer_id == HTT_INVALID_PEER) { peer->peer_id = peer_id; @@ -1944,6 +1959,7 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, QDF_ASSERT(0); } + dp_peer_update_state(soc, peer, DP_PEER_STATE_ACTIVE); return peer; } @@ -2119,6 +2135,8 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id, 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); /* * Remove a reference to the peer. * If there are no more references, delete the peer object. @@ -2298,8 +2316,7 @@ QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, uint32_t alloc_tries = 0; QDF_STATUS err = QDF_STATUS_SUCCESS; - if (peer->delete_in_progress || - !qdf_atomic_read(&peer->is_default_route_set)) + if (!qdf_atomic_read(&peer->is_default_route_set)) return QDF_STATUS_E_FAILURE; rx_tid->ba_win_size = ba_window_size; diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 4271019e4f..7d87257dcc 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -90,7 +90,7 @@ struct dp_peer *dp_peer_get_ref_by_id(struct dp_soc *soc, qdf_spin_lock_bh(&soc->peer_map_lock); peer = __dp_peer_find_by_id(soc, peer_id); - if (!peer || peer->delete_in_progress || + if (!peer || peer->peer_state >= DP_PEER_STATE_LOGICAL_DELETE || (dp_peer_get_ref(soc, peer, mod_id) != QDF_STATUS_SUCCESS)) { qdf_spin_unlock_bh(&soc->peer_map_lock); return NULL; @@ -126,6 +126,62 @@ dp_clear_peer_internal(struct dp_soc *soc, struct dp_peer *peer) dp_rx_flush_rx_cached(peer, true); } +/** + * dp_peer_update_state() - update dp peer state + * + * @soc : core DP soc context + * @peer : DP peer + * @state : new state + * + * Return: None + */ +static inline void +dp_peer_update_state(struct dp_soc *soc, + struct dp_peer *peer, + enum dp_peer_state state) +{ + uint8_t peer_state = peer->peer_state; + + switch (state) { + case DP_PEER_STATE_INIT: + QDF_ASSERT + ((peer_state != DP_PEER_STATE_ACTIVE) || + (peer_state != DP_PEER_STATE_LOGICAL_DELETE)); + break; + + case DP_PEER_STATE_ACTIVE: + QDF_ASSERT(peer_state == DP_PEER_STATE_INIT); + break; + + case DP_PEER_STATE_LOGICAL_DELETE: + QDF_ASSERT((peer_state == DP_PEER_STATE_ACTIVE) || + (peer_state == DP_PEER_STATE_INIT)); + break; + + case DP_PEER_STATE_INACTIVE: + QDF_ASSERT(peer_state == DP_PEER_STATE_LOGICAL_DELETE); + break; + + case DP_PEER_STATE_FREED: + if (peer->sta_self_peer) + QDF_ASSERT(peer_state == + DP_PEER_STATE_INIT); + else + QDF_ASSERT((peer_state == + DP_PEER_STATE_INACTIVE) || + (peer_state == + DP_PEER_STATE_LOGICAL_DELETE)); + break; + + default: + QDF_ASSERT(0); + break; + } + qdf_info("Updating peer state from %u to %u mac %pM\n", + peer_state, state, peer->mac_addr.raw); + peer->peer_state = state; +} + void dp_print_ast_stats(struct dp_soc *soc); QDF_STATUS dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, uint16_t hw_peer_id, uint8_t vdev_id, diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index b4a5c791bd..1538ed95d7 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -6054,10 +6054,6 @@ dp_aggregate_pdev_ctrl_frames_stats(struct dp_pdev *pdev) TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { - if (peer->delete_in_progress) { - dp_err("DP Peer deletion in progress"); - continue; - } if (dp_peer_get_ref(pdev->soc, peer, DP_MOD_ID_GENERIC_STATS) != QDF_STATUS_SUCCESS) diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index f5d18564d2..9693bd8dfe 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -148,6 +148,19 @@ struct dp_rx_fst; struct dp_mon_filter; struct dp_mon_mpdu; +/** + * enum for DP peer state + */ +enum dp_peer_state { + DP_PEER_STATE_NONE, + DP_PEER_STATE_INIT, + DP_PEER_STATE_ACTIVE, + DP_PEER_STATE_LOGICAL_DELETE, + DP_PEER_STATE_INACTIVE, + DP_PEER_STATE_FREED, + DP_PEER_STATE_INVALID, +}; + /** * enum for modules ids of peer reference */ @@ -2413,7 +2426,7 @@ struct dp_peer { rx_cap_enabled:1, /* Peer's rx-capture is enabled */ valid:1, /* valid bit */ in_twt:1, /* in TWT session */ - delete_in_progress:1, /*delete_in_progress bit*/ + delete_in_progress:1, /* Indicate kickout sent */ sta_self_peer:1; /* Indicate STA self peer */ #ifdef QCA_SUPPORT_PEER_ISOLATION @@ -2486,6 +2499,8 @@ struct dp_peer { TAILQ_ENTRY(dp_peer) inactive_list_elem; qdf_atomic_t mod_refs[DP_MOD_ID_MAX]; + + uint8_t peer_state; }; /*