diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/scan.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 115 |
1 files changed, 85 insertions, 30 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index ffcd0ca86041..cfb784fea77b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -110,6 +110,10 @@ static struct iwl_mvm_scan_timing_params scan_timing[] = { .suspend_time = 95, .max_out_time = 44, }, + [IWL_SCAN_TYPE_FAST_BALANCE] = { + .suspend_time = 30, + .max_out_time = 37, + }, }; struct iwl_mvm_scan_params { @@ -235,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) { @@ -249,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; @@ -260,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; @@ -268,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; @@ -282,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 @@ -860,6 +910,12 @@ static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) params->scan_plans[0].iterations == 1; } +static bool iwl_mvm_is_scan_fragmented(enum iwl_mvm_scan_type type) +{ + return (type == IWL_SCAN_TYPE_FRAGMENTED || + type == IWL_SCAN_TYPE_FAST_BALANCE); +} + static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, struct ieee80211_vif *vif) @@ -872,7 +928,7 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; - if (params->type == IWL_SCAN_TYPE_FRAGMENTED) + if (iwl_mvm_is_scan_fragmented(params->type)) flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED; if (iwl_mvm_rrm_scan_needed(mvm) && @@ -895,7 +951,7 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, if (iwl_mvm_is_regular_scan(params) && vif->type != NL80211_IFTYPE_P2P_DEVICE && - params->type != IWL_SCAN_TYPE_FRAGMENTED) + !iwl_mvm_is_scan_fragmented(params->type)) flags |= IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL; return flags; @@ -1044,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); @@ -1077,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] = @@ -1093,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); @@ -1130,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; } @@ -1162,7 +1218,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) SCAN_CONFIG_FLAG_SET_MAC_ADDR | SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS | SCAN_CONFIG_N_CHANNELS(num_channels) | - (type == IWL_SCAN_TYPE_FRAGMENTED ? + (iwl_mvm_is_scan_fragmented(type) ? SCAN_CONFIG_FLAG_SET_FRAGMENTED : SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED); @@ -1177,7 +1233,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) */ if (iwl_mvm_cdb_scan_api(mvm)) { if (iwl_mvm_is_cdb_supported(mvm)) - flags |= (hb_type == IWL_SCAN_TYPE_FRAGMENTED) ? + flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ? SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED; iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags); @@ -1338,11 +1394,11 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT; - if (params->type == IWL_SCAN_TYPE_FRAGMENTED) + if (iwl_mvm_is_scan_fragmented(params->type)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED; if (iwl_mvm_is_cdb_supported(mvm) && - params->hb_type == IWL_SCAN_TYPE_FRAGMENTED) + iwl_mvm_is_scan_fragmented(params->hb_type)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED; if (iwl_mvm_rrm_scan_needed(mvm) && @@ -1380,7 +1436,7 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, */ if (iwl_mvm_is_regular_scan(params) && vif->type != NL80211_IFTYPE_P2P_DEVICE && - params->type != IWL_SCAN_TYPE_FRAGMENTED && + !iwl_mvm_is_scan_fragmented(params->type) && !iwl_mvm_is_adaptive_dwell_supported(mvm) && !iwl_mvm_is_oce_supported(mvm)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL; @@ -1589,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) @@ -1649,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, ¶ms, - vif->type == NL80211_IFTYPE_P2P_DEVICE); + iwl_mvm_fill_scan_type(mvm, ¶ms, vif); ret = iwl_mvm_get_measurement_dwell(mvm, req, ¶ms); if (ret < 0) @@ -1745,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, ¶ms, - vif->type == NL80211_IFTYPE_P2P_DEVICE); + iwl_mvm_fill_scan_type(mvm, ¶ms, 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 |