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.
Unified · Split
| @@ -1596,6 +1596,32 @@ struct cfg80211_wowlan { · 1595 unmodified lines | ||
| 1596 | 1596 | int n_patterns; |
| 1597 | 1597 | }; |
| 1598 | 1598 | |
| 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 | + */ | |
| 1616 | +struct 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 | + | |
| 1599 | 1625 | /** |
| 1600 | 1626 | * struct cfg80211_gtk_rekey_data - rekey data |
| 1601 | 1627 | * @kek: key encryption key |
| @@ -3852,6 +3878,21 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, · 2250 unmodified lines | ||
| 3852 | 3878 | enum ieee80211_p2p_attr_id attr, |
| 3853 | 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 | + */ | |
| 3892 | +void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, | |
| 3893 | + struct cfg80211_wowlan_wakeup *wakeup, | |
| 3894 | + gfp_t gfp); | |
| 3895 | + | |
| 3855 | 3896 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ |
| 3856 | 3897 | |
| 3857 | 3898 | /* wiphy_printk helpers, similar to dev_printk */ |
| @@ -4206,4 +4206,16 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); · 4205 unmodified lines | ||
| 4206 | 4206 | */ |
| 4207 | 4207 | int 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 | + */ | |
| 4217 | +void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, | |
| 4218 | + struct cfg80211_wowlan_wakeup *wakeup, | |
| 4219 | + gfp_t gfp); | |
| 4220 | + | |
| 4209 | 4221 | #endif /* MAC80211_H */ |
| @@ -513,6 +513,12 @@ · 512 unmodified lines | ||
| 513 | 513 | * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For |
| 514 | 514 | * more background information, see |
| 515 | 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 | 523 | * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver |
| 518 | 524 | * the necessary information for supporting GTK rekey offload. This |
| @@ -2947,6 +2953,10 @@ struct nl80211_wowlan_pattern_support { · 2428 unmodified lines | ||
| 2947 | 2953 | * |
| 2948 | 2954 | * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute |
| 2949 | 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 | 2960 | * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be |
| 2951 | 2961 | * used when setting, used only to indicate that GTK rekeying is supported |
| 2952 | 2962 | * by the device (flag) |
| @@ -2957,8 +2967,25 @@ struct nl80211_wowlan_pattern_support { · 4 unmodified lines | ||
| 2957 | 2967 | * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) |
| 2958 | 2968 | * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released |
| 2959 | 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 | 2984 | * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers |
| 2961 | 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 | */ |
| 2963 | 2990 | enum nl80211_wowlan_triggers { |
| 2964 | 2991 | __NL80211_WOWLAN_TRIG_INVALID, |
| @@ -2971,6 +2998,10 @@ enum nl80211_wowlan_triggers { · 6 unmodified lines | ||
| 2971 | 2998 | NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, |
| 2972 | 2999 | NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, |
| 2973 | 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 | 3006 | /* keep last */ |
| 2976 | 3007 | NUM_NL80211_WOWLAN_TRIG, |
| @@ -228,3 +228,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) · 227 unmodified lines | ||
| 228 | 228 | * ieee80211_reconfig(), which is also needed for hardware |
| 229 | 229 | * hang/firmware failure/etc. recovery. |
| 230 | 230 | */ |
| 231 | + | |
| 232 | +void 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 | +} | |
| 240 | +EXPORT_SYMBOL(ieee80211_report_wowlan_wakeup); | |
| @@ -9323,6 +9323,103 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, · 9322 unmodified lines | ||
| 9323 | 9323 | } |
| 9324 | 9324 | EXPORT_SYMBOL(cfg80211_report_obss_beacon); |
| 9325 | 9325 | |
| 9326 | +#ifdef CONFIG_PM | |
| 9327 | +void 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 | +} | |
| 9420 | +EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup); | |
| 9421 | +#endif | |
| 9422 | + | |
| 9326 | 9423 | void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, |
| 9327 | 9424 | enum nl80211_tdls_operation oper, |
| 9328 | 9425 | u16 reason_code, gfp_t gfp) |
| @@ -2333,6 +2333,41 @@ TRACE_EVENT(cfg80211_return_u32, · 2332 unmodified lines | ||
| 2333 | 2333 | TP_printk("ret: %u", __entry->ret) |
| 2334 | 2334 | ); |
| 2335 | 2335 | |
| 2336 | +TRACE_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 | 2371 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
| 2337 | 2372 | |
| 2338 | 2373 | #undef TRACE_INCLUDE_PATH |