diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9905ae54d6..86cb09792e 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -861,25 +861,32 @@ static bool dp_peer_get_ast_info_by_soc_wifi3 { struct dp_ast_entry *ast_entry = NULL; struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_peer *peer = NULL; qdf_spin_lock_bh(&soc->ast_lock); ast_entry = dp_peer_ast_hash_find_soc(soc, ast_mac_addr); - if (!ast_entry || !ast_entry->peer) { + if ((!ast_entry) || + (ast_entry->delete_in_progress && !ast_entry->callback)) { qdf_spin_unlock_bh(&soc->ast_lock); return false; } - if (ast_entry->delete_in_progress && !ast_entry->callback) { + + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_AST); + if (!peer) { qdf_spin_unlock_bh(&soc->ast_lock); return false; } + ast_entry_info->type = ast_entry->type; ast_entry_info->pdev_id = ast_entry->pdev_id; - ast_entry_info->vdev_id = ast_entry->peer->vdev->vdev_id; - ast_entry_info->peer_id = ast_entry->peer->peer_id; + ast_entry_info->vdev_id = ast_entry->vdev_id; + ast_entry_info->peer_id = ast_entry->peer_id; qdf_mem_copy(&ast_entry_info->peer_mac_addr[0], - &ast_entry->peer->mac_addr.raw[0], + &peer->mac_addr.raw[0], QDF_MAC_ADDR_SIZE); + dp_peer_unref_delete(peer, DP_MOD_ID_AST); qdf_spin_unlock_bh(&soc->ast_lock); return true; } @@ -905,26 +912,34 @@ static bool dp_peer_get_ast_info_by_pdevid_wifi3 { struct dp_ast_entry *ast_entry; struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_peer *peer = NULL; qdf_spin_lock_bh(&soc->ast_lock); - ast_entry = dp_peer_ast_hash_find_by_pdevid(soc, ast_mac_addr, pdev_id); + ast_entry = dp_peer_ast_hash_find_by_pdevid(soc, ast_mac_addr, + pdev_id); - if (!ast_entry || !ast_entry->peer) { + if ((!ast_entry) || + (ast_entry->delete_in_progress && !ast_entry->callback)) { qdf_spin_unlock_bh(&soc->ast_lock); return false; } - if (ast_entry->delete_in_progress && !ast_entry->callback) { + + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_AST); + if (!peer) { qdf_spin_unlock_bh(&soc->ast_lock); return false; } + ast_entry_info->type = ast_entry->type; ast_entry_info->pdev_id = ast_entry->pdev_id; - ast_entry_info->vdev_id = ast_entry->peer->vdev->vdev_id; - ast_entry_info->peer_id = ast_entry->peer->peer_id; + ast_entry_info->vdev_id = ast_entry->vdev_id; + ast_entry_info->peer_id = ast_entry->peer_id; qdf_mem_copy(&ast_entry_info->peer_mac_addr[0], - &ast_entry->peer->mac_addr.raw[0], + &peer->mac_addr.raw[0], QDF_MAC_ADDR_SIZE); + dp_peer_unref_delete(peer, DP_MOD_ID_AST); qdf_spin_unlock_bh(&soc->ast_lock); return true; } @@ -1253,8 +1268,8 @@ void dp_print_ast_stats(struct dp_soc *soc) " vdev_id = %d", ++num_entries, ase->mac_addr.raw, - ase->peer->mac_addr.raw, - ase->peer->peer_id, + peer->mac_addr.raw, + ase->peer_id, type[ase->type], ase->next_hop, ase->is_active, @@ -5787,12 +5802,9 @@ static QDF_STATUS dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, 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); + ast_entry = + dp_peer_ast_hash_find_by_vdevid(soc, mac_addr, + vdev_id); /* in case of qwrap we have multiple BSS peers * with same mac address @@ -5800,7 +5812,8 @@ static QDF_STATUS dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, * 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) { + if ((!ast_entry || !ast_entry->delete_in_progress) || + (ast_entry->peer_id != HTT_INVALID_PEER)) { qdf_spin_unlock_bh(&soc->ast_lock); return QDF_STATUS_E_FAILURE; } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 603cdbf451..068b8a9379 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -43,7 +43,7 @@ #ifdef FEATURE_WDS static inline bool -dp_peer_ast_free_in_unmap_supported(struct dp_peer *peer, +dp_peer_ast_free_in_unmap_supported(struct dp_soc *soc, struct dp_ast_entry *ast_entry) { /* if peer map v2 is enabled we are not freeing ast entry @@ -62,7 +62,7 @@ dp_peer_ast_free_in_unmap_supported(struct dp_peer *peer, } #else static inline bool -dp_peer_ast_free_in_unmap_supported(struct dp_peer *peer, +dp_peer_ast_free_in_unmap_supported(struct dp_soc *soc, struct dp_ast_entry *ast_entry) { return false; @@ -597,27 +597,31 @@ void dp_peer_ast_hash_remove(struct dp_soc *soc, } /* - * dp_peer_ast_list_find() - Find AST entry by MAC address from peer ast list + * dp_peer_ast_hash_find_by_vdevid() - Find AST entry by MAC address * @soc: SoC handle - * @peer: peer handle - * @ast_mac_addr: mac address * - * It assumes caller has taken the ast lock to protect the access to ast list + * It assumes caller has taken the ast lock to protect the access to + * AST hash table * * Return: AST entry */ -struct dp_ast_entry *dp_peer_ast_list_find(struct dp_soc *soc, - struct dp_peer *peer, - uint8_t *ast_mac_addr) +struct dp_ast_entry *dp_peer_ast_hash_find_by_vdevid(struct dp_soc *soc, + uint8_t *ast_mac_addr, + uint8_t vdev_id) { - struct dp_ast_entry *ast_entry = NULL; - union dp_align_mac_addr *mac_addr = - (union dp_align_mac_addr *)ast_mac_addr; + union dp_align_mac_addr local_mac_addr_aligned, *mac_addr; + uint32_t index; + struct dp_ast_entry *ase; - TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ase_list_elem) { - if (!dp_peer_find_mac_addr_cmp(mac_addr, - &ast_entry->mac_addr)) { - return ast_entry; + qdf_mem_copy(&local_mac_addr_aligned.raw[0], + ast_mac_addr, QDF_MAC_ADDR_SIZE); + mac_addr = &local_mac_addr_aligned; + + index = dp_peer_ast_hash_index(soc, mac_addr); + TAILQ_FOREACH(ase, &soc->ast_hash.bins[index], hash_list_elem) { + if ((vdev_id == ase->vdev_id) && + !dp_peer_find_mac_addr_cmp(mac_addr, &ase->mac_addr)) { + return ase; } } @@ -722,7 +726,7 @@ static inline QDF_STATUS dp_peer_map_ast(struct dp_soc *soc, qdf_spin_lock_bh(&soc->ast_lock); - ast_entry = dp_peer_ast_list_find(soc, peer, mac_addr); + ast_entry = dp_peer_ast_hash_find_by_vdevid(soc, mac_addr, vdev_id); if (is_wds) { /* @@ -747,7 +751,7 @@ static inline QDF_STATUS dp_peer_map_ast(struct dp_soc *soc, cookie = ast_entry->cookie; peer_type = ast_entry->type; - dp_peer_unlink_ast_entry(soc, ast_entry); + dp_peer_unlink_ast_entry(soc, ast_entry, peer); dp_peer_free_ast_entry(soc, ast_entry); qdf_spin_unlock_bh(&soc->ast_lock); @@ -781,6 +785,11 @@ static inline QDF_STATUS dp_peer_map_ast(struct dp_soc *soc, peer_type = ast_entry->type; ast_entry->ast_hash_value = ast_hash; ast_entry->is_mapped = TRUE; + qdf_assert_always(ast_entry->peer_id == HTT_INVALID_PEER); + + ast_entry->peer_id = peer->peer_id; + TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, + ase_list_elem); } if (ast_entry || (peer->vdev && peer->vdev->proxysta_vdev)) { @@ -1012,7 +1021,7 @@ QDF_STATUS dp_peer_add_ast(struct dp_soc *soc, */ if ((ast_entry->type == CDP_TXRX_AST_TYPE_WDS) && (type == CDP_TXRX_AST_TYPE_MEC) && - (ast_entry->peer == peer)) { + (ast_entry->peer_id == peer->peer_id)) { ast_entry->is_active = FALSE; dp_peer_del_ast(soc, ast_entry); } @@ -1037,6 +1046,9 @@ add_ast_entry: ast_entry->pdev_id = vdev->pdev->pdev_id; ast_entry->is_mapped = false; ast_entry->delete_in_progress = false; + ast_entry->peer_id = HTT_INVALID_PEER; + ast_entry->next_hop = 0; + ast_entry->vdev_id = vdev->vdev_id; switch (type) { case CDP_TXRX_AST_TYPE_STATIC: @@ -1060,6 +1072,9 @@ add_ast_entry: case CDP_TXRX_AST_TYPE_WDS_HM_SEC: ast_entry->next_hop = 1; ast_entry->type = CDP_TXRX_AST_TYPE_WDS_HM_SEC; + ast_entry->peer_id = peer->peer_id; + TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, + ase_list_elem); break; case CDP_TXRX_AST_TYPE_MEC: ast_entry->next_hop = 1; @@ -1087,15 +1102,11 @@ add_ast_entry: soc->num_ast_entries++; dp_peer_ast_hash_add(soc, ast_entry); - ast_entry->peer = peer; - if (type == CDP_TXRX_AST_TYPE_MEC) qdf_mem_copy(next_node_mac, peer->vdev->mac_addr.raw, 6); else qdf_mem_copy(next_node_mac, peer->mac_addr.raw, 6); - TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ase_list_elem); - if ((ast_entry->type != CDP_TXRX_AST_TYPE_STATIC) && (ast_entry->type != CDP_TXRX_AST_TYPE_SELF) && (ast_entry->type != CDP_TXRX_AST_TYPE_STA_BSS) && @@ -1156,6 +1167,7 @@ void dp_peer_free_ast_entry(struct dp_soc *soc, * dp_peer_unlink_ast_entry() - Free up the ast entry memory * @soc: SoC handle * @ast_entry: Address search entry + * @peer: peer * * This API is used to remove/unlink AST entry from the peer list * and hash list. @@ -1163,14 +1175,20 @@ void dp_peer_free_ast_entry(struct dp_soc *soc, * Return: None */ void dp_peer_unlink_ast_entry(struct dp_soc *soc, - struct dp_ast_entry *ast_entry) + struct dp_ast_entry *ast_entry, + struct dp_peer *peer) { + if (!peer) + return; + + if (ast_entry->peer_id == HTT_INVALID_PEER) + return; /* * NOTE: Ensure that call to this API is done * after soc->ast_lock is taken */ - struct dp_peer *peer = ast_entry->peer; + qdf_assert_always(ast_entry->peer_id == peer->peer_id); TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); if (ast_entry == peer->self_ast_entry) @@ -1183,7 +1201,7 @@ void dp_peer_unlink_ast_entry(struct dp_soc *soc, if (ast_entry->is_mapped) soc->ast_table[ast_entry->ast_idx] = NULL; - ast_entry->peer = NULL; + ast_entry->peer_id = HTT_INVALID_PEER; } /* @@ -1199,7 +1217,7 @@ void dp_peer_unlink_ast_entry(struct dp_soc *soc, */ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) { - struct dp_peer *peer; + struct dp_peer *peer = NULL; if (!ast_entry) return; @@ -1209,12 +1227,14 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) ast_entry->delete_in_progress = true; - peer = ast_entry->peer; - dp_peer_ast_send_wds_del(soc, ast_entry); + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_AST); + + dp_peer_ast_send_wds_del(soc, ast_entry, peer); /* Remove SELF and STATIC entries in teardown itself */ if (!ast_entry->next_hop) - dp_peer_unlink_ast_entry(soc, ast_entry); + dp_peer_unlink_ast_entry(soc, ast_entry, peer); if (ast_entry->is_mapped) soc->ast_table[ast_entry->ast_idx] = NULL; @@ -1226,18 +1246,23 @@ 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 (dp_peer_ast_free_in_unmap_supported(peer, ast_entry)) - return; + if (dp_peer_ast_free_in_unmap_supported(soc, ast_entry)) + goto end; /* 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_peer_unlink_ast_entry(soc, ast_entry, peer); dp_peer_free_ast_entry(soc, ast_entry); + +end: + if (peer) + dp_peer_unref_delete(peer, DP_MOD_ID_AST); } /* @@ -1284,16 +1309,22 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, /* * Avoids flood of WMI update messages sent to FW for same peer. */ - if (qdf_unlikely(ast_entry->peer == peer) && + if (qdf_unlikely(ast_entry->peer_id == peer->peer_id) && (ast_entry->type == CDP_TXRX_AST_TYPE_WDS) && - (ast_entry->peer->vdev == peer->vdev) && + (ast_entry->vdev_id == peer->vdev->vdev_id) && (ast_entry->is_active)) return 0; - old_peer = ast_entry->peer; + old_peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_AST); + if (!old_peer) + return 0; + TAILQ_REMOVE(&old_peer->ast_entry_list, ast_entry, ase_list_elem); - ast_entry->peer = peer; + dp_peer_unref_delete(old_peer, DP_MOD_ID_AST); + + ast_entry->peer_id = peer->peer_id; ast_entry->type = CDP_TXRX_AST_TYPE_WDS; ast_entry->pdev_id = peer->vdev->pdev->pdev_id; ast_entry->is_active = TRUE; @@ -1435,29 +1466,33 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, #endif void dp_peer_ast_send_wds_del(struct dp_soc *soc, - struct dp_ast_entry *ast_entry) + struct dp_ast_entry *ast_entry, + struct dp_peer *peer) { - struct dp_peer *peer = ast_entry->peer; struct cdp_soc_t *cdp_soc = &soc->cdp_soc; + bool delete_in_fw = false; 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, - peer->vdev->vdev_id, ast_entry->mac_addr.raw, - ast_entry->next_hop, ast_entry->peer->mac_addr.raw); + "%s: ast_entry->type: %d pdevid: %u vdev: %u mac_addr: %pM next_hop: %u peer_id: %uM\n", + __func__, ast_entry->type, ast_entry->pdev_id, + ast_entry->vdev_id, ast_entry->mac_addr.raw, + ast_entry->next_hop, ast_entry->peer_id); /* - * If peer delete_in_progress is set, the peer is about to get + * If peer is NULL, the peer is about to get * teared down with a peer delete command to firmware, * which will cleanup all the wds ast entries. * So, no need to send explicit wds ast delete to firmware. */ if (ast_entry->next_hop) { + if (peer) + delete_in_fw = true; + cdp_soc->ol_ops->peer_del_wds_entry(soc->ctrl_psoc, - peer->vdev->vdev_id, + ast_entry->vdev_id, ast_entry->mac_addr.raw, ast_entry->type, - !peer->delete_in_progress); + delete_in_fw); } } @@ -1483,18 +1518,18 @@ static uint32_t dp_peer_ast_free_wds_entries(struct dp_soc *soc, qdf_spin_lock_bh(&soc->ast_lock); DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) { - if (ast_entry->next_hop) { - if (ast_entry->is_mapped) - soc->ast_table[ast_entry->ast_idx] = NULL; - - dp_peer_unlink_ast_entry(soc, ast_entry); - DP_STATS_INC(soc, ast.deleted, 1); - dp_peer_ast_hash_remove(soc, ast_entry); - TAILQ_INSERT_TAIL(&ast_local_list, ast_entry, - ase_list_elem); - soc->num_ast_entries--; + if (ast_entry->next_hop) num_ast++; - } + + if (ast_entry->is_mapped) + soc->ast_table[ast_entry->ast_idx] = NULL; + + dp_peer_unlink_ast_entry(soc, ast_entry, peer); + DP_STATS_INC(soc, ast.deleted, 1); + dp_peer_ast_hash_remove(soc, ast_entry); + TAILQ_INSERT_TAIL(&ast_local_list, ast_entry, + ase_list_elem); + soc->num_ast_entries--; } qdf_spin_unlock_bh(&soc->ast_lock); @@ -1551,6 +1586,7 @@ dp_peer_clean_wds_entries(struct dp_soc *soc, struct dp_peer *peer, * dp_peer_ast_free_entry_by_mac() - find ast entry by MAC address and delete * @soc: soc handle * @peer: peer handle + * @vdev_id: vdev_id * @mac_addr: mac address of the AST entry to searc and delete * * find the ast entry from the peer list using the mac address and free @@ -1560,6 +1596,7 @@ dp_peer_clean_wds_entries(struct dp_soc *soc, struct dp_peer *peer, */ static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc, struct dp_peer *peer, + uint8_t vdev_id, uint8_t *mac_addr) { struct dp_ast_entry *ast_entry; @@ -1573,7 +1610,7 @@ static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc, qdf_spin_lock_bh(&soc->ast_lock); - ast_entry = dp_peer_ast_list_find(soc, peer, mac_addr); + ast_entry = dp_peer_ast_hash_find_by_vdevid(soc, mac_addr, vdev_id); if (!ast_entry) { qdf_spin_unlock_bh(&soc->ast_lock); return QDF_STATUS_E_NOENT; @@ -1585,7 +1622,8 @@ static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc, cookie = ast_entry->cookie; - dp_peer_unlink_ast_entry(soc, ast_entry); + dp_peer_unlink_ast_entry(soc, ast_entry, peer); + dp_peer_free_ast_entry(soc, ast_entry); qdf_spin_unlock_bh(&soc->ast_lock); @@ -2043,9 +2081,9 @@ 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 (is_wds) { - if (!dp_peer_ast_free_entry_by_mac(soc, peer, mac_addr)) { + if (!dp_peer_ast_free_entry_by_mac(soc, peer, vdev_id, + mac_addr)) return; - } dp_alert("AST entry not found with peer %pK peer_id %u peer_mac %pM mac_addr %pM vdev_id %u next_hop %u", peer, peer->peer_id, diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 53a8b33247..4271019e4f 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -160,13 +160,13 @@ struct dp_ast_entry *dp_peer_ast_hash_find_by_pdevid(struct dp_soc *soc, uint8_t *ast_mac_addr, uint8_t pdev_id); +struct dp_ast_entry *dp_peer_ast_hash_find_by_vdevid(struct dp_soc *soc, + uint8_t *ast_mac_addr, + uint8_t vdev_id); + struct dp_ast_entry *dp_peer_ast_hash_find_soc(struct dp_soc *soc, uint8_t *ast_mac_addr); -struct dp_ast_entry *dp_peer_ast_list_find(struct dp_soc *soc, - struct dp_peer *peer, - uint8_t *ast_mac_addr); - uint8_t dp_peer_ast_get_pdev_id(struct dp_soc *soc, struct dp_ast_entry *ast_entry); @@ -179,7 +179,8 @@ void dp_peer_ast_set_type(struct dp_soc *soc, enum cdp_txrx_ast_entry_type type); void dp_peer_ast_send_wds_del(struct dp_soc *soc, - struct dp_ast_entry *ast_entry); + struct dp_ast_entry *ast_entry, + struct dp_peer *peer); void dp_peer_free_hmwds_cb(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, struct cdp_soc *dp_soc, @@ -193,7 +194,8 @@ 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); + struct dp_ast_entry *ast_entry, + struct dp_peer *peer); #define DP_AST_ASSERT(_condition) \ do { \ diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index d697a7f6b9..5bc4ca1682 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -567,7 +567,9 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, { uint16_t len; uint8_t is_frag; - struct dp_peer *da_peer; + uint16_t da_peer_id = HTT_INVALID_PEER; + struct dp_peer *da_peer = NULL; + bool is_da_bss_peer = false; struct dp_ast_entry *ast_entry; qdf_nbuf_t nbuf_copy; uint8_t tid = qdf_nbuf_get_tid_val(nbuf); @@ -591,18 +593,28 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, return false; } - da_peer = ast_entry->peer; + da_peer_id = ast_entry->peer_id; - if (!da_peer) + if (da_peer_id == HTT_INVALID_PEER) return false; /* TA peer cannot be same as peer(DA) on which AST is present * this indicates a change in topology and that AST entries * are yet to be updated. */ - if (da_peer == ta_peer) + if (da_peer_id == ta_peer->peer_id) return false; - if (da_peer->vdev == ta_peer->vdev && !da_peer->bss_peer) { + if (ast_entry->vdev_id != ta_peer->vdev->vdev_id) + return false; + + da_peer = dp_peer_get_ref_by_id(soc, da_peer_id, + DP_MOD_ID_RX); + if (!da_peer) + return false; + is_da_bss_peer = da_peer->bss_peer; + dp_peer_unref_delete(da_peer, DP_MOD_ID_RX); + + if (!is_da_bss_peer) { len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); is_frag = qdf_nbuf_is_frag(nbuf); memset(nbuf->cb, 0x0, sizeof(nbuf->cb)); diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 36fe4933d8..ed26a29def 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -115,8 +115,9 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, * ast is not in ast_table, we use the below API to get * AST entry for STA's own mac_address. */ - ase = dp_peer_ast_list_find(soc, peer, - &data[QDF_MAC_ADDR_SIZE]); + ase = dp_peer_ast_hash_find_by_vdevid + (soc, &data[QDF_MAC_ADDR_SIZE], + peer->vdev->vdev_id); if (ase) { ase->ast_idx = sa_idx; soc->ast_table[sa_idx] = ase; @@ -142,7 +143,7 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, } if ((ase->type == CDP_TXRX_AST_TYPE_MEC) || - (ase->peer != peer)) { + (ase->peer_id != peer->peer_id)) { qdf_spin_unlock_bh(&soc->ast_lock); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 06de15c62f..5cc5d7536b 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -220,13 +220,14 @@ dp_rx_populate_cdp_indication_ppdu_user(struct dp_pdev *pdev, } ast_entry = soc->ast_table[ast_index]; - if (!ast_entry) { + if (!ast_entry || ast_entry->peer_id == HTT_INVALID_PEER) { rx_stats_peruser->peer_id = HTT_INVALID_PEER; continue; } - peer = ast_entry->peer; - if (!peer || peer->peer_id == HTT_INVALID_PEER) { + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_RX_PPDU_STATS); + if (!peer) { rx_stats_peruser->peer_id = HTT_INVALID_PEER; continue; } @@ -286,6 +287,7 @@ dp_rx_populate_cdp_indication_ppdu_user(struct dp_pdev *pdev, rx_stats_peruser->vdev_id = peer->vdev->vdev_id; rx_stats_peruser->mu_ul_info_valid = 0; + dp_peer_unref_delete(peer, DP_MOD_ID_RX_PPDU_STATS); if (cdp_rx_ppdu->u.ppdu_type == HAL_RX_TYPE_MU_OFDMA || cdp_rx_ppdu->u.ppdu_type == HAL_RX_TYPE_MU_MIMO) { if (rx_user_status->mu_ul_info_valid) { @@ -372,13 +374,14 @@ dp_rx_populate_cdp_indication_ppdu(struct dp_pdev *pdev, } ast_entry = soc->ast_table[ast_index]; - if (!ast_entry) { + if (!ast_entry || ast_entry->peer_id == HTT_INVALID_PEER) { cdp_rx_ppdu->peer_id = HTT_INVALID_PEER; cdp_rx_ppdu->num_users = 0; goto end; } - peer = ast_entry->peer; - if (!peer || peer->peer_id == HTT_INVALID_PEER) { + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_RX_PPDU_STATS); + if (!peer) { cdp_rx_ppdu->peer_id = HTT_INVALID_PEER; cdp_rx_ppdu->num_users = 0; goto end; @@ -429,6 +432,8 @@ dp_rx_populate_cdp_indication_ppdu(struct dp_pdev *pdev, dp_rx_populate_cdp_indication_ppdu_user(pdev, ppdu_info, cdp_rx_ppdu); + dp_peer_unref_delete(peer, DP_MOD_ID_RX_PPDU_STATS); + return; end: dp_rx_populate_cfr_non_assoc_sta(pdev, ppdu_info, cdp_rx_ppdu); @@ -1075,19 +1080,21 @@ dp_rx_mon_handle_cfr_mu_info(struct dp_pdev *pdev, } ast_entry = soc->ast_table[ast_index]; - if (!ast_entry) { + if (!ast_entry || ast_entry->peer_id == HTT_INVALID_PEER) { rx_stats_peruser->peer_id = HTT_INVALID_PEER; continue; } - peer = ast_entry->peer; - if (!peer || peer->peer_id == HTT_INVALID_PEER) { + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_RX_PPDU_STATS); + if (!peer) { rx_stats_peruser->peer_id = HTT_INVALID_PEER; continue; } qdf_mem_copy(rx_stats_peruser->mac_addr, peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); + dp_peer_unref_delete(peer, DP_MOD_ID_RX_PPDU_STATS); } qdf_spin_unlock_bh(&soc->ast_lock); @@ -1458,15 +1465,19 @@ dp_rx_process_peer_based_pktlog(struct dp_soc *soc, if (ast_index < wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) { ast_entry = soc->ast_table[ast_index]; if (ast_entry) { - peer = ast_entry->peer; - if (peer && (peer->peer_id != HTT_INVALID_PEER)) { - if (peer->peer_based_pktlog_filter) { + peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id, + DP_MOD_ID_RX_PPDU_STATS); + if (peer) { + if ((peer->peer_id != HTT_INVALID_PEER) && + (peer->peer_based_pktlog_filter)) { dp_wdi_event_handler( WDI_EVENT_RX_DESC, soc, status_nbuf, peer->peer_id, WDI_NO_VAL, pdev_id); } + dp_peer_unref_delete(peer, + DP_MOD_ID_RX_PPDU_STATS); } } } diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index e3fcb253d2..b1b5c98521 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1665,8 +1665,8 @@ int dp_tx_frame_is_drop(struct dp_vdev *vdev, uint8_t *srcmac, uint8_t *dstmac) src_ast_entry = dp_peer_ast_hash_find_by_pdevid (soc, srcmac, vdev->pdev->pdev_id); if (dst_ast_entry && src_ast_entry) { - if (dst_ast_entry->peer->peer_id == - src_ast_entry->peer->peer_id) + if (dst_ast_entry->peer_id == + src_ast_entry->peer_id) return 1; } @@ -2379,7 +2379,7 @@ void dp_tx_nawds_handler(struct cdp_soc_t *soc, struct dp_vdev *vdev, qdf_nbuf_t nbuf_clone = NULL; struct dp_soc *dp_soc = (struct dp_soc *)soc; uint16_t peer_id = DP_INVALID_PEER; - struct dp_peer *sa_peer = NULL; + uint16_t sa_peer_id = DP_INVALID_PEER; struct dp_ast_entry *ast_entry = NULL; qdf_ether_header_t *eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); @@ -2392,7 +2392,7 @@ void dp_tx_nawds_handler(struct cdp_soc_t *soc, struct dp_vdev *vdev, vdev->pdev->pdev_id); if (ast_entry) - sa_peer = ast_entry->peer; + sa_peer_id = ast_entry->peer_id; qdf_spin_unlock_bh(&dp_soc->ast_lock); } @@ -2403,7 +2403,7 @@ void dp_tx_nawds_handler(struct cdp_soc_t *soc, struct dp_vdev *vdev, /* Multicast packets needs to be * dropped in case of intra bss forwarding */ - if (sa_peer == peer) { + if (sa_peer_id == peer->peer_id) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, " %s: multicast packet", __func__); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 90e5172a4f..f5d18564d2 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -951,9 +951,9 @@ struct dp_ast_free_cb_params { * dp_ast_entry * * @ast_idx: Hardware AST Index + * @peer_id: Next Hop peer_id (for non-WDS nodes, this will be point to + * associated peer with this MAC address) * @mac_addr: MAC Address for this AST entry - * @peer: Next Hop peer (for non-WDS nodes, this will be point to - * associated peer with this MAC address) * @next_hop: Set to 1 if this is for a WDS node * @is_active: flag to indicate active data traffic on this node * (used for aging out/expiry) @@ -974,12 +974,13 @@ struct dp_ast_free_cb_params { */ struct dp_ast_entry { uint16_t ast_idx; + uint16_t peer_id; union dp_align_mac_addr mac_addr; - struct dp_peer *peer; bool next_hop; bool is_active; bool is_mapped; uint8_t pdev_id; + uint8_t vdev_id; uint16_t ast_hash_value; qdf_atomic_t ref_cnt; enum cdp_txrx_ast_entry_type type;