Commit 690ace20 authored by Ritesh Singh's avatar Ritesh Singh Committed by Kalle Valo

ath11k: peer delete synchronization with firmware

Peer creation in firmware fails, if last peer deletion
is still in progress.
Hence, add wait for the event after deleting every peer
from host driver to synchronize with firmware.
Signed-off-by: default avatarRitesh Singh <ritesi@codeaurora.org>
Signed-off-by: default avatarMaharaja Kennadyrajan <mkenna@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1605514143-17652-3-git-send-email-mkenna@codeaurora.org
parent 3cbbdfbe
...@@ -808,6 +808,7 @@ static void ath11k_core_restart(struct work_struct *work) ...@@ -808,6 +808,7 @@ static void ath11k_core_restart(struct work_struct *work)
complete(&ar->scan.started); complete(&ar->scan.started);
complete(&ar->scan.completed); complete(&ar->scan.completed);
complete(&ar->peer_assoc_done); complete(&ar->peer_assoc_done);
complete(&ar->peer_delete_done);
complete(&ar->install_key_done); complete(&ar->install_key_done);
complete(&ar->vdev_setup_done); complete(&ar->vdev_setup_done);
complete(&ar->vdev_delete_done); complete(&ar->vdev_delete_done);
......
...@@ -506,6 +506,7 @@ struct ath11k { ...@@ -506,6 +506,7 @@ struct ath11k {
u8 lmac_id; u8 lmac_id;
struct completion peer_assoc_done; struct completion peer_assoc_done;
struct completion peer_delete_done;
int install_key_status; int install_key_status;
struct completion install_key_done; struct completion install_key_done;
......
...@@ -4624,8 +4624,22 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, ...@@ -4624,8 +4624,22 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
err_peer_del: err_peer_del:
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
reinit_completion(&ar->peer_delete_done);
ret = ath11k_wmi_send_peer_delete_cmd(ar, vif->addr,
arvif->vdev_id);
if (ret) {
ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
arvif->vdev_id, vif->addr);
return ret;
}
ret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id,
vif->addr);
if (ret)
return ret;
ar->num_peers--; ar->num_peers--;
ath11k_wmi_send_peer_delete_cmd(ar, vif->addr, arvif->vdev_id);
} }
err_vdev_del: err_vdev_del:
...@@ -6470,6 +6484,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab) ...@@ -6470,6 +6484,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
init_completion(&ar->vdev_setup_done); init_completion(&ar->vdev_setup_done);
init_completion(&ar->vdev_delete_done); init_completion(&ar->vdev_delete_done);
init_completion(&ar->peer_assoc_done); init_completion(&ar->peer_assoc_done);
init_completion(&ar->peer_delete_done);
init_completion(&ar->install_key_done); init_completion(&ar->install_key_done);
init_completion(&ar->bss_survey_done); init_completion(&ar->bss_survey_done);
init_completion(&ar->scan.started); init_completion(&ar->scan.started);
......
...@@ -177,12 +177,36 @@ static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 ...@@ -177,12 +177,36 @@ static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8
return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false); 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 ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
{ {
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
reinit_completion(&ar->peer_delete_done);
ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
if (ret) { if (ret) {
ath11k_warn(ar->ab, ath11k_warn(ar->ab,
...@@ -191,7 +215,7 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) ...@@ -191,7 +215,7 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
return ret; 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) if (ret)
return ret; return ret;
...@@ -247,8 +271,22 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -247,8 +271,22 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&ar->ab->base_lock); spin_unlock_bh(&ar->ab->base_lock);
ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
param->peer_addr, param->vdev_id); 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; return -ENOENT;
} }
......
...@@ -41,5 +41,7 @@ void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id); ...@@ -41,5 +41,7 @@ void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id);
int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr); int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr);
int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
struct ieee80211_sta *sta, struct peer_create_params *param); struct ieee80211_sta *sta, struct peer_create_params *param);
int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
const u8 *addr);
#endif /* _PEER_H_ */ #endif /* _PEER_H_ */
...@@ -5730,15 +5730,26 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb) ...@@ -5730,15 +5730,26 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb)
static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff *skb) 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 wmi_peer_delete_resp_event peer_del_resp;
struct ath11k *ar;
if (ath11k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) { if (ath11k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) {
ath11k_warn(ab, "failed to extract peer delete resp"); ath11k_warn(ab, "failed to extract peer delete resp");
return; return;
} }
/* TODO: Do we need to validate whether ath11k_peer_find() return NULL rcu_read_lock();
* Why this is needed when there is HTT event for peer delete 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, static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab,
......
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