aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-05 08:28:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-06 15:31:18 -0400
commit2eb278e083549f4eb29838037004054b3b55df62 (patch)
tree803f076e7d7a1ed58e1c9e196bda7c2c2bb24bdf /net/mac80211/iface.c
parent196ac1c13d4db6c276dbb1c9190c8d7d45a83f1f (diff)
mac80211: unify SW/offload remain-on-channel
Redesign all the off-channel code, getting rid of the generic off-channel work concept, replacing it with a simple remain-on-channel list. This fixes a number of small issues with the ROC implementation: * offloaded remain-on-channel couldn't be queued, now we can queue it as well, if needed * in iwlwifi (the only user) offloaded ROC is mutually exclusive with scanning, use the new queue to handle that case -- I expect that it will later depend on a HW flag The bigger issue though is that there's a bad bug in the current implementation: if we get a mgmt TX request while HW roc is active, and this new request has a wait time, we actually schedule a software ROC instead since we can't guarantee the existing offloaded ROC will still be that long. To fix this, the queuing mechanism was needed. The queuing mechanism for offloaded ROC isn't yet optimal, ideally we should add API to have the HW extend the ROC if needed. We could add that later but for now use a software implementation. Overall, this unifies the behaviour between the offloaded and software-implemented case as much as possible. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c23
1 files changed, 4 insertions, 19 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 968d71c50713..87aeb4f21ffd 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -528,10 +528,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
528 */ 528 */
529 netif_tx_stop_all_queues(sdata->dev); 529 netif_tx_stop_all_queues(sdata->dev);
530 530
531 /* 531 ieee80211_roc_purge(sdata);
532 * Purge work for this interface.
533 */
534 ieee80211_work_purge(sdata);
535 532
536 /* 533 /*
537 * Remove all stations associated with this interface. 534 * Remove all stations associated with this interface.
@@ -637,18 +634,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
637 ieee80211_configure_filter(local); 634 ieee80211_configure_filter(local);
638 break; 635 break;
639 default: 636 default:
640 mutex_lock(&local->mtx);
641 if (local->hw_roc_dev == sdata->dev &&
642 local->hw_roc_channel) {
643 /* ignore return value since this is racy */
644 drv_cancel_remain_on_channel(local);
645 ieee80211_queue_work(&local->hw, &local->hw_roc_done);
646 }
647 mutex_unlock(&local->mtx);
648
649 flush_work(&local->hw_roc_start);
650 flush_work(&local->hw_roc_done);
651
652 flush_work(&sdata->work); 637 flush_work(&sdata->work);
653 /* 638 /*
654 * When we get here, the interface is marked down. 639 * When we get here, the interface is marked down.
@@ -1457,8 +1442,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1457 struct ieee80211_sub_if_data *sdata; 1442 struct ieee80211_sub_if_data *sdata;
1458 int count = 0; 1443 int count = 0;
1459 bool working = false, scanning = false; 1444 bool working = false, scanning = false;
1460 struct ieee80211_work *wk;
1461 unsigned int led_trig_start = 0, led_trig_stop = 0; 1445 unsigned int led_trig_start = 0, led_trig_stop = 0;
1446 struct ieee80211_roc_work *roc;
1462 1447
1463#ifdef CONFIG_PROVE_LOCKING 1448#ifdef CONFIG_PROVE_LOCKING
1464 WARN_ON(debug_locks && !lockdep_rtnl_is_held() && 1449 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
@@ -1494,9 +1479,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1494 } 1479 }
1495 1480
1496 if (!local->ops->remain_on_channel) { 1481 if (!local->ops->remain_on_channel) {
1497 list_for_each_entry(wk, &local->work_list, list) { 1482 list_for_each_entry(roc, &local->roc_list, list) {
1498 working = true; 1483 working = true;
1499 wk->sdata->vif.bss_conf.idle = false; 1484 roc->sdata->vif.bss_conf.idle = false;
1500 } 1485 }
1501 } 1486 }
1502 1487