mac80211: allow driver to impose WoWLAN restrictions
authorJohannes Berg <johannes.berg@intel.com>
Fri, 1 Jul 2011 22:02:01 +0000 (00:02 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 5 Jul 2011 19:26:56 +0000 (15:26 -0400)
If the driver can't support WoWLAN in the current
state, this patch allows it to return 1 from the
suspend callback to do the normal deconfiguration
instead of using suspend/resume calls. Note that
if it does this, resume won't be called.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/pm.c

index c9def42c12867c73804e7fff82807eb2269de729..2858b4d02f5f7ed3004de234ad1d2d429e88d886 100644 (file)
@@ -1628,6 +1628,10 @@ enum ieee80211_ampdu_mlme_action {
  *     ask the device to suspend. This is only invoked when WoWLAN is
  *     configured, otherwise the device is deconfigured completely and
  *     reconfigured at resume time.
+ *     The driver may also impose special conditions under which it
+ *     wants to use the "normal" suspend (deconfigure), say if it only
+ *     supports WoWLAN when the device is associated. In this case, it
+ *     must return 1 from this function.
  *
  * @resume: If WoWLAN was configured, this indicates that mac80211 is
  *     now resuming its operation, after this the device must be fully
index 67839eb90cc178dca9de0be7ee21fe7a4d26e180..f87e993e713bf28ec05b4c6690711ddc6197dde1 100644 (file)
@@ -72,15 +72,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        local->wowlan = wowlan && local->open_count;
        if (local->wowlan) {
                int err = drv_suspend(local, wowlan);
-               if (err) {
+               if (err < 0) {
                        local->quiescing = false;
                        return err;
+               } else if (err > 0) {
+                       WARN_ON(err != 1);
+                       local->wowlan = false;
+               } else {
+                       list_for_each_entry(sdata, &local->interfaces, list) {
+                               cancel_work_sync(&sdata->work);
+                               ieee80211_quiesce(sdata);
+                       }
+                       goto suspend;
                }
-               list_for_each_entry(sdata, &local->interfaces, list) {
-                       cancel_work_sync(&sdata->work);
-                       ieee80211_quiesce(sdata);
-               }
-               goto suspend;
        }
 
        /* disable keys */