aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-22 06:34:29 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-01-31 08:00:21 -0500
commitcd8f7cb4e6dfa4ea08fc250a814240b883ef7911 (patch)
tree2bcb8f04f01ee9768e5524799b0d429e51fb583d
parent3b144658bc7be5f7fa68d13ba24afb4c24489965 (diff)
cfg80211/mac80211: support reporting wakeup reason
When waking up from WoWLAN, it is useful to know what triggered the wakeup. Support reporting the wakeup reason(s) in cfg80211 (and a pass-through in mac80211) to allow userspace to know. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h41
-rw-r--r--include/net/mac80211.h12
-rw-r--r--include/uapi/linux/nl80211.h31
-rw-r--r--net/mac80211/pm.c10
-rw-r--r--net/wireless/nl80211.c97
-rw-r--r--net/wireless/trace.h35
6 files changed, 226 insertions, 0 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 36e076e374d2..48add7e3ba1d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1597,6 +1597,32 @@ struct cfg80211_wowlan {
1597}; 1597};
1598 1598
1599/** 1599/**
1600 * struct cfg80211_wowlan_wakeup - wakeup report
1601 * @disconnect: woke up by getting disconnected
1602 * @magic_pkt: woke up by receiving magic packet
1603 * @gtk_rekey_failure: woke up by GTK rekey failure
1604 * @eap_identity_req: woke up by EAP identity request packet
1605 * @four_way_handshake: woke up by 4-way handshake
1606 * @rfkill_release: woke up by rfkill being released
1607 * @pattern_idx: pattern that caused wakeup, -1 if not due to pattern
1608 * @packet_present_len: copied wakeup packet data
1609 * @packet_len: original wakeup packet length
1610 * @packet: The packet causing the wakeup, if any.
1611 * @packet_80211: For pattern match, magic packet and other data
1612 * frame triggers an 802.3 frame should be reported, for
1613 * disconnect due to deauth 802.11 frame. This indicates which
1614 * it is.
1615 */
1616struct cfg80211_wowlan_wakeup {
1617 bool disconnect, magic_pkt, gtk_rekey_failure,
1618 eap_identity_req, four_way_handshake,
1619 rfkill_release, packet_80211;
1620 s32 pattern_idx;
1621 u32 packet_present_len, packet_len;
1622 const void *packet;
1623};
1624
1625/**
1600 * struct cfg80211_gtk_rekey_data - rekey data 1626 * struct cfg80211_gtk_rekey_data - rekey data
1601 * @kek: key encryption key 1627 * @kek: key encryption key
1602 * @kck: key confirmation key 1628 * @kck: key confirmation key
@@ -3852,6 +3878,21 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
3852 enum ieee80211_p2p_attr_id attr, 3878 enum ieee80211_p2p_attr_id attr,
3853 u8 *buf, unsigned int bufsize); 3879 u8 *buf, unsigned int bufsize);
3854 3880
3881/**
3882 * cfg80211_report_wowlan_wakeup - report wakeup from WoWLAN
3883 * @wdev: the wireless device reporting the wakeup
3884 * @wakeup: the wakeup report
3885 * @gfp: allocation flags
3886 *
3887 * This function reports that the given device woke up. If it
3888 * caused the wakeup, report the reason(s), otherwise you may
3889 * pass %NULL as the @wakeup parameter to advertise that something
3890 * else caused the wakeup.
3891 */
3892void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
3893 struct cfg80211_wowlan_wakeup *wakeup,
3894 gfp_t gfp);
3895
3855/* Logging, debugging and troubleshooting/diagnostic helpers. */ 3896/* Logging, debugging and troubleshooting/diagnostic helpers. */
3856 3897
3857/* wiphy_printk helpers, similar to dev_printk */ 3898/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 21831ee57e3c..7a27e00c513a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4206,4 +4206,16 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
4206 */ 4206 */
4207int ieee80211_ave_rssi(struct ieee80211_vif *vif); 4207int ieee80211_ave_rssi(struct ieee80211_vif *vif);
4208 4208
4209/**
4210 * ieee80211_report_wowlan_wakeup - report WoWLAN wakeup
4211 * @vif: virtual interface
4212 * @wakeup: wakeup reason(s)
4213 * @gfp: allocation flags
4214 *
4215 * See cfg80211_report_wowlan_wakeup().
4216 */
4217void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif,
4218 struct cfg80211_wowlan_wakeup *wakeup,
4219 gfp_t gfp);
4220
4209#endif /* MAC80211_H */ 4221#endif /* MAC80211_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 5b7dbc1ea966..225a65e72219 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -513,6 +513,12 @@
513 * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For 513 * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For
514 * more background information, see 514 * more background information, see
515 * http://wireless.kernel.org/en/users/Documentation/WoWLAN. 515 * http://wireless.kernel.org/en/users/Documentation/WoWLAN.
516 * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification
517 * from the driver reporting the wakeup reason. In this case, the
518 * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason
519 * for the wakeup, if it was caused by wireless. If it is not present
520 * in the wakeup notification, the wireless device didn't cause the
521 * wakeup but reports that it was woken up.
516 * 522 *
517 * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver 523 * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver
518 * the necessary information for supporting GTK rekey offload. This 524 * the necessary information for supporting GTK rekey offload. This
@@ -2947,6 +2953,10 @@ struct nl80211_wowlan_pattern_support {
2947 * 2953 *
2948 * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute 2954 * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
2949 * carrying a &struct nl80211_wowlan_pattern_support. 2955 * carrying a &struct nl80211_wowlan_pattern_support.
2956 *
2957 * When reporting wakeup. it is a u32 attribute containing the 0-based
2958 * index of the pattern that caused the wakeup, in the patterns passed
2959 * to the kernel when configuring.
2950 * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be 2960 * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be
2951 * used when setting, used only to indicate that GTK rekeying is supported 2961 * used when setting, used only to indicate that GTK rekeying is supported
2952 * by the device (flag) 2962 * by the device (flag)
@@ -2957,8 +2967,25 @@ struct nl80211_wowlan_pattern_support {
2957 * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) 2967 * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag)
2958 * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released 2968 * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released
2959 * (on devices that have rfkill in the device) (flag) 2969 * (on devices that have rfkill in the device) (flag)
2970 * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains
2971 * the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame
2972 * may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN
2973 * attribute contains the original length.
2974 * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11
2975 * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211
2976 * attribute if the packet was truncated somewhere.
2977 * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the
2978 * 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may
2979 * be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute
2980 * contains the original length.
2981 * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3
2982 * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023
2983 * attribute if the packet was truncated somewhere.
2960 * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers 2984 * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
2961 * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number 2985 * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
2986 *
2987 * These nested attributes are used to configure the wakeup triggers and
2988 * to report the wakeup reason(s).
2962 */ 2989 */
2963enum nl80211_wowlan_triggers { 2990enum nl80211_wowlan_triggers {
2964 __NL80211_WOWLAN_TRIG_INVALID, 2991 __NL80211_WOWLAN_TRIG_INVALID,
@@ -2971,6 +2998,10 @@ enum nl80211_wowlan_triggers {
2971 NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, 2998 NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST,
2972 NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, 2999 NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE,
2973 NL80211_WOWLAN_TRIG_RFKILL_RELEASE, 3000 NL80211_WOWLAN_TRIG_RFKILL_RELEASE,
3001 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211,
3002 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN,
3003 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023,
3004 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN,
2974 3005
2975 /* keep last */ 3006 /* keep last */
2976 NUM_NL80211_WOWLAN_TRIG, 3007 NUM_NL80211_WOWLAN_TRIG,
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index e45b83610e85..53801d20176d 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -228,3 +228,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
228 * ieee80211_reconfig(), which is also needed for hardware 228 * ieee80211_reconfig(), which is also needed for hardware
229 * hang/firmware failure/etc. recovery. 229 * hang/firmware failure/etc. recovery.
230 */ 230 */
231
232void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif,
233 struct cfg80211_wowlan_wakeup *wakeup,
234 gfp_t gfp)
235{
236 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
237
238 cfg80211_report_wowlan_wakeup(&sdata->wdev, wakeup, gfp);
239}
240EXPORT_SYMBOL(ieee80211_report_wowlan_wakeup);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b5978ab4ad7a..d359734b6972 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9323,6 +9323,103 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
9323} 9323}
9324EXPORT_SYMBOL(cfg80211_report_obss_beacon); 9324EXPORT_SYMBOL(cfg80211_report_obss_beacon);
9325 9325
9326#ifdef CONFIG_PM
9327void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
9328 struct cfg80211_wowlan_wakeup *wakeup,
9329 gfp_t gfp)
9330{
9331 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
9332 struct sk_buff *msg;
9333 void *hdr;
9334 int err, size = 200;
9335
9336 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
9337
9338 if (wakeup)
9339 size += wakeup->packet_present_len;
9340
9341 msg = nlmsg_new(size, gfp);
9342 if (!msg)
9343 return;
9344
9345 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
9346 if (!hdr)
9347 goto free_msg;
9348
9349 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
9350 nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
9351 goto free_msg;
9352
9353 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
9354 wdev->netdev->ifindex))
9355 goto free_msg;
9356
9357 if (wakeup) {
9358 struct nlattr *reasons;
9359
9360 reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
9361
9362 if (wakeup->disconnect &&
9363 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
9364 goto free_msg;
9365 if (wakeup->magic_pkt &&
9366 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
9367 goto free_msg;
9368 if (wakeup->gtk_rekey_failure &&
9369 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
9370 goto free_msg;
9371 if (wakeup->eap_identity_req &&
9372 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
9373 goto free_msg;
9374 if (wakeup->four_way_handshake &&
9375 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
9376 goto free_msg;
9377 if (wakeup->rfkill_release &&
9378 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
9379 goto free_msg;
9380
9381 if (wakeup->pattern_idx >= 0 &&
9382 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
9383 wakeup->pattern_idx))
9384 goto free_msg;
9385
9386 if (wakeup->packet) {
9387 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
9388 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
9389
9390 if (!wakeup->packet_80211) {
9391 pkt_attr =
9392 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
9393 len_attr =
9394 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
9395 }
9396
9397 if (wakeup->packet_len &&
9398 nla_put_u32(msg, len_attr, wakeup->packet_len))
9399 goto free_msg;
9400
9401 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
9402 wakeup->packet))
9403 goto free_msg;
9404 }
9405
9406 nla_nest_end(msg, reasons);
9407 }
9408
9409 err = genlmsg_end(msg, hdr);
9410 if (err < 0)
9411 goto free_msg;
9412
9413 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
9414 nl80211_mlme_mcgrp.id, gfp);
9415 return;
9416
9417 free_msg:
9418 nlmsg_free(msg);
9419}
9420EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
9421#endif
9422
9326void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, 9423void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
9327 enum nl80211_tdls_operation oper, 9424 enum nl80211_tdls_operation oper,
9328 u16 reason_code, gfp_t gfp) 9425 u16 reason_code, gfp_t gfp)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 8bc553199686..c9cafb0ea95f 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2333,6 +2333,41 @@ TRACE_EVENT(cfg80211_return_u32,
2333 TP_printk("ret: %u", __entry->ret) 2333 TP_printk("ret: %u", __entry->ret)
2334); 2334);
2335 2335
2336TRACE_EVENT(cfg80211_report_wowlan_wakeup,
2337 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
2338 struct cfg80211_wowlan_wakeup *wakeup),
2339 TP_ARGS(wiphy, wdev, wakeup),
2340 TP_STRUCT__entry(
2341 WIPHY_ENTRY
2342 WDEV_ENTRY
2343 __field(bool, disconnect)
2344 __field(bool, magic_pkt)
2345 __field(bool, gtk_rekey_failure)
2346 __field(bool, eap_identity_req)
2347 __field(bool, four_way_handshake)
2348 __field(bool, rfkill_release)
2349 __field(s32, pattern_idx)
2350 __field(u32, packet_len)
2351 __dynamic_array(u8, packet, wakeup->packet_present_len)
2352 ),
2353 TP_fast_assign(
2354 WIPHY_ASSIGN;
2355 WDEV_ASSIGN;
2356 __entry->disconnect = wakeup->disconnect;
2357 __entry->magic_pkt = wakeup->magic_pkt;
2358 __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure;
2359 __entry->eap_identity_req = wakeup->eap_identity_req;
2360 __entry->four_way_handshake = wakeup->four_way_handshake;
2361 __entry->rfkill_release = wakeup->rfkill_release;
2362 __entry->pattern_idx = wakeup->pattern_idx;
2363 __entry->packet_len = wakeup->packet_len;
2364 if (wakeup->packet && wakeup->packet_present_len)
2365 memcpy(__get_dynamic_array(packet), wakeup->packet,
2366 wakeup->packet_present_len);
2367 ),
2368 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
2369);
2370
2336#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ 2371#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
2337 2372
2338#undef TRACE_INCLUDE_PATH 2373#undef TRACE_INCLUDE_PATH