aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r--net/mac80211/scan.c88
1 files changed, 63 insertions, 25 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 1ef73be76b25..0ea6adae3e06 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -212,6 +212,14 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
212 if (bss) 212 if (bss)
213 ieee80211_rx_bss_put(sdata->local, bss); 213 ieee80211_rx_bss_put(sdata->local, bss);
214 214
215 /* If we are on-operating-channel, and this packet is for the
216 * current channel, pass the pkt on up the stack so that
217 * the rest of the stack can make use of it.
218 */
219 if (ieee80211_cfg_on_oper_channel(sdata->local)
220 && (channel == sdata->local->oper_channel))
221 return RX_CONTINUE;
222
215 dev_kfree_skb(skb); 223 dev_kfree_skb(skb);
216 return RX_QUEUED; 224 return RX_QUEUED;
217} 225}
@@ -293,15 +301,31 @@ static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
293 bool was_hw_scan) 301 bool was_hw_scan)
294{ 302{
295 struct ieee80211_local *local = hw_to_local(hw); 303 struct ieee80211_local *local = hw_to_local(hw);
304 bool on_oper_chan;
305 bool enable_beacons = false;
306
307 mutex_lock(&local->mtx);
308 on_oper_chan = ieee80211_cfg_on_oper_channel(local);
309
310 if (was_hw_scan || !on_oper_chan) {
311 if (WARN_ON(local->scan_channel))
312 local->scan_channel = NULL;
313 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
314 }
296 315
297 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
298 if (!was_hw_scan) { 316 if (!was_hw_scan) {
317 bool on_oper_chan2;
299 ieee80211_configure_filter(local); 318 ieee80211_configure_filter(local);
300 drv_sw_scan_complete(local); 319 drv_sw_scan_complete(local);
301 ieee80211_offchannel_return(local, true); 320 on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
321 /* We should always be on-channel at this point. */
322 WARN_ON(!on_oper_chan2);
323 if (on_oper_chan2 && (on_oper_chan != on_oper_chan2))
324 enable_beacons = true;
325
326 ieee80211_offchannel_return(local, enable_beacons, true);
302 } 327 }
303 328
304 mutex_lock(&local->mtx);
305 ieee80211_recalc_idle(local); 329 ieee80211_recalc_idle(local);
306 mutex_unlock(&local->mtx); 330 mutex_unlock(&local->mtx);
307 331
@@ -341,13 +365,15 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
341 */ 365 */
342 drv_sw_scan_start(local); 366 drv_sw_scan_start(local);
343 367
344 ieee80211_offchannel_stop_beaconing(local);
345
346 local->leave_oper_channel_time = 0; 368 local->leave_oper_channel_time = 0;
347 local->next_scan_state = SCAN_DECISION; 369 local->next_scan_state = SCAN_DECISION;
348 local->scan_channel_idx = 0; 370 local->scan_channel_idx = 0;
349 371
350 drv_flush(local, false); 372 /* We always want to use off-channel PS, even if we
373 * are not really leaving oper-channel. Don't
374 * tell the AP though, as long as we are on-channel.
375 */
376 ieee80211_offchannel_enable_all_ps(local, false);
351 377
352 ieee80211_configure_filter(local); 378 ieee80211_configure_filter(local);
353 379
@@ -487,7 +513,21 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
487 } 513 }
488 mutex_unlock(&local->iflist_mtx); 514 mutex_unlock(&local->iflist_mtx);
489 515
490 if (local->scan_channel) { 516 next_chan = local->scan_req->channels[local->scan_channel_idx];
517
518 if (ieee80211_cfg_on_oper_channel(local)) {
519 /* We're currently on operating channel. */
520 if ((next_chan == local->oper_channel) &&
521 (local->_oper_channel_type == NL80211_CHAN_NO_HT))
522 /* We don't need to move off of operating channel. */
523 local->next_scan_state = SCAN_SET_CHANNEL;
524 else
525 /*
526 * We do need to leave operating channel, as next
527 * scan is somewhere else.
528 */
529 local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
530 } else {
491 /* 531 /*
492 * we're currently scanning a different channel, let's 532 * we're currently scanning a different channel, let's
493 * see if we can scan another channel without interfering 533 * see if we can scan another channel without interfering
@@ -503,7 +543,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
503 * 543 *
504 * Otherwise switch back to the operating channel. 544 * Otherwise switch back to the operating channel.
505 */ 545 */
506 next_chan = local->scan_req->channels[local->scan_channel_idx];
507 546
508 bad_latency = time_after(jiffies + 547 bad_latency = time_after(jiffies +
509 ieee80211_scan_get_channel_time(next_chan), 548 ieee80211_scan_get_channel_time(next_chan),
@@ -521,12 +560,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
521 local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; 560 local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
522 else 561 else
523 local->next_scan_state = SCAN_SET_CHANNEL; 562 local->next_scan_state = SCAN_SET_CHANNEL;
524 } else {
525 /*
526 * we're on the operating channel currently, let's
527 * leave that channel now to scan another one
528 */
529 local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
530 } 563 }
531 564
532 *next_delay = 0; 565 *next_delay = 0;
@@ -535,9 +568,10 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
535static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, 568static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
536 unsigned long *next_delay) 569 unsigned long *next_delay)
537{ 570{
538 ieee80211_offchannel_stop_station(local); 571 /* PS will already be in off-channel mode,
539 572 * we do that once at the beginning of scanning.
540 __set_bit(SCAN_OFF_CHANNEL, &local->scanning); 573 */
574 ieee80211_offchannel_stop_vifs(local, false);
541 575
542 /* 576 /*
543 * What if the nullfunc frames didn't arrive? 577 * What if the nullfunc frames didn't arrive?
@@ -560,15 +594,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
560{ 594{
561 /* switch back to the operating channel */ 595 /* switch back to the operating channel */
562 local->scan_channel = NULL; 596 local->scan_channel = NULL;
563 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 597 if (!ieee80211_cfg_on_oper_channel(local))
598 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
564 599
565 /* 600 /*
566 * Only re-enable station mode interface now; beaconing will be 601 * Re-enable vifs and beaconing. Leave PS
567 * re-enabled once the full scan has been completed. 602 * in off-channel state..will put that back
603 * on-channel at the end of scanning.
568 */ 604 */
569 ieee80211_offchannel_return(local, false); 605 ieee80211_offchannel_return(local, true, false);
570
571 __clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
572 606
573 *next_delay = HZ / 5; 607 *next_delay = HZ / 5;
574 local->next_scan_state = SCAN_DECISION; 608 local->next_scan_state = SCAN_DECISION;
@@ -584,8 +618,12 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
584 chan = local->scan_req->channels[local->scan_channel_idx]; 618 chan = local->scan_req->channels[local->scan_channel_idx];
585 619
586 local->scan_channel = chan; 620 local->scan_channel = chan;
587 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) 621
588 skip = 1; 622 /* Only call hw-config if we really need to change channels. */
623 if ((chan != local->hw.conf.channel) ||
624 (local->hw.conf.channel_type != NL80211_CHAN_NO_HT))
625 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
626 skip = 1;
589 627
590 /* advance state machine to next channel/band */ 628 /* advance state machine to next channel/band */
591 local->scan_channel_idx++; 629 local->scan_channel_idx++;