cfg80211/mac80211: enable proper device_set_wakeup_enable handling
In WoWLAN, we only get the triggers when we actually get to suspend. As a consequence, drivers currently don't know that the device should enable wakeup. However, the device_set_wakeup_enable() API is intended to be called when the wakeup is enabled, not later when needed. Add a new set_wakeup() call to cfg80211 and mac80211 to allow drivers to properly call device_set_wakeup_enable. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
da951c2417
commit
6d52563f2b
|
@ -1344,6 +1344,9 @@ struct cfg80211_gtk_rekey_data {
|
|||
* be %NULL or contain the enabled Wake-on-Wireless triggers that are
|
||||
* configured for the device.
|
||||
* @resume: wiphy device needs to be resumed
|
||||
* @set_wakeup: Called when WoWLAN is enabled/disabled, use this callback
|
||||
* to call device_set_wakeup_enable() to enable/disable wakeup from
|
||||
* the device.
|
||||
*
|
||||
* @add_virtual_intf: create a new virtual interface with the given name,
|
||||
* must set the struct wireless_dev's iftype. Beware: You must create
|
||||
|
@ -1515,6 +1518,7 @@ struct cfg80211_gtk_rekey_data {
|
|||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
int (*resume)(struct wiphy *wiphy);
|
||||
void (*set_wakeup)(struct wiphy *wiphy, bool enabled);
|
||||
|
||||
struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
|
||||
char *name,
|
||||
|
|
|
@ -2233,6 +2233,7 @@ struct ieee80211_ops {
|
|||
#ifdef CONFIG_PM
|
||||
int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
||||
int (*resume)(struct ieee80211_hw *hw);
|
||||
void (*set_wakeup)(struct ieee80211_hw *hw, bool enabled);
|
||||
#endif
|
||||
int (*add_interface)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
|
|
@ -2695,6 +2695,13 @@ ieee80211_wiphy_get_channel(struct wiphy *wiphy)
|
|||
return local->oper_channel;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled)
|
||||
{
|
||||
drv_set_wakeup(wiphy_priv(wiphy), enabled);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
|
@ -2763,4 +2770,7 @@ struct cfg80211_ops mac80211_config_ops = {
|
|||
.probe_client = ieee80211_probe_client,
|
||||
.get_channel = ieee80211_wiphy_get_channel,
|
||||
.set_noack_map = ieee80211_set_noack_map,
|
||||
#ifdef CONFIG_PM
|
||||
.set_wakeup = ieee80211_set_wakeup,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -91,6 +91,19 @@ static inline int drv_resume(struct ieee80211_local *local)
|
|||
trace_drv_return_int(local, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_set_wakeup(struct ieee80211_local *local,
|
||||
bool enabled)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (!local->ops->set_wakeup)
|
||||
return;
|
||||
|
||||
trace_drv_set_wakeup(local, enabled);
|
||||
local->ops->set_wakeup(&local->hw, enabled);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int drv_add_interface(struct ieee80211_local *local,
|
||||
|
|
|
@ -171,6 +171,20 @@ DEFINE_EVENT(local_only_evt, drv_resume,
|
|||
TP_ARGS(local)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_set_wakeup,
|
||||
TP_PROTO(struct ieee80211_local *local, bool enabled),
|
||||
TP_ARGS(local, enabled),
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(bool, enabled)
|
||||
),
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->enabled = enabled;
|
||||
),
|
||||
TP_printk(LOCAL_PR_FMT " enabled:%d", LOCAL_PR_ARG, __entry->enabled)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_only_evt, drv_stop,
|
||||
TP_PROTO(struct ieee80211_local *local),
|
||||
TP_ARGS(local)
|
||||
|
|
|
@ -708,6 +708,10 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
flush_work(&rdev->scan_done_wk);
|
||||
cancel_work_sync(&rdev->conn_work);
|
||||
flush_work(&rdev->event_work);
|
||||
|
||||
if (rdev->wowlan && rdev->ops->set_wakeup)
|
||||
rdev->ops->set_wakeup(&rdev->wiphy, false);
|
||||
cfg80211_rdev_free_wowlan(rdev);
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_unregister);
|
||||
|
||||
|
@ -720,7 +724,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
|
|||
mutex_destroy(&rdev->sched_scan_mtx);
|
||||
list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
|
||||
cfg80211_put_bss(&scan->pub);
|
||||
cfg80211_rdev_free_wowlan(rdev);
|
||||
kfree(rdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -6014,6 +6014,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_wowlan new_triggers = {};
|
||||
struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
|
||||
int err, i;
|
||||
bool prev_enabled = rdev->wowlan;
|
||||
|
||||
if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -6146,6 +6147,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
rdev->wowlan = NULL;
|
||||
}
|
||||
|
||||
if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)
|
||||
rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
for (i = 0; i < new_triggers.n_patterns; i++)
|
||||
|
|
Loading…
Reference in New Issue