]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/ath/ath10k/mac.c
Merge ath-next from ath.git.
[karo-tx-linux.git] / drivers / net / wireless / ath / ath10k / mac.c
index 218b6af63447458fa81960479afeeecf9a1520e9..c9a7d5b5dffc5d367fe0ad9d84f071430eb8fb24 100644 (file)
@@ -1668,7 +1668,7 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
        return 0;
 }
 
-static int ath10k_mac_ps_vif_count(struct ath10k *ar)
+static int ath10k_mac_num_vifs_started(struct ath10k *ar)
 {
        struct ath10k_vif *arvif;
        int num = 0;
@@ -1676,7 +1676,7 @@ static int ath10k_mac_ps_vif_count(struct ath10k *ar)
        lockdep_assert_held(&ar->conf_mutex);
 
        list_for_each_entry(arvif, &ar->arvifs, list)
-               if (arvif->ps)
+               if (arvif->is_started)
                        num++;
 
        return num;
@@ -1700,7 +1700,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
 
        enable_ps = arvif->ps;
 
-       if (enable_ps && ath10k_mac_ps_vif_count(ar) > 1 &&
+       if (enable_ps && ath10k_mac_num_vifs_started(ar) > 1 &&
            !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
                      ar->fw_features)) {
                ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n",
@@ -3034,38 +3034,16 @@ static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif,
 
        lockdep_assert_held(&ar->htt.tx_lock);
 
-       switch (pause_id) {
-       case WMI_TLV_TX_PAUSE_ID_MCC:
-       case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
-       case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
-       case WMI_TLV_TX_PAUSE_ID_AP_PS:
-       case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
-               switch (action) {
-               case WMI_TLV_TX_PAUSE_ACTION_STOP:
-                       ath10k_mac_vif_tx_lock(arvif, pause_id);
-                       break;
-               case WMI_TLV_TX_PAUSE_ACTION_WAKE:
-                       ath10k_mac_vif_tx_unlock(arvif, pause_id);
-                       break;
-               default:
-                       ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
-                                   action, arvif->vdev_id);
-                       break;
-               }
+       switch (action) {
+       case WMI_TLV_TX_PAUSE_ACTION_STOP:
+               ath10k_mac_vif_tx_lock(arvif, pause_id);
+               break;
+       case WMI_TLV_TX_PAUSE_ACTION_WAKE:
+               ath10k_mac_vif_tx_unlock(arvif, pause_id);
                break;
-       case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
-       case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
-       case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
-       case WMI_TLV_TX_PAUSE_ID_HOST:
        default:
-               /* FIXME: Some pause_ids aren't vdev specific. Instead they
-                * target peer_id and tid. Implementing these could improve
-                * traffic scheduling fairness across multiple connected
-                * stations in AP/IBSS modes.
-                */
-               ath10k_dbg(ar, ATH10K_DBG_MAC,
-                          "mac ignoring unsupported tx pause vdev %i id %d\n",
-                          arvif->vdev_id, pause_id);
+               ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
+                           action, arvif->vdev_id);
                break;
        }
 }
@@ -3082,12 +3060,15 @@ static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac,
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
        struct ath10k_mac_tx_pause *arg = data;
 
+       if (arvif->vdev_id != arg->vdev_id)
+               return;
+
        ath10k_mac_vif_handle_tx_pause(arvif, arg->pause_id, arg->action);
 }
 
-void ath10k_mac_handle_tx_pause(struct ath10k *ar, u32 vdev_id,
-                               enum wmi_tlv_tx_pause_id pause_id,
-                               enum wmi_tlv_tx_pause_action action)
+void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
+                                    enum wmi_tlv_tx_pause_id pause_id,
+                                    enum wmi_tlv_tx_pause_action action)
 {
        struct ath10k_mac_tx_pause arg = {
                .vdev_id = vdev_id,
@@ -3449,14 +3430,13 @@ void __ath10k_scan_finish(struct ath10k *ar)
        case ATH10K_SCAN_IDLE:
                break;
        case ATH10K_SCAN_RUNNING:
-               if (ar->scan.is_roc)
-                       ieee80211_remain_on_channel_expired(ar->hw);
-               /* fall through */
        case ATH10K_SCAN_ABORTING:
                if (!ar->scan.is_roc)
                        ieee80211_scan_completed(ar->hw,
                                                 (ar->scan.state ==
                                                  ATH10K_SCAN_ABORTING));
+               else if (ar->scan.roc_notify)
+                       ieee80211_remain_on_channel_expired(ar->hw);
                /* fall through */
        case ATH10K_SCAN_STARTING:
                ar->scan.state = ATH10K_SCAN_IDLE;
@@ -4641,9 +4621,6 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
        arg.vdev_id = arvif->vdev_id;
        arg.scan_id = ATH10K_SCAN_ID;
 
-       if (!req->no_cck)
-               arg.scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES;
-
        if (req->ie_len) {
                arg.ie_len = req->ie_len;
                memcpy(arg.ie, req->ie, arg.ie_len);
@@ -5462,6 +5439,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
                ar->scan.is_roc = true;
                ar->scan.vdev_id = arvif->vdev_id;
                ar->scan.roc_freq = chan->center_freq;
+               ar->scan.roc_notify = true;
                ret = 0;
                break;
        case ATH10K_SCAN_STARTING:
@@ -5525,7 +5503,13 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw)
        struct ath10k *ar = hw->priv;
 
        mutex_lock(&ar->conf_mutex);
+
+       spin_lock_bh(&ar->data_lock);
+       ar->scan.roc_notify = false;
+       spin_unlock_bh(&ar->data_lock);
+
        ath10k_scan_abort(ar);
+
        mutex_unlock(&ar->conf_mutex);
 
        cancel_delayed_work_sync(&ar->scan.timeout);
@@ -5566,7 +5550,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
        struct ath10k *ar = hw->priv;
        bool skip;
-       int ret;
+       long time_left;
 
        /* mac80211 doesn't care if we really xmit queued frames or not
         * we'll collect those frames either way if we stop/delete vdevs */
@@ -5578,7 +5562,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (ar->state == ATH10K_STATE_WEDGED)
                goto skip;
 
-       ret = wait_event_timeout(ar->htt.empty_tx_wq, ({
+       time_left = wait_event_timeout(ar->htt.empty_tx_wq, ({
                        bool empty;
 
                        spin_lock_bh(&ar->htt.tx_lock);
@@ -5592,9 +5576,9 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                        (empty || skip);
                }), ATH10K_FLUSH_TIMEOUT_HZ);
 
-       if (ret <= 0 || skip)
-               ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %i\n",
-                           skip, ar->state, ret);
+       if (time_left == 0 || skip)
+               ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %ld\n",
+                           skip, ar->state, time_left);
 
 skip:
        mutex_unlock(&ar->conf_mutex);
@@ -6219,6 +6203,13 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 
        arvif->is_started = true;
 
+       ret = ath10k_mac_vif_setup_ps(arvif);
+       if (ret) {
+               ath10k_warn(ar, "failed to update vdev %i ps: %d\n",
+                           arvif->vdev_id, ret);
+               goto err_stop;
+       }
+
        if (vif->type == NL80211_IFTYPE_MONITOR) {
                ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, 0, vif->addr);
                if (ret) {
@@ -6236,6 +6227,7 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 err_stop:
        ath10k_vdev_stop(arvif);
        arvif->is_started = false;
+       ath10k_mac_vif_setup_ps(arvif);
 
 err:
        mutex_unlock(&ar->conf_mutex);
@@ -6565,8 +6557,11 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = {
 static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = {
        {
                .max = 2,
-               .types = BIT(NL80211_IFTYPE_STATION) |
-                        BIT(NL80211_IFTYPE_AP) |
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max = 2,
+               .types = BIT(NL80211_IFTYPE_AP) |
                         BIT(NL80211_IFTYPE_P2P_CLIENT) |
                         BIT(NL80211_IFTYPE_P2P_GO),
        },
@@ -6576,6 +6571,26 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = {
        },
 };
 
+static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = {
+       {
+               .max = 2,
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max = 2,
+               .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_AP) |
+                        BIT(NL80211_IFTYPE_P2P_GO),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+       },
+};
+
 static const struct ieee80211_iface_limit ath10k_tlv_if_limit_ibss[] = {
        {
                .max = 1,
@@ -6594,7 +6609,7 @@ static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = {
        {
                .limits = ath10k_tlv_if_limit,
                .num_different_channels = 1,
-               .max_interfaces = 3,
+               .max_interfaces = 4,
                .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit),
        },
        {
@@ -6608,10 +6623,16 @@ static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = {
 static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = {
        {
                .limits = ath10k_tlv_if_limit,
-               .num_different_channels = 2,
-               .max_interfaces = 3,
+               .num_different_channels = 1,
+               .max_interfaces = 4,
                .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit),
        },
+       {
+               .limits = ath10k_tlv_qcs_if_limit,
+               .num_different_channels = 2,
+               .max_interfaces = 4,
+               .n_limits = ARRAY_SIZE(ath10k_tlv_qcs_if_limit),
+       },
        {
                .limits = ath10k_tlv_if_limit_ibss,
                .num_different_channels = 1,
@@ -6620,6 +6641,33 @@ static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = {
        },
 };
 
+static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = {
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max    = 16,
+               .types  = BIT(NL80211_IFTYPE_AP)
+       },
+};
+
+static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
+       {
+               .limits = ath10k_10_4_if_limits,
+               .n_limits = ARRAY_SIZE(ath10k_10_4_if_limits),
+               .max_interfaces = 16,
+               .num_different_channels = 1,
+               .beacon_int_infra_match = true,
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+               .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                       BIT(NL80211_CHAN_WIDTH_20) |
+                                       BIT(NL80211_CHAN_WIDTH_40) |
+                                       BIT(NL80211_CHAN_WIDTH_80),
+#endif
+       },
+};
+
 static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
 {
        struct ieee80211_sta_vht_cap vht_cap = {0};
@@ -6902,6 +6950,8 @@ int ath10k_mac_register(struct ath10k *ar)
                goto err_free;
        }
 
+       wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+
        /*
         * on LL hardware queues are managed entirely by the FW
         * so we only advertise to mac we can do the queues thing
@@ -6941,6 +6991,11 @@ int ath10k_mac_register(struct ath10k *ar)
                ar->hw->wiphy->n_iface_combinations =
                        ARRAY_SIZE(ath10k_10x_if_comb);
                break;
+       case ATH10K_FW_WMI_OP_VERSION_10_4:
+               ar->hw->wiphy->iface_combinations = ath10k_10_4_if_comb;
+               ar->hw->wiphy->n_iface_combinations =
+                       ARRAY_SIZE(ath10k_10_4_if_comb);
+               break;
        case ATH10K_FW_WMI_OP_VERSION_UNSET:
        case ATH10K_FW_WMI_OP_VERSION_MAX:
                WARN_ON(1);