forked from Minki/linux
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
|
* be %NULL or contain the enabled Wake-on-Wireless triggers that are
|
||||||
* configured for the device.
|
* configured for the device.
|
||||||
* @resume: wiphy device needs to be resumed
|
* @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,
|
* @add_virtual_intf: create a new virtual interface with the given name,
|
||||||
* must set the struct wireless_dev's iftype. Beware: You must create
|
* must set the struct wireless_dev's iftype. Beware: You must create
|
||||||
@ -1515,6 +1518,7 @@ struct cfg80211_gtk_rekey_data {
|
|||||||
struct cfg80211_ops {
|
struct cfg80211_ops {
|
||||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||||
int (*resume)(struct wiphy *wiphy);
|
int (*resume)(struct wiphy *wiphy);
|
||||||
|
void (*set_wakeup)(struct wiphy *wiphy, bool enabled);
|
||||||
|
|
||||||
struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
|
struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
|
||||||
char *name,
|
char *name,
|
||||||
|
@ -2233,6 +2233,7 @@ struct ieee80211_ops {
|
|||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
||||||
int (*resume)(struct ieee80211_hw *hw);
|
int (*resume)(struct ieee80211_hw *hw);
|
||||||
|
void (*set_wakeup)(struct ieee80211_hw *hw, bool enabled);
|
||||||
#endif
|
#endif
|
||||||
int (*add_interface)(struct ieee80211_hw *hw,
|
int (*add_interface)(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif);
|
struct ieee80211_vif *vif);
|
||||||
|
@ -2695,6 +2695,13 @@ ieee80211_wiphy_get_channel(struct wiphy *wiphy)
|
|||||||
return local->oper_channel;
|
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 = {
|
struct cfg80211_ops mac80211_config_ops = {
|
||||||
.add_virtual_intf = ieee80211_add_iface,
|
.add_virtual_intf = ieee80211_add_iface,
|
||||||
.del_virtual_intf = ieee80211_del_iface,
|
.del_virtual_intf = ieee80211_del_iface,
|
||||||
@ -2763,4 +2770,7 @@ struct cfg80211_ops mac80211_config_ops = {
|
|||||||
.probe_client = ieee80211_probe_client,
|
.probe_client = ieee80211_probe_client,
|
||||||
.get_channel = ieee80211_wiphy_get_channel,
|
.get_channel = ieee80211_wiphy_get_channel,
|
||||||
.set_noack_map = ieee80211_set_noack_map,
|
.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);
|
trace_drv_return_int(local, ret);
|
||||||
return 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
|
#endif
|
||||||
|
|
||||||
static inline int drv_add_interface(struct ieee80211_local *local,
|
static inline int drv_add_interface(struct ieee80211_local *local,
|
||||||
|
@ -171,6 +171,20 @@ DEFINE_EVENT(local_only_evt, drv_resume,
|
|||||||
TP_ARGS(local)
|
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,
|
DEFINE_EVENT(local_only_evt, drv_stop,
|
||||||
TP_PROTO(struct ieee80211_local *local),
|
TP_PROTO(struct ieee80211_local *local),
|
||||||
TP_ARGS(local)
|
TP_ARGS(local)
|
||||||
|
@ -708,6 +708,10 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||||||
flush_work(&rdev->scan_done_wk);
|
flush_work(&rdev->scan_done_wk);
|
||||||
cancel_work_sync(&rdev->conn_work);
|
cancel_work_sync(&rdev->conn_work);
|
||||||
flush_work(&rdev->event_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);
|
EXPORT_SYMBOL(wiphy_unregister);
|
||||||
|
|
||||||
@ -720,7 +724,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
|
|||||||
mutex_destroy(&rdev->sched_scan_mtx);
|
mutex_destroy(&rdev->sched_scan_mtx);
|
||||||
list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
|
list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
|
||||||
cfg80211_put_bss(&scan->pub);
|
cfg80211_put_bss(&scan->pub);
|
||||||
cfg80211_rdev_free_wowlan(rdev);
|
|
||||||
kfree(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 cfg80211_wowlan new_triggers = {};
|
||||||
struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
|
struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
|
||||||
int err, i;
|
int err, i;
|
||||||
|
bool prev_enabled = rdev->wowlan;
|
||||||
|
|
||||||
if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
|
if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -6146,6 +6147,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
rdev->wowlan = NULL;
|
rdev->wowlan = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)
|
||||||
|
rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
error:
|
error:
|
||||||
for (i = 0; i < new_triggers.n_patterns; i++)
|
for (i = 0; i < new_triggers.n_patterns; i++)
|
||||||
|
Loading…
Reference in New Issue
Block a user