From 77572fd13d7f468216b85e68a006000726a59e89 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 16 Jun 2011 11:49:33 +0300 Subject: [PATCH] mac80211: quiesce vif before suspending Cancel all relevant timers/works before suspending (wowlan). This patch handles the following warning: WARNING: at net/mac80211/util.c:565 queueing ieee80211 work while going to suspend Backtrace: [] (ieee80211_can_queue_work+0x0/0x4c [mac80211]) [] (ieee80211_queue_work+0x0/0x30 [mac80211]) [] (ieee80211_sta_timer+0x0/0x3c [mac80211]) [] (run_timer_softirq+0x0/0x220) [] (__do_softirq+0x0/0x130) [] (irq_exit+0x0/0xb4) [] (ipi_timer+0x0/0x4c) [] (do_local_timer+0x0/0x88) [] (cpu_idle+0x0/0xe0) [] (rest_init+0x0/0xe0) [] (start_kernel+0x0/0x314) Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- net/mac80211/pm.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 730778a..67839eb 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -6,6 +6,28 @@ #include "driver-ops.h" #include "led.h" +/* return value indicates whether the driver should be further notified */ +static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) +{ + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + ieee80211_sta_quiesce(sdata); + return true; + case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_quiesce(sdata); + return true; + case NL80211_IFTYPE_MESH_POINT: + ieee80211_mesh_quiesce(sdata); + return true; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* don't tell driver about this */ + return false; + default: + return true; + } +} + int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { struct ieee80211_local *local = hw_to_local(hw); @@ -54,6 +76,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) local->quiescing = false; return err; } + list_for_each_entry(sdata, &local->interfaces, list) { + cancel_work_sync(&sdata->work); + ieee80211_quiesce(sdata); + } goto suspend; } @@ -82,23 +108,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) list_for_each_entry(sdata, &local->interfaces, list) { cancel_work_sync(&sdata->work); - switch(sdata->vif.type) { - case NL80211_IFTYPE_STATION: - ieee80211_sta_quiesce(sdata); - break; - case NL80211_IFTYPE_ADHOC: - ieee80211_ibss_quiesce(sdata); - break; - case NL80211_IFTYPE_MESH_POINT: - ieee80211_mesh_quiesce(sdata); - break; - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_MONITOR: - /* don't tell driver about this */ + if (!ieee80211_quiesce(sdata)) continue; - default: - break; - } if (!ieee80211_sdata_running(sdata)) continue; -- 2.7.4