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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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 *));
+39 −2
Original line number Diff line number Diff line
@@ -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);
	}

+21 −0
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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,
Loading