mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 18:07:52 +00:00 
			
		
		
		
	ipq807x_v5.4/mac80211: ath11k: fix peer addition/deletion error on sta band migration
Fix removing rhash when station is roaming between radios and
apply logic from opensource driver during adding/removing
peer.
Fixes: 7374c39d ("ath11k: fix STA roaming between radios")
Fixes: WIFI-14457
Signed-off-by: Arif Alam <arif.alam@netexperience.com>
Signed-off-by: Marek Kwaczynski <marek@shasta.cloud>
			
			
This commit is contained in:
		| @@ -0,0 +1,116 @@ | |||||||
|  | Index: backports-20210222_001-5.4.164-b157d2276/drivers/net/wireless/ath/ath11k/peer.c | ||||||
|  | =================================================================== | ||||||
|  | --- backports-20210222_001-5.4.164-b157d2276.orig/drivers/net/wireless/ath/ath11k/peer.c | ||||||
|  | +++ backports-20210222_001-5.4.164-b157d2276/drivers/net/wireless/ath/ath11k/peer.c | ||||||
|  | @@ -789,8 +789,6 @@ int ath11k_peer_delete(struct ath11k *ar | ||||||
|  |  #endif | ||||||
|  |  	lockdep_assert_held(&ar->conf_mutex); | ||||||
|  |   | ||||||
|  | -	reinit_completion(&ar->peer_delete_done); | ||||||
|  | - | ||||||
|  |  	ath11k_nss_peer_delete(ar->ab, vdev_id, addr); | ||||||
|  |  #ifdef CCPTCFG_ATH11K_NSS_SUPPORTPTCFG_ATH11K_NSS_SUPPORT | ||||||
|  |  	mutex_lock(&ar->ab->base_ast_lock); | ||||||
|  | @@ -799,33 +797,60 @@ int ath11k_peer_delete(struct ath11k *ar | ||||||
|  |  	spin_lock_bh(&ar->ab->base_lock); | ||||||
|  |   | ||||||
|  |  	peer = ath11k_peer_find_by_addr(ar->ab, addr); | ||||||
|  | -	if (peer) { | ||||||
|  | +	/* Check if the found peer is what we want to remove. | ||||||
|  | +	 * While the sta is transitioning to another band we may | ||||||
|  | +	 * have 2 peer with the same addr assigned to different | ||||||
|  | +	 * vdev_id. Make sure we are deleting the correct peer. | ||||||
|  | +	 */ | ||||||
|  | +	if (peer && peer->vdev_id == vdev_id) | ||||||
|  | +		ath11k_peer_rhash_delete(ar->ab, peer); | ||||||
|  | + | ||||||
|  | +	/* Fallback to peer list search if the correct peer can't be found. | ||||||
|  | +	 * Skip the deletion of the peer from the rhash since it has already | ||||||
|  | +	 * been deleted in peer add. | ||||||
|  | +	 */ | ||||||
|  | +	if (!peer) | ||||||
|  | +		peer = ath11k_peer_find(ar->ab, vdev_id, addr); | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +	if (!peer) { | ||||||
|  | +		spin_unlock_bh(&ar->ab->base_lock); | ||||||
|  | +		mutex_unlock(&ar->ab->tbl_mtx_lock); | ||||||
|  |  #ifdef CPTCFG_ATH11K_NSS_SUPPORT | ||||||
|  | -		peer->delete_in_progress = true; | ||||||
|  | -		if (peer->self_ast_entry) { | ||||||
|  | -			ath11k_peer_del_ast(ar, peer->self_ast_entry); | ||||||
|  | -			peer->self_ast_entry = NULL; | ||||||
|  | -		} | ||||||
|  | +		mutex_unlock(&ar->ab->base_ast_lock); | ||||||
|  | +#endif | ||||||
|  | +		ath11k_warn(ar->ab, | ||||||
|  | +			    "failed to find peer vdev_id %d addr %pM in delete\n", | ||||||
|  | +			    vdev_id, addr); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +        } | ||||||
|  | + | ||||||
|  | +#ifdef CPTCFG_ATH11K_NSS_SUPPORT | ||||||
|  | +	peer->delete_in_progress = true; | ||||||
|  | +	if (peer->self_ast_entry) { | ||||||
|  | +		ath11k_peer_del_ast(ar, peer->self_ast_entry); | ||||||
|  | +		peer->self_ast_entry = NULL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -		list_for_each_entry_safe(ast_entry, tmp_ast, | ||||||
|  | -					 &peer->ast_entry_list, ase_list) | ||||||
|  | -			if ((ast_entry->type == ATH11K_AST_TYPE_WDS) || | ||||||
|  | -			    (ast_entry->type == ATH11K_AST_TYPE_MEC)) { | ||||||
|  | -				if (!list_empty(&ast_entry->wmi_list)) { | ||||||
|  | -					ath11k_dbg(ar->ab, ATH11K_DBG_MAC, | ||||||
|  | -						   "%s deleting unprocessed ast entry %pM of peer %pM from wmi list\n", | ||||||
|  | -						    __func__, ast_entry->addr, addr); | ||||||
|  | -					list_del_init(&ast_entry->wmi_list); | ||||||
|  | -				} | ||||||
|  | +	list_for_each_entry_safe(ast_entry, tmp_ast, | ||||||
|  | +				 &peer->ast_entry_list, ase_list) | ||||||
|  | +		if ((ast_entry->type == ATH11K_AST_TYPE_WDS) || | ||||||
|  | +		    (ast_entry->type == ATH11K_AST_TYPE_MEC)) { | ||||||
|  | +			if (!list_empty(&ast_entry->wmi_list)) { | ||||||
|  | +				ath11k_dbg(ar->ab, ATH11K_DBG_MAC, | ||||||
|  | +					   "%s deleting unprocessed ast entry %pM of peer %pM from wmi list\n", | ||||||
|  | +					    __func__, ast_entry->addr, addr); | ||||||
|  | +				list_del_init(&ast_entry->wmi_list); | ||||||
|  |  			} | ||||||
|  | +		} | ||||||
|  |  #endif | ||||||
|  | -		ath11k_peer_rhash_delete(ar->ab, peer); | ||||||
|  | -	} | ||||||
|  |  	spin_unlock_bh(&ar->ab->base_lock); | ||||||
|  |  	mutex_unlock(&ar->ab->tbl_mtx_lock); | ||||||
|  |  #ifdef CPTCFG_ATH11K_NSS_SUPPORT | ||||||
|  |  	mutex_unlock(&ar->ab->base_ast_lock); | ||||||
|  |  #endif | ||||||
|  | +	reinit_completion(&ar->peer_delete_done); | ||||||
|  | + | ||||||
|  |  	ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); | ||||||
|  |  	if (ret) { | ||||||
|  |  		ath11k_warn(ar->ab, | ||||||
|  | @@ -866,14 +891,20 @@ int ath11k_peer_create(struct ath11k *ar | ||||||
|  |  			    "failed to create peer due to insufficient peer entry resource in firmware\n"); | ||||||
|  |  		return -ENOBUFS; | ||||||
|  |  	} | ||||||
|  | - | ||||||
|  | +	mutex_lock(&ar->ab->tbl_mtx_lock); | ||||||
|  |  	spin_lock_bh(&ar->ab->base_lock); | ||||||
|  |  	peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr); | ||||||
|  |  	if (peer) { | ||||||
|  | -		spin_unlock_bh(&ar->ab->base_lock); | ||||||
|  | -		return -EINVAL; | ||||||
|  | +		if (peer->vdev_id == param->vdev_id) { | ||||||
|  | +			spin_unlock_bh(&ar->ab->base_lock); | ||||||
|  | +			mutex_unlock(&ar->ab->tbl_mtx_lock); | ||||||
|  | +			return -EINVAL; | ||||||
|  | +		} | ||||||
|  | +		ath11k_peer_rhash_delete(ar->ab, peer); | ||||||
|  |  	} | ||||||
|  | + | ||||||
|  |  	spin_unlock_bh(&ar->ab->base_lock); | ||||||
|  | +	mutex_unlock(&ar->ab->tbl_mtx_lock); | ||||||
|  |   | ||||||
|  |  	ret = ath11k_wmi_send_peer_create_cmd(ar, param); | ||||||
|  |  	if (ret) { | ||||||
		Reference in New Issue
	
	Block a user
	 Marek Kwaczynski
					Marek Kwaczynski