mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 09:51:26 +00:00
274 lines
8.3 KiB
Diff
274 lines
8.3 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -531,6 +531,7 @@ struct ath11k {
|
|
u8 lmac_id;
|
|
|
|
struct completion peer_assoc_done;
|
|
+ struct completion peer_delete_done;
|
|
|
|
int install_key_status;
|
|
struct completion install_key_done;
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -455,7 +455,7 @@ static u8 ath11k_mac_bitrate_to_rate(int
|
|
(ath11k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
|
|
}
|
|
|
|
-static void ath11k_get_arvif_iter(void *data, u8 *mac,
|
|
+static void ath11k_mac_get_arvif_iter(void *data, u8 *mac,
|
|
struct ieee80211_vif *vif)
|
|
{
|
|
struct ath11k_vif_iter *arvif_iter = data;
|
|
@@ -476,7 +476,7 @@ struct ath11k_vif *ath11k_mac_get_arvif(
|
|
flags = IEEE80211_IFACE_ITER_RESUME_ALL;
|
|
ieee80211_iterate_active_interfaces_atomic(ar->hw,
|
|
flags,
|
|
- ath11k_get_arvif_iter,
|
|
+ ath11k_mac_get_arvif_iter,
|
|
&arvif_iter);
|
|
if (!arvif_iter.arvif) {
|
|
ath11k_warn(ar->ab, "No VIF found for vdev %d\n", vdev_id);
|
|
@@ -578,6 +578,36 @@ struct ath11k *ath11k_mac_get_ar_vdev_st
|
|
return NULL;
|
|
}
|
|
|
|
+struct ath11k *ath11k_mac_get_ar_peer_delete_status(struct ath11k_base *ab, u8 *peer_addr,
|
|
+ u32 vdev_id)
|
|
+{
|
|
+ int i;
|
|
+ struct ath11k_pdev *pdev;
|
|
+ struct ath11k *ar;
|
|
+ struct ath11k_vif *arvif;
|
|
+
|
|
+ for (i = 0; i < ab->num_radios; i++) {
|
|
+ pdev = rcu_dereference(ab->pdevs_active[i]);
|
|
+ if (pdev && pdev->ar) {
|
|
+ ar = pdev->ar;
|
|
+
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+ if (ether_addr_equal(ar->mac_addr, peer_addr)) {
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+ return ar;
|
|
+ } else {
|
|
+ arvif = ath11k_mac_get_arvif(pdev->ar, vdev_id);
|
|
+ if (arvif) {
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+ return arvif->ar;
|
|
+ }
|
|
+ }
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+ }
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
static void ath11k_pdev_caps_update(struct ath11k *ar)
|
|
{
|
|
struct ath11k_base *ab = ar->ab;
|
|
@@ -772,6 +802,28 @@ static int ath11k_monitor_vdev_up(struct
|
|
return 0;
|
|
}
|
|
|
|
+int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
|
|
+ const u8 *addr)
|
|
+{
|
|
+ int ret;
|
|
+ unsigned long time_left;
|
|
+
|
|
+ ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr);
|
|
+ if(ret) {
|
|
+ ath11k_warn(ar->ab, "failed wait for peer deleted");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ time_left = wait_for_completion_timeout(&ar->peer_delete_done,
|
|
+ 3 * HZ);
|
|
+ if(time_left == 0) {
|
|
+ ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
{
|
|
struct ath11k *ar = hw->priv;
|
|
@@ -4638,8 +4690,22 @@ static int ath11k_mac_op_add_interface(s
|
|
|
|
err_peer_del:
|
|
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
|
+ reinit_completion(&ar->peer_delete_done);
|
|
+
|
|
+ free_err = ath11k_wmi_send_peer_delete_cmd(ar, vif->addr,
|
|
+ arvif->vdev_id);
|
|
+ if (free_err) {
|
|
+ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
|
|
+ arvif->vdev_id, vif->addr);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ free_err = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id,
|
|
+ vif->addr);
|
|
+ if (free_err)
|
|
+ goto err;
|
|
+
|
|
ar->num_peers--;
|
|
- ath11k_wmi_send_peer_delete_cmd(ar, vif->addr, arvif->vdev_id);
|
|
}
|
|
|
|
err_vdev_del:
|
|
@@ -6534,6 +6600,7 @@ int ath11k_mac_allocate(struct ath11k_ba
|
|
init_completion(&ar->vdev_setup_done);
|
|
init_completion(&ar->vdev_delete_done);
|
|
init_completion(&ar->peer_assoc_done);
|
|
+ init_completion(&ar->peer_delete_done);
|
|
init_completion(&ar->install_key_done);
|
|
init_completion(&ar->bss_survey_done);
|
|
init_completion(&ar->scan.started);
|
|
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
|
@@ -172,17 +172,41 @@ void ath11k_peer_cleanup(struct ath11k *
|
|
spin_unlock_bh(&ab->base_lock);
|
|
}
|
|
|
|
-static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr)
|
|
+int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr)
|
|
{
|
|
return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false);
|
|
}
|
|
|
|
+int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
|
|
+ const u8 *addr)
|
|
+{
|
|
+ int ret;
|
|
+ unsigned long time_left;
|
|
+
|
|
+ ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "failed wait for peer deleted");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ time_left = wait_for_completion_timeout(&ar->peer_delete_done,
|
|
+ 3 * HZ);
|
|
+ if (time_left == 0) {
|
|
+ ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
|
|
{
|
|
int ret;
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
+ reinit_completion(&ar->peer_delete_done);
|
|
+
|
|
ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
|
|
if (ret) {
|
|
ath11k_warn(ar->ab,
|
|
@@ -191,7 +215,7 @@ int ath11k_peer_delete(struct ath11k *ar
|
|
return ret;
|
|
}
|
|
|
|
- ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr);
|
|
+ ret = ath11k_wait_for_peer_delete_done(ar, vdev_id, addr);
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -247,8 +271,22 @@ int ath11k_peer_create(struct ath11k *ar
|
|
spin_unlock_bh(&ar->ab->base_lock);
|
|
ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
|
|
param->peer_addr, param->vdev_id);
|
|
- ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr,
|
|
- param->vdev_id);
|
|
+
|
|
+ reinit_completion(&ar->peer_delete_done);
|
|
+
|
|
+ ret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr,
|
|
+ param->vdev_id);
|
|
+ if(ret) {
|
|
+ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
|
|
+ param->vdev_id, param->peer_addr);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id,
|
|
+ param->peer_addr);
|
|
+ if(ret)
|
|
+ return ret;
|
|
+
|
|
return -ENOENT;
|
|
}
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -5746,15 +5746,29 @@ static int ath11k_ready_event(struct ath
|
|
static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff *skb)
|
|
{
|
|
struct wmi_peer_delete_resp_event peer_del_resp;
|
|
+ struct ath11k *ar;
|
|
|
|
if (ath11k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) {
|
|
ath11k_warn(ab, "failed to extract peer delete resp");
|
|
return;
|
|
}
|
|
|
|
- /* TODO: Do we need to validate whether ath11k_peer_find() return NULL
|
|
- * Why this is needed when there is HTT event for peer delete
|
|
- */
|
|
+ rcu_read_lock();
|
|
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, peer_del_resp.vdev_id);
|
|
+ if (!ar) {
|
|
+ ath11k_warn(ab, "invalid vdev id in peer delete resp ev %d",
|
|
+ peer_del_resp.vdev_id);
|
|
+ rcu_read_unlock();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ complete(&ar->peer_delete_done);
|
|
+
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "peer delete resp for vdev id %d addr %pM\n",
|
|
+ peer_del_resp.vdev_id, peer_del_resp.peer_macaddr.addr);
|
|
+
|
|
}
|
|
|
|
static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab, struct sk_buff *skb)
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.h
|
|
@@ -147,6 +147,8 @@ void ath11k_mac_drain_tx(struct ath11k *
|
|
void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
|
|
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
|
|
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
|
|
+struct ath11k *ath11k_mac_get_ar_peer_delete_status(struct ath11k_base *ab, u8 *peer_addr,
|
|
+ u32 vdev_id);
|
|
enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
|
|
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
|
|
#endif
|
|
--- a/drivers/net/wireless/ath/ath11k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
|
@@ -710,6 +710,7 @@ static void ath11k_core_restart(struct w
|
|
complete(&ar->scan.started);
|
|
complete(&ar->scan.completed);
|
|
complete(&ar->peer_assoc_done);
|
|
+ complete(&ar->peer_delete_done);
|
|
complete(&ar->install_key_done);
|
|
complete(&ar->vdev_setup_done);
|
|
complete(&ar->vdev_delete_done);
|
|
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
|
@@ -41,5 +41,7 @@ void ath11k_peer_cleanup(struct ath11k *
|
|
int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr);
|
|
int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
struct ieee80211_sta *sta, struct peer_create_params *param);
|
|
+int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr);
|
|
+int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, const u8 *addr);
|
|
|
|
#endif /* _PEER_H_ */
|