aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h4
-rw-r--r--include/net/mac80211.h1
-rw-r--r--net/mac80211/cfg.c10
-rw-r--r--net/mac80211/driver-ops.h13
-rw-r--r--net/mac80211/driver-trace.h14
-rw-r--r--net/wireless/core.c5
-rw-r--r--net/wireless/nl80211.c4
7 files changed, 50 insertions, 1 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ae3a3bb37bf2..1fd1c4acfc8e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1344,6 +1344,9 @@ struct cfg80211_gtk_rekey_data {
1344 * be %NULL or contain the enabled Wake-on-Wireless triggers that are 1344 * be %NULL or contain the enabled Wake-on-Wireless triggers that are
1345 * configured for the device. 1345 * configured for the device.
1346 * @resume: wiphy device needs to be resumed 1346 * @resume: wiphy device needs to be resumed
1347 * @set_wakeup: Called when WoWLAN is enabled/disabled, use this callback
1348 * to call device_set_wakeup_enable() to enable/disable wakeup from
1349 * the device.
1347 * 1350 *
1348 * @add_virtual_intf: create a new virtual interface with the given name, 1351 * @add_virtual_intf: create a new virtual interface with the given name,
1349 * must set the struct wireless_dev's iftype. Beware: You must create 1352 * must set the struct wireless_dev's iftype. Beware: You must create
@@ -1515,6 +1518,7 @@ struct cfg80211_gtk_rekey_data {
1515struct cfg80211_ops { 1518struct cfg80211_ops {
1516 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); 1519 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
1517 int (*resume)(struct wiphy *wiphy); 1520 int (*resume)(struct wiphy *wiphy);
1521 void (*set_wakeup)(struct wiphy *wiphy, bool enabled);
1518 1522
1519 struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, 1523 struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
1520 char *name, 1524 char *name,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ec4995d0c14d..838a4db1c848 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2233,6 +2233,7 @@ struct ieee80211_ops {
2233#ifdef CONFIG_PM 2233#ifdef CONFIG_PM
2234 int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); 2234 int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
2235 int (*resume)(struct ieee80211_hw *hw); 2235 int (*resume)(struct ieee80211_hw *hw);
2236 void (*set_wakeup)(struct ieee80211_hw *hw, bool enabled);
2236#endif 2237#endif
2237 int (*add_interface)(struct ieee80211_hw *hw, 2238 int (*add_interface)(struct ieee80211_hw *hw,
2238 struct ieee80211_vif *vif); 2239 struct ieee80211_vif *vif);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d6163b98f7b7..355735491252 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2695,6 +2695,13 @@ ieee80211_wiphy_get_channel(struct wiphy *wiphy)
2695 return local->oper_channel; 2695 return local->oper_channel;
2696} 2696}
2697 2697
2698#ifdef CONFIG_PM
2699static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled)
2700{
2701 drv_set_wakeup(wiphy_priv(wiphy), enabled);
2702}
2703#endif
2704
2698struct cfg80211_ops mac80211_config_ops = { 2705struct cfg80211_ops mac80211_config_ops = {
2699 .add_virtual_intf = ieee80211_add_iface, 2706 .add_virtual_intf = ieee80211_add_iface,
2700 .del_virtual_intf = ieee80211_del_iface, 2707 .del_virtual_intf = ieee80211_del_iface,
@@ -2763,4 +2770,7 @@ struct cfg80211_ops mac80211_config_ops = {
2763 .probe_client = ieee80211_probe_client, 2770 .probe_client = ieee80211_probe_client,
2764 .get_channel = ieee80211_wiphy_get_channel, 2771 .get_channel = ieee80211_wiphy_get_channel,
2765 .set_noack_map = ieee80211_set_noack_map, 2772 .set_noack_map = ieee80211_set_noack_map,
2773#ifdef CONFIG_PM
2774 .set_wakeup = ieee80211_set_wakeup,
2775#endif
2766}; 2776};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 492c08c27c5f..4a0e559cb26b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -91,6 +91,19 @@ static inline int drv_resume(struct ieee80211_local *local)
91 trace_drv_return_int(local, ret); 91 trace_drv_return_int(local, ret);
92 return ret; 92 return ret;
93} 93}
94
95static inline void drv_set_wakeup(struct ieee80211_local *local,
96 bool enabled)
97{
98 might_sleep();
99
100 if (!local->ops->set_wakeup)
101 return;
102
103 trace_drv_set_wakeup(local, enabled);
104 local->ops->set_wakeup(&local->hw, enabled);
105 trace_drv_return_void(local);
106}
94#endif 107#endif
95 108
96static inline int drv_add_interface(struct ieee80211_local *local, 109static inline int drv_add_interface(struct ieee80211_local *local,
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index d1f017a11988..7c0754bed61b 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -171,6 +171,20 @@ DEFINE_EVENT(local_only_evt, drv_resume,
171 TP_ARGS(local) 171 TP_ARGS(local)
172); 172);
173 173
174TRACE_EVENT(drv_set_wakeup,
175 TP_PROTO(struct ieee80211_local *local, bool enabled),
176 TP_ARGS(local, enabled),
177 TP_STRUCT__entry(
178 LOCAL_ENTRY
179 __field(bool, enabled)
180 ),
181 TP_fast_assign(
182 LOCAL_ASSIGN;
183 __entry->enabled = enabled;
184 ),
185 TP_printk(LOCAL_PR_FMT " enabled:%d", LOCAL_PR_ARG, __entry->enabled)
186);
187
174DEFINE_EVENT(local_only_evt, drv_stop, 188DEFINE_EVENT(local_only_evt, drv_stop,
175 TP_PROTO(struct ieee80211_local *local), 189 TP_PROTO(struct ieee80211_local *local),
176 TP_ARGS(local) 190 TP_ARGS(local)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ccdfed897651..59f4a7e7c092 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -708,6 +708,10 @@ void wiphy_unregister(struct wiphy *wiphy)
708 flush_work(&rdev->scan_done_wk); 708 flush_work(&rdev->scan_done_wk);
709 cancel_work_sync(&rdev->conn_work); 709 cancel_work_sync(&rdev->conn_work);
710 flush_work(&rdev->event_work); 710 flush_work(&rdev->event_work);
711
712 if (rdev->wowlan && rdev->ops->set_wakeup)
713 rdev->ops->set_wakeup(&rdev->wiphy, false);
714 cfg80211_rdev_free_wowlan(rdev);
711} 715}
712EXPORT_SYMBOL(wiphy_unregister); 716EXPORT_SYMBOL(wiphy_unregister);
713 717
@@ -720,7 +724,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
720 mutex_destroy(&rdev->sched_scan_mtx); 724 mutex_destroy(&rdev->sched_scan_mtx);
721 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) 725 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
722 cfg80211_put_bss(&scan->pub); 726 cfg80211_put_bss(&scan->pub);
723 cfg80211_rdev_free_wowlan(rdev);
724 kfree(rdev); 727 kfree(rdev);
725} 728}
726 729
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b12a05243d71..40e5620e5fde 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6014,6 +6014,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
6014 struct cfg80211_wowlan new_triggers = {}; 6014 struct cfg80211_wowlan new_triggers = {};
6015 struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; 6015 struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
6016 int err, i; 6016 int err, i;
6017 bool prev_enabled = rdev->wowlan;
6017 6018
6018 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) 6019 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
6019 return -EOPNOTSUPP; 6020 return -EOPNOTSUPP;
@@ -6146,6 +6147,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
6146 rdev->wowlan = NULL; 6147 rdev->wowlan = NULL;
6147 } 6148 }
6148 6149
6150 if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)
6151 rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan);
6152
6149 return 0; 6153 return 0;
6150 error: 6154 error:
6151 for (i = 0; i < new_triggers.n_patterns; i++) 6155 for (i = 0; i < new_triggers.n_patterns; i++)