From 5dc501507222b38d731b89c3311d8253b73dd0e7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 15 Mar 2021 00:05:42 +0100 Subject: mac80211: backport upstream patches for driver disconnect Needed for an mt76 update Signed-off-by: Felix Fietkau --- ...-support-immediate-reconnect-request-hint.patch | 301 +++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch (limited to 'package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch') diff --git a/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch b/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch new file mode 100644 index 0000000000..d3f4aa7972 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch @@ -0,0 +1,301 @@ +From: Johannes Berg +Date: Sun, 6 Dec 2020 14:54:42 +0200 +Subject: [PATCH] cfg80211: support immediate reconnect request hint + +There are cases where it's necessary to disconnect, but an +immediate reconnection is desired. Support a hint to userspace +that this is the case, by including a new attribute in the +deauth or disassoc event. + +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20201206145305.58d33941fb9d.I0e7168c205c7949529c8e3b86f3c9b12c01a7017@changeid +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6410,13 +6410,15 @@ void cfg80211_abandon_assoc(struct net_d + * @dev: network device + * @buf: 802.11 frame (header + body) + * @len: length of the frame data ++ * @reconnect: immediate reconnect is desired (include the nl80211 attribute) + * + * This function is called whenever deauthentication has been processed in + * station mode. This includes both received deauthentication frames and + * locally generated ones. This function may sleep. The caller must hold the + * corresponding wdev's mutex. + */ +-void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len); ++void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len, ++ bool reconnect); + + /** + * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2527,6 +2527,10 @@ enum nl80211_commands { + * override mask. Used with NL80211_ATTR_S1G_CAPABILITY in + * NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT. + * ++ * @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and ++ * disassoc events to indicate that an immediate reconnect to the AP ++ * is desired. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3016,6 +3020,8 @@ enum nl80211_attrs { + NL80211_ATTR_S1G_CAPABILITY, + NL80211_ATTR_S1G_CAPABILITY_MASK, + ++ NL80211_ATTR_RECONNECT_REQUESTED, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2729,7 +2729,7 @@ static void ieee80211_report_disconnect( + }; + + if (tx) +- cfg80211_tx_mlme_mgmt(sdata->dev, buf, len); ++ cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false); + else + cfg80211_rx_mlme_mgmt(sdata->dev, buf, len); + +@@ -4716,7 +4716,8 @@ void ieee80211_mgd_quiesce(struct ieee80 + if (ifmgd->auth_data) + ieee80211_destroy_auth_data(sdata, false); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, +- IEEE80211_DEAUTH_FRAME_LEN); ++ IEEE80211_DEAUTH_FRAME_LEN, ++ false); + } + + /* This is a bit of a hack - we should find a better and more generic +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -4,7 +4,7 @@ + * + * Copyright (c) 2009, Jouni Malinen + * Copyright (c) 2015 Intel Deutschland GmbH +- * Copyright (C) 2019 Intel Corporation ++ * Copyright (C) 2019-2020 Intel Corporation + */ + + #include +@@ -81,7 +81,8 @@ static void cfg80211_process_auth(struct + } + + static void cfg80211_process_deauth(struct wireless_dev *wdev, +- const u8 *buf, size_t len) ++ const u8 *buf, size_t len, ++ bool reconnect) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; +@@ -89,7 +90,7 @@ static void cfg80211_process_deauth(stru + u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); + bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); + +- nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL); ++ nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL); + + if (!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) +@@ -100,7 +101,8 @@ static void cfg80211_process_deauth(stru + } + + static void cfg80211_process_disassoc(struct wireless_dev *wdev, +- const u8 *buf, size_t len) ++ const u8 *buf, size_t len, ++ bool reconnect) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; +@@ -108,7 +110,8 @@ static void cfg80211_process_disassoc(st + u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); + bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); + +- nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL); ++ nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect, ++ GFP_KERNEL); + + if (WARN_ON(!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) +@@ -133,9 +136,9 @@ void cfg80211_rx_mlme_mgmt(struct net_de + if (ieee80211_is_auth(mgmt->frame_control)) + cfg80211_process_auth(wdev, buf, len); + else if (ieee80211_is_deauth(mgmt->frame_control)) +- cfg80211_process_deauth(wdev, buf, len); ++ cfg80211_process_deauth(wdev, buf, len, false); + else if (ieee80211_is_disassoc(mgmt->frame_control)) +- cfg80211_process_disassoc(wdev, buf, len); ++ cfg80211_process_disassoc(wdev, buf, len, false); + } + EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt); + +@@ -180,22 +183,23 @@ void cfg80211_abandon_assoc(struct net_d + } + EXPORT_SYMBOL(cfg80211_abandon_assoc); + +-void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) ++void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len, ++ bool reconnect) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct ieee80211_mgmt *mgmt = (void *)buf; + + ASSERT_WDEV_LOCK(wdev); + +- trace_cfg80211_tx_mlme_mgmt(dev, buf, len); ++ trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect); + + if (WARN_ON(len < 2)) + return; + + if (ieee80211_is_deauth(mgmt->frame_control)) +- cfg80211_process_deauth(wdev, buf, len); ++ cfg80211_process_deauth(wdev, buf, len, reconnect); + else +- cfg80211_process_disassoc(wdev, buf, len); ++ cfg80211_process_disassoc(wdev, buf, len, reconnect); + } + EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt); + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -732,6 +732,7 @@ static const struct nla_policy nl80211_p + NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN), + [NL80211_ATTR_S1G_CAPABILITY_MASK] = + NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN), ++ [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, + }; + + /* policy for the key attributes */ +@@ -15899,7 +15900,7 @@ static void nl80211_send_mlme_event(stru + const u8 *buf, size_t len, + enum nl80211_commands cmd, gfp_t gfp, + int uapsd_queues, const u8 *req_ies, +- size_t req_ies_len) ++ size_t req_ies_len, bool reconnect) + { + struct sk_buff *msg; + void *hdr; +@@ -15921,6 +15922,9 @@ static void nl80211_send_mlme_event(stru + nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies))) + goto nla_put_failure; + ++ if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED)) ++ goto nla_put_failure; ++ + if (uapsd_queues >= 0) { + struct nlattr *nla_wmm = + nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME); +@@ -15949,7 +15953,8 @@ void nl80211_send_rx_auth(struct cfg8021 + size_t len, gfp_t gfp) + { + nl80211_send_mlme_event(rdev, netdev, buf, len, +- NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0); ++ NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0, ++ false); + } + + void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, +@@ -15959,23 +15964,25 @@ void nl80211_send_rx_assoc(struct cfg802 + { + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_ASSOCIATE, gfp, uapsd_queues, +- req_ies, req_ies_len); ++ req_ies, req_ies_len, false); + } + + void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, +- size_t len, gfp_t gfp) ++ size_t len, bool reconnect, gfp_t gfp) + { + nl80211_send_mlme_event(rdev, netdev, buf, len, +- NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0); ++ NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0, ++ reconnect); + } + + void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, +- size_t len, gfp_t gfp) ++ size_t len, bool reconnect, gfp_t gfp) + { + nl80211_send_mlme_event(rdev, netdev, buf, len, +- NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0); ++ NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0, ++ reconnect); + } + + void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, +@@ -16006,7 +16013,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct + + trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); + nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1, +- NULL, 0); ++ NULL, 0, false); + } + EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); + +--- a/net/wireless/nl80211.h ++++ b/net/wireless/nl80211.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* + * Portions of this file +- * Copyright (C) 2018 Intel Corporation ++ * Copyright (C) 2018, 2020 Intel Corporation + */ + #ifndef __NET_WIRELESS_NL80211_H + #define __NET_WIRELESS_NL80211_H +@@ -69,10 +69,12 @@ void nl80211_send_rx_assoc(struct cfg802 + const u8 *req_ies, size_t req_ies_len); + void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, +- const u8 *buf, size_t len, gfp_t gfp); ++ const u8 *buf, size_t len, ++ bool reconnect, gfp_t gfp); + void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, +- const u8 *buf, size_t len, gfp_t gfp); ++ const u8 *buf, size_t len, ++ bool reconnect, gfp_t gfp); + void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *addr, gfp_t gfp); +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -2684,19 +2684,23 @@ DEFINE_EVENT(netdev_frame_event, cfg8021 + ); + + TRACE_EVENT(cfg80211_tx_mlme_mgmt, +- TP_PROTO(struct net_device *netdev, const u8 *buf, int len), +- TP_ARGS(netdev, buf, len), ++ TP_PROTO(struct net_device *netdev, const u8 *buf, int len, ++ bool reconnect), ++ TP_ARGS(netdev, buf, len, reconnect), + TP_STRUCT__entry( + NETDEV_ENTRY + __dynamic_array(u8, frame, len) ++ __field(int, reconnect) + ), + TP_fast_assign( + NETDEV_ASSIGN; + memcpy(__get_dynamic_array(frame), buf, len); ++ __entry->reconnect = reconnect; + ), +- TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x", ++ TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x reconnect:%d", + NETDEV_PR_ARG, +- le16_to_cpup((__le16 *)__get_dynamic_array(frame))) ++ le16_to_cpup((__le16 *)__get_dynamic_array(frame)), ++ __entry->reconnect) + ); + + DECLARE_EVENT_CLASS(netdev_mac_evt, -- cgit v1.2.3