diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index cf24c2703c9b..efc750d2fc5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -38,8 +38,11 @@ | |||
38 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after | 38 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after |
39 | * sending probe req. This should be set long enough to hear probe responses | 39 | * sending probe req. This should be set long enough to hear probe responses |
40 | * from more than one AP. */ | 40 | * from more than one AP. */ |
41 | #define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ | 41 | #define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ |
42 | #define IWL_ACTIVE_DWELL_TIME_52 (10) | 42 | #define IWL_ACTIVE_DWELL_TIME_52 (20) |
43 | |||
44 | #define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) | ||
45 | #define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) | ||
43 | 46 | ||
44 | /* For faster active scanning, scan will move to the next channel if fewer than | 47 | /* For faster active scanning, scan will move to the next channel if fewer than |
45 | * PLCP_QUIET_THRESH packets are heard on this channel within | 48 | * PLCP_QUIET_THRESH packets are heard on this channel within |
@@ -48,7 +51,7 @@ | |||
48 | * no other traffic). | 51 | * no other traffic). |
49 | * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ | 52 | * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ |
50 | #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ | 53 | #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ |
51 | #define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ | 54 | #define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ |
52 | 55 | ||
53 | /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. | 56 | /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. |
54 | * Must be set longer than active dwell time. | 57 | * Must be set longer than active dwell time. |
@@ -58,10 +61,15 @@ | |||
58 | #define IWL_PASSIVE_DWELL_BASE (100) | 61 | #define IWL_PASSIVE_DWELL_BASE (100) |
59 | #define IWL_CHANNEL_TUNE_TIME 5 | 62 | #define IWL_CHANNEL_TUNE_TIME 5 |
60 | 63 | ||
64 | #define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) | ||
65 | |||
66 | |||
61 | static int scan_tx_ant[3] = { | 67 | static int scan_tx_ant[3] = { |
62 | RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK | 68 | RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK |
63 | }; | 69 | }; |
64 | 70 | ||
71 | |||
72 | |||
65 | static int iwl_is_empty_essid(const char *essid, int essid_len) | 73 | static int iwl_is_empty_essid(const char *essid, int essid_len) |
66 | { | 74 | { |
67 | /* Single white space is for Linksys APs */ | 75 | /* Single white space is for Linksys APs */ |
@@ -226,8 +234,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | |||
226 | "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", | 234 | "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", |
227 | notif->channel, | 235 | notif->channel, |
228 | notif->band ? "bg" : "a", | 236 | notif->band ? "bg" : "a", |
229 | notif->tsf_high, | 237 | le32_to_cpu(notif->tsf_high), |
230 | notif->tsf_low, notif->status, notif->beacon_timer); | 238 | le32_to_cpu(notif->tsf_low), |
239 | notif->status, notif->beacon_timer); | ||
231 | } | 240 | } |
232 | 241 | ||
233 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ | 242 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ |
@@ -332,19 +341,21 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | |||
332 | EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); | 341 | EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); |
333 | 342 | ||
334 | static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 343 | static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
335 | enum ieee80211_band band) | 344 | enum ieee80211_band band, |
345 | u8 n_probes) | ||
336 | { | 346 | { |
337 | if (band == IEEE80211_BAND_5GHZ) | 347 | if (band == IEEE80211_BAND_5GHZ) |
338 | return IWL_ACTIVE_DWELL_TIME_52; | 348 | return IWL_ACTIVE_DWELL_TIME_52 + |
349 | IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); | ||
339 | else | 350 | else |
340 | return IWL_ACTIVE_DWELL_TIME_24; | 351 | return IWL_ACTIVE_DWELL_TIME_24 + |
352 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); | ||
341 | } | 353 | } |
342 | 354 | ||
343 | static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 355 | static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
344 | enum ieee80211_band band) | 356 | enum ieee80211_band band) |
345 | { | 357 | { |
346 | u16 active = iwl_get_active_dwell_time(priv, band); | 358 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? |
347 | u16 passive = (band != IEEE80211_BAND_5GHZ) ? | ||
348 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : | 359 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : |
349 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; | 360 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; |
350 | 361 | ||
@@ -358,15 +369,12 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
358 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 369 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; |
359 | } | 370 | } |
360 | 371 | ||
361 | if (passive <= active) | ||
362 | passive = active + 1; | ||
363 | |||
364 | return passive; | 372 | return passive; |
365 | } | 373 | } |
366 | 374 | ||
367 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | 375 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, |
368 | enum ieee80211_band band, | 376 | enum ieee80211_band band, |
369 | u8 is_active, u8 direct_mask, | 377 | u8 is_active, u8 n_probes, |
370 | struct iwl_scan_channel *scan_ch) | 378 | struct iwl_scan_channel *scan_ch) |
371 | { | 379 | { |
372 | const struct ieee80211_channel *channels = NULL; | 380 | const struct ieee80211_channel *channels = NULL; |
@@ -383,9 +391,12 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
383 | 391 | ||
384 | channels = sband->channels; | 392 | channels = sband->channels; |
385 | 393 | ||
386 | active_dwell = iwl_get_active_dwell_time(priv, band); | 394 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); |
387 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | 395 | passive_dwell = iwl_get_passive_dwell_time(priv, band); |
388 | 396 | ||
397 | if (passive_dwell <= active_dwell) | ||
398 | passive_dwell = active_dwell + 1; | ||
399 | |||
389 | for (i = 0, added = 0; i < sband->n_channels; i++) { | 400 | for (i = 0, added = 0; i < sband->n_channels; i++) { |
390 | if (channels[i].flags & IEEE80211_CHAN_DISABLED) | 401 | if (channels[i].flags & IEEE80211_CHAN_DISABLED) |
391 | continue; | 402 | continue; |
@@ -407,8 +418,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
407 | else | 418 | else |
408 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 419 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; |
409 | 420 | ||
410 | if (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) | 421 | if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes) |
411 | scan_ch->type |= cpu_to_le32(direct_mask << 1); | 422 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); |
412 | 423 | ||
413 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | 424 | scan_ch->active_dwell = cpu_to_le16(active_dwell); |
414 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | 425 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); |
@@ -416,18 +427,17 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
416 | /* Set txpower levels to defaults */ | 427 | /* Set txpower levels to defaults */ |
417 | scan_ch->dsp_atten = 110; | 428 | scan_ch->dsp_atten = 110; |
418 | 429 | ||
430 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
431 | * power level: | ||
432 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
433 | */ | ||
419 | if (band == IEEE80211_BAND_5GHZ) | 434 | if (band == IEEE80211_BAND_5GHZ) |
420 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | 435 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; |
421 | else { | 436 | else |
422 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | 437 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); |
423 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
424 | * power level: | ||
425 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
426 | */ | ||
427 | } | ||
428 | 438 | ||
429 | IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", | 439 | IWL_DEBUG_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", |
430 | channel, | 440 | channel, le32_to_cpu(scan_ch->type), |
431 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | 441 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? |
432 | "ACTIVE" : "PASSIVE", | 442 | "ACTIVE" : "PASSIVE", |
433 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | 443 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? |
@@ -676,7 +686,7 @@ static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band) | |||
676 | break; | 686 | break; |
677 | } | 687 | } |
678 | } | 688 | } |
679 | 689 | IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind); | |
680 | return scan_tx_ant[ind]; | 690 | return scan_tx_ant[ind]; |
681 | } | 691 | } |
682 | 692 | ||
@@ -696,7 +706,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
696 | u32 tx_ant; | 706 | u32 tx_ant; |
697 | u16 cmd_len; | 707 | u16 cmd_len; |
698 | enum ieee80211_band band; | 708 | enum ieee80211_band band; |
699 | u8 direct_mask; | 709 | u8 n_probes = 2; |
700 | u8 rx_chain = 0x7; /* bitmap: ABC chains */ | 710 | u8 rx_chain = 0x7; /* bitmap: ABC chains */ |
701 | 711 | ||
702 | conf = ieee80211_get_hw_conf(priv->hw); | 712 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -796,17 +806,16 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
796 | scan->direct_scan[0].len = priv->direct_ssid_len; | 806 | scan->direct_scan[0].len = priv->direct_ssid_len; |
797 | memcpy(scan->direct_scan[0].ssid, | 807 | memcpy(scan->direct_scan[0].ssid, |
798 | priv->direct_ssid, priv->direct_ssid_len); | 808 | priv->direct_ssid, priv->direct_ssid_len); |
799 | direct_mask = 1; | 809 | n_probes++; |
800 | } else if (!iwl_is_associated(priv) && priv->essid_len) { | 810 | } else if (!iwl_is_associated(priv) && priv->essid_len) { |
801 | IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", | 811 | IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", |
802 | iwl_escape_essid(priv->essid, priv->essid_len)); | 812 | iwl_escape_essid(priv->essid, priv->essid_len)); |
803 | scan->direct_scan[0].id = WLAN_EID_SSID; | 813 | scan->direct_scan[0].id = WLAN_EID_SSID; |
804 | scan->direct_scan[0].len = priv->essid_len; | 814 | scan->direct_scan[0].len = priv->essid_len; |
805 | memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); | 815 | memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); |
806 | direct_mask = 1; | 816 | n_probes++; |
807 | } else { | 817 | } else { |
808 | IWL_DEBUG_SCAN("Start indirect scan.\n"); | 818 | IWL_DEBUG_SCAN("Start indirect scan.\n"); |
809 | direct_mask = 0; | ||
810 | } | 819 | } |
811 | 820 | ||
812 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 821 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
@@ -863,16 +872,11 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
863 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | 872 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | |
864 | RXON_FILTER_BCON_AWARE_MSK); | 873 | RXON_FILTER_BCON_AWARE_MSK); |
865 | 874 | ||
866 | if (direct_mask) | 875 | scan->channel_count = |
867 | scan->channel_count = | 876 | iwl_get_channels_for_scan(priv, band, 1, /* active */ |
868 | iwl_get_channels_for_scan(priv, band, 1, /* active */ | 877 | n_probes, |
869 | direct_mask, | 878 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); |
870 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | 879 | |
871 | else | ||
872 | scan->channel_count = | ||
873 | iwl_get_channels_for_scan(priv, band, 0, /* passive */ | ||
874 | direct_mask, | ||
875 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | ||
876 | if (scan->channel_count == 0) { | 880 | if (scan->channel_count == 0) { |
877 | IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); | 881 | IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); |
878 | goto done; | 882 | goto done; |