From patchwork Thu Apr 1 05:01:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai-Heng Feng X-Patchwork-Id: 1460840 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4F9rjb65Wdz9sjJ; Thu, 1 Apr 2021 16:05:39 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1lRpWO-0005oU-B8; Thu, 01 Apr 2021 05:05:32 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lRpSf-0000q3-E0 for kernel-team@lists.ubuntu.com; Thu, 01 Apr 2021 05:01:41 +0000 Received: from 61-220-137-37.hinet-ip.hinet.net ([61.220.137.37] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lRpSe-0006y6-AG for kernel-team@lists.ubuntu.com; Thu, 01 Apr 2021 05:01:40 +0000 From: Kai-Heng Feng To: kernel-team@lists.ubuntu.com Subject: [OEM-5.10] [PATCH 1/3] cfg80211: support immediate reconnect request hint Date: Thu, 1 Apr 2021 13:01:30 +0800 Message-Id: <20210401050133.1901312-2-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210401050133.1901312-1-kai.heng.feng@canonical.com> References: <20210401050133.1901312-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Johannes Berg BugLink: https://bugs.launchpad.net/bugs/1922171 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 (backported from commit 3bb02143ff55fec55558da4ad48425bf368eb8ed) Signed-off-by: Kai-Heng Feng --- include/net/cfg80211.h | 4 +++- include/uapi/linux/nl80211.h | 6 ++++++ net/mac80211/mlme.c | 5 +++-- net/wireless/mlme.c | 26 +++++++++++++++----------- net/wireless/nl80211.c | 23 +++++++++++++++-------- net/wireless/nl80211.h | 8 +++++--- net/wireless/trace.h | 12 ++++++++---- 7 files changed, 55 insertions(+), 29 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d5ab8d99739f..9b0b9fddde25 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -6406,13 +6406,15 @@ void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss); * @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 diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 47700a2b9af9..fc2363223eba 100644 --- 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, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6adfcb9c06dc..673a1838691c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2729,7 +2729,7 @@ static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata, }; 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 ieee80211_sub_if_data *sdata) 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 diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 0ac820780437..e1e90761dc00 100644 --- 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 wireless_dev *wdev, } 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(struct wireless_dev *wdev, 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(struct wireless_dev *wdev, } 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(struct wireless_dev *wdev, 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_device *dev, const u8 *buf, size_t len) 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_device *dev, struct cfg80211_bss *bss) } 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); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 535e34a84d65..645d31790637 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -715,6 +715,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { 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 */ @@ -15855,7 +15856,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, 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; @@ -15877,6 +15878,9 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, 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); @@ -15905,7 +15909,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, 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, @@ -15915,23 +15920,25 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, { 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, @@ -15962,7 +15969,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, 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); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index d3e8e426c486..a3f387770f1b 100644 --- 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 cfg80211_registered_device *rdev, 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); diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 6e218a0acd4e..b50f479dc0f6 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2684,19 +2684,23 @@ DEFINE_EVENT(netdev_frame_event, cfg80211_rx_mlme_mgmt, ); 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, From patchwork Thu Apr 1 05:01:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai-Heng Feng X-Patchwork-Id: 1460841 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4F9rjb6bVtz9srX; Thu, 1 Apr 2021 16:05:39 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1lRpWO-0005om-Jd; Thu, 01 Apr 2021 05:05:32 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lRpSj-0000t5-BW for kernel-team@lists.ubuntu.com; Thu, 01 Apr 2021 05:01:45 +0000 Received: from 61-220-137-37.hinet-ip.hinet.net ([61.220.137.37] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lRpSi-0006yI-CQ for kernel-team@lists.ubuntu.com; Thu, 01 Apr 2021 05:01:45 +0000 From: Kai-Heng Feng To: kernel-team@lists.ubuntu.com Subject: [OEM-5.10] [PATCH 2/3] mac80211: support driver-based disconnect with reconnect hint Date: Thu, 1 Apr 2021 13:01:31 +0800 Message-Id: <20210401050133.1901312-3-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210401050133.1901312-1-kai.heng.feng@canonical.com> References: <20210401050133.1901312-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Johannes Berg BugLink: https://bugs.launchpad.net/bugs/1922171 Support the driver indicating that a disconnection needs to be performed, and pass through the reconnect hint in this case. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20201206145305.5c8dab7a22a0.I58459fdf6968b16c90cab9c574f0f04ca22b0c79@changeid Signed-off-by: Johannes Berg (cherry picked from commit 3f8a39ff28078e4b56d94e8676f49d9975f82e51) Signed-off-by: Kai-Heng Feng --- include/net/mac80211.h | 11 ++++++ net/mac80211/ieee80211_i.h | 4 ++- net/mac80211/mlme.c | 69 ++++++++++++++++++++++++++++---------- net/mac80211/trace.h | 23 ++++++++++++- 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index dcdba96814a2..7d32b6f0e955 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -5876,6 +5876,17 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif); */ void ieee80211_connection_loss(struct ieee80211_vif *vif); +/** + * ieee80211_disconnect - request disconnection + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @reconnect: immediate reconnect is desired + * + * Request disconnection from the current network and, if enabled, send a + * hint to the higher layers that immediate reconnect is desired. + */ +void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect); + /** * ieee80211_resume_disconnect - disconnect from AP after resume * diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d6913784be2b..d3f70f40ce74 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -457,7 +457,9 @@ struct ieee80211_if_managed { unsigned long probe_timeout; int probe_send_count; bool nullfunc_failed; - bool connection_loss; + u8 connection_loss:1, + driver_disconnect:1, + reconnect:1; struct cfg80211_bss *associated; struct ieee80211_mgd_auth_data *auth_data; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 673a1838691c..1c9cc65bccba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2720,7 +2720,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get); static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata, const u8 *buf, size_t len, bool tx, - u16 reason) + u16 reason, bool reconnect) { struct ieee80211_event event = { .type = MLME_EVENT, @@ -2729,7 +2729,7 @@ static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata, }; if (tx) - cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false); + cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, reconnect); else cfg80211_rx_mlme_mgmt(sdata->dev, buf, len); @@ -2751,13 +2751,18 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) tx = !sdata->csa_block_tx; - /* AP is probably out of range (or not reachable for another reason) so - * remove the bss struct for that AP. - */ - cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated); + if (!ifmgd->driver_disconnect) { + /* + * AP is probably out of range (or not reachable for another + * reason) so remove the bss struct for that AP. + */ + cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated); + } ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, + ifmgd->driver_disconnect ? + WLAN_REASON_DEAUTH_LEAVING : + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, tx, frame_buf); mutex_lock(&local->mtx); sdata->vif.csa_active = false; @@ -2770,7 +2775,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) mutex_unlock(&local->mtx); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, + ifmgd->reconnect); + ifmgd->reconnect = false; sdata_unlock(sdata); } @@ -2789,6 +2796,13 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work) sdata_info(sdata, "Connection to AP %pM lost\n", ifmgd->bssid); __ieee80211_disconnect(sdata); + ifmgd->connection_loss = false; + } else if (ifmgd->driver_disconnect) { + sdata_info(sdata, + "Driver requested disconnection from AP %pM\n", + ifmgd->bssid); + __ieee80211_disconnect(sdata); + ifmgd->driver_disconnect = false; } else { ieee80211_mgd_probe_ap(sdata, true); } @@ -2827,6 +2841,21 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif) } EXPORT_SYMBOL(ieee80211_connection_loss); +void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_hw *hw = &sdata->local->hw; + + trace_api_disconnect(sdata, reconnect); + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + return; + + sdata->u.mgd.driver_disconnect = true; + sdata->u.mgd.reconnect = reconnect; + ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); +} +EXPORT_SYMBOL(ieee80211_disconnect); static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, bool assoc) @@ -3130,7 +3159,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, - reason_code); + reason_code, false); return; } @@ -3179,7 +3208,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code); + ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code, + false); } static void ieee80211_get_rates(struct ieee80211_supported_band *sband, @@ -4199,7 +4229,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, true, deauth_buf); ieee80211_report_disconnect(sdata, deauth_buf, sizeof(deauth_buf), true, - WLAN_REASON_DEAUTH_LEAVING); + WLAN_REASON_DEAUTH_LEAVING, + false); return; } @@ -4344,7 +4375,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, tx, frame_buf); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - reason); + reason, false); } static int ieee80211_auth(struct ieee80211_sub_if_data *sdata) @@ -5431,7 +5462,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - WLAN_REASON_UNSPECIFIED); + WLAN_REASON_UNSPECIFIED, + false); } sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); @@ -5503,7 +5535,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - WLAN_REASON_UNSPECIFIED); + WLAN_REASON_UNSPECIFIED, + false); } if (ifmgd->auth_data && !ifmgd->auth_data->done) { @@ -5802,7 +5835,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_destroy_auth_data(sdata, false); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - req->reason_code); + req->reason_code, false); return 0; } @@ -5822,7 +5855,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_destroy_assoc_data(sdata, false, true); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - req->reason_code); + req->reason_code, false); return 0; } @@ -5837,7 +5870,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, req->reason_code, tx, frame_buf); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - req->reason_code); + req->reason_code, false); return 0; } @@ -5870,7 +5903,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, frame_buf); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, - req->reason_code); + req->reason_code, false); return 0; } diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 89723907a094..601322e16957 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -2,7 +2,7 @@ /* * Portions of this file * Copyright(c) 2016-2017 Intel Deutschland GmbH -* Copyright (C) 2018 - 2019 Intel Corporation +* Copyright (C) 2018 - 2020 Intel Corporation */ #if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ) @@ -2086,6 +2086,27 @@ TRACE_EVENT(api_connection_loss, ) ); +TRACE_EVENT(api_disconnect, + TP_PROTO(struct ieee80211_sub_if_data *sdata, bool reconnect), + + TP_ARGS(sdata, reconnect), + + TP_STRUCT__entry( + VIF_ENTRY + __field(int, reconnect) + ), + + TP_fast_assign( + VIF_ASSIGN; + __entry->reconnect = reconnect; + ), + + TP_printk( + VIF_PR_FMT " reconnect:%d", + VIF_PR_ARG, __entry->reconnect + ) +); + TRACE_EVENT(api_cqm_rssi_notify, TP_PROTO(struct ieee80211_sub_if_data *sdata, enum nl80211_cqm_rssi_threshold_event rssi_event, From patchwork Thu Apr 1 05:01:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai-Heng Feng X-Patchwork-Id: 1460839 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4F9rjb5SHbz9sjD; Thu, 1 Apr 2021 16:05:39 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1lRpWP-0005pu-QA; Thu, 01 Apr 2021 05:05:33 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lRpSr-00013i-I9 for kernel-team@lists.ubuntu.com; Thu, 01 Apr 2021 05:01:53 +0000 Received: from 61-220-137-37.hinet-ip.hinet.net ([61.220.137.37] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lRpSq-0006yf-H9 for kernel-team@lists.ubuntu.com; Thu, 01 Apr 2021 05:01:53 +0000 From: Kai-Heng Feng To: kernel-team@lists.ubuntu.com Subject: [OEM-5.10] [PATCH 3/3] iwlwifi: mvm: handle CCA-EXT delay firmware notification Date: Thu, 1 Apr 2021 13:01:33 +0800 Message-Id: <20210401050133.1901312-5-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210401050133.1901312-1-kai.heng.feng@canonical.com> References: <20210401050133.1901312-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Johannes Berg BugLink: https://bugs.launchpad.net/bugs/1922171 If there are frequent CCA delays due to the extension channel as detected by the firmware, and we're on 2.4 GHz, then handle this by disconnecting (with a reconnect hint). When we disconnect, we'll also update our capabilities to use only 20 MHz on the next connection (if it's on 2.4 GHz) as to avoid the use of the extension channel that has too much noise. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210117130510.4de9c363b0b5.I709b7e6f73a7537c53f22d7418927691259de8a8@changeid Signed-off-by: Luca Coelho (backported from commit f7d6ef33a779c866721eea2b980f51bda1994a04) Signed-off-by: Kai-Heng Feng --- .../wireless/intel/iwlwifi/fw/api/datapath.h | 86 +++++-------------- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 39 +++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 68 +++++++++++++++ .../net/wireless/intel/iwlwifi/mvm/utils.c | 30 +++++++ 5 files changed, 162 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 93c06e6c1ced..d299bba3aa54 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -1,67 +1,9 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2013-2015 Intel Mobile Communications GmbH + * Copyright (C) 2016-2017 Intel Deutschland GmbH + */ #ifndef __iwl_fw_api_datapath_h__ #define __iwl_fw_api_datapath_h__ @@ -110,6 +52,12 @@ enum iwl_data_path_subcmd_ids { */ CHEST_COLLECTOR_FILTER_CONFIG_CMD = 0x14, + /** + * @MONITOR_NOTIF: Datapath monitoring notification, using + * &struct iwl_datapath_monitor_notif + */ + MONITOR_NOTIF = 0xF4, + /** * @RX_NO_DATA_NOTIF: &struct iwl_rx_no_data */ @@ -211,4 +159,14 @@ struct iwl_channel_estimation_cfg { __le64 frame_types; } __packed; /* CHEST_COLLECTOR_FILTER_CMD_API_S_VER_1 */ +enum iwl_datapath_monitor_notif_type { + IWL_DP_MON_NOTIF_TYPE_EXT_CCA, +}; + +struct iwl_datapath_monitor_notif { + __le32 type; + u8 mac_id; + u8 reserved[3]; +} __packed; /* MONITOR_NTF_API_S_VER_1 */ + #endif /* __iwl_fw_api_datapath_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d42165559df6..9e3e387afaa6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3064,6 +3064,39 @@ static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw, mvmvif->he_ru_2mhz_block = !iter_data.tolerated; } +static void iwl_mvm_reset_cca_40mhz_workaround(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct ieee80211_supported_band *sband; + const struct ieee80211_sta_he_cap *he_cap; + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (!mvm->cca_40mhz_workaround) + return; + + /* decrement and check that we reached zero */ + mvm->cca_40mhz_workaround--; + if (mvm->cca_40mhz_workaround) + return; + + sband = mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]; + + sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + he_cap = ieee80211_get_he_iftype_cap(sband, + ieee80211_vif_type_p2p(vif)); + + if (he_cap) { + /* we know that ours is writable */ + struct ieee80211_sta_he_cap *he = (void *)he_cap; + + he->he_cap_elem.phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; + } +} + static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -3103,6 +3136,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, * No need to make sure deferred TX indication is off since the * worker will already remove it if it was on */ + + /* + * Additionally, reset the 40 MHz capability if we disconnected + * from the AP now. + */ + iwl_mvm_reset_cca_40mhz_workaround(mvm, vif); } mutex_lock(&mvm->mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 7159d1da3e77..486cc3655ab2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -852,6 +852,8 @@ struct iwl_mvm { bool hw_registered; bool rfkill_safe_init_done; + u8 cca_40mhz_workaround; + u32 ampdu_ref; bool ampdu_toggle; @@ -2059,6 +2061,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, u32 size); void iwl_mvm_reorder_timer_expired(struct timer_list *t); struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); +struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid); bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm); #define MVM_TCM_PERIOD_MSEC 500 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index cb83490f1016..d8f56a7992fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -201,6 +201,70 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); } +static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_datapath_monitor_notif *notif = (void *)pkt->data; + struct ieee80211_supported_band *sband; + const struct ieee80211_sta_he_cap *he_cap; + struct ieee80211_vif *vif; + + if (notif->type != cpu_to_le32(IWL_DP_MON_NOTIF_TYPE_EXT_CCA)) + return; + + vif = iwl_mvm_get_vif_by_macid(mvm, notif->mac_id); + if (!vif || vif->type != NL80211_IFTYPE_STATION) + return; + + if (!vif->bss_conf.chandef.chan || + vif->bss_conf.chandef.chan->band != NL80211_BAND_2GHZ || + vif->bss_conf.chandef.width < NL80211_CHAN_WIDTH_40) + return; + + if (!vif->bss_conf.assoc) + return; + + /* this shouldn't happen *again*, ignore it */ + if (mvm->cca_40mhz_workaround) + return; + + /* + * We'll decrement this on disconnect - so set to 2 since we'll + * still have to disconnect from the current AP first. + */ + mvm->cca_40mhz_workaround = 2; + + /* + * This capability manipulation isn't really ideal, but it's the + * easiest choice - otherwise we'd have to do some major changes + * in mac80211 to support this, which isn't worth it. This does + * mean that userspace may have outdated information, but that's + * actually not an issue at all. + */ + sband = mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]; + + WARN_ON(!sband->ht_cap.ht_supported); + WARN_ON(!(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)); + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + he_cap = ieee80211_get_he_iftype_cap(sband, + ieee80211_vif_type_p2p(vif)); + + if (he_cap) { + /* we know that ours is writable */ + struct ieee80211_sta_he_cap *he = (void *)he_cap; + + WARN_ON(!he->has_he); + WARN_ON(!(he->he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)); + he->he_cap_elem.phy_cap_info[0] &= + ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; + } + + ieee80211_disconnect(vif, true); +} + /** * enum iwl_rx_handler_context context for Rx handler * @RX_HANDLER_SYNC : this means that it will be called in the Rx path @@ -321,6 +385,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_NOA_NOTIF, iwl_mvm_channel_switch_noa_notif, RX_HANDLER_SYNC), + RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF, + iwl_mvm_rx_monitor_notif, + RX_HANDLER_ASYNC_LOCKED), }; #undef RX_HANDLER #undef RX_HANDLER_GRP @@ -465,6 +532,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(RFH_QUEUE_CONFIG_CMD), HCMD_NAME(TLC_MNG_CONFIG_CMD), HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), + HCMD_NAME(MONITOR_NOTIF), HCMD_NAME(STA_PM_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), HCMD_NAME(RX_QUEUES_NOTIFICATION), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 3123036978a5..f7748a8c009f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -887,6 +887,36 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm) return bss_iter_data.vif; } +struct iwl_bss_find_iter_data { + struct ieee80211_vif *vif; + u32 macid; +}; + +static void iwl_mvm_bss_find_iface_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_bss_find_iter_data *data = _data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + if (mvmvif->id == data->macid) + data->vif = vif; +} + +struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid) +{ + struct iwl_bss_find_iter_data data = { + .macid = macid, + }; + + lockdep_assert_held(&mvm->mutex); + + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_bss_find_iface_iterator, &data); + + return data.vif; +} + struct iwl_sta_iter_data { bool assoc; };