Skip to content

Commit

Permalink
cfg80211/mac80211: enable proper device_set_wakeup_enable handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Apr 11, 2012
1 parent da951c2 commit 6d52563
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 1 deletion.
4 changes: 4 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
};
13 changes: 13 additions & 0 deletions net/mac80211/driver-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
14 changes: 14 additions & 0 deletions net/mac80211/driver-trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
}

Expand Down
4 changes: 4 additions & 0 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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++)
Expand Down

0 comments on commit 6d52563

Please sign in to comment.