Commit 1e744bf2 authored by Karthikeyan Periyasamy's avatar Karthikeyan Periyasamy Committed by Kalle Valo

ath11k: fix duplication peer create on same radio

Add the pdev index information in the peer object to validate
the peer creation. Ignore the peer creation request, if the given
MAC address is already present in the peer list with same radio.
If we allow the peer creation in above scenario, FW assert will happen.
Above scenario occurred in two cases, where Multiple AP VAP created in
the same radio.

1. when testing tool sends association request to two AP with same
   MAC address
2. when a station do roaming from one AP VAP to another AP VAP.
Signed-off-by: default avatarKarthikeyan Periyasamy <periyasa@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1586343795-21422-1-git-send-email-periyasa@codeaurora.org
parent c61a7483
...@@ -17,7 +17,26 @@ struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, ...@@ -17,7 +17,26 @@ struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id,
list_for_each_entry(peer, &ab->peers, list) { list_for_each_entry(peer, &ab->peers, list) {
if (peer->vdev_id != vdev_id) if (peer->vdev_id != vdev_id)
continue; continue;
if (memcmp(peer->addr, addr, ETH_ALEN)) if (!ether_addr_equal(peer->addr, addr))
continue;
return peer;
}
return NULL;
}
static struct ath11k_peer *ath11k_peer_find_by_pdev_idx(struct ath11k_base *ab,
u8 pdev_idx, const u8 *addr)
{
struct ath11k_peer *peer;
lockdep_assert_held(&ab->base_lock);
list_for_each_entry(peer, &ab->peers, list) {
if (peer->pdev_idx != pdev_idx)
continue;
if (!ether_addr_equal(peer->addr, addr))
continue; continue;
return peer; return peer;
...@@ -34,7 +53,7 @@ struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, ...@@ -34,7 +53,7 @@ struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab,
lockdep_assert_held(&ab->base_lock); lockdep_assert_held(&ab->base_lock);
list_for_each_entry(peer, &ab->peers, list) { list_for_each_entry(peer, &ab->peers, list) {
if (memcmp(peer->addr, addr, ETH_ALEN)) if (!ether_addr_equal(peer->addr, addr))
continue; continue;
return peer; return peer;
...@@ -200,6 +219,17 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -200,6 +219,17 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
return -ENOBUFS; return -ENOBUFS;
} }
spin_lock_bh(&ar->ab->base_lock);
peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr);
if (peer) {
spin_unlock_bh(&ar->ab->base_lock);
ath11k_info(ar->ab,
"ignoring the peer %pM creation on same pdev idx %d\n",
param->peer_addr, ar->pdev_idx);
return -EINVAL;
}
spin_unlock_bh(&ar->ab->base_lock);
ret = ath11k_wmi_send_peer_create_cmd(ar, param); ret = ath11k_wmi_send_peer_create_cmd(ar, param);
if (ret) { if (ret) {
ath11k_warn(ar->ab, ath11k_warn(ar->ab,
...@@ -225,6 +255,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -225,6 +255,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
return -ENOENT; return -ENOENT;
} }
peer->pdev_idx = ar->pdev_idx;
peer->sta = sta; peer->sta = sta;
arvif->ast_hash = peer->ast_hash; arvif->ast_hash = peer->ast_hash;
......
...@@ -13,6 +13,7 @@ struct ath11k_peer { ...@@ -13,6 +13,7 @@ struct ath11k_peer {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
int peer_id; int peer_id;
u16 ast_hash; u16 ast_hash;
u8 pdev_idx;
/* protected by ab->data_lock */ /* protected by ab->data_lock */
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment