Merge commit 'c1e140bf79d817d4a7aa9932eb98b0359c87af33' from mac80211-next
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / mac.c
index 13c2bad..08f2934 100644 (file)
@@ -269,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;
@@ -1099,28 +1102,34 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
        return 0;
 }
 
-/*
- * Review this when mac80211 gains per-interface powersave support.
- */
 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);
@@ -1462,9 +1471,16 @@ 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)
@@ -2932,6 +2948,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        int bit;
        u32 vdev_param;
 
+       vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
+
        mutex_lock(&ar->conf_mutex);
 
        memset(arvif, 0, sizeof(*arvif));
@@ -2955,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;
@@ -3369,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);
 }
 
@@ -3638,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);
@@ -4847,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)
        },
@@ -5066,13 +5097,13 @@ 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);
 
        ar->hw->flags = IEEE80211_HW_SIGNAL_DBM |
                        IEEE80211_HW_SUPPORTS_PS |
                        IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
-                       IEEE80211_HW_SUPPORTS_UAPSD |
                        IEEE80211_HW_MFP_CAPABLE |
                        IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                        IEEE80211_HW_HAS_RATE_CONTROL |
@@ -5110,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;