diff options
author | Alexander Bondar <alexander.bondar@intel.com> | 2014-03-12 14:30:51 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-03-18 15:15:39 -0400 |
commit | 50df8a3065404b9b953b1ae1455dd991e04a9ab7 (patch) | |
tree | fbb0d793eed0a5474608d24f3c653e6e5f07b4e3 /drivers/net | |
parent | 8a110d9be1c14a95f502343b8b4783eb3228e1e3 (diff) |
iwlwifi: mvm: configure low latency dependent scan parameters
In case of system low latency configure passive scan to be fragmented.
Set the following scan parameters for both immediate and scheduled scan:
- passive scan fragment duration = 20ms
- out-of-channel time = 70ms
- suspend time = 105ms
Restructure channel's active/passive dwell time configuration to better
suit the above change.
The idea is that under low latency traffic passive scan is fragmented,
i.e. that dwell on a particular channel will be fragmented. Each
fragment dwell time is 20ms and fragments period is 105ms. Skipping to
next channel will be delayed by the same period (105ms). So suspend_time
parameter describing both fragments and channels skipping periods is set
to 105ms. This value is chosen so that overall passive scan duration
will not be too long. Max_out_time in this case is set to 70ms, so for
active scanning operating channel will be left for 70ms while for
passive still for 20ms (fragment dwell).
Signed-off-by: Alexander Bondar <alexander.bondar@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/scan.c | 108 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 19 |
3 files changed, 101 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index d58118241d61..abfa5676762b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -984,6 +984,8 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
984 | /* Low latency */ | 984 | /* Low latency */ |
985 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 985 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
986 | bool value); | 986 | bool value); |
987 | /* get SystemLowLatencyMode - only needed for beacon threshold? */ | ||
988 | bool iwl_mvm_low_latency(struct iwl_mvm *mvm); | ||
987 | /* get VMACLowLatencyMode */ | 989 | /* get VMACLowLatencyMode */ |
988 | static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) | 990 | static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) |
989 | { | 991 | { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index ee3f67f5e42b..c91dc8498852 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -74,6 +74,11 @@ | |||
74 | struct iwl_mvm_scan_params { | 74 | struct iwl_mvm_scan_params { |
75 | u32 max_out_time; | 75 | u32 max_out_time; |
76 | u32 suspend_time; | 76 | u32 suspend_time; |
77 | bool passive_fragmented; | ||
78 | struct _dwell { | ||
79 | u16 passive; | ||
80 | u16 active; | ||
81 | } dwell[IEEE80211_NUM_BANDS]; | ||
77 | }; | 82 | }; |
78 | 83 | ||
79 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | 84 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) |
@@ -165,15 +170,14 @@ static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) | |||
165 | 170 | ||
166 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | 171 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, |
167 | struct cfg80211_scan_request *req, | 172 | struct cfg80211_scan_request *req, |
168 | bool basic_ssid) | 173 | bool basic_ssid, |
174 | struct iwl_mvm_scan_params *params) | ||
169 | { | 175 | { |
170 | u16 passive_dwell = iwl_mvm_get_passive_dwell(req->channels[0]->band); | ||
171 | u16 active_dwell = iwl_mvm_get_active_dwell(req->channels[0]->band, | ||
172 | req->n_ssids); | ||
173 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) | 176 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) |
174 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); | 177 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); |
175 | int i; | 178 | int i; |
176 | int type = BIT(req->n_ssids) - 1; | 179 | int type = BIT(req->n_ssids) - 1; |
180 | enum ieee80211_band band = req->channels[0]->band; | ||
177 | 181 | ||
178 | if (!basic_ssid) | 182 | if (!basic_ssid) |
179 | type |= BIT(req->n_ssids); | 183 | type |= BIT(req->n_ssids); |
@@ -183,8 +187,8 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | |||
183 | chan->type = cpu_to_le32(type); | 187 | chan->type = cpu_to_le32(type); |
184 | if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) | 188 | if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) |
185 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); | 189 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); |
186 | chan->active_dwell = cpu_to_le16(active_dwell); | 190 | chan->active_dwell = cpu_to_le16(params->dwell[band].active); |
187 | chan->passive_dwell = cpu_to_le16(passive_dwell); | 191 | chan->passive_dwell = cpu_to_le16(params->dwell[band].passive); |
188 | chan->iteration_count = cpu_to_le16(1); | 192 | chan->iteration_count = cpu_to_le16(1); |
189 | chan++; | 193 | chan++; |
190 | } | 194 | } |
@@ -262,19 +266,65 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, | |||
262 | } | 266 | } |
263 | 267 | ||
264 | static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | 268 | static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, |
269 | struct ieee80211_vif *vif, | ||
270 | int n_ssids, | ||
265 | struct iwl_mvm_scan_params *params) | 271 | struct iwl_mvm_scan_params *params) |
266 | { | 272 | { |
267 | bool global_bound = false; | 273 | bool global_bound = false; |
274 | enum ieee80211_band band; | ||
268 | 275 | ||
269 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | 276 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, |
270 | IEEE80211_IFACE_ITER_NORMAL, | 277 | IEEE80211_IFACE_ITER_NORMAL, |
271 | iwl_mvm_scan_condition_iterator, | 278 | iwl_mvm_scan_condition_iterator, |
272 | &global_bound); | 279 | &global_bound); |
273 | if (!global_bound) | 280 | /* |
274 | return; | 281 | * Under low latency traffic passive scan is fragmented meaning |
282 | * that dwell on a particular channel will be fragmented. Each fragment | ||
283 | * dwell time is 20ms and fragments period is 105ms. Skipping to next | ||
284 | * channel will be delayed by the same period - 105ms. So suspend_time | ||
285 | * parameter describing both fragments and channels skipping periods is | ||
286 | * set to 105ms. This value is chosen so that overall passive scan | ||
287 | * duration will not be too long. Max_out_time in this case is set to | ||
288 | * 70ms, so for active scanning operating channel will be left for 70ms | ||
289 | * while for passive still for 20ms (fragment dwell). | ||
290 | */ | ||
291 | if (global_bound) { | ||
292 | if (!iwl_mvm_low_latency(mvm)) { | ||
293 | params->suspend_time = ieee80211_tu_to_usec(100); | ||
294 | params->max_out_time = ieee80211_tu_to_usec(600); | ||
295 | } else { | ||
296 | params->suspend_time = ieee80211_tu_to_usec(105); | ||
297 | /* P2P doesn't support fragmented passive scan, so | ||
298 | * configure max_out_time to be at least longest dwell | ||
299 | * time for passive scan. | ||
300 | */ | ||
301 | if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) { | ||
302 | params->max_out_time = ieee80211_tu_to_usec(70); | ||
303 | params->passive_fragmented = true; | ||
304 | } else { | ||
305 | u32 passive_dwell; | ||
306 | |||
307 | /* | ||
308 | * Use band G so that passive channel dwell time | ||
309 | * will be assigned with maximum value. | ||
310 | */ | ||
311 | band = IEEE80211_BAND_2GHZ; | ||
312 | passive_dwell = iwl_mvm_get_passive_dwell(band); | ||
313 | params->max_out_time = | ||
314 | ieee80211_tu_to_usec(passive_dwell); | ||
315 | } | ||
316 | } | ||
317 | } | ||
275 | 318 | ||
276 | params->suspend_time = ieee80211_tu_to_usec(100); | 319 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { |
277 | params->max_out_time = ieee80211_tu_to_usec(600); | 320 | if (params->passive_fragmented) |
321 | params->dwell[band].passive = 20; | ||
322 | else | ||
323 | params->dwell[band].passive = | ||
324 | iwl_mvm_get_passive_dwell(band); | ||
325 | params->dwell[band].active = iwl_mvm_get_active_dwell(band, | ||
326 | n_ssids); | ||
327 | } | ||
278 | } | 328 | } |
279 | 329 | ||
280 | int iwl_mvm_scan_request(struct iwl_mvm *mvm, | 330 | int iwl_mvm_scan_request(struct iwl_mvm *mvm, |
@@ -311,9 +361,11 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
311 | cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | 361 | cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); |
312 | cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); | 362 | cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); |
313 | 363 | ||
314 | iwl_mvm_scan_calc_params(mvm, ¶ms); | 364 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, ¶ms); |
315 | cmd->max_out_time = cpu_to_le32(params.max_out_time); | 365 | cmd->max_out_time = cpu_to_le32(params.max_out_time); |
316 | cmd->suspend_time = cpu_to_le32(params.suspend_time); | 366 | cmd->suspend_time = cpu_to_le32(params.suspend_time); |
367 | if (params.passive_fragmented) | ||
368 | cmd->scan_flags |= SCAN_FLAGS_FRAGMENTED_SCAN; | ||
317 | 369 | ||
318 | cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); | 370 | cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); |
319 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | 371 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | |
@@ -360,7 +412,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
360 | req->ie, req->ie_len, | 412 | req->ie, req->ie_len, |
361 | mvm->fw->ucode_capa.max_probe_length)); | 413 | mvm->fw->ucode_capa.max_probe_length)); |
362 | 414 | ||
363 | iwl_mvm_scan_fill_channels(cmd, req, basic_ssid); | 415 | iwl_mvm_scan_fill_channels(cmd, req, basic_ssid, ¶ms); |
364 | 416 | ||
365 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + | 417 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + |
366 | le16_to_cpu(cmd->tx_cmd.len) + | 418 | le16_to_cpu(cmd->tx_cmd.len) + |
@@ -554,10 +606,9 @@ static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm, | |||
554 | static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | 606 | static void iwl_build_scan_cmd(struct iwl_mvm *mvm, |
555 | struct ieee80211_vif *vif, | 607 | struct ieee80211_vif *vif, |
556 | struct cfg80211_sched_scan_request *req, | 608 | struct cfg80211_sched_scan_request *req, |
557 | struct iwl_scan_offload_cmd *scan) | 609 | struct iwl_scan_offload_cmd *scan, |
610 | struct iwl_mvm_scan_params *params) | ||
558 | { | 611 | { |
559 | struct iwl_mvm_scan_params params = {}; | ||
560 | |||
561 | scan->channel_count = | 612 | scan->channel_count = |
562 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + | 613 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + |
563 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | 614 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; |
@@ -566,14 +617,16 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | |||
566 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; | 617 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; |
567 | scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); | 618 | scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); |
568 | 619 | ||
569 | iwl_mvm_scan_calc_params(mvm, ¶ms); | 620 | scan->max_out_time = cpu_to_le32(params->max_out_time); |
570 | scan->max_out_time = cpu_to_le32(params.max_out_time); | 621 | scan->suspend_time = cpu_to_le32(params->suspend_time); |
571 | scan->suspend_time = cpu_to_le32(params.suspend_time); | ||
572 | 622 | ||
573 | scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | 623 | scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | |
574 | MAC_FILTER_IN_BEACON); | 624 | MAC_FILTER_IN_BEACON); |
575 | scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); | 625 | scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); |
576 | scan->rep_count = cpu_to_le32(1); | 626 | scan->rep_count = cpu_to_le32(1); |
627 | |||
628 | if (params->passive_fragmented) | ||
629 | scan->scan_flags |= SCAN_FLAGS_FRAGMENTED_SCAN; | ||
577 | } | 630 | } |
578 | 631 | ||
579 | static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list) | 632 | static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list) |
@@ -638,12 +691,11 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
638 | struct iwl_scan_channel_cfg *channels, | 691 | struct iwl_scan_channel_cfg *channels, |
639 | enum ieee80211_band band, | 692 | enum ieee80211_band band, |
640 | int *head, int *tail, | 693 | int *head, int *tail, |
641 | u32 ssid_bitmap) | 694 | u32 ssid_bitmap, |
695 | struct iwl_mvm_scan_params *params) | ||
642 | { | 696 | { |
643 | struct ieee80211_supported_band *s_band; | 697 | struct ieee80211_supported_band *s_band; |
644 | int n_probes = req->n_ssids; | ||
645 | int n_channels = req->n_channels; | 698 | int n_channels = req->n_channels; |
646 | u8 active_dwell, passive_dwell; | ||
647 | int i, j, index = 0; | 699 | int i, j, index = 0; |
648 | bool partial; | 700 | bool partial; |
649 | 701 | ||
@@ -653,8 +705,6 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
653 | * to scan. So add requested channels to head of the list and others to | 705 | * to scan. So add requested channels to head of the list and others to |
654 | * the end. | 706 | * the end. |
655 | */ | 707 | */ |
656 | active_dwell = iwl_mvm_get_active_dwell(band, n_probes); | ||
657 | passive_dwell = iwl_mvm_get_passive_dwell(band); | ||
658 | s_band = &mvm->nvm_data->bands[band]; | 708 | s_band = &mvm->nvm_data->bands[band]; |
659 | 709 | ||
660 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { | 710 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { |
@@ -678,8 +728,8 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
678 | channels->channel_number[index] = | 728 | channels->channel_number[index] = |
679 | cpu_to_le16(ieee80211_frequency_to_channel( | 729 | cpu_to_le16(ieee80211_frequency_to_channel( |
680 | s_band->channels[i].center_freq)); | 730 | s_band->channels[i].center_freq)); |
681 | channels->dwell_time[index][0] = active_dwell; | 731 | channels->dwell_time[index][0] = params->dwell[band].active; |
682 | channels->dwell_time[index][1] = passive_dwell; | 732 | channels->dwell_time[index][1] = params->dwell[band].passive; |
683 | 733 | ||
684 | channels->iter_count[index] = cpu_to_le16(1); | 734 | channels->iter_count[index] = cpu_to_le16(1); |
685 | channels->iter_interval[index] = 0; | 735 | channels->iter_interval[index] = 0; |
@@ -721,6 +771,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
721 | .id = SCAN_OFFLOAD_CONFIG_CMD, | 771 | .id = SCAN_OFFLOAD_CONFIG_CMD, |
722 | .flags = CMD_SYNC, | 772 | .flags = CMD_SYNC, |
723 | }; | 773 | }; |
774 | struct iwl_mvm_scan_params params = {}; | ||
724 | 775 | ||
725 | lockdep_assert_held(&mvm->mutex); | 776 | lockdep_assert_held(&mvm->mutex); |
726 | 777 | ||
@@ -731,7 +782,8 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
731 | if (!scan_cfg) | 782 | if (!scan_cfg) |
732 | return -ENOMEM; | 783 | return -ENOMEM; |
733 | 784 | ||
734 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd); | 785 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, ¶ms); |
786 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, ¶ms); | ||
735 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); | 787 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); |
736 | 788 | ||
737 | iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap); | 789 | iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap); |
@@ -743,7 +795,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
743 | scan_cfg->data); | 795 | scan_cfg->data); |
744 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | 796 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, |
745 | IEEE80211_BAND_2GHZ, &head, &tail, | 797 | IEEE80211_BAND_2GHZ, &head, &tail, |
746 | ssid_bitmap); | 798 | ssid_bitmap, ¶ms); |
747 | } | 799 | } |
748 | if (band_5ghz) { | 800 | if (band_5ghz) { |
749 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | 801 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, |
@@ -753,7 +805,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
753 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | 805 | SCAN_OFFLOAD_PROBE_REQ_SIZE); |
754 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | 806 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, |
755 | IEEE80211_BAND_5GHZ, &head, &tail, | 807 | IEEE80211_BAND_5GHZ, &head, &tail, |
756 | ssid_bitmap); | 808 | ssid_bitmap, ¶ms); |
757 | } | 809 | } |
758 | 810 | ||
759 | cmd.data[0] = scan_cfg; | 811 | cmd.data[0] = scan_cfg; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index e9de033d6b9e..c28da90cd347 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -622,3 +622,22 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
622 | 622 | ||
623 | return iwl_mvm_power_update_mac(mvm, vif); | 623 | return iwl_mvm_power_update_mac(mvm, vif); |
624 | } | 624 | } |
625 | |||
626 | static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) | ||
627 | { | ||
628 | bool *result = _data; | ||
629 | |||
630 | if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(vif))) | ||
631 | *result = true; | ||
632 | } | ||
633 | |||
634 | bool iwl_mvm_low_latency(struct iwl_mvm *mvm) | ||
635 | { | ||
636 | bool result = false; | ||
637 | |||
638 | ieee80211_iterate_active_interfaces_atomic( | ||
639 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
640 | iwl_mvm_ll_iter, &result); | ||
641 | |||
642 | return result; | ||
643 | } | ||