Browse Source

qcacmn: remove peer backpointer in DP ast entry

Remove the peer backpointer in ast entry and store
peer_id instead

Assign peer_id in AST entry in AST MAP event,
also add the ast entry to peers ast list

In AST map & AST unmap APIs use ast find by vdev_id

Change-Id: I74d9828dc309149d98f6f577b5c8304cb087fd76
Chaithanya Garrepalli 4 years ago
parent
commit
f4701f13ec

+ 33 - 20
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;
 	}

+ 99 - 61
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;
+
+	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
+		     ast_mac_addr, QDF_MAC_ADDR_SIZE);
+	mac_addr = &local_mac_addr_aligned;
 
-	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;
+	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,

+ 8 - 6
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 { \

+ 17 - 5
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 (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 (da_peer->vdev == ta_peer->vdev && !da_peer->bss_peer) {
+		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));

+ 4 - 3
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,

+ 23 - 12
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);
 			}
 		}
 	}

+ 5 - 5
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__);

+ 4 - 3
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;