Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a13e76e authored by Kalle Valo's avatar Kalle Valo
Browse files

ath10k: enable firmware STA quick kickout



Firmware has a feature to track if the associated STA is not acking the frames.
When that happens, the firmware sends WMI_PEER_STA_KICKOUT_EVENTID event to the
host. Enable that to faster detect when a STA has left BSS without sending a
deauth frame.

Also set huge keepalive timeouts to avoid using the keepalive functionality in
the firmware.

Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 542fb174
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,18 @@


#define ATH10K_MAX_NUM_MGMT_PENDING 128
#define ATH10K_MAX_NUM_MGMT_PENDING 128


/* number of failed packets */
#define ATH10K_KICKOUT_THRESHOLD 50

/*
 * Use insanely high numbers to make sure that the firmware implementation
 * won't start, we have the same functionality already in hostapd. Unit
 * is seconds.
 */
#define ATH10K_KEEPALIVE_MIN_IDLE 3747
#define ATH10K_KEEPALIVE_MAX_IDLE 3895
#define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900

struct ath10k;
struct ath10k;


struct ath10k_skb_cb {
struct ath10k_skb_cb {
+51 −7
Original line number Original line Diff line number Diff line
@@ -339,6 +339,50 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
	return 0;
	return 0;
}
}


static int ath10k_mac_set_kickout(struct ath10k_vif *arvif)
{
	struct ath10k *ar = arvif->ar;
	u32 param;
	int ret;

	param = ar->wmi.pdev_param->sta_kickout_th;
	ret = ath10k_wmi_pdev_set_param(ar, param,
					ATH10K_KICKOUT_THRESHOLD);
	if (ret) {
		ath10k_warn("Failed to set kickout threshold: %d\n", ret);
		return ret;
	}

	param = ar->wmi.vdev_param->ap_keepalive_min_idle_inactive_time_secs;
	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
					ATH10K_KEEPALIVE_MIN_IDLE);
	if (ret) {
		ath10k_warn("Failed to set keepalive minimum idle time : %d\n",
			    ret);
		return ret;
	}

	param = ar->wmi.vdev_param->ap_keepalive_max_idle_inactive_time_secs;
	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
					ATH10K_KEEPALIVE_MAX_IDLE);
	if (ret) {
		ath10k_warn("Failed to set keepalive maximum idle time: %d\n",
			    ret);
		return ret;
	}

	param = ar->wmi.vdev_param->ap_keepalive_max_unresponsive_time_secs;
	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
					ATH10K_KEEPALIVE_MAX_UNRESPONSIVE);
	if (ret) {
		ath10k_warn("Failed to set keepalive maximum unresponsive time: %d\n",
			    ret);
		return ret;
	}

	return 0;
}

static int  ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
static int  ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
{
{
	struct ath10k *ar = arvif->ar;
	struct ath10k *ar = arvif->ar;
@@ -2214,7 +2258,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
	enum wmi_sta_powersave_param param;
	enum wmi_sta_powersave_param param;
	int ret = 0;
	int ret = 0;
	u32 value, param_id;
	u32 value;
	int bit;
	int bit;
	u32 vdev_param;
	u32 vdev_param;


@@ -2307,12 +2351,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
			goto err_vdev_delete;
			goto err_vdev_delete;
		}
		}


		param_id = ar->wmi.pdev_param->sta_kickout_th;
		ret = ath10k_mac_set_kickout(arvif);

		if (ret) {
		/* Disable STA KICKOUT functionality in FW */
			ath10k_warn("Failed to set kickout parameters: %d\n",
		ret = ath10k_wmi_pdev_set_param(ar, param_id, 0);
				    ret);
		if (ret)
			goto err_peer_delete;
			ath10k_warn("Failed to disable STA KICKOUT\n");
		}
	}
	}


	if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
	if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
+21 −1
Original line number Original line Diff line number Diff line
@@ -1116,7 +1116,27 @@ static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar,
static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar,
static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar,
					      struct sk_buff *skb)
					      struct sk_buff *skb)
{
{
	ath10k_dbg(ATH10K_DBG_WMI, "WMI_PEER_STA_KICKOUT_EVENTID\n");
	struct wmi_peer_sta_kickout_event *ev;
	struct ieee80211_sta *sta;

	ev = (struct wmi_peer_sta_kickout_event *)skb->data;

	ath10k_dbg(ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n",
		   ev->peer_macaddr.addr);

	rcu_read_lock();

	sta = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL);
	if (!sta) {
		ath10k_warn("Spurious quick kickout for STA %pM\n",
			    ev->peer_macaddr.addr);
		goto exit;
	}

	ieee80211_report_low_ack(sta, 10);

exit:
	rcu_read_unlock();
}
}


/*
/*
+4 −0
Original line number Original line Diff line number Diff line
@@ -4039,6 +4039,10 @@ struct wmi_chan_info_event {
	__le32 cycle_count;
	__le32 cycle_count;
} __packed;
} __packed;


struct wmi_peer_sta_kickout_event {
	struct wmi_mac_addr peer_macaddr;
} __packed;

#define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)
#define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)


/* FIXME: empirically extrapolated */
/* FIXME: empirically extrapolated */