diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0c2ccc1011763addf85be6a9b9ec4cc789051914..4ee74f660443a92edd06602ba600eba82dd52eda 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1286,6 +1286,38 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) return 0; } +static int ath10k_mac_vif_disable_keepalive(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + struct wmi_sta_keepalive_arg arg = {}; + int ret; + + lockdep_assert_held(&arvif->ar->conf_mutex); + + if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + return 0; + + if (!test_bit(WMI_SERVICE_STA_KEEP_ALIVE, ar->wmi.svc_map)) + return 0; + + /* Some firmware revisions have a bug and ignore the `enabled` field. + * Instead use the interval to disable the keepalive. + */ + arg.vdev_id = arvif->vdev_id; + arg.enabled = 1; + arg.method = WMI_STA_KEEPALIVE_METHOD_NULL_FRAME; + arg.interval = WMI_STA_KEEPALIVE_INTERVAL_DISABLE; + + ret = ath10k_wmi_sta_keepalive(ar, &arg); + if (ret) { + ath10k_warn(ar, "failed to submit keepalive on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + + return 0; +} + /**********************/ /* Station management */ /**********************/ @@ -3180,6 +3212,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ar->free_vdev_map &= ~(1LL << arvif->vdev_id); list_add(&arvif->list, &ar->arvifs); + /* It makes no sense to have firmware do keepalives. mac80211 already + * takes care of this with idle connection polling. + */ + ret = ath10k_mac_vif_disable_keepalive(arvif); + if (ret) { + ath10k_warn(ar, "failed to disable keepalive on vdev %i: %d\n", + arvif->vdev_id, ret); + goto err_vdev_delete; + } + vdev_param = ar->wmi.vdev_param->def_keyid; ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, arvif->def_wep_key_idx); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 1a99a7dd0e956990c87605d76d302937f87bcabd..4b654083b85727ed769b74237ed368f8adddf05a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4665,6 +4665,11 @@ enum wmi_sta_keepalive_method { WMI_STA_KEEPALIVE_METHOD_UNSOLICITATED_ARP_RESPONSE = 2, }; +#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 + +/* Firmware crashes if keepalive interval exceeds this limit */ +#define WMI_STA_KEEPALIVE_INTERVAL_MAX_SECONDS 0xffff + /* note: ip4 addresses are in network byte order, i.e. big endian */ struct wmi_sta_keepalive_arp_resp { __be32 src_ip4_addr;