Merge commit 'c1e140bf79d817d4a7aa9932eb98b0359c87af33' from mac80211-next
[sfrench/cifs-2.6.git] / drivers / net / wireless / ath / ath10k / mac.c
index 2619db1e3e7468c05c8232749ca1d8a448a48afb..08f293411bf0957cc720c67b3b1a1e2bfe0733a3 100644 (file)
@@ -27,6 +27,8 @@
 #include "htt.h"
 #include "txrx.h"
 #include "testmode.h"
+#include "wmi.h"
+#include "wmi-ops.h"
 
 /**********/
 /* Crypto */
@@ -267,7 +269,10 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
        case IEEE80211_BAND_2GHZ:
                switch (chandef->width) {
                case NL80211_CHAN_WIDTH_20_NOHT:
-                       phymode = MODE_11G;
+                       if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM)
+                               phymode = MODE_11B;
+                       else
+                               phymode = MODE_11G;
                        break;
                case NL80211_CHAN_WIDTH_20:
                        phymode = MODE_11NG_HT20;
@@ -1046,28 +1051,85 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
                            arvif->vdev_id, ret);
 }
 
-/*
- * Review this when mac80211 gains per-interface powersave support.
- */
+static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
+{
+       struct ath10k *ar = arvif->ar;
+       u32 param;
+       u32 value;
+       int ret;
+
+       lockdep_assert_held(&arvif->ar->conf_mutex);
+
+       if (arvif->u.sta.uapsd)
+               value = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
+       else
+               value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
+
+       param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
+       ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, value);
+       if (ret) {
+               ath10k_warn(ar, "failed to submit ps wake threshold %u on vdev %i: %d\n",
+                           value, arvif->vdev_id, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
+{
+       struct ath10k *ar = arvif->ar;
+       u32 param;
+       u32 value;
+       int ret;
+
+       lockdep_assert_held(&arvif->ar->conf_mutex);
+
+       if (arvif->u.sta.uapsd)
+               value = WMI_STA_PS_PSPOLL_COUNT_UAPSD;
+       else
+               value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
+
+       param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
+       ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
+                                         param, value);
+       if (ret) {
+               ath10k_warn(ar, "failed to submit ps poll count %u on vdev %i: %d\n",
+                           value, arvif->vdev_id, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
 {
        struct ath10k *ar = arvif->ar;
+       struct ieee80211_vif *vif = arvif->vif;
        struct ieee80211_conf *conf = &ar->hw->conf;
        enum wmi_sta_powersave_param param;
        enum wmi_sta_ps_mode psmode;
        int ret;
+       int ps_timeout;
 
        lockdep_assert_held(&arvif->ar->conf_mutex);
 
        if (arvif->vif->type != NL80211_IFTYPE_STATION)
                return 0;
 
-       if (conf->flags & IEEE80211_CONF_PS) {
+       if (vif->bss_conf.ps) {
                psmode = WMI_STA_PS_MODE_ENABLED;
                param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
 
+               ps_timeout = conf->dynamic_ps_timeout;
+               if (ps_timeout == 0) {
+                       /* Firmware doesn't like 0 */
+                       ps_timeout = ieee80211_tu_to_usec(
+                               vif->bss_conf.beacon_int) / 1000;
+               }
+
                ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
-                                                 conf->dynamic_ps_timeout);
+                                                 ps_timeout);
                if (ret) {
                        ath10k_warn(ar, "failed to set inactivity time for vdev %d: %i\n",
                                    arvif->vdev_id, ret);
@@ -1409,9 +1471,22 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
                if (vif->bss_conf.qos)
                        arg->peer_flags |= WMI_PEER_QOS;
                break;
+       case WMI_VDEV_TYPE_IBSS:
+               if (sta->wme)
+                       arg->peer_flags |= WMI_PEER_QOS;
+               break;
        default:
                break;
        }
+
+       ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
+                  sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
+}
+
+static bool ath10k_mac_sta_has_11g_rates(struct ieee80211_sta *sta)
+{
+       /* First 4 rates in ath10k_rates are CCK (11b) rates. */
+       return sta->supp_rates[IEEE80211_BAND_2GHZ] >> 4;
 }
 
 static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
@@ -1428,8 +1503,10 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
                                phymode = MODE_11NG_HT40;
                        else
                                phymode = MODE_11NG_HT20;
-               } else {
+               } else if (ath10k_mac_sta_has_11g_rates(sta)) {
                        phymode = MODE_11G;
+               } else {
+                       phymode = MODE_11B;
                }
 
                break;
@@ -2896,10 +2973,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        arvif->vdev_id = bit;
        arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
 
-       if (ar->p2p)
-               arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
-
        switch (vif->type) {
+       case NL80211_IFTYPE_P2P_DEVICE:
+               arvif->vdev_type = WMI_VDEV_TYPE_STA;
+               arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
+               break;
        case NL80211_IFTYPE_UNSPECIFIED:
        case NL80211_IFTYPE_STATION:
                arvif->vdev_type = WMI_VDEV_TYPE_STA;
@@ -3028,22 +3106,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
                        goto err_peer_delete;
                }
 
-               param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
-               value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
-               ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
-                                                 param, value);
+               ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
                if (ret) {
-                       ath10k_warn(ar, "failed to set vdev %i TX wake thresh: %d\n",
+                       ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
                                    arvif->vdev_id, ret);
                        goto err_peer_delete;
                }
 
-               param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
-               value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
-               ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
-                                                 param, value);
+               ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
                if (ret) {
-                       ath10k_warn(ar, "failed to set vdev %i PSPOLL count: %d\n",
+                       ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
                                    arvif->vdev_id, ret);
                        goto err_peer_delete;
                }
@@ -3316,6 +3388,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
                        ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
        }
 
+       if (changed & BSS_CHANGED_PS) {
+               ret = ath10k_mac_vif_setup_ps(arvif);
+               if (ret)
+                       ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
+                                   arvif->vdev_id, ret);
+       }
+
        mutex_unlock(&ar->conf_mutex);
 }
 
@@ -3585,8 +3664,9 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
                                    sta->addr, smps, err);
        }
 
-       if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
-               ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
+       if (changed & IEEE80211_RC_SUPP_RATES_CHANGED ||
+           changed & IEEE80211_RC_NSS_CHANGED) {
+               ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n",
                           sta->addr);
 
                err = ath10k_station_assoc(ar, arvif->vif, sta, true);
@@ -3810,6 +3890,20 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
        if (ret)
                ath10k_warn(ar, "failed to set rx wake param: %d\n", ret);
 
+       ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
+       if (ret) {
+               ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
+                           arvif->vdev_id, ret);
+               return ret;
+       }
+
+       ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
+       if (ret) {
+               ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
+                           arvif->vdev_id, ret);
+               return ret;
+       }
+
 exit:
        return ret;
 }
@@ -3991,29 +4085,6 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
        return ret;
 }
 
-static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
-{
-       struct ath10k *ar = hw->priv;
-       struct ath10k_vif *arvif;
-       int ret = 0;
-
-       mutex_lock(&ar->conf_mutex);
-       list_for_each_entry(arvif, &ar->arvifs, list) {
-               ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
-                          arvif->vdev_id, value);
-
-               ret = ath10k_mac_set_frag(arvif, value);
-               if (ret) {
-                       ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n",
-                                   arvif->vdev_id, ret);
-                       break;
-               }
-       }
-       mutex_unlock(&ar->conf_mutex);
-
-       return ret;
-}
-
 static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                         u32 queues, bool drop)
 {
@@ -4657,7 +4728,6 @@ static const struct ieee80211_ops ath10k_ops = {
        .remain_on_channel              = ath10k_remain_on_channel,
        .cancel_remain_on_channel       = ath10k_cancel_remain_on_channel,
        .set_rts_threshold              = ath10k_set_rts_threshold,
-       .set_frag_threshold             = ath10k_set_frag_threshold,
        .flush                          = ath10k_flush,
        .tx_last_beacon                 = ath10k_tx_last_beacon,
        .set_antenna                    = ath10k_set_antenna,
@@ -4748,6 +4818,9 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
        CHAN5G(165, 5825, 0),
 };
 
+/* Note: Be careful if you re-order these. There is code which depends on this
+ * ordering.
+ */
 static struct ieee80211_rate ath10k_rates[] = {
        /* CCK */
        RATETAB_ENT(10,  0x82, 0),
@@ -4801,6 +4874,10 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
        .types  = BIT(NL80211_IFTYPE_P2P_GO)
        },
        {
+       .max    = 1,
+       .types  = BIT(NL80211_IFTYPE_P2P_DEVICE)
+       },
+       {
        .max    = 7,
        .types  = BIT(NL80211_IFTYPE_AP)
        },
@@ -5020,6 +5097,7 @@ int ath10k_mac_register(struct ath10k *ar)
 
        if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
                ar->hw->wiphy->interface_modes |=
+                       BIT(NL80211_IFTYPE_P2P_DEVICE) |
                        BIT(NL80211_IFTYPE_P2P_CLIENT) |
                        BIT(NL80211_IFTYPE_P2P_GO);
 
@@ -5063,16 +5141,26 @@ int ath10k_mac_register(struct ath10k *ar)
         */
        ar->hw->queues = 4;
 
-       if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-               ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
-               ar->hw->wiphy->n_iface_combinations =
-                       ARRAY_SIZE(ath10k_10x_if_comb);
-       } else {
+       switch (ar->wmi.op_version) {
+       case ATH10K_FW_WMI_OP_VERSION_MAIN:
+       case ATH10K_FW_WMI_OP_VERSION_TLV:
                ar->hw->wiphy->iface_combinations = ath10k_if_comb;
                ar->hw->wiphy->n_iface_combinations =
                        ARRAY_SIZE(ath10k_if_comb);
-
                ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+               break;
+       case ATH10K_FW_WMI_OP_VERSION_10_1:
+       case ATH10K_FW_WMI_OP_VERSION_10_2:
+       case ATH10K_FW_WMI_OP_VERSION_10_2_4:
+               ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
+               ar->hw->wiphy->n_iface_combinations =
+                       ARRAY_SIZE(ath10k_10x_if_comb);
+               break;
+       case ATH10K_FW_WMI_OP_VERSION_UNSET:
+       case ATH10K_FW_WMI_OP_VERSION_MAX:
+               WARN_ON(1);
+               ret = -EINVAL;
+               goto err_free;
        }
 
        ar->hw->netdev_features = NETIF_F_HW_CSUM;