aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-07-10 23:53:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-14 14:53:00 -0400
commitfe905f1d5a8404f45fa0df26e6a870bf1e3b5983 (patch)
tree2bee5a6519a0fb19e0dd20af18726e19a3f6879a
parentd16dc48a2ea14af9980d0ea79d041f4b53e47b62 (diff)
iwlwifi: enable active scanning
This patch enables active scan on active channels. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c86
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
61static int scan_tx_ant[3] = { 67static 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
65static int iwl_is_empty_essid(const char *essid, int essid_len) 73static 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)
332EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); 341EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
333 342
334static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, 343static 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
343static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, 355static 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
367static int iwl_get_channels_for_scan(struct iwl_priv *priv, 375static 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;