ath10k: Add peer delete response event

Peer creation in firmware fails if last peer deletion is still
in progress.

The firmware sends a peer delete response event if it advertises
the service WMI_SERVICE_SYNC_DELETE_CMDS. This peer delete response
event is used to synchronize the peer deletion.

Add peer delete response event and wait for the event after
deleting every peer from host driver to synchronize with firmware.

Tested HW: WCN3990
Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1

Signed-off-by: Dundi Raviteja <dundi@codeaurora.org>
Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Dundi Raviteja
2019-06-03 17:41:51 +03:00
committed by Kalle Valo
parent fe36e70f76
commit c6f537a11b
6 changed files with 69 additions and 2 deletions

View File

@@ -693,6 +693,26 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
*def = &conf->def;
}
static void ath10k_wait_for_peer_delete_done(struct ath10k *ar, u32 vdev_id,
const u8 *addr)
{
unsigned long time_left;
int ret;
if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
ret = ath10k_wait_for_peer_deleted(ar, vdev_id, addr);
if (ret) {
ath10k_warn(ar, "failed wait for peer deleted");
return;
}
time_left = wait_for_completion_timeout(&ar->peer_delete_done,
5 * HZ);
if (!time_left)
ath10k_warn(ar, "Timeout in receiving peer delete response\n");
}
}
static int ath10k_peer_create(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -737,7 +757,7 @@ static int ath10k_peer_create(struct ath10k *ar,
spin_unlock_bh(&ar->data_lock);
ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n",
addr, vdev_id);
ath10k_wmi_peer_delete(ar, vdev_id, addr);
ath10k_wait_for_peer_delete_done(ar, vdev_id, addr);
return -ENOENT;
}
@@ -819,6 +839,18 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
if (ret)
return ret;
if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
unsigned long time_left;
time_left = wait_for_completion_timeout
(&ar->peer_delete_done, 5 * HZ);
if (!time_left) {
ath10k_warn(ar, "Timeout in receiving peer delete response\n");
return -ETIMEDOUT;
}
}
ar->num_peers--;
return 0;
@@ -5423,8 +5455,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
err_peer_delete:
if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
arvif->vdev_type == WMI_VDEV_TYPE_IBSS)
arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr);
ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id,
vif->addr);
}
err_vdev_delete:
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
@@ -5490,6 +5525,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to submit AP/IBSS self-peer removal on vdev %i: %d\n",
arvif->vdev_id, ret);
ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id,
vif->addr);
kfree(arvif->u.ap.noa_data);
}