diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
| -rw-r--r-- | net/mac80211/debugfs.c | 2 | ||||
| -rw-r--r-- | net/mac80211/driver-ops.h | 27 | ||||
| -rw-r--r-- | net/mac80211/driver-trace.h | 10 | ||||
| -rw-r--r-- | net/mac80211/ieee80211_i.h | 9 | ||||
| -rw-r--r-- | net/mac80211/main.c | 4 | ||||
| -rw-r--r-- | net/mac80211/pm.c | 13 | ||||
| -rw-r--r-- | net/mac80211/util.c | 19 |
8 files changed, 81 insertions, 5 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 321d598eb8cb..1ebc13383ae7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -1300,7 +1300,7 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
| 1300 | static int ieee80211_suspend(struct wiphy *wiphy, | 1300 | static int ieee80211_suspend(struct wiphy *wiphy, |
| 1301 | struct cfg80211_wowlan *wowlan) | 1301 | struct cfg80211_wowlan *wowlan) |
| 1302 | { | 1302 | { |
| 1303 | return __ieee80211_suspend(wiphy_priv(wiphy)); | 1303 | return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); |
| 1304 | } | 1304 | } |
| 1305 | 1305 | ||
| 1306 | static int ieee80211_resume(struct wiphy *wiphy) | 1306 | static int ieee80211_resume(struct wiphy *wiphy) |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 0a602dbfdb2b..186e02f7cc32 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
| @@ -135,7 +135,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, | |||
| 135 | struct ieee80211_local *local = file->private_data; | 135 | struct ieee80211_local *local = file->private_data; |
| 136 | 136 | ||
| 137 | rtnl_lock(); | 137 | rtnl_lock(); |
| 138 | __ieee80211_suspend(&local->hw); | 138 | __ieee80211_suspend(&local->hw, NULL); |
| 139 | __ieee80211_resume(&local->hw); | 139 | __ieee80211_resume(&local->hw); |
| 140 | rtnl_unlock(); | 140 | rtnl_unlock(); |
| 141 | 141 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 2ddb56e5b51f..aa16bd8ef789 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
| @@ -41,6 +41,33 @@ static inline void drv_stop(struct ieee80211_local *local) | |||
| 41 | local->started = false; | 41 | local->started = false; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | #ifdef CONFIG_PM | ||
| 45 | static inline int drv_suspend(struct ieee80211_local *local, | ||
| 46 | struct cfg80211_wowlan *wowlan) | ||
| 47 | { | ||
| 48 | int ret; | ||
| 49 | |||
| 50 | might_sleep(); | ||
| 51 | |||
| 52 | trace_drv_suspend(local); | ||
| 53 | ret = local->ops->suspend(&local->hw, wowlan); | ||
| 54 | trace_drv_return_int(local, ret); | ||
| 55 | return ret; | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline int drv_resume(struct ieee80211_local *local) | ||
| 59 | { | ||
| 60 | int ret; | ||
| 61 | |||
| 62 | might_sleep(); | ||
| 63 | |||
| 64 | trace_drv_resume(local); | ||
| 65 | ret = local->ops->resume(&local->hw); | ||
| 66 | trace_drv_return_int(local, ret); | ||
| 67 | return ret; | ||
| 68 | } | ||
| 69 | #endif | ||
| 70 | |||
| 44 | static inline int drv_add_interface(struct ieee80211_local *local, | 71 | static inline int drv_add_interface(struct ieee80211_local *local, |
| 45 | struct ieee80211_vif *vif) | 72 | struct ieee80211_vif *vif) |
| 46 | { | 73 | { |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 191e834ec46b..11e1ea5111ea 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
| @@ -108,6 +108,16 @@ DEFINE_EVENT(local_only_evt, drv_start, | |||
| 108 | TP_ARGS(local) | 108 | TP_ARGS(local) |
| 109 | ); | 109 | ); |
| 110 | 110 | ||
| 111 | DEFINE_EVENT(local_only_evt, drv_suspend, | ||
| 112 | TP_PROTO(struct ieee80211_local *local), | ||
| 113 | TP_ARGS(local) | ||
| 114 | ); | ||
| 115 | |||
| 116 | DEFINE_EVENT(local_only_evt, drv_resume, | ||
| 117 | TP_PROTO(struct ieee80211_local *local), | ||
| 118 | TP_ARGS(local) | ||
| 119 | ); | ||
| 120 | |||
| 111 | DEFINE_EVENT(local_only_evt, drv_stop, | 121 | DEFINE_EVENT(local_only_evt, drv_stop, |
| 112 | TP_PROTO(struct ieee80211_local *local), | 122 | TP_PROTO(struct ieee80211_local *local), |
| 113 | TP_ARGS(local) | 123 | TP_ARGS(local) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9e3b4f0f31bd..e89bc27f8dc3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -764,6 +764,9 @@ struct ieee80211_local { | |||
| 764 | /* device is started */ | 764 | /* device is started */ |
| 765 | bool started; | 765 | bool started; |
| 766 | 766 | ||
| 767 | /* wowlan is enabled -- don't reconfig on resume */ | ||
| 768 | bool wowlan; | ||
| 769 | |||
| 767 | int tx_headroom; /* required headroom for hardware/radiotap */ | 770 | int tx_headroom; /* required headroom for hardware/radiotap */ |
| 768 | 771 | ||
| 769 | /* count for keys needing tailroom space allocation */ | 772 | /* count for keys needing tailroom space allocation */ |
| @@ -1250,7 +1253,8 @@ int ieee80211_reconfig(struct ieee80211_local *local); | |||
| 1250 | void ieee80211_stop_device(struct ieee80211_local *local); | 1253 | void ieee80211_stop_device(struct ieee80211_local *local); |
| 1251 | 1254 | ||
| 1252 | #ifdef CONFIG_PM | 1255 | #ifdef CONFIG_PM |
| 1253 | int __ieee80211_suspend(struct ieee80211_hw *hw); | 1256 | int __ieee80211_suspend(struct ieee80211_hw *hw, |
| 1257 | struct cfg80211_wowlan *wowlan); | ||
| 1254 | 1258 | ||
| 1255 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | 1259 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) |
| 1256 | { | 1260 | { |
| @@ -1263,7 +1267,8 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) | |||
| 1263 | return ieee80211_reconfig(hw_to_local(hw)); | 1267 | return ieee80211_reconfig(hw_to_local(hw)); |
| 1264 | } | 1268 | } |
| 1265 | #else | 1269 | #else |
| 1266 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw) | 1270 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw, |
| 1271 | struct cfg80211_wowlan *wowlan) | ||
| 1267 | { | 1272 | { |
| 1268 | return 0; | 1273 | return 0; |
| 1269 | } | 1274 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d8be1986a108..cb326d36be9c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -696,6 +696,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 696 | WLAN_CIPHER_SUITE_AES_CMAC | 696 | WLAN_CIPHER_SUITE_AES_CMAC |
| 697 | }; | 697 | }; |
| 698 | 698 | ||
| 699 | if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && | ||
| 700 | (!local->ops->suspend || !local->ops->resume)) | ||
| 701 | return -EINVAL; | ||
| 702 | |||
| 699 | if (hw->max_report_rates == 0) | 703 | if (hw->max_report_rates == 0) |
| 700 | hw->max_report_rates = hw->max_rates; | 704 | hw->max_report_rates = hw->max_rates; |
| 701 | 705 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 042461710880..730778a2c90c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "driver-ops.h" | 6 | #include "driver-ops.h" |
| 7 | #include "led.h" | 7 | #include "led.h" |
| 8 | 8 | ||
| 9 | int __ieee80211_suspend(struct ieee80211_hw *hw) | 9 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
| 10 | { | 10 | { |
| 11 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
| 12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
| @@ -47,6 +47,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
| 47 | cancel_work_sync(&local->dynamic_ps_enable_work); | 47 | cancel_work_sync(&local->dynamic_ps_enable_work); |
| 48 | del_timer_sync(&local->dynamic_ps_timer); | 48 | del_timer_sync(&local->dynamic_ps_timer); |
| 49 | 49 | ||
| 50 | local->wowlan = wowlan && local->open_count; | ||
| 51 | if (local->wowlan) { | ||
| 52 | int err = drv_suspend(local, wowlan); | ||
| 53 | if (err) { | ||
| 54 | local->quiescing = false; | ||
| 55 | return err; | ||
| 56 | } | ||
| 57 | goto suspend; | ||
| 58 | } | ||
| 59 | |||
| 50 | /* disable keys */ | 60 | /* disable keys */ |
| 51 | list_for_each_entry(sdata, &local->interfaces, list) | 61 | list_for_each_entry(sdata, &local->interfaces, list) |
| 52 | ieee80211_disable_keys(sdata); | 62 | ieee80211_disable_keys(sdata); |
| @@ -104,6 +114,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
| 104 | if (local->open_count) | 114 | if (local->open_count) |
| 105 | ieee80211_stop_device(local); | 115 | ieee80211_stop_device(local); |
| 106 | 116 | ||
| 117 | suspend: | ||
| 107 | local->suspended = true; | 118 | local->suspended = true; |
| 108 | /* need suspended to be visible before quiescing is false */ | 119 | /* need suspended to be visible before quiescing is false */ |
| 109 | barrier(); | 120 | barrier(); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ef0560a2346a..d3fe2d237485 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -1125,9 +1125,27 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1125 | struct sta_info *sta; | 1125 | struct sta_info *sta; |
| 1126 | int res; | 1126 | int res; |
| 1127 | 1127 | ||
| 1128 | #ifdef CONFIG_PM | ||
| 1128 | if (local->suspended) | 1129 | if (local->suspended) |
| 1129 | local->resuming = true; | 1130 | local->resuming = true; |
| 1130 | 1131 | ||
| 1132 | if (local->wowlan) { | ||
| 1133 | local->wowlan = false; | ||
| 1134 | res = drv_resume(local); | ||
| 1135 | if (res < 0) { | ||
| 1136 | local->resuming = false; | ||
| 1137 | return res; | ||
| 1138 | } | ||
| 1139 | if (res == 0) | ||
| 1140 | goto wake_up; | ||
| 1141 | WARN_ON(res > 1); | ||
| 1142 | /* | ||
| 1143 | * res is 1, which means the driver requested | ||
| 1144 | * to go through a regular reset on wakeup. | ||
| 1145 | */ | ||
| 1146 | } | ||
| 1147 | #endif | ||
| 1148 | |||
| 1131 | /* restart hardware */ | 1149 | /* restart hardware */ |
| 1132 | if (local->open_count) { | 1150 | if (local->open_count) { |
| 1133 | /* | 1151 | /* |
| @@ -1258,6 +1276,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1258 | if (ieee80211_sdata_running(sdata)) | 1276 | if (ieee80211_sdata_running(sdata)) |
| 1259 | ieee80211_enable_keys(sdata); | 1277 | ieee80211_enable_keys(sdata); |
| 1260 | 1278 | ||
| 1279 | wake_up: | ||
| 1261 | ieee80211_wake_queues_by_reason(hw, | 1280 | ieee80211_wake_queues_by_reason(hw, |
| 1262 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1281 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
| 1263 | 1282 | ||
