Browse Source

qcacmn: Don't take peer ref by id on AST cleanup in unmap handling

In the scanerio where peer teardown and peer map happen
in parallel, AST entries could get added to the peer AST
list after cleanup happens as part of peer teardown. AST
cleanup as part of peer unmap handling would not remove
the entry from the peer AST list. This is because
dp_peer_get_ref_by_id returns NULL as peer state is moved
to logically deleted state.

Fix is to not take peer ref by id and use the peer
argument passed in which already holds ref in the
peer unmap handling.

Change-Id: I844d3f07e9eec962d44bbfba851ad46f350e4f97
CRs-Fixed: 2766779
Yeshwanth Sriram Guntuka 4 years ago
parent
commit
004e29eceb
1 changed files with 29 additions and 5 deletions
  1. 29 5
      dp/wifi3.0/dp_peer.c

+ 29 - 5
dp/wifi3.0/dp_peer.c

@@ -1187,11 +1187,17 @@ void dp_peer_unlink_ast_entry(struct dp_soc *soc,
 			      struct dp_ast_entry *ast_entry,
 			      struct dp_peer *peer)
 {
-	if (!peer)
+	if (!peer) {
+		dp_err_rl("NULL peer");
 		return;
+	}
 
-	if (ast_entry->peer_id == HTT_INVALID_PEER)
+	if (ast_entry->peer_id == HTT_INVALID_PEER) {
+		dp_err_rl("Invalid peer id in AST entry mac addr:"QDF_MAC_ADDR_FMT" type:%d",
+			  QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw),
+			  ast_entry->type);
 		return;
+	}
 	/*
 	 * NOTE: Ensure that call to this API is done
 	 * after soc->ast_lock is taken
@@ -1228,11 +1234,17 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry)
 {
 	struct dp_peer *peer = NULL;
 
-	if (!ast_entry)
+	if (!ast_entry) {
+		dp_err_rl("NULL AST entry");
 		return;
+	}
 
-	if (ast_entry->delete_in_progress)
+	if (ast_entry->delete_in_progress) {
+		dp_err_rl("AST entry deletion in progress mac addr:"QDF_MAC_ADDR_FMT" type:%d",
+			  QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw),
+			  ast_entry->type);
 		return;
+	}
 
 	ast_entry->delete_in_progress = true;
 
@@ -1591,8 +1603,20 @@ static void
 dp_peer_clean_wds_entries(struct dp_soc *soc, struct dp_peer *peer,
 			  uint32_t free_wds_count)
 {
+	struct dp_ast_entry *ast_entry, *temp_ast_entry;
+
 	qdf_spin_lock_bh(&soc->ast_lock);
-	dp_peer_delete_ast_entries(soc, peer);
+
+	DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) {
+		dp_peer_unlink_ast_entry(soc, ast_entry, peer);
+
+		if (ast_entry->is_mapped)
+			soc->ast_table[ast_entry->ast_idx] = NULL;
+
+		dp_peer_free_ast_entry(soc, ast_entry);
+	}
+
+	peer->self_ast_entry = NULL;
 	qdf_spin_unlock_bh(&soc->ast_lock);
 }
 #endif