From 64b4848aa0dc8c6d64f9bde186be87a93a3388e8 Mon Sep 17 00:00:00 2001 From: Radha Krishna Simha Jiguru Date: Mon, 23 Dec 2019 17:09:41 +0530 Subject: [PATCH] qcacmn: Do cleanup related to peer_map_unmap_v2 AST entry delete logic has some conditional checks making code with respect to HTT V1 and V2 messages making it tough to follow. Change-Id: I229324446134b32021a956fb689e4726256fcc28 --- dp/wifi3.0/dp_main.c | 6 +- dp/wifi3.0/dp_peer.c | 138 ++++++++++++++++++++++++++++--------------- dp/wifi3.0/dp_peer.h | 6 ++ 3 files changed, 100 insertions(+), 50 deletions(-) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 7f79080cbd..6851c970a7 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -6240,7 +6240,7 @@ void dp_peer_unref_delete(struct dp_peer *peer) struct cdp_peer_cookie peer_cookie; enum wlan_op_mode vdev_opmode; uint8_t vdev_mac_addr[QDF_MAC_ADDR_SIZE]; - + struct dp_ast_entry *peer_ast_entry = NULL; /* * Hold the lock all the way from checking if the peer ref count @@ -6272,7 +6272,9 @@ void dp_peer_unref_delete(struct dp_peer *peer) qdf_spin_lock_bh(&soc->ast_lock); if (peer->self_ast_entry) { - dp_peer_del_ast(soc, peer->self_ast_entry); + peer_ast_entry = peer->self_ast_entry; + dp_peer_unlink_ast_entry(soc, peer_ast_entry); + dp_peer_free_ast_entry(soc, peer_ast_entry); peer->self_ast_entry = NULL; } qdf_spin_unlock_bh(&soc->ast_lock); diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index aab8ef1a28..727b0b3b13 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -677,8 +677,7 @@ int dp_peer_add_ast(struct dp_soc *soc, * can take care of adding HMWDS ast enty on delete * confirmation from target */ - if ((type == CDP_TXRX_AST_TYPE_WDS_HM) && - soc->is_peer_map_unmap_v2) { + if (type == CDP_TXRX_AST_TYPE_WDS_HM) { struct dp_ast_free_cb_params *param = NULL; if (ast_entry->type == @@ -835,6 +834,67 @@ add_ast_entry: return ret; } +/* + * dp_peer_free_ast_entry() - Free up the ast entry memory + * @soc: SoC handle + * @ast_entry: Address search entry + * + * This API is used to free up the memory associated with + * AST entry. + * + * Return: None + */ +void dp_peer_free_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + /* + * NOTE: Ensure that call to this API is done + * after soc->ast_lock is taken + */ + ast_entry->callback = NULL; + ast_entry->cookie = NULL; + + DP_STATS_INC(soc, ast.deleted, 1); + dp_peer_ast_hash_remove(soc, ast_entry); + dp_peer_ast_cleanup(soc, ast_entry); + qdf_mem_free(ast_entry); + soc->num_ast_entries--; +} + +/* + * dp_peer_unlink_ast_entry() - Free up the ast entry memory + * @soc: SoC handle + * @ast_entry: Address search entry + * + * This API is used to remove/unlink AST entry from the peer list + * and hash list. + * + * Return: None + */ +void dp_peer_unlink_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + /* + * NOTE: Ensure that call to this API is done + * after soc->ast_lock is taken + */ + struct dp_peer *peer = ast_entry->peer; + + TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); + + if (ast_entry == peer->self_ast_entry) + peer->self_ast_entry = NULL; + + /* + * release the reference only if it is mapped + * to ast_table + */ + if (ast_entry->is_mapped) + soc->ast_table[ast_entry->ast_idx] = NULL; + + ast_entry->peer = NULL; +} + /* * dp_peer_del_ast() - Delete and free AST entry * @soc: SoC handle @@ -853,45 +913,45 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) if (!ast_entry) return; - peer = ast_entry->peer; + if (ast_entry->delete_in_progress) + return; + ast_entry->delete_in_progress = true; + + peer = ast_entry->peer; dp_peer_ast_send_wds_del(soc, ast_entry); - /* - * release the reference only if it is mapped - * to ast_table - */ + /* Remove SELF and STATIC entries in teardown itself */ + if (!ast_entry->next_hop) + dp_peer_unlink_ast_entry(soc, ast_entry); + if (ast_entry->is_mapped) soc->ast_table[ast_entry->ast_idx] = NULL; - /* - * if peer map v2 is enabled we are not freeing ast entry + /* if peer map v2 is enabled we are not freeing ast entry * here and it is supposed to be freed in unmap event (after * we receive delete confirmation from target) * * 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) { - /* - * For HM_SEC and SELF type we do not receive unmap event - * free ast_entry from here it self - */ - if ((ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC) && - (ast_entry->type != CDP_TXRX_AST_TYPE_SELF)) - return; - } + /* For HM_SEC and SELF type we do not receive unmap event + * free ast_entry from here it self + */ + if ((ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC) && + (ast_entry->type != CDP_TXRX_AST_TYPE_SELF)) + return; - /* 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); + /* for WDS secondary entry ast_entry->next_hop would be set so + * unlinking has to be done explicitly here. + * As this entry is not a mapped entry unmap notification from + * FW wil not come. Hence unlinkling is done right here. + */ + if (ast_entry->type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) + dp_peer_unlink_ast_entry(soc, ast_entry); - DP_STATS_INC(soc, ast.deleted, 1); - dp_peer_ast_hash_remove(soc, ast_entry); - dp_peer_ast_cleanup(soc, ast_entry); - qdf_mem_free(ast_entry); - soc->num_ast_entries--; + dp_peer_free_ast_entry(soc, ast_entry); } /* @@ -1088,9 +1148,6 @@ void dp_peer_ast_send_wds_del(struct dp_soc *soc, struct dp_peer *peer = ast_entry->peer; struct cdp_soc_t *cdp_soc = &soc->cdp_soc; - if (ast_entry->delete_in_progress) - return; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_TRACE, "%s: ast_entry->type: %d pdevid: %u vdev: %u mac_addr: %pM next_hop: %u peer_mac: %pM\n", __func__, ast_entry->type, peer->vdev->pdev->pdev_id, @@ -1104,14 +1161,6 @@ 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; } /** @@ -1148,19 +1197,13 @@ static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc, soc->ast_table[ast_entry->ast_idx] = NULL; } - 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); - cb = ast_entry->callback; cookie = ast_entry->cookie; - ast_entry->callback = NULL; - ast_entry->cookie = NULL; - if (ast_entry == peer->self_ast_entry) - peer->self_ast_entry = NULL; - soc->num_ast_entries--; + dp_peer_unlink_ast_entry(soc, ast_entry); + dp_peer_free_ast_entry(soc, ast_entry); + qdf_spin_unlock_bh(&soc->ast_lock); if (cb) { @@ -1169,7 +1212,6 @@ static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc, cookie, CDP_TXRX_AST_DELETED); } - qdf_mem_free(ast_entry); return QDF_STATUS_SUCCESS; } @@ -1602,7 +1644,7 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, 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 && is_wds) { + if (is_wds) { if (!dp_peer_ast_free_entry_by_mac(soc, peer, mac_addr)) return; diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index dff74d5e9c..2544110b37 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -148,6 +148,12 @@ void dp_peer_free_hmwds_cb(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, void dp_peer_ast_hash_remove(struct dp_soc *soc, struct dp_ast_entry *ase); +void dp_peer_free_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +void dp_peer_unlink_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + /* * dp_peer_find_by_id_exist - check if peer exists for given id * @soc: core DP soc context