iwlwifi: mvm: use fast balance scan in case of DCM mode with P2P GO
authorAyala Beker <ayala.beker@intel.com>
Wed, 4 Jul 2018 09:08:23 +0000 (12:08 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Mon, 8 Oct 2018 07:36:18 +0000 (10:36 +0300)
Currently in case of DCM with P2P GO where BSS DTIM interval < 220 msec
the fw fails to allocate events for the P2P GO dtim due to long passive
scan events.

Fix this by requesting all scans in this scenario to be fragmented with
fast balance scan time settings.  The only exception is in case
fragmented scan was planned to be set due to low latency or high
throughput reason, set the scan timing as planned.

Signed-off-by: Ayala Beker <ayala.beker@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/scan.c

index b43bf116c7e83df47a30cb98086273ff136c67cd..cfb784fea77bbce100b64c03765c826ce7c271a1 100644 (file)
@@ -239,8 +239,32 @@ iwl_mvm_get_traffic_load_band(struct iwl_mvm *mvm, enum nl80211_band band)
        return mvm->tcm.result.band_load[band];
 }
 
+struct iwl_is_dcm_with_go_iterator_data {
+       struct ieee80211_vif *current_vif;
+       bool is_dcm_with_p2p_go;
+};
+
+static void iwl_mvm_is_dcm_with_go_iterator(void *_data, u8 *mac,
+                                           struct ieee80211_vif *vif)
+{
+       struct iwl_is_dcm_with_go_iterator_data *data = _data;
+       struct iwl_mvm_vif *other_mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm_vif *curr_mvmvif =
+               iwl_mvm_vif_from_mac80211(data->current_vif);
+
+       /* exclude the given vif */
+       if (vif == data->current_vif)
+               return;
+
+       if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
+           other_mvmvif->phy_ctxt && curr_mvmvif->phy_ctxt &&
+           other_mvmvif->phy_ctxt->id != curr_mvmvif->phy_ctxt->id)
+               data->is_dcm_with_p2p_go = true;
+}
+
 static enum
-iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device,
+iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm,
+                                        struct ieee80211_vif *vif,
                                         enum iwl_mvm_traffic_load load,
                                         bool low_latency)
 {
@@ -253,9 +277,30 @@ iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device,
        if (!global_cnt)
                return IWL_SCAN_TYPE_UNASSOC;
 
-       if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) && !p2p_device &&
-           fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAGMENTED_SCAN))
-               return IWL_SCAN_TYPE_FRAGMENTED;
+       if (fw_has_api(&mvm->fw->ucode_capa,
+                      IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {
+               if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) &&
+                   (!vif || vif->type != NL80211_IFTYPE_P2P_DEVICE))
+                       return IWL_SCAN_TYPE_FRAGMENTED;
+
+               /* in case of DCM with GO where BSS DTIM interval < 220msec
+                * set all scan requests as fast-balance scan
+                * */
+               if (vif && vif->type == NL80211_IFTYPE_STATION &&
+                   vif->bss_conf.dtim_period < 220) {
+                       struct iwl_is_dcm_with_go_iterator_data data = {
+                               .current_vif = vif,
+                               .is_dcm_with_p2p_go = false,
+                       };
+
+                       ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+                                               IEEE80211_IFACE_ITER_NORMAL,
+                                               iwl_mvm_is_dcm_with_go_iterator,
+                                               &data);
+                       if (data.is_dcm_with_p2p_go)
+                               return IWL_SCAN_TYPE_FAST_BALANCE;
+               }
+       }
 
        if (load >= IWL_MVM_TRAFFIC_MEDIUM || low_latency)
                return IWL_SCAN_TYPE_MILD;
@@ -264,7 +309,8 @@ iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device,
 }
 
 static enum
-iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
+iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif)
 {
        enum iwl_mvm_traffic_load load;
        bool low_latency;
@@ -272,12 +318,12 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
        load = iwl_mvm_get_traffic_load(mvm);
        low_latency = iwl_mvm_low_latency(mvm);
 
-       return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency);
+       return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency);
 }
 
 static enum
 iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm,
-                                            bool p2p_device,
+                                            struct ieee80211_vif *vif,
                                             enum nl80211_band band)
 {
        enum iwl_mvm_traffic_load load;
@@ -286,7 +332,7 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm,
        load = iwl_mvm_get_traffic_load_band(mvm, band);
        low_latency = iwl_mvm_low_latency_band(mvm, band);
 
-       return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency);
+       return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency);
 }
 
 static int
@@ -1054,7 +1100,7 @@ static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels)
 static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
                                        u32 flags, u8 channel_flags)
 {
-       enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
+       enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL);
        struct iwl_scan_config_v1 *cfg = config;
 
        cfg->flags = cpu_to_le32(flags);
@@ -1087,9 +1133,9 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
        if (iwl_mvm_is_cdb_supported(mvm)) {
                enum iwl_mvm_scan_type lb_type, hb_type;
 
-               lb_type = iwl_mvm_get_scan_type_band(mvm, false,
+               lb_type = iwl_mvm_get_scan_type_band(mvm, NULL,
                                                     NL80211_BAND_2GHZ);
-               hb_type = iwl_mvm_get_scan_type_band(mvm, false,
+               hb_type = iwl_mvm_get_scan_type_band(mvm, NULL,
                                                     NL80211_BAND_5GHZ);
 
                cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =
@@ -1103,7 +1149,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
                        cpu_to_le32(scan_timing[hb_type].suspend_time);
        } else {
                enum iwl_mvm_scan_type type =
-                       iwl_mvm_get_scan_type(mvm, false);
+                       iwl_mvm_get_scan_type(mvm, NULL);
 
                cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =
                        cpu_to_le32(scan_timing[type].max_out_time);
@@ -1140,14 +1186,14 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
                return -ENOBUFS;
 
        if (iwl_mvm_is_cdb_supported(mvm)) {
-               type = iwl_mvm_get_scan_type_band(mvm, false,
+               type = iwl_mvm_get_scan_type_band(mvm, NULL,
                                                  NL80211_BAND_2GHZ);
-               hb_type = iwl_mvm_get_scan_type_band(mvm, false,
+               hb_type = iwl_mvm_get_scan_type_band(mvm, NULL,
                                                     NL80211_BAND_5GHZ);
                if (type == mvm->scan_type && hb_type == mvm->hb_scan_type)
                        return 0;
        } else {
-               type = iwl_mvm_get_scan_type(mvm, false);
+               type = iwl_mvm_get_scan_type(mvm, NULL);
                if (type == mvm->scan_type)
                        return 0;
        }
@@ -1599,19 +1645,20 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work)
 
 static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,
                                   struct iwl_mvm_scan_params *params,
-                                  bool p2p)
+                                  struct ieee80211_vif *vif)
 {
        if (iwl_mvm_is_cdb_supported(mvm)) {
                params->type =
-                       iwl_mvm_get_scan_type_band(mvm, p2p,
+                       iwl_mvm_get_scan_type_band(mvm, vif,
                                                   NL80211_BAND_2GHZ);
                params->hb_type =
-                       iwl_mvm_get_scan_type_band(mvm, p2p,
+                       iwl_mvm_get_scan_type_band(mvm, vif,
                                                   NL80211_BAND_5GHZ);
        } else {
-               params->type = iwl_mvm_get_scan_type(mvm, p2p);
+               params->type = iwl_mvm_get_scan_type(mvm, vif);
        }
 }
+
 int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                           struct cfg80211_scan_request *req,
                           struct ieee80211_scan_ies *ies)
@@ -1659,8 +1706,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        params.scan_plans = &scan_plan;
        params.n_scan_plans = 1;
 
-       iwl_mvm_fill_scan_type(mvm, &params,
-                              vif->type == NL80211_IFTYPE_P2P_DEVICE);
+       iwl_mvm_fill_scan_type(mvm, &params, vif);
 
        ret = iwl_mvm_get_measurement_dwell(mvm, req, &params);
        if (ret < 0)
@@ -1755,8 +1801,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
        params.n_scan_plans = req->n_scan_plans;
        params.scan_plans = req->scan_plans;
 
-       iwl_mvm_fill_scan_type(mvm, &params,
-                              vif->type == NL80211_IFTYPE_P2P_DEVICE);
+       iwl_mvm_fill_scan_type(mvm, &params, vif);
 
        /* In theory, LMAC scans can handle a 32-bit delay, but since
         * waiting for over 18 hours to start the scan is a bit silly