diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index c80c9cbf1a..87d6cd958a 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -363,6 +363,34 @@ static inline void cdp_peer_setup peer); } +/* + * cdp_cp_peer_del_response - Call the peer delete response handler + * @soc: Datapath SOC handle + * @vdev_hdl: virtual device object + * @peer_mac_addr: Mac address of the peer + * + * Return: void + */ +static inline void cdp_cp_peer_del_response + (ol_txrx_soc_handle soc, + struct cdp_vdev *vdev_hdl, + uint8_t *peer_mac_addr) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_cp_peer_del_response) + return; + + return soc->ops->cmn_drv_ops->txrx_cp_peer_del_response(soc, + vdev_hdl, + peer_mac_addr); +} /** * cdp_peer_get_ast_info_by_soc() - search the soc AST hash table * and return ast entry information diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 53298638a0..e96305eec2 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -99,6 +99,10 @@ struct cdp_cmn_ops { void (*txrx_peer_setup) (struct cdp_vdev *vdev_hdl, void *peer_hdl); + void (*txrx_cp_peer_del_response) + (ol_txrx_soc_handle soc, struct cdp_vdev *vdev_hdl, + uint8_t *peer_mac_addr); + void (*txrx_peer_teardown) (struct cdp_vdev *vdev_hdl, void *peer_hdl); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9810723819..6faf60fbf3 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5163,6 +5163,67 @@ static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl) return; } +/* + * dp_cp_peer_del_resp_handler - Handle the peer delete response + * @soc_hdl: Datapath SOC handle + * @vdev_hdl: virtual device object + * @mac_addr: Mac address of the peer + * + * Return: void + */ +static void dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, + struct cdp_vdev *vdev_hdl, + uint8_t *mac_addr) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_ast_entry *ast_entry = NULL; + struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; + txrx_ast_free_cb cb = NULL; + void *cookie; + + qdf_spin_lock_bh(&soc->ast_lock); + + if (soc->ast_override_support) + ast_entry = + dp_peer_ast_hash_find_by_pdevid(soc, mac_addr, + vdev->pdev->pdev_id); + else + ast_entry = dp_peer_ast_hash_find_soc(soc, mac_addr); + + /* in case of qwrap we have multiple BSS peers + * with same mac address + * + * AST entry for this mac address will be created + * only for one peer hence it will be NULL here + */ + if (!ast_entry || ast_entry->peer || !ast_entry->delete_in_progress) { + qdf_spin_unlock_bh(&soc->ast_lock); + return; + } + + if (ast_entry->is_mapped) + soc->ast_table[ast_entry->ast_idx] = NULL; + + DP_STATS_INC(soc, ast.deleted, 1); + dp_peer_ast_hash_remove(soc, ast_entry); + + cb = ast_entry->callback; + cookie = ast_entry->cookie; + ast_entry->callback = NULL; + ast_entry->cookie = NULL; + + soc->num_ast_entries--; + qdf_spin_unlock_bh(&soc->ast_lock); + + if (cb) { + cb(soc->ctrl_psoc, + soc, + cookie, + CDP_TXRX_AST_DELETED); + } + qdf_mem_free(ast_entry); +} + /* * dp_set_vdev_tx_encap_type() - set the encap type of the vdev * @vdev_handle: virtual device object @@ -9804,6 +9865,8 @@ static struct cdp_cmn_ops dp_ops_cmn = { .set_vdev_pcp_tid_map = dp_set_vdev_pcp_tid_map_wifi3, .set_vdev_tidmap_prty = dp_set_vdev_tidmap_prty_wifi3, .set_vdev_tidmap_tbl_id = dp_set_vdev_tidmap_tbl_id_wifi3, + + .txrx_cp_peer_del_response = dp_cp_peer_del_resp_handler, }; static struct cdp_ctrl_ops dp_ops_ctrl = { diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index bb280f6392..a8d5cae045 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -360,8 +360,8 @@ static inline void dp_peer_ast_hash_add(struct dp_soc *soc, * * Return: None */ -static inline void dp_peer_ast_hash_remove(struct dp_soc *soc, - struct dp_ast_entry *ase) +void dp_peer_ast_hash_remove(struct dp_soc *soc, + struct dp_ast_entry *ase) { unsigned index; struct dp_ast_entry *tmpase; @@ -823,8 +823,12 @@ add_ast_entry: */ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) { - struct dp_peer *peer = ast_entry->peer; - uint16_t peer_id = peer->peer_ids[0]; + struct dp_peer *peer; + + if (!ast_entry) + return; + + peer = ast_entry->peer; dp_peer_ast_send_wds_del(soc, ast_entry); @@ -836,7 +840,7 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) * if peer_id is invalid we did not get the peer map event * for the peer free ast entry from here only in this case */ - if (soc->is_peer_map_unmap_v2 && (peer_id != HTT_INVALID_PEER)) { + if (soc->is_peer_map_unmap_v2) { /* * For HM_SEC and SELF type we do not receive unmap event @@ -853,10 +857,10 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) */ if (ast_entry->is_mapped) soc->ast_table[ast_entry->ast_idx] = NULL; - TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); - if (ast_entry == peer->self_ast_entry) - peer->self_ast_entry = NULL; + /* SELF and STATIC entries are removed in teardown itself */ + if (ast_entry->next_hop) + TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); DP_STATS_INC(soc, ast.deleted, 1); dp_peer_ast_hash_remove(soc, ast_entry); @@ -1053,6 +1057,13 @@ void dp_peer_ast_send_wds_del(struct dp_soc *soc, ast_entry->type); } + /* Remove SELF and STATIC entries in teardown itself */ + if (!ast_entry->next_hop) { + TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); + peer->self_ast_entry = NULL; + ast_entry->peer = NULL; + } + ast_entry->delete_in_progress = true; } @@ -1503,54 +1514,27 @@ dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, /* If V2 Peer map messages are enabled AST entry has to be freed here */ - if (soc->is_peer_map_unmap_v2) { + if (soc->is_peer_map_unmap_v2 && is_wds) { qdf_spin_lock_bh(&soc->ast_lock); ast_entry = dp_peer_ast_list_find(soc, peer, mac_addr); - - if (!ast_entry) { - /* in case of qwrap we have multiple BSS peers - * with same mac address - * - * AST entry for this mac address will be created - * only for one peer - */ - if (peer->vdev->proxysta_vdev) { - qdf_spin_unlock_bh(&soc->ast_lock); - goto peer_unmap; - } - - /* Ideally we should not enter this case where - * ast_entry is not present in host table and - * we received a unmap event - */ - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s:%d AST entry not found with peer %pK peer_id %u peer_mac %pM mac_addr %pM vdev_id %u next_hop %u\n", - __func__, __LINE__, peer, peer->peer_ids[0], - peer->mac_addr.raw, mac_addr, vdev_id, - is_wds); - - qdf_spin_unlock_bh(&soc->ast_lock); - - if (!is_wds) - goto peer_unmap; - - return; - } qdf_spin_unlock_bh(&soc->ast_lock); - /* Reuse the AST entry if delete_in_progress - * not set - */ - if (ast_entry->delete_in_progress) + if (ast_entry) { dp_peer_ast_free_entry(soc, ast_entry); - - if (is_wds) return; + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s:%d AST entry not found with peer %pK peer_id %u peer_mac %pM mac_addr %pM vdev_id %u next_hop %u\n", + __func__, __LINE__, peer, peer->peer_ids[0], + peer->mac_addr.raw, mac_addr, vdev_id, + is_wds); + + return; } -peer_unmap: QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, "peer_unmap_event (soc:%pK) peer_id %d peer %pK", soc, peer_id, peer); diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 3458cab568..6eed9aab0d 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -145,6 +145,9 @@ void dp_peer_free_hmwds_cb(void *ctrl_psoc, void *cookie, enum cdp_ast_free_status status); +void dp_peer_ast_hash_remove(struct dp_soc *soc, + struct dp_ast_entry *ase); + /* * dp_get_vdev_from_soc_vdev_id_wifi3() - * Returns vdev object given the vdev id