aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h99
-rw-r--r--include/net/cfg80211.h74
-rw-r--r--net/mac80211/cfg.c3
-rw-r--r--net/wireless/core.c8
-rw-r--r--net/wireless/core.h14
-rw-r--r--net/wireless/nl80211.c243
-rw-r--r--net/wireless/sysfs.c2
7 files changed, 439 insertions, 4 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index be8df57b789d..a75dea9c416e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -420,6 +420,14 @@
420 * new station with the AUTHENTICATED flag unset and maybe change it later 420 * new station with the AUTHENTICATED flag unset and maybe change it later
421 * depending on the authentication result. 421 * depending on the authentication result.
422 * 422 *
423 * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings.
424 * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings.
425 * Since wireless is more complex than wired ethernet, it supports
426 * various triggers. These triggers can be configured through this
427 * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For
428 * more background information, see
429 * http://wireless.kernel.org/en/users/Documentation/WoWLAN.
430 *
423 * @NL80211_CMD_MAX: highest used command number 431 * @NL80211_CMD_MAX: highest used command number
424 * @__NL80211_CMD_AFTER_LAST: internal use 432 * @__NL80211_CMD_AFTER_LAST: internal use
425 */ 433 */
@@ -534,6 +542,9 @@ enum nl80211_commands {
534 542
535 NL80211_CMD_NEW_PEER_CANDIDATE, 543 NL80211_CMD_NEW_PEER_CANDIDATE,
536 544
545 NL80211_CMD_GET_WOWLAN,
546 NL80211_CMD_SET_WOWLAN,
547
537 /* add new commands above here */ 548 /* add new commands above here */
538 549
539 /* used to define NL80211_CMD_MAX below */ 550 /* used to define NL80211_CMD_MAX below */
@@ -903,6 +914,13 @@ enum nl80211_commands {
903 * allows auth frames in a mesh to be passed to userspace for processing via 914 * allows auth frames in a mesh to be passed to userspace for processing via
904 * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. 915 * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
905 * 916 *
917 * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities,
918 * the supported WoWLAN triggers
919 * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to
920 * indicate which WoW triggers should be enabled. This is also
921 * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN
922 * triggers.
923 *
906 * @NL80211_ATTR_MAX: highest attribute number currently defined 924 * @NL80211_ATTR_MAX: highest attribute number currently defined
907 * @__NL80211_ATTR_AFTER_LAST: internal use 925 * @__NL80211_ATTR_AFTER_LAST: internal use
908 */ 926 */
@@ -1092,6 +1110,9 @@ enum nl80211_attrs {
1092 1110
1093 NL80211_ATTR_SUPPORT_MESH_AUTH, 1111 NL80211_ATTR_SUPPORT_MESH_AUTH,
1094 1112
1113 NL80211_ATTR_WOWLAN_TRIGGERS,
1114 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED,
1115
1095 /* add attributes here, update the policy in nl80211.c */ 1116 /* add attributes here, update the policy in nl80211.c */
1096 1117
1097 __NL80211_ATTR_AFTER_LAST, 1118 __NL80211_ATTR_AFTER_LAST,
@@ -2061,4 +2082,82 @@ enum nl80211_tx_power_setting {
2061 NL80211_TX_POWER_FIXED, 2082 NL80211_TX_POWER_FIXED,
2062}; 2083};
2063 2084
2085/**
2086 * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
2087 * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
2088 * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
2089 * a zero bit are ignored
2090 * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
2091 * a bit for each byte in the pattern. The lowest-order bit corresponds
2092 * to the first byte of the pattern, but the bytes of the pattern are
2093 * in a little-endian-like format, i.e. the 9th byte of the pattern
2094 * corresponds to the lowest-order bit in the second byte of the mask.
2095 * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where
2096 * xx indicates "don't care") would be represented by a pattern of
2097 * twelve zero bytes, and a mask of "0xed,0x07".
2098 * Note that the pattern matching is done as though frames were not
2099 * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
2100 * first (including SNAP header unpacking) and then matched.
2101 * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
2102 * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
2103 */
2104enum nl80211_wowlan_packet_pattern_attr {
2105 __NL80211_WOWLAN_PKTPAT_INVALID,
2106 NL80211_WOWLAN_PKTPAT_MASK,
2107 NL80211_WOWLAN_PKTPAT_PATTERN,
2108
2109 NUM_NL80211_WOWLAN_PKTPAT,
2110 MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
2111};
2112
2113/**
2114 * struct nl80211_wowlan_pattern_support - pattern support information
2115 * @max_patterns: maximum number of patterns supported
2116 * @min_pattern_len: minimum length of each pattern
2117 * @max_pattern_len: maximum length of each pattern
2118 *
2119 * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
2120 * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
2121 * capability information given by the kernel to userspace.
2122 */
2123struct nl80211_wowlan_pattern_support {
2124 __u32 max_patterns;
2125 __u32 min_pattern_len;
2126 __u32 max_pattern_len;
2127} __attribute__((packed));
2128
2129/**
2130 * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
2131 * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
2132 * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put
2133 * the chip into a special state -- works best with chips that have
2134 * support for low-power operation already (flag)
2135 * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect
2136 * is detected is implementation-specific (flag)
2137 * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed
2138 * by 16 repetitions of MAC addr, anywhere in payload) (flag)
2139 * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
2140 * which are passed in an array of nested attributes, each nested attribute
2141 * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
2142 * Each pattern defines a wakeup packet. The matching is done on the MSDU,
2143 * i.e. as though the packet was an 802.3 packet, so the pattern matching
2144 * is done after the packet is converted to the MSDU.
2145 *
2146 * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
2147 * carrying a &struct nl80211_wowlan_pattern_support.
2148 * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
2149 * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
2150 */
2151enum nl80211_wowlan_triggers {
2152 __NL80211_WOWLAN_TRIG_INVALID,
2153 NL80211_WOWLAN_TRIG_ANY,
2154 NL80211_WOWLAN_TRIG_DISCONNECT,
2155 NL80211_WOWLAN_TRIG_MAGIC_PKT,
2156 NL80211_WOWLAN_TRIG_PKT_PATTERN,
2157
2158 /* keep last */
2159 NUM_NL80211_WOWLAN_TRIG,
2160 MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1
2161};
2162
2064#endif /* __LINUX_NL80211_H */ 2163#endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4932dfcb72b4..0920daf36807 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1088,6 +1088,38 @@ struct cfg80211_pmksa {
1088}; 1088};
1089 1089
1090/** 1090/**
1091 * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
1092 * @mask: bitmask where to match pattern and where to ignore bytes,
1093 * one bit per byte, in same format as nl80211
1094 * @pattern: bytes to match where bitmask is 1
1095 * @pattern_len: length of pattern (in bytes)
1096 *
1097 * Internal note: @mask and @pattern are allocated in one chunk of
1098 * memory, free @mask only!
1099 */
1100struct cfg80211_wowlan_trig_pkt_pattern {
1101 u8 *mask, *pattern;
1102 int pattern_len;
1103};
1104
1105/**
1106 * struct cfg80211_wowlan - Wake on Wireless-LAN support info
1107 *
1108 * This structure defines the enabled WoWLAN triggers for the device.
1109 * @any: wake up on any activity -- special trigger if device continues
1110 * operating as normal during suspend
1111 * @disconnect: wake up if getting disconnected
1112 * @magic_pkt: wake up on receiving magic packet
1113 * @patterns: wake up on receiving packet matching a pattern
1114 * @n_patterns: number of patterns
1115 */
1116struct cfg80211_wowlan {
1117 bool any, disconnect, magic_pkt;
1118 struct cfg80211_wowlan_trig_pkt_pattern *patterns;
1119 int n_patterns;
1120};
1121
1122/**
1091 * struct cfg80211_ops - backend description for wireless configuration 1123 * struct cfg80211_ops - backend description for wireless configuration
1092 * 1124 *
1093 * This struct is registered by fullmac card drivers and/or wireless stacks 1125 * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -1100,7 +1132,9 @@ struct cfg80211_pmksa {
1100 * wireless extensions but this is subject to reevaluation as soon as this 1132 * wireless extensions but this is subject to reevaluation as soon as this
1101 * code is used more widely and we have a first user without wext. 1133 * code is used more widely and we have a first user without wext.
1102 * 1134 *
1103 * @suspend: wiphy device needs to be suspended 1135 * @suspend: wiphy device needs to be suspended. The variable @wow will
1136 * be %NULL or contain the enabled Wake-on-Wireless triggers that are
1137 * configured for the device.
1104 * @resume: wiphy device needs to be resumed 1138 * @resume: wiphy device needs to be resumed
1105 * 1139 *
1106 * @add_virtual_intf: create a new virtual interface with the given name, 1140 * @add_virtual_intf: create a new virtual interface with the given name,
@@ -1244,7 +1278,7 @@ struct cfg80211_pmksa {
1244 * @get_ringparam: Get tx and rx ring current and maximum sizes. 1278 * @get_ringparam: Get tx and rx ring current and maximum sizes.
1245 */ 1279 */
1246struct cfg80211_ops { 1280struct cfg80211_ops {
1247 int (*suspend)(struct wiphy *wiphy); 1281 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
1248 int (*resume)(struct wiphy *wiphy); 1282 int (*resume)(struct wiphy *wiphy);
1249 1283
1250 struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, 1284 struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
@@ -1480,6 +1514,38 @@ struct ieee80211_txrx_stypes {
1480}; 1514};
1481 1515
1482/** 1516/**
1517 * enum wiphy_wowlan_support_flags - WoWLAN support flags
1518 * @WIPHY_WOWLAN_ANY: supports wakeup for the special "any"
1519 * trigger that keeps the device operating as-is and
1520 * wakes up the host on any activity, for example a
1521 * received packet that passed filtering; note that the
1522 * packet should be preserved in that case
1523 * @WIPHY_WOWLAN_MAGIC_PKT: supports wakeup on magic packet
1524 * (see nl80211.h)
1525 * @WIPHY_WOWLAN_DISCONNECT: supports wakeup on disconnect
1526 */
1527enum wiphy_wowlan_support_flags {
1528 WIPHY_WOWLAN_ANY = BIT(0),
1529 WIPHY_WOWLAN_MAGIC_PKT = BIT(1),
1530 WIPHY_WOWLAN_DISCONNECT = BIT(2),
1531};
1532
1533/**
1534 * struct wiphy_wowlan_support - WoWLAN support data
1535 * @flags: see &enum wiphy_wowlan_support_flags
1536 * @n_patterns: number of supported wakeup patterns
1537 * (see nl80211.h for the pattern definition)
1538 * @pattern_max_len: maximum length of each pattern
1539 * @pattern_min_len: minimum length of each pattern
1540 */
1541struct wiphy_wowlan_support {
1542 u32 flags;
1543 int n_patterns;
1544 int pattern_max_len;
1545 int pattern_min_len;
1546};
1547
1548/**
1483 * struct wiphy - wireless hardware description 1549 * struct wiphy - wireless hardware description
1484 * @reg_notifier: the driver's regulatory notification callback, 1550 * @reg_notifier: the driver's regulatory notification callback,
1485 * note that if your driver uses wiphy_apply_custom_regulatory() 1551 * note that if your driver uses wiphy_apply_custom_regulatory()
@@ -1546,6 +1612,8 @@ struct ieee80211_txrx_stypes {
1546 * 1612 *
1547 * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation 1613 * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation
1548 * may request, if implemented. 1614 * may request, if implemented.
1615 *
1616 * @wowlan: WoWLAN support information
1549 */ 1617 */
1550struct wiphy { 1618struct wiphy {
1551 /* assign these fields before you register the wiphy */ 1619 /* assign these fields before you register the wiphy */
@@ -1583,6 +1651,8 @@ struct wiphy {
1583 char fw_version[ETHTOOL_BUSINFO_LEN]; 1651 char fw_version[ETHTOOL_BUSINFO_LEN];
1584 u32 hw_version; 1652 u32 hw_version;
1585 1653
1654 struct wiphy_wowlan_support wowlan;
1655
1586 u16 max_remain_on_channel_duration; 1656 u16 max_remain_on_channel_duration;
1587 1657
1588 u8 max_num_pmkids; 1658 u8 max_num_pmkids;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 12d52cec9515..321d598eb8cb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1297,7 +1297,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
1297} 1297}
1298 1298
1299#ifdef CONFIG_PM 1299#ifdef CONFIG_PM
1300static int ieee80211_suspend(struct wiphy *wiphy) 1300static int ieee80211_suspend(struct wiphy *wiphy,
1301 struct cfg80211_wowlan *wowlan)
1301{ 1302{
1302 return __ieee80211_suspend(wiphy_priv(wiphy)); 1303 return __ieee80211_suspend(wiphy_priv(wiphy));
1303} 1304}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index bbf1fa11107a..bea0d80710c8 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -493,6 +493,13 @@ int wiphy_register(struct wiphy *wiphy)
493 return -EINVAL; 493 return -EINVAL;
494 } 494 }
495 495
496 if (rdev->wiphy.wowlan.n_patterns) {
497 if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len ||
498 rdev->wiphy.wowlan.pattern_min_len >
499 rdev->wiphy.wowlan.pattern_max_len))
500 return -EINVAL;
501 }
502
496 /* check and set up bitrates */ 503 /* check and set up bitrates */
497 ieee80211_set_bitrate_flags(wiphy); 504 ieee80211_set_bitrate_flags(wiphy);
498 505
@@ -631,6 +638,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
631 mutex_destroy(&rdev->devlist_mtx); 638 mutex_destroy(&rdev->devlist_mtx);
632 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) 639 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
633 cfg80211_put_bss(&scan->pub); 640 cfg80211_put_bss(&scan->pub);
641 cfg80211_rdev_free_wowlan(rdev);
634 kfree(rdev); 642 kfree(rdev);
635} 643}
636 644
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 26a0a084e16b..7a18c10a7fb6 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -70,6 +70,8 @@ struct cfg80211_registered_device {
70 struct work_struct conn_work; 70 struct work_struct conn_work;
71 struct work_struct event_work; 71 struct work_struct event_work;
72 72
73 struct cfg80211_wowlan *wowlan;
74
73 /* must be last because of the way we do wiphy_priv(), 75 /* must be last because of the way we do wiphy_priv(),
74 * and it should at least be aligned to NETDEV_ALIGN */ 76 * and it should at least be aligned to NETDEV_ALIGN */
75 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); 77 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -89,6 +91,18 @@ bool wiphy_idx_valid(int wiphy_idx)
89 return wiphy_idx >= 0; 91 return wiphy_idx >= 0;
90} 92}
91 93
94static inline void
95cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
96{
97 int i;
98
99 if (!rdev->wowlan)
100 return;
101 for (i = 0; i < rdev->wowlan->n_patterns; i++)
102 kfree(rdev->wowlan->patterns[i].mask);
103 kfree(rdev->wowlan->patterns);
104 kfree(rdev->wowlan);
105}
92 106
93extern struct workqueue_struct *cfg80211_wq; 107extern struct workqueue_struct *cfg80211_wq;
94extern struct mutex cfg80211_mutex; 108extern struct mutex cfg80211_mutex;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ab77f943dc04..0a199a1ca9b6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -173,6 +173,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
173 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, 173 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
174 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, 174 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
175 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, 175 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
176 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
176}; 177};
177 178
178/* policy for the key attributes */ 179/* policy for the key attributes */
@@ -194,6 +195,15 @@ nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
194 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, 195 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
195}; 196};
196 197
198/* policy for WoWLAN attributes */
199static const struct nla_policy
200nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
201 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
202 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
203 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
204 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
205};
206
197/* ifidx get helper */ 207/* ifidx get helper */
198static int nl80211_get_ifidx(struct netlink_callback *cb) 208static int nl80211_get_ifidx(struct netlink_callback *cb)
199{ 209{
@@ -821,6 +831,35 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
821 nla_nest_end(msg, nl_ifs); 831 nla_nest_end(msg, nl_ifs);
822 } 832 }
823 833
834 if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) {
835 struct nlattr *nl_wowlan;
836
837 nl_wowlan = nla_nest_start(msg,
838 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
839 if (!nl_wowlan)
840 goto nla_put_failure;
841
842 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY)
843 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
844 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT)
845 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
846 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT)
847 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
848 if (dev->wiphy.wowlan.n_patterns) {
849 struct nl80211_wowlan_pattern_support pat = {
850 .max_patterns = dev->wiphy.wowlan.n_patterns,
851 .min_pattern_len =
852 dev->wiphy.wowlan.pattern_min_len,
853 .max_pattern_len =
854 dev->wiphy.wowlan.pattern_max_len,
855 };
856 NLA_PUT(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
857 sizeof(pat), &pat);
858 }
859
860 nla_nest_end(msg, nl_wowlan);
861 }
862
824 return genlmsg_end(msg, hdr); 863 return genlmsg_end(msg, hdr);
825 864
826 nla_put_failure: 865 nla_put_failure:
@@ -4808,6 +4847,194 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
4808 return cfg80211_leave_mesh(rdev, dev); 4847 return cfg80211_leave_mesh(rdev, dev);
4809} 4848}
4810 4849
4850static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
4851{
4852 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4853 struct sk_buff *msg;
4854 void *hdr;
4855
4856 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
4857 return -EOPNOTSUPP;
4858
4859 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4860 if (!msg)
4861 return -ENOMEM;
4862
4863 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
4864 NL80211_CMD_GET_WOWLAN);
4865 if (!hdr)
4866 goto nla_put_failure;
4867
4868 if (rdev->wowlan) {
4869 struct nlattr *nl_wowlan;
4870
4871 nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
4872 if (!nl_wowlan)
4873 goto nla_put_failure;
4874
4875 if (rdev->wowlan->any)
4876 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
4877 if (rdev->wowlan->disconnect)
4878 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
4879 if (rdev->wowlan->magic_pkt)
4880 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
4881 if (rdev->wowlan->n_patterns) {
4882 struct nlattr *nl_pats, *nl_pat;
4883 int i, pat_len;
4884
4885 nl_pats = nla_nest_start(msg,
4886 NL80211_WOWLAN_TRIG_PKT_PATTERN);
4887 if (!nl_pats)
4888 goto nla_put_failure;
4889
4890 for (i = 0; i < rdev->wowlan->n_patterns; i++) {
4891 nl_pat = nla_nest_start(msg, i + 1);
4892 if (!nl_pat)
4893 goto nla_put_failure;
4894 pat_len = rdev->wowlan->patterns[i].pattern_len;
4895 NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_MASK,
4896 DIV_ROUND_UP(pat_len, 8),
4897 rdev->wowlan->patterns[i].mask);
4898 NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
4899 pat_len,
4900 rdev->wowlan->patterns[i].pattern);
4901 nla_nest_end(msg, nl_pat);
4902 }
4903 nla_nest_end(msg, nl_pats);
4904 }
4905
4906 nla_nest_end(msg, nl_wowlan);
4907 }
4908
4909 genlmsg_end(msg, hdr);
4910 return genlmsg_reply(msg, info);
4911
4912nla_put_failure:
4913 nlmsg_free(msg);
4914 return -ENOBUFS;
4915}
4916
4917static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
4918{
4919 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4920 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
4921 struct cfg80211_wowlan no_triggers = {};
4922 struct cfg80211_wowlan new_triggers = {};
4923 struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
4924 int err, i;
4925
4926 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
4927 return -EOPNOTSUPP;
4928
4929 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS])
4930 goto no_triggers;
4931
4932 err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG,
4933 nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
4934 nla_len(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
4935 nl80211_wowlan_policy);
4936 if (err)
4937 return err;
4938
4939 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
4940 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
4941 return -EINVAL;
4942 new_triggers.any = true;
4943 }
4944
4945 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
4946 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
4947 return -EINVAL;
4948 new_triggers.disconnect = true;
4949 }
4950
4951 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
4952 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
4953 return -EINVAL;
4954 new_triggers.magic_pkt = true;
4955 }
4956
4957 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
4958 struct nlattr *pat;
4959 int n_patterns = 0;
4960 int rem, pat_len, mask_len;
4961 struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
4962
4963 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
4964 rem)
4965 n_patterns++;
4966 if (n_patterns > wowlan->n_patterns)
4967 return -EINVAL;
4968
4969 new_triggers.patterns = kcalloc(n_patterns,
4970 sizeof(new_triggers.patterns[0]),
4971 GFP_KERNEL);
4972 if (!new_triggers.patterns)
4973 return -ENOMEM;
4974
4975 new_triggers.n_patterns = n_patterns;
4976 i = 0;
4977
4978 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
4979 rem) {
4980 nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
4981 nla_data(pat), nla_len(pat), NULL);
4982 err = -EINVAL;
4983 if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
4984 !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
4985 goto error;
4986 pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
4987 mask_len = DIV_ROUND_UP(pat_len, 8);
4988 if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
4989 mask_len)
4990 goto error;
4991 if (pat_len > wowlan->pattern_max_len ||
4992 pat_len < wowlan->pattern_min_len)
4993 goto error;
4994
4995 new_triggers.patterns[i].mask =
4996 kmalloc(mask_len + pat_len, GFP_KERNEL);
4997 if (!new_triggers.patterns[i].mask) {
4998 err = -ENOMEM;
4999 goto error;
5000 }
5001 new_triggers.patterns[i].pattern =
5002 new_triggers.patterns[i].mask + mask_len;
5003 memcpy(new_triggers.patterns[i].mask,
5004 nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
5005 mask_len);
5006 new_triggers.patterns[i].pattern_len = pat_len;
5007 memcpy(new_triggers.patterns[i].pattern,
5008 nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
5009 pat_len);
5010 i++;
5011 }
5012 }
5013
5014 if (memcmp(&new_triggers, &no_triggers, sizeof(new_triggers))) {
5015 struct cfg80211_wowlan *ntrig;
5016 ntrig = kmemdup(&new_triggers, sizeof(new_triggers),
5017 GFP_KERNEL);
5018 if (!ntrig) {
5019 err = -ENOMEM;
5020 goto error;
5021 }
5022 cfg80211_rdev_free_wowlan(rdev);
5023 rdev->wowlan = ntrig;
5024 } else {
5025 no_triggers:
5026 cfg80211_rdev_free_wowlan(rdev);
5027 rdev->wowlan = NULL;
5028 }
5029
5030 return 0;
5031 error:
5032 for (i = 0; i < new_triggers.n_patterns; i++)
5033 kfree(new_triggers.patterns[i].mask);
5034 kfree(new_triggers.patterns);
5035 return err;
5036}
5037
4811#define NL80211_FLAG_NEED_WIPHY 0x01 5038#define NL80211_FLAG_NEED_WIPHY 0x01
4812#define NL80211_FLAG_NEED_NETDEV 0x02 5039#define NL80211_FLAG_NEED_NETDEV 0x02
4813#define NL80211_FLAG_NEED_RTNL 0x04 5040#define NL80211_FLAG_NEED_RTNL 0x04
@@ -5306,6 +5533,22 @@ static struct genl_ops nl80211_ops[] = {
5306 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 5533 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5307 NL80211_FLAG_NEED_RTNL, 5534 NL80211_FLAG_NEED_RTNL,
5308 }, 5535 },
5536 {
5537 .cmd = NL80211_CMD_GET_WOWLAN,
5538 .doit = nl80211_get_wowlan,
5539 .policy = nl80211_policy,
5540 /* can be retrieved by unprivileged users */
5541 .internal_flags = NL80211_FLAG_NEED_WIPHY |
5542 NL80211_FLAG_NEED_RTNL,
5543 },
5544 {
5545 .cmd = NL80211_CMD_SET_WOWLAN,
5546 .doit = nl80211_set_wowlan,
5547 .policy = nl80211_policy,
5548 .flags = GENL_ADMIN_PERM,
5549 .internal_flags = NL80211_FLAG_NEED_WIPHY |
5550 NL80211_FLAG_NEED_RTNL,
5551 },
5309}; 5552};
5310 5553
5311static struct genl_multicast_group nl80211_mlme_mcgrp = { 5554static struct genl_multicast_group nl80211_mlme_mcgrp = {
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 4294fa22bb2d..c6e4ca6a7d2e 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -93,7 +93,7 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
93 93
94 if (rdev->ops->suspend) { 94 if (rdev->ops->suspend) {
95 rtnl_lock(); 95 rtnl_lock();
96 ret = rdev->ops->suspend(&rdev->wiphy); 96 ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
97 rtnl_unlock(); 97 rtnl_unlock();
98 } 98 }
99 99