Commit c6f537a1 authored by Dundi Raviteja's avatar Dundi Raviteja Committed by Kalle Valo

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: default avatarDundi Raviteja <dundi@codeaurora.org>
Signed-off-by: default avatarRakesh Pillai <pillair@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent fe36e70f
......@@ -3167,6 +3167,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
init_completion(&ar->vdev_delete_done);
init_completion(&ar->thermal.wmi_sync);
init_completion(&ar->bss_survey_done);
init_completion(&ar->peer_delete_done);
INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);
......
......@@ -1208,6 +1208,7 @@ struct ath10k {
struct ath10k_radar_found_info last_radar_info;
struct work_struct radar_confirmation_work;
struct ath10k_bus_params bus_param;
struct completion peer_delete_done;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
......
......@@ -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);
}
......
......@@ -465,6 +465,24 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
kfree(tb);
}
static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
struct sk_buff *skb)
{
struct wmi_peer_delete_resp_ev_arg *arg;
struct wmi_tlv *tlv_hdr;
tlv_hdr = (struct wmi_tlv *)skb->data;
arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;
ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");
complete(&ar->peer_delete_done);
return 0;
}
/***********/
/* TLV ops */
/***********/
......@@ -617,6 +635,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_TLV_TDLS_PEER_EVENTID:
ath10k_wmi_event_tdls_peer(ar, skb);
break;
case WMI_TLV_PEER_DELETE_RESP_EVENTID:
ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
break;
case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
ath10k_wmi_event_mgmt_tx_compl(ar, skb);
break;
......
......@@ -308,6 +308,8 @@ enum wmi_tlv_event_id {
WMI_TLV_PEER_TX_FAIL_CNT_THR_EVENTID,
WMI_TLV_PEER_ESTIMATED_LINKSPEED_EVENTID,
WMI_TLV_PEER_STATE_EVENTID,
WMI_TLV_PEER_ASSOC_CONF_EVENTID,
WMI_TLV_PEER_DELETE_RESP_EVENTID,
WMI_TLV_MGMT_RX_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MGMT),
WMI_TLV_HOST_SWBA_EVENTID,
WMI_TLV_TBTTOFFSET_UPDATE_EVENTID,
......
......@@ -6760,6 +6760,11 @@ struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
const __le32 *ack_rssi;
};
struct wmi_peer_delete_resp_ev_arg {
__le32 vdev_id;
struct wmi_mac_addr peer_addr;
};
struct wmi_mgmt_rx_ev_arg {
__le32 channel;
__le32 snr;
......
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