aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-scan.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-09-20 18:37:22 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-21 16:19:42 -0400
commit390808db4ab5c658dc1eb8078d82027ce7d0ea78 (patch)
tree4e584861dfdd93b6ace23b63e10678b7e7f0042e /drivers/net/wireless/iwlwifi/iwl-scan.c
parentc68929060181eb088bef252c5f493a66a44e77b1 (diff)
iwlagn: split remain-on-channel
If we're associated and want to do P2P at the same time, the scan for remain-on-channel is currently limited to 80ms because of the way the device will behave in that case. Instead of doing that, split up the dwell times into little pieces. It will not actually be a single big dwell time then, but will be close enough. This improves robustness of P2P in such scenarios. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c99
1 files changed, 60 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 8ac6b05c6c78..8386a86e2ca2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -218,8 +218,11 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
218 le32_to_cpu(notif->tsf_low), 218 le32_to_cpu(notif->tsf_low),
219 notif->status, notif->beacon_timer); 219 notif->status, notif->beacon_timer);
220 220
221 if (priv->scan_type == IWL_SCAN_ROC) 221 if (priv->scan_type == IWL_SCAN_ROC &&
222 !priv->hw_roc_start_notified) {
222 ieee80211_ready_on_channel(priv->hw); 223 ieee80211_ready_on_channel(priv->hw);
224 priv->hw_roc_start_notified = true;
225 }
223} 226}
224 227
225/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ 228/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
@@ -310,34 +313,38 @@ static u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
310 IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); 313 IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
311} 314}
312 315
316static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
317{
318 struct iwl_rxon_context *ctx;
319
320 /*
321 * If we're associated, we clamp the dwell time 98%
322 * of the smallest beacon interval (minus 2 * channel
323 * tune time)
324 */
325 for_each_context(priv, ctx) {
326 u16 value;
327
328 if (!iwl_is_associated_ctx(ctx))
329 continue;
330 value = ctx->beacon_int;
331 if (!value)
332 value = IWL_PASSIVE_DWELL_BASE;
333 value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
334 dwell_time = min(value, dwell_time);
335 }
336
337 return dwell_time;
338}
339
313static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, 340static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
314 enum ieee80211_band band) 341 enum ieee80211_band band)
315{ 342{
316 struct iwl_rxon_context *ctx;
317 u16 passive = (band == IEEE80211_BAND_2GHZ) ? 343 u16 passive = (band == IEEE80211_BAND_2GHZ) ?
318 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : 344 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
319 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; 345 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
320 346
321 if (iwl_is_any_associated(priv)) { 347 return iwl_limit_dwell(priv, passive);
322 /*
323 * If we're associated, we clamp the maximum passive
324 * dwell time to be 98% of the smallest beacon interval
325 * (minus 2 * channel tune time)
326 */
327 for_each_context(priv, ctx) {
328 u16 value;
329
330 if (!iwl_is_associated_ctx(ctx))
331 continue;
332 value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
333 if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
334 value = IWL_PASSIVE_DWELL_BASE;
335 value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
336 passive = min(value, passive);
337 }
338 }
339
340 return passive;
341} 348}
342 349
343static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, 350static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
@@ -716,29 +723,43 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
716 break; 723 break;
717 case IWL_SCAN_ROC: { 724 case IWL_SCAN_ROC: {
718 struct iwl_scan_channel *scan_ch; 725 struct iwl_scan_channel *scan_ch;
726 int n_chan, i;
727 u16 dwell;
728
729 dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
730 n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
719 731
720 scan->channel_count = 1; 732 scan->channel_count = n_chan;
721 733
722 scan_ch = (void *)&scan->data[cmd_len]; 734 scan_ch = (void *)&scan->data[cmd_len];
723 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
724 scan_ch->channel =
725 cpu_to_le16(priv->hw_roc_channel->hw_value);
726 scan_ch->active_dwell =
727 scan_ch->passive_dwell =
728 cpu_to_le16(priv->hw_roc_duration);
729 735
730 /* Set txpower levels to defaults */ 736 for (i = 0; i < n_chan; i++) {
731 scan_ch->dsp_atten = 110; 737 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
738 scan_ch->channel =
739 cpu_to_le16(priv->hw_roc_channel->hw_value);
732 740
733 /* NOTE: if we were doing 6Mb OFDM for scans we'd use 741 if (i == n_chan - 1)
734 * power level: 742 dwell = priv->hw_roc_duration - i * dwell;
735 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; 743
736 */ 744 scan_ch->active_dwell =
737 if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) 745 scan_ch->passive_dwell = cpu_to_le16(dwell);
738 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; 746
739 else 747 /* Set txpower levels to defaults */
740 scan_ch->tx_gain = ((1 << 5) | (5 << 3)); 748 scan_ch->dsp_atten = 110;
749
750 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
751 * power level:
752 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
753 */
754 if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
755 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
756 else
757 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
758
759 scan_ch++;
741 } 760 }
761 }
762
742 break; 763 break;
743 } 764 }
744 765