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: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
Kalle Valo 2014-01-20 11:01:46 +02:00
parent 542fb17400
commit 5a13e76eca
4 changed files with 88 additions and 8 deletions

View File

@ -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 {

View File

@ -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) {

View File

@ -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();
} }
/* /*

View File

@ -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 */