aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-05-15 03:30:07 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-27 09:10:58 -0400
commit6abb9cb99f33b20c2f32f18a3ae9cc7543e46edb (patch)
treea230daf7c9ff4cab240d048216db1ec3a0cd2ae4
parent83739b03de97049181d711c95200b94a14d3f693 (diff)
cfg80211: make WoWLAN configuration available to drivers
Make the current WoWLAN configuration available to drivers at runtime. This isn't really useful for the normal WoWLAN behaviour and accessing it can also be racy, but drivers may use it for testing the WoWLAN device behaviour while the host stays up & running to observe the device. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h4
-rw-r--r--net/wireless/core.c4
-rw-r--r--net/wireless/core.h21
-rw-r--r--net/wireless/nl80211.c53
-rw-r--r--net/wireless/sysfs.c8
5 files changed, 52 insertions, 38 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9f45d74ce3c2..b3b076a46d50 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2583,6 +2583,9 @@ struct wiphy_wowlan_support {
2583 * may request, if implemented. 2583 * may request, if implemented.
2584 * 2584 *
2585 * @wowlan: WoWLAN support information 2585 * @wowlan: WoWLAN support information
2586 * @wowlan_config: current WoWLAN configuration; this should usually not be
2587 * used since access to it is necessarily racy, use the parameter passed
2588 * to the suspend() operation instead.
2586 * 2589 *
2587 * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. 2590 * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
2588 * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. 2591 * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
@@ -2650,6 +2653,7 @@ struct wiphy {
2650 2653
2651#ifdef CONFIG_PM 2654#ifdef CONFIG_PM
2652 struct wiphy_wowlan_support wowlan; 2655 struct wiphy_wowlan_support wowlan;
2656 struct cfg80211_wowlan *wowlan_config;
2653#endif 2657#endif
2654 2658
2655 u16 max_remain_on_channel_duration; 2659 u16 max_remain_on_channel_duration;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ee422871fe9e..41cec1776f4f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -663,8 +663,10 @@ void wiphy_unregister(struct wiphy *wiphy)
663 flush_work(&rdev->event_work); 663 flush_work(&rdev->event_work);
664 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); 664 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
665 665
666 if (rdev->wowlan && rdev->ops->set_wakeup) 666#ifdef CONFIG_PM
667 if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
667 rdev_set_wakeup(rdev, false); 668 rdev_set_wakeup(rdev, false);
669#endif
668 cfg80211_rdev_free_wowlan(rdev); 670 cfg80211_rdev_free_wowlan(rdev);
669} 671}
670EXPORT_SYMBOL(wiphy_unregister); 672EXPORT_SYMBOL(wiphy_unregister);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index b4b4a566626b..a65eaf8a84c1 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -74,8 +74,6 @@ struct cfg80211_registered_device {
74 struct work_struct conn_work; 74 struct work_struct conn_work;
75 struct work_struct event_work; 75 struct work_struct event_work;
76 76
77 struct cfg80211_wowlan *wowlan;
78
79 struct delayed_work dfs_update_channels_wk; 77 struct delayed_work dfs_update_channels_wk;
80 78
81 /* netlink port which started critical protocol (0 means not started) */ 79 /* netlink port which started critical protocol (0 means not started) */
@@ -96,17 +94,20 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy)
96static inline void 94static inline void
97cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) 95cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
98{ 96{
97#ifdef CONFIG_PM
99 int i; 98 int i;
100 99
101 if (!rdev->wowlan) 100 if (!rdev->wiphy.wowlan_config)
102 return; 101 return;
103 for (i = 0; i < rdev->wowlan->n_patterns; i++) 102 for (i = 0; i < rdev->wiphy.wowlan_config->n_patterns; i++)
104 kfree(rdev->wowlan->patterns[i].mask); 103 kfree(rdev->wiphy.wowlan_config->patterns[i].mask);
105 kfree(rdev->wowlan->patterns); 104 kfree(rdev->wiphy.wowlan_config->patterns);
106 if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock) 105 if (rdev->wiphy.wowlan_config->tcp &&
107 sock_release(rdev->wowlan->tcp->sock); 106 rdev->wiphy.wowlan_config->tcp->sock)
108 kfree(rdev->wowlan->tcp); 107 sock_release(rdev->wiphy.wowlan_config->tcp->sock);
109 kfree(rdev->wowlan); 108 kfree(rdev->wiphy.wowlan_config->tcp);
109 kfree(rdev->wiphy.wowlan_config);
110#endif
110} 111}
111 112
112extern struct workqueue_struct *cfg80211_wq; 113extern struct workqueue_struct *cfg80211_wq;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a09f36bb957c..fb6abcb359a1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7489,28 +7489,29 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
7489static int nl80211_send_wowlan_patterns(struct sk_buff *msg, 7489static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
7490 struct cfg80211_registered_device *rdev) 7490 struct cfg80211_registered_device *rdev)
7491{ 7491{
7492 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
7492 struct nlattr *nl_pats, *nl_pat; 7493 struct nlattr *nl_pats, *nl_pat;
7493 int i, pat_len; 7494 int i, pat_len;
7494 7495
7495 if (!rdev->wowlan->n_patterns) 7496 if (!wowlan->n_patterns)
7496 return 0; 7497 return 0;
7497 7498
7498 nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); 7499 nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
7499 if (!nl_pats) 7500 if (!nl_pats)
7500 return -ENOBUFS; 7501 return -ENOBUFS;
7501 7502
7502 for (i = 0; i < rdev->wowlan->n_patterns; i++) { 7503 for (i = 0; i < wowlan->n_patterns; i++) {
7503 nl_pat = nla_nest_start(msg, i + 1); 7504 nl_pat = nla_nest_start(msg, i + 1);
7504 if (!nl_pat) 7505 if (!nl_pat)
7505 return -ENOBUFS; 7506 return -ENOBUFS;
7506 pat_len = rdev->wowlan->patterns[i].pattern_len; 7507 pat_len = wowlan->patterns[i].pattern_len;
7507 if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, 7508 if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
7508 DIV_ROUND_UP(pat_len, 8), 7509 DIV_ROUND_UP(pat_len, 8),
7509 rdev->wowlan->patterns[i].mask) || 7510 wowlan->patterns[i].mask) ||
7510 nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, 7511 nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
7511 pat_len, rdev->wowlan->patterns[i].pattern) || 7512 pat_len, wowlan->patterns[i].pattern) ||
7512 nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, 7513 nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
7513 rdev->wowlan->patterns[i].pkt_offset)) 7514 wowlan->patterns[i].pkt_offset))
7514 return -ENOBUFS; 7515 return -ENOBUFS;
7515 nla_nest_end(msg, nl_pat); 7516 nla_nest_end(msg, nl_pat);
7516 } 7517 }
@@ -7573,12 +7574,12 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
7573 !rdev->wiphy.wowlan.tcp) 7574 !rdev->wiphy.wowlan.tcp)
7574 return -EOPNOTSUPP; 7575 return -EOPNOTSUPP;
7575 7576
7576 if (rdev->wowlan && rdev->wowlan->tcp) { 7577 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
7577 /* adjust size to have room for all the data */ 7578 /* adjust size to have room for all the data */
7578 size += rdev->wowlan->tcp->tokens_size + 7579 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
7579 rdev->wowlan->tcp->payload_len + 7580 rdev->wiphy.wowlan_config->tcp->payload_len +
7580 rdev->wowlan->tcp->wake_len + 7581 rdev->wiphy.wowlan_config->tcp->wake_len +
7581 rdev->wowlan->tcp->wake_len / 8; 7582 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
7582 } 7583 }
7583 7584
7584 msg = nlmsg_new(size, GFP_KERNEL); 7585 msg = nlmsg_new(size, GFP_KERNEL);
@@ -7590,33 +7591,34 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
7590 if (!hdr) 7591 if (!hdr)
7591 goto nla_put_failure; 7592 goto nla_put_failure;
7592 7593
7593 if (rdev->wowlan) { 7594 if (rdev->wiphy.wowlan_config) {
7594 struct nlattr *nl_wowlan; 7595 struct nlattr *nl_wowlan;
7595 7596
7596 nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); 7597 nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
7597 if (!nl_wowlan) 7598 if (!nl_wowlan)
7598 goto nla_put_failure; 7599 goto nla_put_failure;
7599 7600
7600 if ((rdev->wowlan->any && 7601 if ((rdev->wiphy.wowlan_config->any &&
7601 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || 7602 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
7602 (rdev->wowlan->disconnect && 7603 (rdev->wiphy.wowlan_config->disconnect &&
7603 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || 7604 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
7604 (rdev->wowlan->magic_pkt && 7605 (rdev->wiphy.wowlan_config->magic_pkt &&
7605 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || 7606 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
7606 (rdev->wowlan->gtk_rekey_failure && 7607 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
7607 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || 7608 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
7608 (rdev->wowlan->eap_identity_req && 7609 (rdev->wiphy.wowlan_config->eap_identity_req &&
7609 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || 7610 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
7610 (rdev->wowlan->four_way_handshake && 7611 (rdev->wiphy.wowlan_config->four_way_handshake &&
7611 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || 7612 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
7612 (rdev->wowlan->rfkill_release && 7613 (rdev->wiphy.wowlan_config->rfkill_release &&
7613 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) 7614 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
7614 goto nla_put_failure; 7615 goto nla_put_failure;
7615 7616
7616 if (nl80211_send_wowlan_patterns(msg, rdev)) 7617 if (nl80211_send_wowlan_patterns(msg, rdev))
7617 goto nla_put_failure; 7618 goto nla_put_failure;
7618 7619
7619 if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp)) 7620 if (nl80211_send_wowlan_tcp(msg,
7621 rdev->wiphy.wowlan_config->tcp))
7620 goto nla_put_failure; 7622 goto nla_put_failure;
7621 7623
7622 nla_nest_end(msg, nl_wowlan); 7624 nla_nest_end(msg, nl_wowlan);
@@ -7783,7 +7785,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
7783 struct cfg80211_wowlan *ntrig; 7785 struct cfg80211_wowlan *ntrig;
7784 struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; 7786 struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
7785 int err, i; 7787 int err, i;
7786 bool prev_enabled = rdev->wowlan; 7788 bool prev_enabled = rdev->wiphy.wowlan_config;
7787 7789
7788 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && 7790 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns &&
7789 !rdev->wiphy.wowlan.tcp) 7791 !rdev->wiphy.wowlan.tcp)
@@ -7791,7 +7793,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
7791 7793
7792 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { 7794 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
7793 cfg80211_rdev_free_wowlan(rdev); 7795 cfg80211_rdev_free_wowlan(rdev);
7794 rdev->wowlan = NULL; 7796 rdev->wiphy.wowlan_config = NULL;
7795 goto set_wakeup; 7797 goto set_wakeup;
7796 } 7798 }
7797 7799
@@ -7927,11 +7929,12 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
7927 goto error; 7929 goto error;
7928 } 7930 }
7929 cfg80211_rdev_free_wowlan(rdev); 7931 cfg80211_rdev_free_wowlan(rdev);
7930 rdev->wowlan = ntrig; 7932 rdev->wiphy.wowlan_config = ntrig;
7931 7933
7932 set_wakeup: 7934 set_wakeup:
7933 if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) 7935 if (rdev->ops->set_wakeup &&
7934 rdev_set_wakeup(rdev, rdev->wowlan); 7936 prev_enabled != !!rdev->wiphy.wowlan_config)
7937 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
7935 7938
7936 return 0; 7939 return 0;
7937 error: 7940 error:
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 8f28b9f798d8..360a42c6f694 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -91,6 +91,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
91 cfg80211_leave(rdev, wdev); 91 cfg80211_leave(rdev, wdev);
92} 92}
93 93
94#ifdef CONFIG_PM
94static int wiphy_suspend(struct device *dev, pm_message_t state) 95static int wiphy_suspend(struct device *dev, pm_message_t state)
95{ 96{
96 struct cfg80211_registered_device *rdev = dev_to_rdev(dev); 97 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
@@ -100,10 +101,10 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
100 101
101 rtnl_lock(); 102 rtnl_lock();
102 if (rdev->wiphy.registered) { 103 if (rdev->wiphy.registered) {
103 if (!rdev->wowlan) 104 if (!rdev->wiphy.wowlan_config)
104 cfg80211_leave_all(rdev); 105 cfg80211_leave_all(rdev);
105 if (rdev->ops->suspend) 106 if (rdev->ops->suspend)
106 ret = rdev_suspend(rdev, rdev->wowlan); 107 ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
107 if (ret == 1) { 108 if (ret == 1) {
108 /* Driver refuse to configure wowlan */ 109 /* Driver refuse to configure wowlan */
109 cfg80211_leave_all(rdev); 110 cfg80211_leave_all(rdev);
@@ -132,6 +133,7 @@ static int wiphy_resume(struct device *dev)
132 133
133 return ret; 134 return ret;
134} 135}
136#endif
135 137
136static const void *wiphy_namespace(struct device *d) 138static const void *wiphy_namespace(struct device *d)
137{ 139{
@@ -146,8 +148,10 @@ struct class ieee80211_class = {
146 .dev_release = wiphy_dev_release, 148 .dev_release = wiphy_dev_release,
147 .dev_attrs = ieee80211_dev_attrs, 149 .dev_attrs = ieee80211_dev_attrs,
148 .dev_uevent = wiphy_uevent, 150 .dev_uevent = wiphy_uevent,
151#ifdef CONFIG_PM
149 .suspend = wiphy_suspend, 152 .suspend = wiphy_suspend,
150 .resume = wiphy_resume, 153 .resume = wiphy_resume,
154#endif
151 .ns_type = &net_ns_type_operations, 155 .ns_type = &net_ns_type_operations,
152 .namespace = wiphy_namespace, 156 .namespace = wiphy_namespace,
153}; 157};