summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2026-03-19 15:30:19 +0100
committerPaolo Abeni <pabeni@redhat.com>2026-03-19 15:30:20 +0100
commit9ac76f3d0bb2940db3a9684d596b9c8f301ef315 (patch)
tree834230c2bdc906e364465db2f0ce1164ff6ceaa2
parent96450df197bda7de927b51372c13f1002d0e76e3 (diff)
parentdee55bc7cb8ad70b8c8598df60f378b7aed2e41b (diff)
Merge tag 'wireless-next-2026-03-19' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Johannes Berg says: ==================== Aside from various small improvements/cleanups, not much: - cfg80211/mac80211: S1G and UHR improvements - hwsim: incumbent signal report test support * tag 'wireless-next-2026-03-19' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (31 commits) qtnfmac: use alloc_netdev macro for single queue devices wifi: libertas: don't kill URBs in interrupt context wifi: libertas: use USB anchors for tracking in-flight URBs wifi: nl80211: use int for band coming from netlink wifi: rsi_91x_usb: do not pause rfkill polling when stopping mac80211 wifi: mac80211: fix STA link removal during link removal wifi: nl80211: reject S1G/60G with HT chantype wifi: ieee80211: fix definition of EHT-MCS 15 in MRU wifi: cfg80211: check non-S1G width with S1G chandef wifi: cfg80211: restrict cfg80211_chandef_create() to only HT-based bands wifi: mac80211: don't use cfg80211_chandef_create() for default chandef wifi: mac80211: Remove deleted sta links in ieee80211_ml_reconf_work() wifi: b43: use register definitions in nphy_op_software_rfkill wifi: cfg80211: split control freq check from chandef check wifi: mac80211: always use full chanctx compatible check wifi: mac80211: refactor chandef tracing macros wifi: mac80211: validate HE 6 GHz operation when EHT is used wifi: nl80211: split out UHR operation information wifi: mwifiex: drop redundant device reference wifi: rt2x00: drop redundant device reference ... ==================== Link: https://patch.msgid.link/20260319082439.79875-3-johannes@sipsolutions.net Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hw.c2
-rw-r--r--drivers/net/wireless/atmel/at76c50x-usb.c12
-rw-r--r--drivers/net/wireless/broadcom/b43/phy_n.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/time_sync.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c6
-rw-r--r--drivers/net/wireless/marvell/libertas/if_usb.c35
-rw-r--r--drivers/net/wireless/marvell/libertas/if_usb.h3
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/if_usb.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/tdls.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/usb.c4
-rw-r--r--drivers/net/wireless/marvell/mwl8k.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mac.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.c4
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00usb.c12
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/core.c14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c17
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_common.h1
-rw-r--r--drivers/net/wireless/silabs/wfx/data_rx.c8
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c64
-rw-r--r--include/linux/ieee80211-eht.h4
-rw-r--r--include/linux/ieee80211-ht.h3
-rw-r--r--include/linux/ieee80211-uhr.h4
-rw-r--r--include/linux/ieee80211.h85
-rw-r--r--include/net/mac80211.h4
-rw-r--r--include/uapi/linux/nl80211.h6
-rw-r--r--net/mac80211/agg-rx.c49
-rw-r--r--net/mac80211/agg-tx.c39
-rw-r--r--net/mac80211/chan.c86
-rw-r--r--net/mac80211/debugfs.c1
-rw-r--r--net/mac80211/eht.c21
-rw-r--r--net/mac80211/ht.c37
-rw-r--r--net/mac80211/ibss.c18
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/iface.c21
-rw-r--r--net/mac80211/main.c18
-rw-r--r--net/mac80211/mesh.c14
-rw-r--r--net/mac80211/mesh_hwmp.c20
-rw-r--r--net/mac80211/mesh_plink.c21
-rw-r--r--net/mac80211/mlme.c113
-rw-r--r--net/mac80211/rx.c134
-rw-r--r--net/mac80211/s1g.c36
-rw-r--r--net/mac80211/spectmgmt.c31
-rw-r--r--net/mac80211/sta_info.h3
-rw-r--r--net/mac80211/tdls.c29
-rw-r--r--net/mac80211/trace.h100
-rw-r--r--net/mac80211/util.c5
-rw-r--r--net/mac80211/vht.c10
-rw-r--r--net/wireless/chan.c110
-rw-r--r--net/wireless/nl80211.c37
-rw-r--r--net/wireless/of.c13
-rw-r--r--net/wireless/radiotap.c10
-rw-r--r--net/wireless/reg.c13
-rw-r--r--net/wireless/reg.h13
-rw-r--r--net/wireless/trace.c1
-rw-r--r--net/wireless/wext-core.c3
-rw-r--r--net/wireless/wext-priv.c3
-rw-r--r--net/wireless/wext-proc.c3
65 files changed, 735 insertions, 682 deletions
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index d1c121e943cb..a48b6bf1f29a 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6288,10 +6288,10 @@ static int ath11k_mac_mgmt_action_frame_fill_elem_data(struct ath11k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
/* make sure category field is present */
- if (skb->len < IEEE80211_MIN_ACTION_SIZE)
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(category))
return -EINVAL;
- remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE;
+ remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE(category);
has_protected = ieee80211_has_protected(hdr->frame_control);
/* In case of SW crypto and hdr protected (PMF), packet will already be encrypted,
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index af7590639dbf..a03881c73d68 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9119,10 +9119,10 @@ static int ath12k_mac_mgmt_action_frame_fill_elem_data(struct ath12k_link_vif *a
lockdep_assert_wiphy(wiphy);
/* make sure category field is present */
- if (skb->len < IEEE80211_MIN_ACTION_SIZE)
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(category))
return -EINVAL;
- remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE;
+ remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE(category);
has_protected = ieee80211_has_protected(hdr->frame_control);
/* In case of SW crypto and hdr protected (PMF), packet will already be encrypted,
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
index 27acdfc35459..ec6dba96640b 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
@@ -104,7 +104,7 @@ static bool ath12k_is_addba_resp_action_code(struct ieee80211_mgmt *mgmt)
if (mgmt->u.action.category != WLAN_CATEGORY_BACK)
return false;
- if (mgmt->u.action.u.addba_resp.action_code != WLAN_ACTION_ADDBA_RESP)
+ if (mgmt->u.action.action_code != WLAN_ACTION_ADDBA_RESP)
return false;
return true;
diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c
index 6445332801a4..44b04ea3cc8b 100644
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -2440,13 +2440,11 @@ static int at76_probe(struct usb_interface *interface,
struct mib_fw_version *fwv;
int board_type = (int)id->driver_info;
- udev = usb_get_dev(interface_to_usbdev(interface));
+ udev = interface_to_usbdev(interface);
fwv = kmalloc_obj(*fwv);
- if (!fwv) {
- ret = -ENOMEM;
- goto exit;
- }
+ if (!fwv)
+ return -ENOMEM;
/* Load firmware into kernel memory */
fwe = at76_load_firmware(udev, board_type);
@@ -2534,8 +2532,7 @@ static int at76_probe(struct usb_interface *interface,
exit:
kfree(fwv);
- if (ret < 0)
- usb_put_dev(udev);
+
return ret;
}
@@ -2552,7 +2549,6 @@ static void at76_disconnect(struct usb_interface *interface)
wiphy_info(priv->hw->wiphy, "disconnecting\n");
at76_delete_device(priv);
- usb_put_dev(interface_to_usbdev(interface));
dev_info(&interface->dev, "disconnected\n");
}
diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c
index bbc30cbad0bb..22359bd9db47 100644
--- a/drivers/net/wireless/broadcom/b43/phy_n.c
+++ b/drivers/net/wireless/broadcom/b43/phy_n.c
@@ -6566,19 +6566,19 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
b43_radio_mask(dev, 0x09, ~0x2);
- b43_radio_write(dev, 0x204D, 0);
- b43_radio_write(dev, 0x2053, 0);
- b43_radio_write(dev, 0x2058, 0);
- b43_radio_write(dev, 0x205E, 0);
- b43_radio_mask(dev, 0x2062, ~0xF0);
- b43_radio_write(dev, 0x2064, 0);
-
- b43_radio_write(dev, 0x304D, 0);
- b43_radio_write(dev, 0x3053, 0);
- b43_radio_write(dev, 0x3058, 0);
- b43_radio_write(dev, 0x305E, 0);
- b43_radio_mask(dev, 0x3062, ~0xF0);
- b43_radio_write(dev, 0x3064, 0);
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE, 0);
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE, 0);
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE, 0);
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE, 0);
+ b43_radio_mask(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE, ~0xF0);
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE, 0);
+
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE, 0);
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE, 0);
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE, 0);
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE, 0);
+ b43_radio_mask(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE, ~0xF0);
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE, 0);
}
} else {
if (phy->rev >= 19) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/time_sync.c b/drivers/net/wireless/intel/iwlwifi/mld/time_sync.c
index 897ab65b71aa..474dd555e70b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/time_sync.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/time_sync.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2025 Intel Corporation
+ * Copyright (C) 2025-2026 Intel Corporation
*/
#include "mld.h"
@@ -116,9 +116,9 @@ static bool iwl_mld_is_skb_match(struct sk_buff *skb, u8 *addr, u8 dialog_token)
u8 skb_dialog_token;
if (ieee80211_is_timing_measurement(skb))
- skb_dialog_token = mgmt->u.action.u.wnm_timing_msr.dialog_token;
+ skb_dialog_token = mgmt->u.action.wnm_timing_msr.dialog_token;
else
- skb_dialog_token = mgmt->u.action.u.ftm.dialog_token;
+ skb_dialog_token = mgmt->u.action.ftm.dialog_token;
if ((ether_addr_equal(mgmt->sa, addr) ||
ether_addr_equal(mgmt->da, addr)) &&
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index ebc569e94f55..1b67836b1fac 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2025 Intel Corporation
+ * Copyright (C) 2018-2026 Intel Corporation
*/
#include <linux/etherdevice.h>
#include <linux/math64.h>
@@ -1409,8 +1409,7 @@ void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
struct iwl_mvm_loc_entry *entry;
const u8 *ies, *lci, *civic, *msr_ie;
size_t ies_len, lci_len = 0, civic_len = 0;
- size_t baselen = IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.ftm);
+ size_t baselen = IEEE80211_MIN_ACTION_SIZE(ftm);
static const u8 rprt_type_lci = IEEE80211_SPCT_MSR_RPRT_TYPE_LCI;
static const u8 rprt_type_civic = IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC;
@@ -1419,7 +1418,7 @@ void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
lockdep_assert_held(&mvm->mutex);
- ies = mgmt->u.action.u.ftm.variable;
+ ies = mgmt->u.action.ftm.variable;
ies_len = len - baselen;
msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c
index edae3e24192b..039b4daac73f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022, 2026 Intel Corporation
*/
#include "mvm.h"
@@ -18,9 +18,9 @@ static bool iwl_mvm_is_skb_match(struct sk_buff *skb, u8 *addr, u8 dialog_token)
u8 skb_dialog_token;
if (ieee80211_is_timing_measurement(skb))
- skb_dialog_token = mgmt->u.action.u.wnm_timing_msr.dialog_token;
+ skb_dialog_token = mgmt->u.action.wnm_timing_msr.dialog_token;
else
- skb_dialog_token = mgmt->u.action.u.ftm.dialog_token;
+ skb_dialog_token = mgmt->u.action.ftm.dialog_token;
if ((ether_addr_equal(mgmt->sa, addr) ||
ether_addr_equal(mgmt->da, addr)) &&
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c
index 8a6bf1365cfa..176f2106bab6 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -114,8 +114,8 @@ static void if_usb_write_bulk_callback(struct urb *urb)
static void if_usb_free(struct if_usb_card *cardp)
{
/* Unlink tx & rx urb */
- usb_kill_urb(cardp->tx_urb);
- usb_kill_urb(cardp->rx_urb);
+ usb_kill_anchored_urbs(&cardp->tx_submitted);
+ usb_kill_anchored_urbs(&cardp->rx_submitted);
usb_free_urb(cardp->tx_urb);
cardp->tx_urb = NULL;
@@ -221,6 +221,9 @@ static int if_usb_probe(struct usb_interface *intf,
udev->descriptor.bDeviceSubClass,
udev->descriptor.bDeviceProtocol);
+ init_usb_anchor(&cardp->rx_submitted);
+ init_usb_anchor(&cardp->tx_submitted);
+
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_in(endpoint)) {
@@ -276,7 +279,6 @@ static int if_usb_probe(struct usb_interface *intf,
cardp->boot2_version = udev->descriptor.bcdDevice;
- usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
@@ -287,7 +289,6 @@ static int if_usb_probe(struct usb_interface *intf,
return 0;
err_get_fw:
- usb_put_dev(udev);
lbs_remove_card(priv);
err_add_card:
if_usb_reset_device(cardp);
@@ -321,7 +322,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
kfree(cardp);
usb_set_intfdata(intf, NULL);
- usb_put_dev(interface_to_usbdev(intf));
}
/**
@@ -426,7 +426,12 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
goto tx_ret;
}
- usb_kill_urb(cardp->tx_urb);
+ /* check if there are pending URBs */
+ if (!usb_anchor_empty(&cardp->tx_submitted)) {
+ lbs_deb_usbd(&cardp->udev->dev, "%s failed: pending URB\n", __func__);
+ ret = -EBUSY;
+ goto tx_ret;
+ }
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
usb_sndbulkpipe(cardp->udev,
@@ -435,8 +440,10 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
+ usb_anchor_urb(cardp->tx_urb, &cardp->tx_submitted);
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
+ usb_unanchor_urb(cardp->tx_urb);
} else {
lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
ret = 0;
@@ -467,8 +474,10 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
cardp);
lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+ usb_anchor_urb(cardp->rx_urb, &cardp->rx_submitted);
if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
+ usb_unanchor_urb(cardp->rx_urb);
kfree_skb(skb);
cardp->rx_skb = NULL;
ret = -1;
@@ -838,8 +847,8 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
}
/* Cancel any pending usb business */
- usb_kill_urb(cardp->rx_urb);
- usb_kill_urb(cardp->tx_urb);
+ usb_kill_anchored_urbs(&cardp->rx_submitted);
+ usb_kill_anchored_urbs(&cardp->tx_submitted);
cardp->fwlastblksent = 0;
cardp->fwdnldover = 0;
@@ -869,8 +878,8 @@ restart:
if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) {
/* Return to normal operation */
ret = -EOPNOTSUPP;
- usb_kill_urb(cardp->rx_urb);
- usb_kill_urb(cardp->tx_urb);
+ usb_kill_anchored_urbs(&cardp->rx_submitted);
+ usb_kill_anchored_urbs(&cardp->tx_submitted);
if (if_usb_submit_rx_urb(cardp) < 0)
ret = -EIO;
goto done;
@@ -900,7 +909,7 @@ restart:
wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
timer_delete_sync(&cardp->fw_timeout);
- usb_kill_urb(cardp->rx_urb);
+ usb_kill_anchored_urbs(&cardp->rx_submitted);
if (!cardp->fwdnldover) {
pr_info("failed to load fw, resetting device!\n");
@@ -960,8 +969,8 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
goto out;
/* Unlink tx & rx urb */
- usb_kill_urb(cardp->tx_urb);
- usb_kill_urb(cardp->rx_urb);
+ usb_kill_anchored_urbs(&cardp->tx_submitted);
+ usb_kill_anchored_urbs(&cardp->rx_submitted);
out:
return ret;
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.h b/drivers/net/wireless/marvell/libertas/if_usb.h
index 7d0daeb33c3f..a0cd36197c2b 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.h
+++ b/drivers/net/wireless/marvell/libertas/if_usb.h
@@ -48,6 +48,9 @@ struct if_usb_card {
struct urb *rx_urb, *tx_urb;
struct lbs_private *priv;
+ struct usb_anchor rx_submitted;
+ struct usb_anchor tx_submitted;
+
struct sk_buff *rx_skb;
uint8_t ep_in;
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
index f49151c18b79..07b38f2b8f58 100644
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -223,7 +223,6 @@ static int if_usb_probe(struct usb_interface *intf,
if (!priv)
goto dealloc;
- usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
return 0;
@@ -258,7 +257,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
kfree(cardp);
usb_set_intfdata(intf, NULL);
- usb_put_dev(interface_to_usbdev(intf));
lbtf_deb_leave(LBTF_DEB_MAIN);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
index a4cf323e704b..845f2a22e071 100644
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -755,16 +755,12 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
switch (action_code) {
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
/* See the layout of 'struct ieee80211_mgmt'. */
- extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
- sizeof(mgmt->u.action.category);
+ extra = IEEE80211_MIN_ACTION_SIZE(tdls_discover_resp) - 24;
skb_put(skb, extra);
mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
- mgmt->u.action.u.tdls_discover_resp.action_code =
- WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
- mgmt->u.action.u.tdls_discover_resp.dialog_token =
- dialog_token;
- mgmt->u.action.u.tdls_discover_resp.capability =
- cpu_to_le16(capab);
+ mgmt->u.action.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+ mgmt->u.action.tdls_discover_resp.dialog_token = dialog_token;
+ mgmt->u.action.tdls_discover_resp.capability = cpu_to_le16(capab);
/* move back for addr4 */
memmove(pos + ETH_ALEN, &mgmt->u.action, extra);
/* init address 4 */
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 947ecb0a7b40..f4b94a1054f6 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -520,8 +520,6 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
return ret;
}
- usb_get_dev(udev);
-
return 0;
}
@@ -666,8 +664,6 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
mwifiex_dbg(adapter, FATAL,
"%s: removing card\n", __func__);
mwifiex_remove_card(adapter);
-
- usb_put_dev(interface_to_usbdev(intf));
}
static void mwifiex_usb_coredump(struct device *dev)
diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c
index 99321d180f34..b1af02180341 100644
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
@@ -1985,9 +1985,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
*/
if (unlikely(ieee80211_is_action(wh->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
- mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ &&
+ mgmt->u.action.action_code == WLAN_ACTION_ADDBA_REQ &&
priv->ap_fw)) {
- u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ u16 capab = le16_to_cpu(mgmt->u.action.addba_req.capab);
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
index = mwl8k_tid_queue_mapping(tid);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index b41ca1410da9..f946ddc20a47 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -413,10 +413,10 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
u32 val;
if (ieee80211_is_action(fc) &&
- skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + 1 + 2 &&
+ skb->len >= IEEE80211_MIN_ACTION_SIZE(addba_req.capab) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
- mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
- u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ mgmt->u.action.action_code == WLAN_ACTION_ADDBA_REQ) {
+ u16 capab = le16_to_cpu(mgmt->u.action.addba_req.capab);
txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA);
tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 0d9435900423..caaf71c31480 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -668,9 +668,9 @@ mt7925_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
u32 val;
if (ieee80211_is_action(fc) &&
- skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 &&
+ skb->len >= IEEE80211_MIN_ACTION_SIZE(action_code) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
- mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
+ mgmt->u.action.action_code == WLAN_ACTION_ADDBA_REQ)
tid = MT_TX_ADDBA;
else if (ieee80211_is_mgmt(hdr->frame_control))
tid = MT_TX_NORMAL;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index d4f3ee943b47..84cbf36b493c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -800,9 +800,9 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
u32 val;
if (ieee80211_is_action(fc) &&
- skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 &&
+ skb->len >= IEEE80211_MIN_ACTION_SIZE(action_code) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
- mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
+ mgmt->u.action.action_code == WLAN_ACTION_ADDBA_REQ) {
if (is_mt7990(&dev->mt76))
txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TID_ADDBA, tid));
else
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 0c106709ae29..0b5b60815c7f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -452,8 +452,8 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
void *qdev_vif;
int ret;
- dev = alloc_netdev_mqs(sizeof(struct qtnf_vif *), name,
- name_assign_type, ether_setup, 1, 1);
+ dev = alloc_netdev(sizeof(struct qtnf_vif *), name,
+ name_assign_type, ether_setup);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index 54599cad78f9..83d00b6baf64 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -802,14 +802,12 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
struct rt2x00_dev *rt2x00dev;
int retval;
- usb_dev = usb_get_dev(usb_dev);
usb_reset_device(usb_dev);
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
rt2x00_probe_err("Failed to allocate hardware\n");
- retval = -ENOMEM;
- goto exit_put_device;
+ return -ENOMEM;
}
usb_set_intfdata(usb_intf, hw);
@@ -851,10 +849,6 @@ exit_free_reg:
exit_free_device:
ieee80211_free_hw(hw);
-
-exit_put_device:
- usb_put_dev(usb_dev);
-
usb_set_intfdata(usb_intf, NULL);
return retval;
@@ -873,11 +867,7 @@ void rt2x00usb_disconnect(struct usb_interface *usb_intf)
rt2x00usb_free_reg(rt2x00dev);
ieee80211_free_hw(hw);
- /*
- * Free the USB device data.
- */
usb_set_intfdata(usb_intf, NULL);
- usb_put_dev(interface_to_usbdev(usb_intf));
}
EXPORT_SYMBOL_GPL(rt2x00usb_disconnect);
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
index 794187d28caa..804fc604e5f8 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
@@ -5146,10 +5146,10 @@ static void rtl8xxxu_dump_action(struct device *dev,
if (!(rtl8xxxu_debug & RTL8XXXU_DEBUG_ACTION))
return;
- switch (mgmt->u.action.u.addba_resp.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_ACTION_ADDBA_RESP:
- cap = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
- timeout = le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
+ cap = le16_to_cpu(mgmt->u.action.addba_resp.capab);
+ timeout = le16_to_cpu(mgmt->u.action.addba_resp.timeout);
dev_info(dev, "WLAN_ACTION_ADDBA_RESP: "
"timeout %i, tid %02x, buf_size %02x, policy %02x, "
"status %02x\n",
@@ -5157,11 +5157,11 @@ static void rtl8xxxu_dump_action(struct device *dev,
(cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2,
(cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6,
(cap >> 1) & 0x1,
- le16_to_cpu(mgmt->u.action.u.addba_resp.status));
+ le16_to_cpu(mgmt->u.action.addba_resp.status));
break;
case WLAN_ACTION_ADDBA_REQ:
- cap = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
- timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
+ cap = le16_to_cpu(mgmt->u.action.addba_req.capab);
+ timeout = le16_to_cpu(mgmt->u.action.addba_req.timeout);
dev_info(dev, "WLAN_ACTION_ADDBA_REQ: "
"timeout %i, tid %02x, buf_size %02x, policy %02x\n",
timeout,
@@ -5171,7 +5171,7 @@ static void rtl8xxxu_dump_action(struct device *dev,
break;
default:
dev_info(dev, "action frame %02x\n",
- mgmt->u.action.u.addba_resp.action_code);
+ mgmt->u.action.action_code);
break;
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 0ac9cf0937aa..aad377864e73 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1409,7 +1409,7 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
sta_entry =
(struct rtl_sta_info *)sta->drv_priv;
capab =
- le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ le16_to_cpu(mgmt->u.action.addba_req.capab);
tid = (capab &
IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
if (tid >= MAX_TID_COUNT) {
@@ -2392,35 +2392,35 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw,
struct sk_buff *skb;
struct ieee80211_mgmt *action_frame;
- /* 27 = header + category + action + smps mode */
- skb = dev_alloc_skb(27 + hw->extra_tx_headroom);
+ skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(ht_smps) +
+ hw->extra_tx_headroom);
if (!skb)
return NULL;
skb_reserve(skb, hw->extra_tx_headroom);
- action_frame = skb_put_zero(skb, 27);
+ action_frame = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(ht_smps));
memcpy(action_frame->da, da, ETH_ALEN);
memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN);
memcpy(action_frame->bssid, bssid, ETH_ALEN);
action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
action_frame->u.action.category = WLAN_CATEGORY_HT;
- action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS;
+ action_frame->u.action.action_code = WLAN_HT_ACTION_SMPS;
switch (smps) {
case IEEE80211_SMPS_AUTOMATIC:/* 0 */
case IEEE80211_SMPS_NUM_MODES:/* 4 */
WARN_ON(1);
fallthrough;
case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/
- action_frame->u.action.u.ht_smps.smps_control =
+ action_frame->u.action.ht_smps.smps_control =
WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */
break;
case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/
- action_frame->u.action.u.ht_smps.smps_control =
+ action_frame->u.action.ht_smps.smps_control =
WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */
break;
case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/
- action_frame->u.action.u.ht_smps.smps_control =
+ action_frame->u.action.ht_smps.smps_control =
WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */
break;
}
@@ -2519,25 +2519,25 @@ struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
struct ieee80211_mgmt *action_frame;
u16 params;
- /* 27 = header + category + action + smps mode */
- skb = dev_alloc_skb(34 + hw->extra_tx_headroom);
+ skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(delba) +
+ hw->extra_tx_headroom);
if (!skb)
return NULL;
skb_reserve(skb, hw->extra_tx_headroom);
- action_frame = skb_put_zero(skb, 34);
+ action_frame = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(delba));
memcpy(action_frame->sa, sa, ETH_ALEN);
memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN);
memcpy(action_frame->bssid, bssid, ETH_ALEN);
action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
action_frame->u.action.category = WLAN_CATEGORY_BACK;
- action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
+ action_frame->u.action.action_code = WLAN_ACTION_DELBA;
params = (u16)(1 << 11); /* bit 11 initiator */
params |= (u16)(tid << 12); /* bit 15:12 TID number */
- action_frame->u.action.u.delba.params = cpu_to_le16(params);
- action_frame->u.action.u.delba.reason_code =
+ action_frame->u.action.delba.params = cpu_to_le16(params);
+ action_frame->u.action.delba.reason_code =
cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
return skb;
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index d080469264cf..19e2ff62d9f1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -507,7 +507,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
if (ieee80211_is_action(fc)) {
struct ieee80211_mgmt *action_frame =
(struct ieee80211_mgmt *)skb->data;
- if (action_frame->u.action.u.ht_smps.action ==
+ if (action_frame->u.action.action_code ==
WLAN_HT_ACTION_SMPS) {
dev_kfree_skb(skb);
goto tx_status_ok;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index c7ae8031436a..3faf2235728b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -326,6 +326,22 @@ void rsi_mac80211_detach(struct rsi_hw *adapter)
EXPORT_SYMBOL_GPL(rsi_mac80211_detach);
/**
+ * rsi_mac80211_rfkill_exit() - This function is used to stop rfkill polling
+ * when the device is removed.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+void rsi_mac80211_rfkill_exit(struct rsi_hw *adapter)
+{
+ struct ieee80211_hw *hw = adapter->hw;
+
+ if (hw)
+ wiphy_rfkill_stop_polling(hw->wiphy);
+}
+EXPORT_SYMBOL_GPL(rsi_mac80211_rfkill_exit);
+
+/**
* rsi_indicate_tx_status() - This function indicates the transmit status.
* @adapter: Pointer to the adapter structure.
* @skb: Pointer to the socket buffer structure.
@@ -422,7 +438,6 @@ static void rsi_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
mutex_lock(&common->mutex);
common->iface_down = true;
- wiphy_rfkill_stop_polling(hw->wiphy);
/* Block all rx frames */
rsi_send_rx_filter_frame(common, 0xffff);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index d83204701e27..8765cac6f875 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -877,6 +877,8 @@ static void rsi_disconnect(struct usb_interface *pfunction)
if (!adapter)
return;
+ rsi_mac80211_rfkill_exit(adapter);
+
rsi_mac80211_detach(adapter);
if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 &&
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 7aa5124575cf..591602beeec6 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -79,6 +79,7 @@ static inline int rsi_kill_thread(struct rsi_thread *handle)
}
void rsi_mac80211_detach(struct rsi_hw *hw);
+void rsi_mac80211_rfkill_exit(struct rsi_hw *hw);
u16 rsi_get_connected_channel(struct ieee80211_vif *vif);
struct rsi_hw *rsi_91x_init(u16 oper_mode);
void rsi_91x_deinit(struct rsi_hw *adapter);
diff --git a/drivers/net/wireless/silabs/wfx/data_rx.c b/drivers/net/wireless/silabs/wfx/data_rx.c
index e099a9e65bae..15c06b2b8633 100644
--- a/drivers/net/wireless/silabs/wfx/data_rx.c
+++ b/drivers/net/wireless/silabs/wfx/data_rx.c
@@ -21,14 +21,14 @@ static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt)
if (wfx_api_older_than(wvif->wdev, 3, 6))
return;
- switch (mgmt->u.action.u.addba_req.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_ACTION_ADDBA_REQ:
- params = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ params = le16_to_cpu(mgmt->u.action.addba_req.capab);
tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
ieee80211_start_rx_ba_session_offl(vif, mgmt->sa, tid);
break;
case WLAN_ACTION_DELBA:
- params = le16_to_cpu(mgmt->u.action.u.delba.params);
+ params = le16_to_cpu(mgmt->u.action.delba.params);
tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
ieee80211_stop_rx_ba_session_offl(vif, mgmt->sa, tid);
break;
@@ -80,7 +80,7 @@ void wfx_rx_cb(struct wfx_vif *wvif, const struct wfx_hif_ind_rx *arg, struct sk
*/
if (ieee80211_is_action(frame->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
- skb->len > IEEE80211_MIN_ACTION_SIZE) {
+ skb->len > IEEE80211_MIN_ACTION_SIZE(action_code)) {
wfx_rx_handle_ba(wvif, mgmt);
goto drop;
}
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 32897d88bda3..82adcc848189 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -36,6 +36,8 @@
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
#include "mac80211_hwsim.h"
#define WARN_QUEUE 100
@@ -1203,6 +1205,65 @@ static const struct file_operations hwsim_background_cac_ops = {
.llseek = default_llseek,
};
+struct hwsim_chanctx_iter_arg {
+ struct ieee80211_chanctx_conf *conf;
+ u32 freq_mhz;
+};
+
+static void hwsim_6ghz_chanctx_iter(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf,
+ void *data)
+{
+ struct hwsim_chanctx_iter_arg *arg = data;
+
+ if (conf->def.chan &&
+ conf->def.chan->band == NL80211_BAND_6GHZ &&
+ conf->def.chan->center_freq == arg->freq_mhz)
+ arg->conf = conf;
+}
+
+static ssize_t hwsim_simulate_incumbent_signal_write(struct file *file,
+ const char __user *ubuf,
+ size_t len, loff_t *ppos)
+{
+ struct mac80211_hwsim_data *data = file->private_data;
+ struct hwsim_chanctx_iter_arg arg = {};
+ u32 bitmap;
+ char buf[64];
+
+ if (!len || len > sizeof(buf) - 1)
+ return -EINVAL;
+
+ if (copy_from_user(buf, ubuf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ if (sscanf(buf, "%u %i", &arg.freq_mhz, &bitmap) != 2)
+ return -EINVAL;
+
+ if (!arg.freq_mhz)
+ return -EINVAL;
+
+ ieee80211_iter_chan_contexts_atomic(data->hw,
+ hwsim_6ghz_chanctx_iter,
+ &arg);
+
+ if (!arg.conf)
+ return -EINVAL;
+
+ cfg80211_incumbent_signal_notify(data->hw->wiphy,
+ &arg.conf->def,
+ bitmap,
+ GFP_KERNEL);
+
+ return len;
+}
+
+static const struct file_operations hwsim_simulate_incumbent_signal_fops = {
+ .open = simple_open,
+ .write = hwsim_simulate_incumbent_signal_write,
+};
+
static int hwsim_fops_group_read(void *dat, u64 *val)
{
struct mac80211_hwsim_data *data = dat;
@@ -5950,6 +6011,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
debugfs_create_file("dfs_background_cac", 0200,
data->debugfs,
data, &hwsim_background_cac_ops);
+ debugfs_create_file("simulate_incumbent_signal_interference", 0200,
+ data->debugfs,
+ data, &hwsim_simulate_incumbent_signal_fops);
if (param->pmsr_capa) {
data->pmsr_capa = *param->pmsr_capa;
diff --git a/include/linux/ieee80211-eht.h b/include/linux/ieee80211-eht.h
index f8e9f5d36d2a..a97b1d01f3ac 100644
--- a/include/linux/ieee80211-eht.h
+++ b/include/linux/ieee80211-eht.h
@@ -251,8 +251,8 @@ struct ieee80211_eht_operation_info {
#define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF 0x40
#define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK 0x07
-#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_80MHZ 0x08
-#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_160MHZ 0x30
+#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_80MHZ 0x10
+#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_160MHZ 0x20
#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_320MHZ 0x40
#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK 0x78
#define IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP 0x80
diff --git a/include/linux/ieee80211-ht.h b/include/linux/ieee80211-ht.h
index 21bbf470540f..7612b72f9c7c 100644
--- a/include/linux/ieee80211-ht.h
+++ b/include/linux/ieee80211-ht.h
@@ -281,6 +281,9 @@ enum ieee80211_back_actioncode {
WLAN_ACTION_ADDBA_REQ = 0,
WLAN_ACTION_ADDBA_RESP = 1,
WLAN_ACTION_DELBA = 2,
+ WLAN_ACTION_NDP_ADDBA_REQ = 128,
+ WLAN_ACTION_NDP_ADDBA_RESP = 129,
+ WLAN_ACTION_NDP_DELBA = 130,
};
/* BACK (block-ack) parties */
diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h
index 9729d23e4766..d199f3ebdba0 100644
--- a/include/linux/ieee80211-uhr.h
+++ b/include/linux/ieee80211-uhr.h
@@ -12,8 +12,8 @@
#define IEEE80211_UHR_OPER_PARAMS_DPS_ENA 0x0001
#define IEEE80211_UHR_OPER_PARAMS_NPCA_ENA 0x0002
-#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0004
-#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0008
+#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0004
+#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0008
struct ieee80211_uhr_operation {
__le16 params;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 3651b2e6c518..52db36120314 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1046,31 +1046,28 @@ struct ieee80211_mgmt {
} __packed probe_resp;
struct {
u8 category;
+ u8 action_code;
union {
struct {
- u8 action_code;
u8 dialog_token;
u8 status_code;
u8 variable[];
} __packed wme_action;
struct{
- u8 action_code;
+ u8 no_fixed_fields[0];
u8 variable[];
} __packed chan_switch;
struct{
- u8 action_code;
struct ieee80211_ext_chansw_ie data;
u8 variable[];
} __packed ext_chan_switch;
struct{
- u8 action_code;
u8 dialog_token;
u8 element_id;
u8 length;
struct ieee80211_msrment_ie msr_elem;
} __packed measurement;
struct{
- u8 action_code;
u8 dialog_token;
__le16 capab;
__le16 timeout;
@@ -1079,7 +1076,6 @@ struct ieee80211_mgmt {
u8 variable[];
} __packed addba_req;
struct{
- u8 action_code;
u8 dialog_token;
__le16 status;
__le16 capab;
@@ -1088,54 +1084,45 @@ struct ieee80211_mgmt {
u8 variable[];
} __packed addba_resp;
struct{
- u8 action_code;
__le16 params;
__le16 reason_code;
} __packed delba;
struct {
- u8 action_code;
+ u8 no_fixed_fields[0];
u8 variable[];
} __packed self_prot;
struct{
- u8 action_code;
+ u8 no_fixed_fields[0];
u8 variable[];
} __packed mesh_action;
struct {
- u8 action;
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} __packed sa_query;
struct {
- u8 action;
u8 smps_control;
} __packed ht_smps;
struct {
- u8 action_code;
u8 chanwidth;
} __packed ht_notify_cw;
struct {
- u8 action_code;
u8 dialog_token;
__le16 capability;
u8 variable[];
} __packed tdls_discover_resp;
struct {
- u8 action_code;
u8 operating_mode;
} __packed vht_opmode_notif;
struct {
- u8 action_code;
u8 membership[WLAN_MEMBERSHIP_LEN];
u8 position[WLAN_USER_POSITION_LEN];
} __packed vht_group_notif;
struct {
- u8 action_code;
u8 dialog_token;
u8 tpc_elem_id;
u8 tpc_elem_length;
struct ieee80211_tpc_report_ie tpc;
} __packed tpc_report;
struct {
- u8 action_code;
u8 dialog_token;
u8 follow_up;
u8 tod[6];
@@ -1145,11 +1132,10 @@ struct ieee80211_mgmt {
u8 variable[];
} __packed ftm;
struct {
- u8 action_code;
+ u8 no_fixed_fields[0];
u8 variable[];
} __packed s1g;
struct {
- u8 action_code;
u8 dialog_token;
u8 follow_up;
u32 tod;
@@ -1158,41 +1144,37 @@ struct ieee80211_mgmt {
u8 max_toa_error;
} __packed wnm_timing_msr;
struct {
- u8 action_code;
u8 dialog_token;
u8 variable[];
} __packed ttlm_req;
struct {
- u8 action_code;
u8 dialog_token;
__le16 status_code;
u8 variable[];
} __packed ttlm_res;
struct {
- u8 action_code;
+ u8 no_fixed_fields[0];
+ /* no variable fields either */
} __packed ttlm_tear_down;
struct {
- u8 action_code;
u8 dialog_token;
u8 variable[];
} __packed ml_reconf_req;
struct {
- u8 action_code;
u8 dialog_token;
u8 count;
u8 variable[];
} __packed ml_reconf_resp;
struct {
- u8 action_code;
+ u8 no_fixed_fields[0];
u8 variable[];
} __packed epcs;
struct {
- u8 action_code;
u8 dialog_token;
u8 control;
u8 variable[];
} __packed eml_omn;
- } u;
+ };
} __packed action;
DECLARE_FLEX_ARRAY(u8, body); /* Generic frame body */
} u;
@@ -1210,8 +1192,7 @@ struct ieee80211_mgmt {
#define BSS_MEMBERSHIP_SELECTOR_MIN BSS_MEMBERSHIP_SELECTOR_UHR_PHY
-/* mgmt header + 1 byte category code */
-#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
+#define IEEE80211_MIN_ACTION_SIZE(type) offsetofend(struct ieee80211_mgmt, u.action.type)
/* Management MIC information element (IEEE 802.11w) for CMAC */
@@ -1501,6 +1482,8 @@ enum ieee80211_statuscode {
WLAN_STATUS_REJECT_DSE_BAND = 96,
WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
+ /* 802.11ah */
+ WLAN_STATUS_REJECTED_NDP_BLOCK_ACK_SUGGESTED = 109,
/* 802.11ai */
WLAN_STATUS_FILS_AUTHENTICATION_FAILURE = 112,
WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER = 113,
@@ -2391,7 +2374,7 @@ static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb)
if (!ieee80211_is_action(fc))
return false;
- if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(action_code))
return true;
/* action frame - additionally check for non-bufferable FTM */
@@ -2400,8 +2383,8 @@ static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb)
mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
return true;
- if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
- mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_RESPONSE)
+ if (mgmt->u.action.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
+ mgmt->u.action.action_code == WLAN_PUB_ACTION_FTM_RESPONSE)
return false;
return true;
@@ -2451,7 +2434,7 @@ static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
*/
static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
{
- if (skb->len < IEEE80211_MIN_ACTION_SIZE)
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(category))
return false;
return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
}
@@ -2467,7 +2450,7 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
{
struct ieee80211_mgmt *mgmt = (void *)hdr;
- if (len < IEEE80211_MIN_ACTION_SIZE)
+ if (len < IEEE80211_MIN_ACTION_SIZE(category))
return false;
if (!ieee80211_is_action(hdr->frame_control))
return false;
@@ -2485,13 +2468,14 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
static inline bool
ieee80211_is_protected_dual_of_public_action(struct sk_buff *skb)
{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
u8 action;
if (!ieee80211_is_public_action((void *)skb->data, skb->len) ||
- skb->len < IEEE80211_MIN_ACTION_SIZE + 1)
+ skb->len < IEEE80211_MIN_ACTION_SIZE(action_code))
return false;
- action = *(u8 *)(skb->data + IEEE80211_MIN_ACTION_SIZE);
+ action = mgmt->u.action.action_code;
return action != WLAN_PUB_ACTION_20_40_BSS_COEX &&
action != WLAN_PUB_ACTION_DSE_REG_LOC_ANN &&
@@ -2530,7 +2514,7 @@ static inline bool _ieee80211_is_group_privacy_action(struct ieee80211_hdr *hdr)
*/
static inline bool ieee80211_is_group_privacy_action(struct sk_buff *skb)
{
- if (skb->len < IEEE80211_MIN_ACTION_SIZE)
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(category))
return false;
return _ieee80211_is_group_privacy_action((void *)skb->data);
}
@@ -2626,8 +2610,7 @@ static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb)
if (!ieee80211_is_action(mgmt->frame_control))
return false;
- if (skb->len < IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.tpc_report))
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(tpc_report))
return false;
/*
@@ -2646,12 +2629,11 @@ static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb)
return false;
/* both spectrum mgmt and link measurement have same action code */
- if (mgmt->u.action.u.tpc_report.action_code !=
- WLAN_ACTION_SPCT_TPC_RPRT)
+ if (mgmt->u.action.action_code != WLAN_ACTION_SPCT_TPC_RPRT)
return false;
- if (mgmt->u.action.u.tpc_report.tpc_elem_id != WLAN_EID_TPC_REPORT ||
- mgmt->u.action.u.tpc_report.tpc_elem_length !=
+ if (mgmt->u.action.tpc_report.tpc_elem_id != WLAN_EID_TPC_REPORT ||
+ mgmt->u.action.tpc_report.tpc_elem_length !=
sizeof(struct ieee80211_tpc_report_ie))
return false;
@@ -2667,16 +2649,15 @@ static inline bool ieee80211_is_timing_measurement(struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- if (skb->len < IEEE80211_MIN_ACTION_SIZE)
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(wnm_timing_msr))
return false;
if (!ieee80211_is_action(mgmt->frame_control))
return false;
if (mgmt->u.action.category == WLAN_CATEGORY_WNM_UNPROTECTED &&
- mgmt->u.action.u.wnm_timing_msr.action_code ==
- WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE &&
- skb->len >= offsetofend(typeof(*mgmt), u.action.u.wnm_timing_msr))
+ mgmt->u.action.action_code ==
+ WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE)
return true;
return false;
@@ -2691,15 +2672,13 @@ static inline bool ieee80211_is_ftm(struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- if (!ieee80211_is_public_action((void *)mgmt, skb->len))
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(ftm))
return false;
- if (mgmt->u.action.u.ftm.action_code ==
- WLAN_PUB_ACTION_FTM_RESPONSE &&
- skb->len >= offsetofend(typeof(*mgmt), u.action.u.ftm))
- return true;
+ if (!ieee80211_is_public_action((void *)mgmt, skb->len))
+ return false;
- return false;
+ return mgmt->u.action.action_code == WLAN_PUB_ACTION_FTM_RESPONSE;
}
struct element {
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9f8251fb9832..9cc482191ab9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2913,6 +2913,9 @@ struct ieee80211_txq {
* HW flag so drivers can opt in according to their own control, e.g. in
* testing.
*
+ * @IEEE80211_HW_SUPPORTS_NDP_BLOCKACK: HW can transmit/receive S1G NDP
+ * BlockAck frames.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2973,6 +2976,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_DISALLOW_PUNCTURING,
IEEE80211_HW_HANDLES_QUIET_CSA,
IEEE80211_HW_STRICT,
+ IEEE80211_HW_SUPPORTS_NDP_BLOCKACK,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0b7a06c2b9f7..67d764023988 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3001,6 +3001,10 @@ enum nl80211_commands {
* interference detection is not performed on these sub-channels, their
* corresponding bits are consistently set to zero.
*
+ * @NL80211_ATTR_UHR_OPERATION: Full UHR Operation element, as it appears in
+ * association response etc., since it's abridged in the beacon. Used
+ * for START_AP etc.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3576,6 +3580,8 @@ enum nl80211_attrs {
NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
+ NL80211_ATTR_UHR_OPERATION,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f301a8622bee..0140ac826b23 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -9,7 +9,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2010, Intel Corporation
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2025 Intel Corporation
+ * Copyright (C) 2018-2026 Intel Corporation
*/
/**
@@ -94,7 +94,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
/* check if this is a self generated aggregation halt */
if (initiator == WLAN_BACK_RECIPIENT && tx)
ieee80211_send_delba(sta->sdata, sta->sta.addr,
- tid, WLAN_BACK_RECIPIENT, reason);
+ tid, WLAN_BACK_RECIPIENT, reason,
+ ieee80211_s1g_use_ndp_ba(sta->sdata, sta));
/*
* return here in case tid_rx is not assigned - which will happen if
@@ -240,6 +241,7 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU);
+ bool use_ndp = ieee80211_s1g_use_ndp_ba(sdata, sta);
u16 capab;
skb = dev_alloc_skb(sizeof(*mgmt) +
@@ -251,19 +253,21 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
skb_reserve(skb, local->hw.extra_tx_headroom);
mgmt = ieee80211_mgmt_ba(skb, da, sdata);
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
+ skb_put(skb, 2 + sizeof(mgmt->u.action.addba_resp));
mgmt->u.action.category = WLAN_CATEGORY_BACK;
- mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
- mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
+ mgmt->u.action.action_code = use_ndp ?
+ WLAN_ACTION_NDP_ADDBA_RESP : WLAN_ACTION_ADDBA_RESP;
+
+ mgmt->u.action.addba_resp.dialog_token = dialog_token;
capab = u16_encode_bits(amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK);
capab |= u16_encode_bits(policy, IEEE80211_ADDBA_PARAM_POLICY_MASK);
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
capab |= u16_encode_bits(buf_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
- mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
- mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
- mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
+ mgmt->u.action.addba_resp.capab = cpu_to_le16(capab);
+ mgmt->u.action.addba_resp.timeout = cpu_to_le16(timeout);
+ mgmt->u.action.addba_resp.status = cpu_to_le16(status);
if (sta->sta.valid_links || sta->sta.deflink.he_cap.has_he)
ieee80211_add_addbaext(skb, req_addba_ext_data, buf_size);
@@ -275,6 +279,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
u8 dialog_token, u16 timeout,
u16 start_seq_num, u16 ba_policy, u16 tid,
u16 buf_size, bool tx, bool auto_seq,
+ bool req_ndp,
const u8 addba_ext_data)
{
struct ieee80211_local *local = sta->sdata->local;
@@ -300,6 +305,18 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
goto end;
}
+ if (tx && ieee80211_s1g_use_ndp_ba(sta->sdata, sta) && !req_ndp) {
+ /*
+ * According to IEEE 802.11-2024: Inform S1G originator
+ * ADDBA rejected as NDP BlockAck is preferred
+ */
+ status = WLAN_STATUS_REJECTED_NDP_BLOCK_ACK_SUGGESTED;
+ ht_dbg(sta->sdata,
+ "Rejecting AddBA Req from %pM tid %u - require NDP BlockAck\n",
+ sta->sta.addr, tid);
+ goto end;
+ }
+
if (!sta->sta.valid_links &&
!sta->sta.deflink.ht_cap.ht_supported &&
!sta->sta.deflink.he_cap.has_he &&
@@ -473,31 +490,33 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
struct ieee80211_mgmt *mgmt,
size_t len)
{
+ bool req_ndp = mgmt->u.action.action_code == WLAN_ACTION_NDP_ADDBA_REQ;
u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
u8 dialog_token, addba_ext_data;
/* extract session parameters from addba request frame */
- dialog_token = mgmt->u.action.u.addba_req.dialog_token;
- timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
+ dialog_token = mgmt->u.action.addba_req.dialog_token;
+ timeout = le16_to_cpu(mgmt->u.action.addba_req.timeout);
start_seq_num =
- le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
+ le16_to_cpu(mgmt->u.action.addba_req.start_seq_num) >> 4;
- capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ capab = le16_to_cpu(mgmt->u.action.addba_req.capab);
ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
addba_ext_data =
ieee80211_retrieve_addba_ext_data(sta,
- mgmt->u.action.u.addba_req.variable,
+ mgmt->u.action.addba_req.variable,
len -
offsetof(typeof(*mgmt),
- u.action.u.addba_req.variable),
+ u.action.addba_req.variable),
&buf_size);
__ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
start_seq_num, ba_policy, tid,
- buf_size, true, false, addba_ext_data);
+ buf_size, true, false,
+ req_ndp, addba_ext_data);
}
void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 93b47a7ba9c4..01d927b88264 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -9,7 +9,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2010, Intel Corporation
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2024 Intel Corporation
+ * Copyright (C) 2018-2026 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -60,7 +60,7 @@
static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid,
u8 dialog_token, u16 start_seq_num,
- u16 agg_size, u16 timeout)
+ u16 agg_size, u16 timeout, bool ndp)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
@@ -68,7 +68,7 @@ static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid,
struct ieee80211_mgmt *mgmt;
u16 capab;
- skb = dev_alloc_skb(sizeof(*mgmt) +
+ skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(addba_req) +
2 + sizeof(struct ieee80211_addba_ext_ie) +
local->hw.extra_tx_headroom);
if (!skb)
@@ -77,21 +77,22 @@ static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid,
skb_reserve(skb, local->hw.extra_tx_headroom);
mgmt = ieee80211_mgmt_ba(skb, sta->sta.addr, sdata);
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
+ skb_put(skb, 2 + sizeof(mgmt->u.action.addba_req));
mgmt->u.action.category = WLAN_CATEGORY_BACK;
- mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
+ mgmt->u.action.action_code = ndp ?
+ WLAN_ACTION_NDP_ADDBA_REQ : WLAN_ACTION_ADDBA_REQ;
- mgmt->u.action.u.addba_req.dialog_token = dialog_token;
+ mgmt->u.action.addba_req.dialog_token = dialog_token;
capab = IEEE80211_ADDBA_PARAM_AMSDU_MASK;
capab |= IEEE80211_ADDBA_PARAM_POLICY_MASK;
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
- mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
+ mgmt->u.action.addba_req.capab = cpu_to_le16(capab);
- mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
- mgmt->u.action.u.addba_req.start_seq_num =
+ mgmt->u.action.addba_req.timeout = cpu_to_le16(timeout);
+ mgmt->u.action.addba_req.start_seq_num =
cpu_to_le16(start_seq_num << 4);
if (sta->sta.deflink.he_cap.has_he)
@@ -484,7 +485,8 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
/* send AddBA request */
ieee80211_send_addba_request(sta, tid, tid_tx->dialog_token,
- tid_tx->ssn, buf_size, tid_tx->timeout);
+ tid_tx->ssn, buf_size, tid_tx->timeout,
+ tid_tx->ndp);
WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state));
}
@@ -521,6 +523,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
*/
synchronize_net();
+ tid_tx->ndp = ieee80211_s1g_use_ndp_ba(sdata, sta);
params.ssn = sta->tid_seq[tid] >> 4;
ret = drv_ampdu_action(local, sdata, &params);
tid_tx->ssn = params.ssn;
@@ -940,7 +943,9 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
if (send_delba)
ieee80211_send_delba(sdata, sta->sta.addr, tid,
- WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
+ WLAN_BACK_INITIATOR,
+ WLAN_REASON_QSTA_NOT_USE,
+ tid_tx->ndp);
}
void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
@@ -978,15 +983,15 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
lockdep_assert_wiphy(sta->local->hw.wiphy);
- capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
+ capab = le16_to_cpu(mgmt->u.action.addba_resp.capab);
amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK;
tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK);
buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
ieee80211_retrieve_addba_ext_data(sta,
- mgmt->u.action.u.addba_resp.variable,
+ mgmt->u.action.addba_resp.variable,
len - offsetof(typeof(*mgmt),
- u.action.u.addba_resp.variable),
+ u.action.addba_resp.variable),
&buf_size);
buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
@@ -999,7 +1004,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
if (!tid_tx)
return;
- if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) {
+ if (mgmt->u.action.addba_resp.dialog_token != tid_tx->dialog_token) {
ht_dbg(sta->sdata, "wrong addBA response token, %pM tid %d\n",
sta->sta.addr, tid);
return;
@@ -1029,7 +1034,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
* is set to 0, the Buffer Size subfield is set to a value
* of at least 1.
*/
- if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
+ if (le16_to_cpu(mgmt->u.action.addba_resp.status)
== WLAN_STATUS_SUCCESS && buf_size) {
if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
&tid_tx->state)) {
@@ -1046,7 +1051,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
sta->ampdu_mlme.addba_req_num[tid] = 0;
tid_tx->timeout =
- le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
+ le16_to_cpu(mgmt->u.action.addba_resp.timeout);
if (tid_tx->timeout) {
mod_timer(&tid_tx->session_timer,
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 4447cf03c41b..2f0c93f3ace6 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* mac80211 - channel management
- * Copyright 2020 - 2025 Intel Corporation
+ * Copyright 2020-2026 Intel Corporation
*/
#include <linux/nl80211.h>
@@ -239,27 +239,48 @@ ieee80211_chanreq_compatible(const struct ieee80211_chan_req *a,
return tmp;
}
+/*
+ * When checking for compatible, check against all the links using
+ * the chanctx (except the one passed that might be changing) to
+ * allow changes to the AP's bandwidth for wider bandwidth OFDMA
+ * purposes, which wouldn't be treated as compatible by checking
+ * against the chanctx's oper/ap chandefs.
+ */
static const struct ieee80211_chan_req *
-ieee80211_chanctx_compatible(struct ieee80211_chanctx *ctx,
- const struct ieee80211_chan_req *req,
- struct ieee80211_chan_req *tmp)
+_ieee80211_chanctx_compatible(struct ieee80211_local *local,
+ struct ieee80211_link_data *skip_link,
+ struct ieee80211_chanctx *ctx,
+ const struct ieee80211_chan_req *req,
+ struct ieee80211_chan_req *tmp)
{
- const struct ieee80211_chan_req *ret;
- struct ieee80211_chan_req tmp2;
+ const struct ieee80211_chan_req *ret = req;
+ struct ieee80211_chanctx_user_iter iter;
- *tmp = (struct ieee80211_chan_req){
- .oper = ctx->conf.def,
- .ap = ctx->conf.ap,
- };
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+ for_each_chanctx_user_all(local, ctx, &iter) {
+ if (iter.link && iter.link == skip_link)
+ continue;
+
+ ret = ieee80211_chanreq_compatible(ret, iter.chanreq, tmp);
+ if (!ret)
+ return NULL;
+ }
- ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
- if (!ret)
- return NULL;
*tmp = *ret;
return tmp;
}
static const struct ieee80211_chan_req *
+ieee80211_chanctx_compatible(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx,
+ const struct ieee80211_chan_req *req,
+ struct ieee80211_chan_req *tmp)
+{
+ return _ieee80211_chanctx_compatible(local, NULL, ctx, req, tmp);
+}
+
+static const struct ieee80211_chan_req *
ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
struct ieee80211_chanctx *ctx,
const struct ieee80211_chan_req *req,
@@ -756,7 +777,8 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
continue;
- compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp);
+ compat = ieee80211_chanctx_compatible(local, ctx, chanreq,
+ &tmp);
if (!compat)
continue;
@@ -2128,40 +2150,6 @@ int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
return 0;
}
-/*
- * This is similar to ieee80211_chanctx_compatible(), but rechecks
- * against all the links actually using it (except the one that's
- * passed, since that one is changing).
- * This is done in order to allow changes to the AP's bandwidth for
- * wider bandwidth OFDMA purposes, which wouldn't be treated as
- * compatible by ieee80211_chanctx_recheck() but is OK if the link
- * requesting the update is the only one using it.
- */
-static const struct ieee80211_chan_req *
-ieee80211_chanctx_recheck(struct ieee80211_local *local,
- struct ieee80211_link_data *skip_link,
- struct ieee80211_chanctx *ctx,
- const struct ieee80211_chan_req *req,
- struct ieee80211_chan_req *tmp)
-{
- const struct ieee80211_chan_req *ret = req;
- struct ieee80211_chanctx_user_iter iter;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
- for_each_chanctx_user_all(local, ctx, &iter) {
- if (iter.link == skip_link)
- continue;
-
- ret = ieee80211_chanreq_compatible(ret, iter.chanreq, tmp);
- if (!ret)
- return NULL;
- }
-
- *tmp = *ret;
- return tmp;
-}
-
int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
const struct ieee80211_chan_req *chanreq,
u64 *changed)
@@ -2198,7 +2186,7 @@ int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
ctx = container_of(conf, struct ieee80211_chanctx, conf);
- compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
+ compat = _ieee80211_chanctx_compatible(local, link, ctx, chanreq, &tmp);
if (!compat)
return -EINVAL;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index d02f07368c51..e8d0a8b71d59 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -490,6 +490,7 @@ static const char *hw_flag_names[] = {
FLAG(DISALLOW_PUNCTURING),
FLAG(HANDLES_QUIET_CSA),
FLAG(STRICT),
+ FLAG(SUPPORTS_NDP_BLOCKACK),
#undef FLAG
};
diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c
index 078e1e23d8d1..768bfc4e737d 100644
--- a/net/mac80211/eht.c
+++ b/net/mac80211/eht.c
@@ -108,7 +108,7 @@ static void
ieee80211_send_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *req, int opt_len)
{
- int len = offsetofend(struct ieee80211_mgmt, u.action.u.eml_omn);
+ int len = IEEE80211_MIN_ACTION_SIZE(eml_omn);
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
struct sk_buff *skb;
@@ -127,16 +127,15 @@ ieee80211_send_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
- mgmt->u.action.u.eml_omn.action_code =
- WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF;
- mgmt->u.action.u.eml_omn.dialog_token =
- req->u.action.u.eml_omn.dialog_token;
- mgmt->u.action.u.eml_omn.control = req->u.action.u.eml_omn.control &
+ mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF;
+ mgmt->u.action.eml_omn.dialog_token =
+ req->u.action.eml_omn.dialog_token;
+ mgmt->u.action.eml_omn.control = req->u.action.eml_omn.control &
~(IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE |
IEEE80211_EML_CTRL_INDEV_COEX_ACT);
/* Copy optional fields from the received notification frame */
- memcpy(mgmt->u.action.u.eml_omn.variable,
- req->u.action.u.eml_omn.variable, opt_len);
+ memcpy(mgmt->u.action.eml_omn.variable,
+ req->u.action.eml_omn.variable, opt_len);
ieee80211_tx_skb(sdata, skb);
}
@@ -144,14 +143,14 @@ ieee80211_send_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,
void ieee80211_rx_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
- int len = offsetofend(struct ieee80211_mgmt, u.action.u.eml_omn);
+ int len = IEEE80211_MIN_ACTION_SIZE(eml_omn);
enum nl80211_iftype type = ieee80211_vif_type_p2p(&sdata->vif);
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
const struct wiphy_iftype_ext_capab *ift_ext_capa;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_local *local = sdata->local;
- u8 control = mgmt->u.action.u.eml_omn.control;
- u8 *ptr = mgmt->u.action.u.eml_omn.variable;
+ u8 control = mgmt->u.action.eml_omn.control;
+ u8 *ptr = mgmt->u.action.eml_omn.variable;
struct ieee80211_eml_params eml_params = {
.link_id = status->link_id,
.control = control,
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 1c82a28b03de..33f1e1b235e9 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -9,7 +9,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2010, Intel Corporation
* Copyright 2017 Intel Deutschland GmbH
- * Copyright(c) 2020-2025 Intel Corporation
+ * Copyright(c) 2020-2026 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -379,7 +379,7 @@ void ieee80211_ba_session_work(struct wiphy *wiphy, struct wiphy_work *work)
sta->ampdu_mlme.tid_rx_manage_offl))
__ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
IEEE80211_MAX_AMPDU_BUF_HT,
- false, true, 0);
+ false, true, false, 0);
if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
sta->ampdu_mlme.tid_rx_manage_offl))
@@ -455,29 +455,32 @@ void ieee80211_ba_session_work(struct wiphy *wiphy, struct wiphy_work *work)
void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
const u8 *da, u16 tid,
- u16 initiator, u16 reason_code)
+ u16 initiator, u16 reason_code,
+ bool use_ndp)
{
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u16 params;
- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
+ skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(delba) +
+ local->hw.extra_tx_headroom);
if (!skb)
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
mgmt = ieee80211_mgmt_ba(skb, da, sdata);
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
+ skb_put(skb, 2 + sizeof(mgmt->u.action.delba));
mgmt->u.action.category = WLAN_CATEGORY_BACK;
- mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
+ mgmt->u.action.action_code = use_ndp ?
+ WLAN_ACTION_NDP_DELBA : WLAN_ACTION_DELBA;
params = (u16)(initiator << 11); /* bit 11 initiator */
params |= (u16)(tid << 12); /* bit 15:12 TID number */
- mgmt->u.action.u.delba.params = cpu_to_le16(params);
- mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
+ mgmt->u.action.delba.params = cpu_to_le16(params);
+ mgmt->u.action.delba.reason_code = cpu_to_le16(reason_code);
ieee80211_tx_skb(sdata, skb);
}
@@ -489,14 +492,14 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
u16 tid, params;
u16 initiator;
- params = le16_to_cpu(mgmt->u.action.u.delba.params);
+ params = le16_to_cpu(mgmt->u.action.delba.params);
tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
ht_dbg_ratelimited(sdata, "delba from %pM (%s) tid %d reason code %d\n",
mgmt->sa, initiator ? "initiator" : "recipient",
tid,
- le16_to_cpu(mgmt->u.action.u.delba.reason_code));
+ le16_to_cpu(mgmt->u.action.delba.reason_code));
if (initiator == WLAN_BACK_INITIATOR)
__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
@@ -530,20 +533,20 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_info *info;
u8 status_link_id = link_id < 0 ? 0 : link_id;
- /* 27 = header + category + action + smps mode */
- skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom);
+ skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(ht_smps) +
+ local->hw.extra_tx_headroom);
if (!skb)
return -ENOMEM;
skb_reserve(skb, local->hw.extra_tx_headroom);
- action_frame = skb_put(skb, 27);
+ action_frame = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(ht_smps));
memcpy(action_frame->da, da, ETH_ALEN);
memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(action_frame->bssid, bssid, ETH_ALEN);
action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
action_frame->u.action.category = WLAN_CATEGORY_HT;
- action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS;
+ action_frame->u.action.action_code = WLAN_HT_ACTION_SMPS;
switch (smps) {
case IEEE80211_SMPS_AUTOMATIC:
case IEEE80211_SMPS_NUM_MODES:
@@ -551,15 +554,15 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
smps = IEEE80211_SMPS_OFF;
fallthrough;
case IEEE80211_SMPS_OFF:
- action_frame->u.action.u.ht_smps.smps_control =
+ action_frame->u.action.ht_smps.smps_control =
WLAN_HT_SMPS_CONTROL_DISABLED;
break;
case IEEE80211_SMPS_STATIC:
- action_frame->u.action.u.ht_smps.smps_control =
+ action_frame->u.action.ht_smps.smps_control =
WLAN_HT_SMPS_CONTROL_STATIC;
break;
case IEEE80211_SMPS_DYNAMIC:
- action_frame->u.action.u.ht_smps.smps_control =
+ action_frame->u.action.ht_smps.smps_control =
WLAN_HT_SMPS_CONTROL_DYNAMIC;
break;
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 168f84a1353b..0298272c37ec 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -9,7 +9,7 @@
* Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright(c) 2018-2025 Intel Corporation
+ * Copyright(c) 2018-2026 Intel Corporation
*/
#include <linux/delay.h>
@@ -888,19 +888,11 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
struct ieee80211_rx_status *rx_status,
struct ieee802_11_elems *elems)
{
- int required_len;
-
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ if (len < IEEE80211_MIN_ACTION_SIZE(chan_switch))
return;
/* CSA is the only action we handle for now */
- if (mgmt->u.action.u.measurement.action_code !=
- WLAN_ACTION_SPCT_CHL_SWITCH)
- return;
-
- required_len = IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.chan_switch);
- if (len < required_len)
+ if (mgmt->u.action.action_code != WLAN_ACTION_SPCT_CHL_SWITCH)
return;
if (!sdata->vif.bss_conf.csa_active)
@@ -1613,12 +1605,12 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
case WLAN_CATEGORY_SPECTRUM_MGMT:
ies_len = skb->len -
offsetof(struct ieee80211_mgmt,
- u.action.u.chan_switch.variable);
+ u.action.chan_switch.variable);
if (ies_len < 0)
break;
- elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable,
+ elems = ieee802_11_parse_elems(mgmt->u.action.chan_switch.variable,
ies_len,
IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a4babf7624e5..d71e0c6d2165 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2190,7 +2190,8 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
struct link_sta_info *link_sta);
void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
const u8 *da, u16 tid,
- u16 initiator, u16 reason_code);
+ u16 initiator, u16 reason_code,
+ bool use_ndp);
int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode smps, const u8 *da,
const u8 *bssid, int link_id);
@@ -2206,6 +2207,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
u8 dialog_token, u16 timeout,
u16 start_seq_num, u16 ba_policy, u16 tid,
u16 buf_size, bool tx, bool auto_seq,
+ bool req_ndp,
const u8 addba_ext_data);
void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
enum ieee80211_agg_stop_reason reason);
@@ -2331,6 +2333,8 @@ void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata,
void ieee80211_s1g_cap_to_sta_s1g_cap(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_s1g_cap *s1g_cap_ie,
struct link_sta_info *link_sta);
+bool ieee80211_s1g_use_ndp_ba(const struct ieee80211_sub_if_data *sdata,
+ const struct sta_info *sta);
/* Spectrum management */
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 676b2a43c9f2..40ce0bb72726 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1579,16 +1579,19 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
sta = sta_info_get_bss(sdata, mgmt->sa);
if (sta) {
- switch (mgmt->u.action.u.addba_req.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_ACTION_ADDBA_REQ:
+ case WLAN_ACTION_NDP_ADDBA_REQ:
ieee80211_process_addba_request(local, sta,
mgmt, len);
break;
case WLAN_ACTION_ADDBA_RESP:
+ case WLAN_ACTION_NDP_ADDBA_RESP:
ieee80211_process_addba_resp(local, sta,
mgmt, len);
break;
case WLAN_ACTION_DELBA:
+ case WLAN_ACTION_NDP_DELBA:
ieee80211_process_delba(sdata, sta,
mgmt, len);
break;
@@ -1599,9 +1602,9 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
}
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_HT) {
- switch (mgmt->u.action.u.ht_smps.action) {
+ switch (mgmt->u.action.action_code) {
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
- u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
+ u8 chanwidth = mgmt->u.action.ht_notify_cw.chanwidth;
struct ieee80211_rx_status *status;
struct link_sta_info *link_sta;
struct sta_info *sta;
@@ -1628,7 +1631,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
}
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_VHT) {
- switch (mgmt->u.action.u.vht_group_notif.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
struct ieee80211_rx_status *status;
enum nl80211_band band;
@@ -1637,7 +1640,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
status = IEEE80211_SKB_RXCB(skb);
band = status->band;
- opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
+ opmode = mgmt->u.action.vht_opmode_notif.operating_mode;
sta = sta_info_get_bss(sdata, mgmt->sa);
@@ -1658,7 +1661,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
}
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_S1G) {
- switch (mgmt->u.action.u.s1g.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_S1G_TWT_TEARDOWN:
case WLAN_S1G_TWT_SETUP:
ieee80211_s1g_rx_twt_action(sdata, skb);
@@ -1669,7 +1672,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_PROTECTED_EHT) {
if (sdata->vif.type == NL80211_IFTYPE_AP) {
- switch (mgmt->u.action.u.eml_omn.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF:
ieee80211_rx_eml_op_mode_notif(sdata, skb);
break;
@@ -1677,7 +1680,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
break;
}
} else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- switch (mgmt->u.action.u.ttlm_req.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ:
ieee80211_process_neg_ttlm_req(sdata, mgmt,
skb->len);
@@ -1765,7 +1768,7 @@ static void ieee80211_iface_process_status(struct ieee80211_sub_if_data *sdata,
if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_S1G) {
- switch (mgmt->u.action.u.s1g.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_S1G_TWT_TEARDOWN:
case WLAN_S1G_TWT_SETUP:
ieee80211_s1g_status_twt_action(sdata, skb);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b0451f1c8e79..d1bb6353908d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1118,6 +1118,19 @@ ieee80211_ifcomb_check(const struct ieee80211_iface_combination *c, int n_comb)
return true;
}
+static void ieee80211_create_default_chandef(struct cfg80211_chan_def *chandef,
+ struct ieee80211_channel *chan)
+{
+ *chandef = (struct cfg80211_chan_def) {
+ .chan = chan,
+ .width = chan->band == NL80211_BAND_S1GHZ ?
+ NL80211_CHAN_WIDTH_1 :
+ NL80211_CHAN_WIDTH_20_NOHT,
+ .center_freq1 = chan->center_freq,
+ .freq1_offset = chan->freq_offset,
+ };
+}
+
int ieee80211_register_hw(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
@@ -1261,9 +1274,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
/* if none found then use the first anyway */
if (i == sband->n_channels)
i = 0;
- cfg80211_chandef_create(&dflt_chandef,
- &sband->channels[i],
- NL80211_CHAN_NO_HT);
+ ieee80211_create_default_chandef(&dflt_chandef,
+ &sband->channels[i]);
/* init channel we're on */
local->monitor_chanreq.oper = dflt_chandef;
if (local->emulate_chanctx) {
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 28624e57aa49..6696c611dfa4 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2018 - 2025 Intel Corporation
+ * Copyright (C) 2018-2026 Intel Corporation
* Authors: Luis Carlos Cobo <luisca@cozybit.com>
* Javier Cardona <javier@cozybit.com>
*/
@@ -19,8 +19,7 @@ static struct kmem_cache *rm_cache;
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
{
- return (mgmt->u.action.u.mesh_action.action_code ==
- WLAN_MESH_ACTION_HWMP_PATH_SELECTION);
+ return mgmt->u.action.action_code == WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
}
void ieee80211s_init(void)
@@ -1618,13 +1617,12 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
size_t baselen;
u8 *pos;
- if (mgmt->u.action.u.measurement.action_code !=
- WLAN_ACTION_SPCT_CHL_SWITCH)
+ if (mgmt->u.action.action_code != WLAN_ACTION_SPCT_CHL_SWITCH)
return;
- pos = mgmt->u.action.u.chan_switch.variable;
+ pos = mgmt->u.action.chan_switch.variable;
baselen = offsetof(struct ieee80211_mgmt,
- u.action.u.chan_switch.variable);
+ u.action.chan_switch.variable);
elems = ieee802_11_parse_elems(pos, len - baselen,
IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION,
@@ -1670,7 +1668,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
{
switch (mgmt->u.action.category) {
case WLAN_CATEGORY_SELF_PROTECTED:
- switch (mgmt->u.action.u.self_prot.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_SP_MESH_PEERING_OPEN:
case WLAN_SP_MESH_PEERING_CLOSE:
case WLAN_SP_MESH_PEERING_CONFIRM:
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 98d5aaa36d00..9d89ebcce1c1 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2019, 2021-2023, 2025 Intel Corporation
+ * Copyright (C) 2019, 2021-2023, 2025-2026 Intel Corporation
* Author: Luis Carlos Cobo <luisca@cozybit.com>
*/
@@ -105,12 +105,11 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
u32 lifetime, u32 metric, u32 preq_id,
struct ieee80211_sub_if_data *sdata)
{
+ int hdr_len = IEEE80211_MIN_ACTION_SIZE(mesh_action);
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos, ie_len;
- int hdr_len = offsetofend(struct ieee80211_mgmt,
- u.action.u.mesh_action);
skb = dev_alloc_skb(local->tx_headroom +
hdr_len +
@@ -127,8 +126,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
/* BSSID == SA */
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
- mgmt->u.action.u.mesh_action.action_code =
- WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
+ mgmt->u.action.action_code = WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
switch (action) {
case MPATH_PREQ:
@@ -237,13 +235,12 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
u8 ttl, const u8 *target, u32 target_sn,
u16 target_rcode, const u8 *ra)
{
+ int hdr_len = IEEE80211_MIN_ACTION_SIZE(mesh_action);
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_mgmt *mgmt;
u8 *pos, ie_len;
- int hdr_len = offsetofend(struct ieee80211_mgmt,
- u.action.u.mesh_action);
if (time_before(jiffies, ifmsh->next_perr))
return -EAGAIN;
@@ -265,8 +262,7 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
/* BSSID == SA */
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
- mgmt->u.action.u.mesh_action.action_code =
- WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
+ mgmt->u.action.action_code = WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
ie_len = 15;
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_PERR;
@@ -938,7 +934,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
/* need action_code */
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ if (len < IEEE80211_MIN_ACTION_SIZE(mesh_action))
return;
rcu_read_lock();
@@ -949,8 +945,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
}
rcu_read_unlock();
- baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
- elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
+ baselen = mgmt->u.action.mesh_action.variable - (u8 *)mgmt;
+ elems = ieee802_11_parse_elems(mgmt->u.action.mesh_action.variable,
len - baselen,
IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION,
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 04c931cd2063..7d823a55636f 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2019, 2021-2025 Intel Corporation
+ * Copyright (C) 2019, 2021-2026 Intel Corporation
* Author: Luis Carlos Cobo <luisca@cozybit.com>
*/
#include <linux/gfp.h>
@@ -13,7 +13,7 @@
#include "rate.h"
#include "mesh.h"
-#define PLINK_CNF_AID(mgmt) ((mgmt)->u.action.u.self_prot.variable + 2)
+#define PLINK_CNF_AID(mgmt) ((mgmt)->u.action.self_prot.variable + 2)
#define PLINK_GET_LLID(p) (p + 2)
#define PLINK_GET_PLID(p) (p + 4)
@@ -215,6 +215,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
enum ieee80211_self_protected_actioncode action,
u8 *da, u16 llid, u16 plid, u16 reason)
{
+ int hdr_len = IEEE80211_MIN_ACTION_SIZE(self_prot);
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
@@ -223,7 +224,6 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
u16 peering_proto = 0;
u8 *pos, ie_len = 4;
u8 ie_len_he_cap, ie_len_eht_cap;
- int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot);
int err = -ENOMEM;
ie_len_he_cap = ieee80211_ie_len_he_cap(sdata);
@@ -260,7 +260,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
- mgmt->u.action.u.self_prot.action_code = action;
+ mgmt->u.action.action_code = action;
if (action != WLAN_SP_MESH_PEERING_CLOSE) {
struct ieee80211_supported_band *sband;
@@ -1141,7 +1141,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
return;
}
- ftype = mgmt->u.action.u.self_prot.action_code;
+ ftype = mgmt->u.action.action_code;
if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
(ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
(ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
@@ -1224,8 +1224,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
size_t baselen;
u8 *baseaddr;
- /* need action_code, aux */
- if (len < IEEE80211_MIN_ACTION_SIZE + 3)
+ /* need aux */
+ if (len < IEEE80211_MIN_ACTION_SIZE(self_prot) + 1)
return;
if (sdata->u.mesh.user_mpm)
@@ -1238,10 +1238,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
return;
}
- baseaddr = mgmt->u.action.u.self_prot.variable;
- baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
- if (mgmt->u.action.u.self_prot.action_code ==
- WLAN_SP_MESH_PEERING_CONFIRM) {
+ baseaddr = mgmt->u.action.self_prot.variable;
+ baselen = mgmt->u.action.self_prot.variable - (u8 *)mgmt;
+ if (mgmt->u.action.action_code == WLAN_SP_MESH_PEERING_CONFIRM) {
baseaddr += 4;
baselen += 4;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 170330d924a3..0cd8d07bf668 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -216,6 +216,24 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
return IEEE80211_CONN_MODE_LEGACY;
}
+ if (eht_oper && ieee80211_hw_check(&sdata->local->hw, STRICT)) {
+ struct cfg80211_chan_def he_chandef = *chandef;
+
+ if (!ieee80211_chandef_he_6ghz_oper(sdata->local,
+ he_oper, NULL,
+ &he_chandef)) {
+ sdata_info(sdata,
+ "bad HE operation in EHT AP\n");
+ return IEEE80211_CONN_MODE_LEGACY;
+ }
+
+ if (!cfg80211_chandef_compatible(chandef,
+ &he_chandef)) {
+ sdata_info(sdata, "HE/EHT incompatible\n");
+ return IEEE80211_CONN_MODE_LEGACY;
+ }
+ }
+
if (mode <= IEEE80211_CONN_MODE_EHT)
return mode;
goto check_uhr;
@@ -6721,7 +6739,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
sdata_info(sdata,
"RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n",
reassoc ? "Rea" : "A", assoc_data->ap_addr,
- capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
+ capab_info, status_code, aid);
ifmgd->broken_ap = false;
@@ -7058,6 +7076,7 @@ static void ieee80211_ml_reconf_work(struct wiphy *wiphy,
container_of(work, struct ieee80211_sub_if_data,
u.mgd.ml_reconf_work.work);
u16 new_valid_links, new_active_links, new_dormant_links;
+ struct sta_info *sta;
int ret;
if (!sdata->u.mgd.removed_links)
@@ -7093,6 +7112,16 @@ static void ieee80211_ml_reconf_work(struct wiphy *wiphy,
}
}
+ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
+ if (sta) {
+ unsigned long removed_links = sdata->u.mgd.removed_links;
+ unsigned int link_id;
+
+ for_each_set_bit(link_id, &removed_links,
+ IEEE80211_MLD_MAX_NUM_LINKS)
+ ieee80211_sta_remove_link(sta, link_id);
+ }
+
new_dormant_links = sdata->vif.dormant_links & ~sdata->u.mgd.removed_links;
ret = ieee80211_vif_set_links(sdata, new_valid_links,
@@ -7957,7 +7986,7 @@ ieee80211_send_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
struct sk_buff *skb;
- int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.ttlm_req);
+ int hdr_len = IEEE80211_MIN_ACTION_SIZE(ttlm_req);
int ttlm_max_len = 2 + 1 + sizeof(struct ieee80211_ttlm_elem) + 1 +
2 * 2 * IEEE80211_TTLM_NUM_TIDS;
@@ -7974,9 +8003,8 @@ ieee80211_send_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
- mgmt->u.action.u.ttlm_req.action_code =
- WLAN_PROTECTED_EHT_ACTION_TTLM_REQ;
- mgmt->u.action.u.ttlm_req.dialog_token = dialog_token;
+ mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_TTLM_REQ;
+ mgmt->u.action.ttlm_req.dialog_token = dialog_token;
ieee80211_neg_ttlm_add_suggested_map(skb, neg_ttlm);
ieee80211_tx_skb(sdata, skb);
}
@@ -8026,7 +8054,7 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
struct sk_buff *skb;
- int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.ttlm_res);
+ int hdr_len = IEEE80211_MIN_ACTION_SIZE(ttlm_res);
int ttlm_max_len = 2 + 1 + sizeof(struct ieee80211_ttlm_elem) + 1 +
2 * 2 * IEEE80211_TTLM_NUM_TIDS;
u16 status_code;
@@ -8044,9 +8072,8 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
- mgmt->u.action.u.ttlm_res.action_code =
- WLAN_PROTECTED_EHT_ACTION_TTLM_RES;
- mgmt->u.action.u.ttlm_res.dialog_token = dialog_token;
+ mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_TTLM_RES;
+ mgmt->u.action.ttlm_res.dialog_token = dialog_token;
switch (ttlm_res) {
default:
WARN_ON(1);
@@ -8063,7 +8090,7 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
break;
}
- mgmt->u.action.u.ttlm_res.status_code = cpu_to_le16(status_code);
+ mgmt->u.action.ttlm_res.status_code = cpu_to_le16(status_code);
ieee80211_tx_skb(sdata, skb);
}
@@ -8163,10 +8190,9 @@ void ieee80211_process_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
if (!ieee80211_vif_is_mld(&sdata->vif))
return;
- dialog_token = mgmt->u.action.u.ttlm_req.dialog_token;
- ies_len = len - offsetof(struct ieee80211_mgmt,
- u.action.u.ttlm_req.variable);
- elems = ieee802_11_parse_elems(mgmt->u.action.u.ttlm_req.variable,
+ dialog_token = mgmt->u.action.ttlm_req.dialog_token;
+ ies_len = len - IEEE80211_MIN_ACTION_SIZE(ttlm_req);
+ elems = ieee802_11_parse_elems(mgmt->u.action.ttlm_req.variable,
ies_len,
IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION,
@@ -8217,8 +8243,7 @@ void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len)
{
if (!ieee80211_vif_is_mld(&sdata->vif) ||
- mgmt->u.action.u.ttlm_req.dialog_token !=
- sdata->u.mgd.dialog_token_alloc)
+ mgmt->u.action.ttlm_res.dialog_token != sdata->u.mgd.dialog_token_alloc)
return;
wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
@@ -8232,7 +8257,7 @@ void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
* This can be better implemented in the future, to handle request
* rejections.
*/
- if (le16_to_cpu(mgmt->u.action.u.ttlm_res.status_code) != WLAN_STATUS_SUCCESS)
+ if (le16_to_cpu(mgmt->u.action.ttlm_res.status_code) != WLAN_STATUS_SUCCESS)
__ieee80211_disconnect(sdata);
}
@@ -8265,12 +8290,11 @@ static void ieee80211_teardown_ttlm_work(struct wiphy *wiphy,
void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif)
{
+ int frame_len = IEEE80211_MIN_ACTION_SIZE(ttlm_tear_down);
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
struct sk_buff *skb;
- int frame_len = offsetofend(struct ieee80211_mgmt,
- u.action.u.ttlm_tear_down);
struct ieee80211_tx_info *info;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + frame_len);
@@ -8286,8 +8310,7 @@ void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif)
memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
- mgmt->u.action.u.ttlm_tear_down.action_code =
- WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN;
+ mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN;
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
@@ -8370,13 +8393,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
case WLAN_CATEGORY_SPECTRUM_MGMT:
ies_len = skb->len -
offsetof(struct ieee80211_mgmt,
- u.action.u.chan_switch.variable);
+ u.action.chan_switch.variable);
if (ies_len < 0)
break;
/* CSA IE cannot be overridden, no need for BSSID */
- elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable,
+ elems = ieee802_11_parse_elems(mgmt->u.action.chan_switch.variable,
ies_len,
IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION,
@@ -8398,7 +8421,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
case WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION:
ies_len = skb->len -
offsetof(struct ieee80211_mgmt,
- u.action.u.ext_chan_switch.variable);
+ u.action.ext_chan_switch.variable);
if (ies_len < 0)
break;
@@ -8407,7 +8430,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
* extended CSA IE can't be overridden, no need for
* BSSID
*/
- elems = ieee802_11_parse_elems(mgmt->u.action.u.ext_chan_switch.variable,
+ elems = ieee802_11_parse_elems(mgmt->u.action.ext_chan_switch.variable,
ies_len,
IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION,
@@ -8424,7 +8447,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
/* for the handling code pretend it was an IE */
elems->ext_chansw_ie =
- &mgmt->u.action.u.ext_chan_switch.data;
+ &mgmt->u.action.ext_chan_switch.data;
ieee80211_sta_process_chanswitch(link,
rx_status->mactime,
@@ -10426,25 +10449,25 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
u8 *pos;
if (!ieee80211_vif_is_mld(&sdata->vif) ||
- len < offsetofend(typeof(*mgmt), u.action.u.ml_reconf_resp) ||
- mgmt->u.action.u.ml_reconf_resp.dialog_token !=
- sdata->u.mgd.reconf.dialog_token ||
+ len < IEEE80211_MIN_ACTION_SIZE(ml_reconf_resp) ||
+ mgmt->u.action.ml_reconf_resp.dialog_token !=
+ sdata->u.mgd.reconf.dialog_token ||
!sta_changed_links)
return;
- pos = mgmt->u.action.u.ml_reconf_resp.variable;
- len -= offsetofend(typeof(*mgmt), u.action.u.ml_reconf_resp);
+ pos = mgmt->u.action.ml_reconf_resp.variable;
+ len -= offsetofend(typeof(*mgmt), u.action.ml_reconf_resp);
/* each status duple is 3 octets */
- if (len < mgmt->u.action.u.ml_reconf_resp.count * 3) {
+ if (len < mgmt->u.action.ml_reconf_resp.count * 3) {
sdata_info(sdata,
"mlo: reconf: unexpected len=%zu, count=%u\n",
- len, mgmt->u.action.u.ml_reconf_resp.count);
+ len, mgmt->u.action.ml_reconf_resp.count);
goto disconnect;
}
link_mask = sta_changed_links;
- for (i = 0; i < mgmt->u.action.u.ml_reconf_resp.count; i++) {
+ for (i = 0; i < mgmt->u.action.ml_reconf_resp.count; i++) {
u16 status = get_unaligned_le16(pos + 1);
link_id = *pos;
@@ -10729,8 +10752,7 @@ ieee80211_build_ml_reconf_req(struct ieee80211_sub_if_data *sdata,
return NULL;
skb_reserve(skb, local->hw.extra_tx_headroom);
- mgmt = skb_put_zero(skb, offsetofend(struct ieee80211_mgmt,
- u.action.u.ml_reconf_req));
+ mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(ml_reconf_req));
/* Add the MAC header */
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -10741,12 +10763,11 @@ ieee80211_build_ml_reconf_req(struct ieee80211_sub_if_data *sdata,
/* Add the action frame fixed fields */
mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
- mgmt->u.action.u.ml_reconf_req.action_code =
- WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_REQ;
+ mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_REQ;
/* allocate a dialog token and store it */
sdata->u.mgd.reconf.dialog_token = ++sdata->u.mgd.dialog_token_alloc;
- mgmt->u.action.u.ml_reconf_req.dialog_token =
+ mgmt->u.action.ml_reconf_req.dialog_token =
sdata->u.mgd.reconf.dialog_token;
/* Add the ML reconfiguration element and the common information */
@@ -11116,11 +11137,10 @@ static bool ieee80211_mgd_epcs_supp(struct ieee80211_sub_if_data *sdata)
int ieee80211_mgd_set_epcs(struct ieee80211_sub_if_data *sdata, bool enable)
{
+ int frame_len = IEEE80211_MIN_ACTION_SIZE(epcs) + (enable ? 1 : 0);
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
struct sk_buff *skb;
- int frame_len = offsetofend(struct ieee80211_mgmt,
- u.action.u.epcs) + (enable ? 1 : 0);
if (!ieee80211_mgd_epcs_supp(sdata))
return -EINVAL;
@@ -11149,15 +11169,15 @@ int ieee80211_mgd_set_epcs(struct ieee80211_sub_if_data *sdata, bool enable)
mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
if (enable) {
- u8 *pos = mgmt->u.action.u.epcs.variable;
+ u8 *pos = mgmt->u.action.epcs.variable;
- mgmt->u.action.u.epcs.action_code =
+ mgmt->u.action.action_code =
WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_REQ;
*pos = ++sdata->u.mgd.dialog_token_alloc;
sdata->u.mgd.epcs.dialog_token = *pos;
} else {
- mgmt->u.action.u.epcs.action_code =
+ mgmt->u.action.action_code =
WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_TEARDOWN;
ieee80211_epcs_teardown(sdata);
@@ -11246,7 +11266,7 @@ void ieee80211_process_epcs_ena_resp(struct ieee80211_sub_if_data *sdata,
return;
/* Handle dialog token and status code */
- pos = mgmt->u.action.u.epcs.variable;
+ pos = mgmt->u.action.epcs.variable;
dialog_token = *pos;
status_code = get_unaligned_le16(pos + 1);
@@ -11268,8 +11288,7 @@ void ieee80211_process_epcs_ena_resp(struct ieee80211_sub_if_data *sdata,
return;
pos += IEEE80211_EPCS_ENA_RESP_BODY_LEN;
- ies_len = len - offsetof(struct ieee80211_mgmt,
- u.action.u.epcs.variable) -
+ ies_len = len - IEEE80211_MIN_ACTION_SIZE(epcs) -
IEEE80211_EPCS_ENA_RESP_BODY_LEN;
elems = ieee802_11_parse_elems(pos, ies_len,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6c4b549444c6..19c33f7a8193 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -274,7 +274,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
if (!sdata)
return;
- BUILD_BUG_ON(sizeof(action) != IEEE80211_MIN_ACTION_SIZE + 1);
+ BUILD_BUG_ON(sizeof(action) != IEEE80211_MIN_ACTION_SIZE(action_code));
if (skb->len < rtap_space + sizeof(action) +
VHT_MUMIMO_GROUPS_DATA_LEN)
@@ -1162,7 +1162,7 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
u8 category;
/* make sure category field is present */
- if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE(category))
return RX_DROP_U_RUNT_ACTION;
mgmt = (struct ieee80211_mgmt *)hdr;
@@ -1475,7 +1475,9 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
!test_and_set_bit(tid, rx->sta->ampdu_mlme.unexpected_agg))
ieee80211_send_delba(rx->sdata, rx->sta->sta.addr, tid,
WLAN_BACK_RECIPIENT,
- WLAN_REASON_QSTA_REQUIRE_SETUP);
+ WLAN_REASON_QSTA_REQUIRE_SETUP,
+ ieee80211_s1g_use_ndp_ba(rx->sdata,
+ rx->sta));
goto dont_reorder;
}
@@ -3372,7 +3374,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
!test_and_set_bit(tid, rx->sta->ampdu_mlme.unexpected_agg))
ieee80211_send_delba(rx->sdata, rx->sta->sta.addr, tid,
WLAN_BACK_RECIPIENT,
- WLAN_REASON_QSTA_REQUIRE_SETUP);
+ WLAN_REASON_QSTA_REQUIRE_SETUP,
+ ieee80211_s1g_use_ndp_ba(rx->sdata,
+ rx->sta));
tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]);
if (!tid_agg_rx)
@@ -3422,7 +3426,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
return;
}
- if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) {
+ if (len < IEEE80211_MIN_ACTION_SIZE(sa_query)) {
/* Too short SA Query request frame */
return;
}
@@ -3432,17 +3436,16 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- resp = skb_put_zero(skb, 24);
+ resp = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(sa_query));
memcpy(resp->da, sdata->vif.cfg.ap_addr, ETH_ALEN);
memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
memcpy(resp->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
- skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));
resp->u.action.category = WLAN_CATEGORY_SA_QUERY;
- resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE;
- memcpy(resp->u.action.u.sa_query.trans_id,
- mgmt->u.action.u.sa_query.trans_id,
+ resp->u.action.action_code = WLAN_ACTION_SA_QUERY_RESPONSE;
+ memcpy(resp->u.action.sa_query.trans_id,
+ mgmt->u.action.sa_query.trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
ieee80211_tx_skb(sdata, skb);
@@ -3516,7 +3519,7 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
/* drop too small action frames */
if (ieee80211_is_action(mgmt->frame_control) &&
- rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+ rx->skb->len < IEEE80211_MIN_ACTION_SIZE(category))
return RX_DROP_U_RUNT_ACTION;
/* Drop non-broadcast Beacon frames */
@@ -3565,29 +3568,28 @@ ieee80211_process_rx_twt_action(struct ieee80211_rx_data *rx)
if (!rx->sta)
return false;
- switch (mgmt->u.action.u.s1g.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_S1G_TWT_SETUP: {
struct ieee80211_twt_setup *twt;
- if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE +
- 1 + /* action code */
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE(action_code) +
sizeof(struct ieee80211_twt_setup) +
2 /* TWT req_type agrt */)
break;
- twt = (void *)mgmt->u.action.u.s1g.variable;
+ twt = (void *)mgmt->u.action.s1g.variable;
if (twt->element_id != WLAN_EID_S1G_TWT)
break;
- if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE +
- 4 + /* action code + token + tlv */
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE(action_code) +
+ 3 + /* token + tlv */
twt->length)
break;
return true; /* queue the frame */
}
case WLAN_S1G_TWT_TEARDOWN:
- if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + 2)
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE(action_code) + 1)
break;
return true; /* queue the frame */
@@ -3632,10 +3634,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
/* verify action & smps_control/chanwidth are present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 2)
+ if (len < IEEE80211_MIN_ACTION_SIZE(ht_smps))
goto invalid;
- switch (mgmt->u.action.u.ht_smps.action) {
+ switch (mgmt->u.action.action_code) {
case WLAN_HT_ACTION_SMPS: {
struct ieee80211_supported_band *sband;
enum ieee80211_smps_mode smps_mode;
@@ -3646,7 +3648,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto handled;
/* convert to HT capability */
- switch (mgmt->u.action.u.ht_smps.smps_control) {
+ switch (mgmt->u.action.ht_smps.smps_control) {
case WLAN_HT_SMPS_CONTROL_DISABLED:
smps_mode = IEEE80211_SMPS_OFF;
break;
@@ -3679,7 +3681,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto handled;
}
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
- u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
+ u8 chanwidth = mgmt->u.action.ht_notify_cw.chanwidth;
if (chanwidth != IEEE80211_HT_CHANWIDTH_20MHZ &&
chanwidth != IEEE80211_HT_CHANWIDTH_ANY)
@@ -3699,7 +3701,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
case WLAN_CATEGORY_PUBLIC:
case WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION:
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
goto invalid;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
@@ -3707,11 +3709,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
if (!ether_addr_equal(mgmt->bssid, sdata->deflink.u.mgd.bssid))
break;
- if (mgmt->u.action.u.ext_chan_switch.action_code !=
+ if (mgmt->u.action.action_code !=
WLAN_PUB_ACTION_EXT_CHANSW_ANN)
break;
- if (len < offsetof(struct ieee80211_mgmt,
- u.action.u.ext_chan_switch.variable))
+ if (len < IEEE80211_MIN_ACTION_SIZE(ext_chan_switch))
goto invalid;
goto queue;
case WLAN_CATEGORY_VHT:
@@ -3723,18 +3724,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
/* verify action code is present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
goto invalid;
- switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
/* verify opmode is present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 2)
+ if (len < IEEE80211_MIN_ACTION_SIZE(vht_opmode_notif))
goto invalid;
goto queue;
}
case WLAN_VHT_ACTION_GROUPID_MGMT: {
- if (len < IEEE80211_MIN_ACTION_SIZE + 25)
+ if (len < IEEE80211_MIN_ACTION_SIZE(vht_group_notif))
goto invalid;
goto queue;
}
@@ -3751,23 +3752,23 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
/* verify action_code is present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
break;
- switch (mgmt->u.action.u.addba_req.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_ACTION_ADDBA_REQ:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.addba_req)))
+ case WLAN_ACTION_NDP_ADDBA_REQ:
+ if (len < IEEE80211_MIN_ACTION_SIZE(addba_req))
goto invalid;
break;
case WLAN_ACTION_ADDBA_RESP:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.addba_resp)))
+ case WLAN_ACTION_NDP_ADDBA_RESP:
+ if (len < IEEE80211_MIN_ACTION_SIZE(addba_resp))
goto invalid;
break;
case WLAN_ACTION_DELBA:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.delba)))
+ case WLAN_ACTION_NDP_DELBA:
+ if (len < IEEE80211_MIN_ACTION_SIZE(delba))
goto invalid;
break;
default:
@@ -3777,16 +3778,15 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto queue;
case WLAN_CATEGORY_SPECTRUM_MGMT:
/* verify action_code is present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
break;
- switch (mgmt->u.action.u.measurement.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_ACTION_SPCT_MSR_REQ:
if (status->band != NL80211_BAND_5GHZ)
break;
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.measurement)))
+ if (len < IEEE80211_MIN_ACTION_SIZE(measurement))
break;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
@@ -3796,8 +3796,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto handled;
case WLAN_ACTION_SPCT_CHL_SWITCH: {
u8 *bssid;
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.chan_switch)))
+ if (len < IEEE80211_MIN_ACTION_SIZE(chan_switch))
break;
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
@@ -3822,11 +3821,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
}
break;
case WLAN_CATEGORY_SELF_PROTECTED:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.self_prot.action_code)))
+ if (len < IEEE80211_MIN_ACTION_SIZE(self_prot))
break;
- switch (mgmt->u.action.u.self_prot.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_SP_MESH_PEERING_OPEN:
case WLAN_SP_MESH_PEERING_CLOSE:
case WLAN_SP_MESH_PEERING_CONFIRM:
@@ -3844,8 +3842,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
}
break;
case WLAN_CATEGORY_MESH_ACTION:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.mesh_action.action_code)))
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
break;
if (!ieee80211_vif_is_mesh(&sdata->vif))
@@ -3855,11 +3852,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
goto queue;
case WLAN_CATEGORY_S1G:
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.s1g.action_code))
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
break;
- switch (mgmt->u.action.u.s1g.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_S1G_TWT_SETUP:
case WLAN_S1G_TWT_TEARDOWN:
if (ieee80211_process_rx_twt_action(rx))
@@ -3870,33 +3866,29 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
}
break;
case WLAN_CATEGORY_PROTECTED_EHT:
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.ttlm_req.action_code))
+ if (len < IEEE80211_MIN_ACTION_SIZE(action_code))
break;
- switch (mgmt->u.action.u.ttlm_req.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.ttlm_req))
+ if (len < IEEE80211_MIN_ACTION_SIZE(ttlm_req))
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_TTLM_RES:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.ttlm_res))
+ if (len < IEEE80211_MIN_ACTION_SIZE(ttlm_res))
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.ttlm_tear_down))
+ if (len < IEEE80211_MIN_ACTION_SIZE(ttlm_tear_down))
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_RESP:
@@ -3906,34 +3898,29 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
/* The reconfiguration response action frame must
* least one 'Status Duple' entry (3 octets)
*/
- if (len <
- offsetofend(typeof(*mgmt),
- u.action.u.ml_reconf_resp) + 3)
+ if (len < IEEE80211_MIN_ACTION_SIZE(ml_reconf_resp) + 3)
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_RESP:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.epcs) +
- IEEE80211_EPCS_ENA_RESP_BODY_LEN)
+ if (len < IEEE80211_MIN_ACTION_SIZE(epcs) +
+ IEEE80211_EPCS_ENA_RESP_BODY_LEN)
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_TEARDOWN:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.epcs))
+ if (len < IEEE80211_MIN_ACTION_SIZE(epcs))
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF:
if (sdata->vif.type != NL80211_IFTYPE_AP)
break;
- if (len < offsetofend(typeof(*mgmt),
- u.action.u.eml_omn))
+ if (len < IEEE80211_MIN_ACTION_SIZE(eml_omn))
goto invalid;
goto queue;
default:
@@ -4015,11 +4002,10 @@ ieee80211_rx_h_action_post_userspace(struct ieee80211_rx_data *rx)
switch (mgmt->u.action.category) {
case WLAN_CATEGORY_SA_QUERY:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.sa_query)))
+ if (len < IEEE80211_MIN_ACTION_SIZE(sa_query))
break;
- switch (mgmt->u.action.u.sa_query.action) {
+ switch (mgmt->u.action.action_code) {
case WLAN_ACTION_SA_QUERY_REQUEST:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
diff --git a/net/mac80211/s1g.c b/net/mac80211/s1g.c
index 1f68df6e8067..5af4a0c6c642 100644
--- a/net/mac80211/s1g.c
+++ b/net/mac80211/s1g.c
@@ -2,7 +2,7 @@
/*
* S1G handling
* Copyright(c) 2020 Adapt-IP
- * Copyright (C) 2023 Intel Corporation
+ * Copyright (C) 2023, 2026 Intel Corporation
*/
#include <linux/ieee80211.h>
#include <net/mac80211.h>
@@ -27,14 +27,14 @@ bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb)
if (likely(mgmt->u.action.category != WLAN_CATEGORY_S1G))
return false;
- return mgmt->u.action.u.s1g.action_code == WLAN_S1G_TWT_SETUP;
+ return mgmt->u.action.action_code == WLAN_S1G_TWT_SETUP;
}
static void
ieee80211_s1g_send_twt_setup(struct ieee80211_sub_if_data *sdata, const u8 *da,
const u8 *bssid, struct ieee80211_twt_setup *twt)
{
- int len = IEEE80211_MIN_ACTION_SIZE + 4 + twt->length;
+ int len = IEEE80211_MIN_ACTION_SIZE(s1g) + 3 + twt->length;
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
struct sk_buff *skb;
@@ -52,8 +52,8 @@ ieee80211_s1g_send_twt_setup(struct ieee80211_sub_if_data *sdata, const u8 *da,
memcpy(mgmt->bssid, bssid, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_S1G;
- mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_SETUP;
- memcpy(mgmt->u.action.u.s1g.variable, twt, 3 + twt->length);
+ mgmt->u.action.action_code = WLAN_S1G_TWT_SETUP;
+ memcpy(mgmt->u.action.s1g.variable, twt, 3 + twt->length);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
IEEE80211_TX_INTFL_MLME_CONN_TX |
@@ -71,12 +71,12 @@ ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata,
u8 *id;
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
- IEEE80211_MIN_ACTION_SIZE + 2);
+ IEEE80211_MIN_ACTION_SIZE(s1g) + 1);
if (!skb)
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE + 2);
+ mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(s1g) + 1);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
memcpy(mgmt->da, da, ETH_ALEN);
@@ -84,8 +84,8 @@ ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->bssid, bssid, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_S1G;
- mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_TEARDOWN;
- id = (u8 *)mgmt->u.action.u.s1g.variable;
+ mgmt->u.action.action_code = WLAN_S1G_TWT_TEARDOWN;
+ id = (u8 *)mgmt->u.action.s1g.variable;
*id = flowid;
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
@@ -98,7 +98,7 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable;
+ struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.s1g.variable;
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST);
@@ -128,7 +128,7 @@ ieee80211_s1g_rx_twt_teardown(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
drv_twt_teardown_request(sdata->local, sdata, &sta->sta,
- mgmt->u.action.u.s1g.variable[0]);
+ mgmt->u.action.s1g.variable[0]);
}
static void
@@ -136,7 +136,7 @@ ieee80211_s1g_tx_twt_setup_fail(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable;
+ struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.s1g.variable;
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
u8 flowid = le16_get_bits(twt_agrt->req_type,
IEEE80211_TWT_REQTYPE_FLOWID);
@@ -160,7 +160,7 @@ void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata,
if (!sta)
return;
- switch (mgmt->u.action.u.s1g.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_S1G_TWT_SETUP:
ieee80211_s1g_rx_twt_setup(sdata, sta, skb);
break;
@@ -185,7 +185,7 @@ void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata,
if (!sta)
return;
- switch (mgmt->u.action.u.s1g.action_code) {
+ switch (mgmt->u.action.action_code) {
case WLAN_S1G_TWT_SETUP:
/* process failed twt setup frames */
ieee80211_s1g_tx_twt_setup_fail(sdata, sta, skb);
@@ -220,3 +220,11 @@ void ieee80211_s1g_cap_to_sta_s1g_cap(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_recalc_aggregates(&link_sta->sta->sta);
}
+
+bool ieee80211_s1g_use_ndp_ba(const struct ieee80211_sub_if_data *sdata,
+ const struct sta_info *sta)
+{
+ return sdata->vif.cfg.s1g &&
+ ieee80211_hw_check(&sdata->local->hw, SUPPORTS_NDP_BLOCKACK) &&
+ (sta && sta->sta.deflink.s1g_cap.s1g);
+}
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 7422888d3640..e2eaf8d8d7ff 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -9,7 +9,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2008, Intel Corporation
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright (C) 2018, 2020, 2022-2024 Intel Corporation
+ * Copyright (C) 2018, 2020, 2022-2024, 2026 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -409,35 +409,30 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da
struct sk_buff *skb;
struct ieee80211_mgmt *msr_report;
- skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom +
- sizeof(struct ieee80211_msrment_ie));
+ skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(measurement) +
+ local->hw.extra_tx_headroom);
if (!skb)
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- msr_report = skb_put_zero(skb, 24);
+ msr_report = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(measurement));
memcpy(msr_report->da, da, ETH_ALEN);
memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN);
memcpy(msr_report->bssid, bssid, ETH_ALEN);
msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
- skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement));
msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
- msr_report->u.action.u.measurement.action_code =
- WLAN_ACTION_SPCT_MSR_RPRT;
- msr_report->u.action.u.measurement.dialog_token = dialog_token;
+ msr_report->u.action.action_code = WLAN_ACTION_SPCT_MSR_RPRT;
- msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT;
- msr_report->u.action.u.measurement.length =
+ msr_report->u.action.measurement.dialog_token = dialog_token;
+ msr_report->u.action.measurement.element_id = WLAN_EID_MEASURE_REPORT;
+ msr_report->u.action.measurement.length =
sizeof(struct ieee80211_msrment_ie);
-
- memset(&msr_report->u.action.u.measurement.msr_elem, 0,
- sizeof(struct ieee80211_msrment_ie));
- msr_report->u.action.u.measurement.msr_elem.token = request_ie->token;
- msr_report->u.action.u.measurement.msr_elem.mode |=
+ msr_report->u.action.measurement.msr_elem.token = request_ie->token;
+ msr_report->u.action.measurement.msr_elem.mode |=
IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED;
- msr_report->u.action.u.measurement.msr_elem.type = request_ie->type;
+ msr_report->u.action.measurement.msr_elem.type = request_ie->type;
ieee80211_tx_skb(sdata, skb);
}
@@ -454,7 +449,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
* TODO: Answer basic measurement as unmeasured
*/
ieee80211_send_refuse_measurement_request(sdata,
- &mgmt->u.action.u.measurement.msr_elem,
+ &mgmt->u.action.measurement.msr_elem,
mgmt->sa, mgmt->bssid,
- mgmt->u.action.u.measurement.dialog_token);
+ mgmt->u.action.measurement.dialog_token);
}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2875ef7d7946..58ccbea7f6f6 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -171,6 +171,7 @@ struct sta_info;
* @bar_pending: BAR needs to be re-sent
* @amsdu: support A-MSDU within A-MDPU
* @ssn: starting sequence number of the session
+ * @ndp: this session is using NDP Block ACKs
*
* This structure's lifetime is managed by RCU, assignments to
* the array holding it must hold the aggregation mutex.
@@ -199,6 +200,7 @@ struct tid_ampdu_tx {
u16 failed_bar_ssn;
bool bar_pending;
bool amsdu;
+ bool ndp;
u8 tid;
};
@@ -510,7 +512,6 @@ struct ieee80211_fragment_cache {
* during finalize
* @debugfs_dir: debug filesystem directory dentry
* @pub: public (driver visible) link STA data
- * TODO Move other link params from sta_info as required for MLD operation
*/
struct link_sta_info {
u8 addr[ETH_ALEN];
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index dbbfe2d6842f..1f30a4eda374 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -6,7 +6,7 @@
* Copyright 2014, Intel Corporation
* Copyright 2014 Intel Mobile Communications GmbH
* Copyright 2015 - 2016 Intel Deutschland GmbH
- * Copyright (C) 2019, 2021-2025 Intel Corporation
+ * Copyright (C) 2019, 2021-2026 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -879,28 +879,23 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_mgmt *mgmt;
- mgmt = skb_put_zero(skb, 24);
+ if (action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES)
+ return -EINVAL;
+
+ mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(tdls_discover_resp));
memcpy(mgmt->da, peer, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
memcpy(mgmt->bssid, link->u.mgd.bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
- switch (action_code) {
- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
- mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
- mgmt->u.action.u.tdls_discover_resp.action_code =
- WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
- mgmt->u.action.u.tdls_discover_resp.dialog_token =
- dialog_token;
- mgmt->u.action.u.tdls_discover_resp.capability =
- cpu_to_le16(ieee80211_get_tdls_sta_capab(link,
- status_code));
- break;
- default:
- return -EINVAL;
- }
+ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+ mgmt->u.action.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+
+ mgmt->u.action.tdls_discover_resp.dialog_token = dialog_token;
+ mgmt->u.action.tdls_discover_resp.capability =
+ cpu_to_le16(ieee80211_get_tdls_sta_capab(link,
+ status_code));
return 0;
}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index c04d4547e8f4..1f0c07eaad1b 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 - 2024 Intel Corporation
+ * Copyright (C) 2018-2024, 2026 Intel Corporation
*/
#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
@@ -37,64 +37,46 @@
#define VIF_PR_FMT " vif:%s(%d%s)"
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
-#define CHANDEF_ENTRY __field(u32, control_freq) \
- __field(u32, freq_offset) \
- __field(u32, chan_width) \
- __field(u32, center_freq1) \
- __field(u32, freq1_offset) \
- __field(u32, center_freq2)
-#define CHANDEF_ASSIGN(c) \
- __entry->control_freq = (c) ? ((c)->chan ? (c)->chan->center_freq : 0) : 0; \
- __entry->freq_offset = (c) ? ((c)->chan ? (c)->chan->freq_offset : 0) : 0; \
- __entry->chan_width = (c) ? (c)->width : 0; \
- __entry->center_freq1 = (c) ? (c)->center_freq1 : 0; \
- __entry->freq1_offset = (c) ? (c)->freq1_offset : 0; \
- __entry->center_freq2 = (c) ? (c)->center_freq2 : 0;
-#define CHANDEF_PR_FMT " chandef(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz)"
-#define CHANDEF_PR_ARG __entry->control_freq, __entry->freq_offset, __entry->chan_width, \
- __entry->center_freq1, __entry->freq1_offset, __entry->center_freq2
-
-#define MIN_CHANDEF_ENTRY \
- __field(u32, min_control_freq) \
- __field(u32, min_freq_offset) \
- __field(u32, min_chan_width) \
- __field(u32, min_center_freq1) \
- __field(u32, min_freq1_offset) \
- __field(u32, min_center_freq2)
-
-#define MIN_CHANDEF_ASSIGN(c) \
- __entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
- __entry->min_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0; \
- __entry->min_chan_width = (c)->width; \
- __entry->min_center_freq1 = (c)->center_freq1; \
- __entry->min_freq1_offset = (c)->freq1_offset; \
- __entry->min_center_freq2 = (c)->center_freq2;
-#define MIN_CHANDEF_PR_FMT " mindef(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz)"
-#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_freq_offset, \
- __entry->min_chan_width, \
- __entry->min_center_freq1, __entry->min_freq1_offset, \
- __entry->min_center_freq2
-
-#define AP_CHANDEF_ENTRY \
- __field(u32, ap_control_freq) \
- __field(u32, ap_freq_offset) \
- __field(u32, ap_chan_width) \
- __field(u32, ap_center_freq1) \
- __field(u32, ap_freq1_offset) \
- __field(u32, ap_center_freq2)
-
-#define AP_CHANDEF_ASSIGN(c) \
- __entry->ap_control_freq = (c)->chan ? (c)->chan->center_freq : 0;\
- __entry->ap_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0;\
- __entry->ap_chan_width = (c)->chan ? (c)->width : 0; \
- __entry->ap_center_freq1 = (c)->chan ? (c)->center_freq1 : 0; \
- __entry->ap_freq1_offset = (c)->chan ? (c)->freq1_offset : 0; \
- __entry->ap_center_freq2 = (c)->chan ? (c)->center_freq2 : 0;
-#define AP_CHANDEF_PR_FMT " ap(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz)"
-#define AP_CHANDEF_PR_ARG __entry->ap_control_freq, __entry->ap_freq_offset, \
- __entry->ap_chan_width, \
- __entry->ap_center_freq1, __entry->ap_freq1_offset, \
- __entry->ap_center_freq2
+#define __CHANDEF_ENTRY(n) \
+ __field(u32, n##control_freq) \
+ __field(u32, n##freq_offset) \
+ __field(u32, n##chan_width) \
+ __field(u32, n##center_freq1) \
+ __field(u32, n##freq1_offset) \
+ __field(u32, n##center_freq2) \
+ __field(u16, n##punctured)
+#define __CHANDEF_ASSIGN(n, c) \
+ __entry->n##control_freq = (c) && (c)->chan ? \
+ (c)->chan->center_freq : 0; \
+ __entry->n##freq_offset = (c) && (c)->chan ? \
+ (c)->chan->freq_offset : 0; \
+ __entry->n##chan_width = (c) ? (c)->width : 0; \
+ __entry->n##center_freq1 = (c) ? (c)->center_freq1 : 0; \
+ __entry->n##freq1_offset = (c) ? (c)->freq1_offset : 0; \
+ __entry->n##center_freq2 = (c) ? (c)->center_freq2 : 0; \
+ __entry->n##punctured = (c) ? (c)->punctured : 0;
+#define __CHANDEF_PR_FMT(n) \
+ " " #n "(%d.%03d MHz,width:%d,center: %d.%03d/%d MHz, punct:0x%x)"
+#define __CHANDEF_PR_ARG(n) \
+ __entry->n##control_freq, __entry->n##freq_offset, \
+ __entry->n##chan_width, __entry->n##center_freq1, \
+ __entry->n##freq1_offset, __entry->n##center_freq2, \
+ __entry->n##punctured
+
+#define CHANDEF_ENTRY __CHANDEF_ENTRY()
+#define CHANDEF_ASSIGN(c) __CHANDEF_ASSIGN(, c)
+#define CHANDEF_PR_FMT __CHANDEF_PR_FMT(chandef)
+#define CHANDEF_PR_ARG __CHANDEF_PR_ARG()
+
+#define MIN_CHANDEF_ENTRY __CHANDEF_ENTRY(min)
+#define MIN_CHANDEF_ASSIGN(c) __CHANDEF_ASSIGN(min, c)
+#define MIN_CHANDEF_PR_FMT __CHANDEF_PR_FMT(mindef)
+#define MIN_CHANDEF_PR_ARG __CHANDEF_PR_ARG(min)
+
+#define AP_CHANDEF_ENTRY __CHANDEF_ENTRY(ap)
+#define AP_CHANDEF_ASSIGN(c) __CHANDEF_ASSIGN(ap, c)
+#define AP_CHANDEF_PR_FMT __CHANDEF_PR_FMT(ap)
+#define AP_CHANDEF_PR_ARG __CHANDEF_PR_ARG(ap)
#define CHANCTX_ENTRY CHANDEF_ENTRY \
MIN_CHANDEF_ENTRY \
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b2e6c8b98381..55054de62508 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3766,12 +3766,11 @@ again:
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings *csa_settings)
{
+ int hdr_len = IEEE80211_MIN_ACTION_SIZE(chan_switch);
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
struct ieee80211_local *local = sdata->local;
int freq;
- int hdr_len = offsetofend(struct ieee80211_mgmt,
- u.action.u.chan_switch);
u8 *pos;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
@@ -3800,7 +3799,7 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
}
mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
- mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
+ mgmt->u.action.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
pos = skb_put(skb, 5);
*pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */
*pos++ = 3; /* IE length */
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index b099d79e8fbb..80120f9f17b6 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -4,7 +4,7 @@
*
* Portions of this file
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2024 Intel Corporation
+ * Copyright (C) 2018-2026 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -723,17 +723,17 @@ void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
if (!link_conf->mu_mimo_owner)
return;
- if (!memcmp(mgmt->u.action.u.vht_group_notif.position,
+ if (!memcmp(mgmt->u.action.vht_group_notif.position,
link_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
- !memcmp(mgmt->u.action.u.vht_group_notif.membership,
+ !memcmp(mgmt->u.action.vht_group_notif.membership,
link_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
return;
memcpy(link_conf->mu_group.membership,
- mgmt->u.action.u.vht_group_notif.membership,
+ mgmt->u.action.vht_group_notif.membership,
WLAN_MEMBERSHIP_LEN);
memcpy(link_conf->mu_group.position,
- mgmt->u.action.u.vht_group_notif.position,
+ mgmt->u.action.vht_group_notif.position,
WLAN_USER_POSITION_LEN);
ieee80211_link_info_change_notify(sdata, link,
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index d9d4e043bb39..fa0764ede9c5 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -6,7 +6,7 @@
*
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
- * Copyright 2018-2025 Intel Corporation
+ * Copyright 2018-2026 Intel Corporation
*/
#include <linux/export.h>
@@ -29,9 +29,11 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
*chandef = (struct cfg80211_chan_def) {
.chan = chan,
- .freq1_offset = chan->freq_offset,
};
+ WARN_ON(chan->band == NL80211_BAND_60GHZ ||
+ chan->band == NL80211_BAND_S1GHZ);
+
switch (chan_type) {
case NL80211_CHAN_NO_HT:
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -339,6 +341,58 @@ static bool cfg80211_valid_center_freq(u32 center,
return (center - bw / 2 - 5945) % step == 0;
}
+static bool
+cfg80211_chandef_valid_control_freq(const struct cfg80211_chan_def *chandef,
+ u32 control_freq)
+{
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_1:
+ case NL80211_CHAN_WIDTH_2:
+ case NL80211_CHAN_WIDTH_4:
+ case NL80211_CHAN_WIDTH_8:
+ case NL80211_CHAN_WIDTH_16:
+ /* checked separately */
+ break;
+ case NL80211_CHAN_WIDTH_320:
+ if (chandef->center_freq1 == control_freq + 150 ||
+ chandef->center_freq1 == control_freq + 130 ||
+ chandef->center_freq1 == control_freq + 110 ||
+ chandef->center_freq1 == control_freq + 90 ||
+ chandef->center_freq1 == control_freq - 90 ||
+ chandef->center_freq1 == control_freq - 110 ||
+ chandef->center_freq1 == control_freq - 130 ||
+ chandef->center_freq1 == control_freq - 150)
+ break;
+ fallthrough;
+ case NL80211_CHAN_WIDTH_160:
+ if (chandef->center_freq1 == control_freq + 70 ||
+ chandef->center_freq1 == control_freq + 50 ||
+ chandef->center_freq1 == control_freq - 50 ||
+ chandef->center_freq1 == control_freq - 70)
+ break;
+ fallthrough;
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_80:
+ if (chandef->center_freq1 == control_freq + 30 ||
+ chandef->center_freq1 == control_freq - 30)
+ break;
+ fallthrough;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 == control_freq + 10 ||
+ chandef->center_freq1 == control_freq - 10)
+ break;
+ fallthrough;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
{
u32 control_freq, control_freq_khz, start_khz, end_khz;
@@ -351,6 +405,14 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
control_freq = chandef->chan->center_freq;
+ if (cfg80211_chandef_is_s1g(chandef) &&
+ chandef->width != NL80211_CHAN_WIDTH_1 &&
+ chandef->width != NL80211_CHAN_WIDTH_2 &&
+ chandef->width != NL80211_CHAN_WIDTH_4 &&
+ chandef->width != NL80211_CHAN_WIDTH_8 &&
+ chandef->width != NL80211_CHAN_WIDTH_16)
+ return false;
+
switch (chandef->width) {
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
@@ -393,50 +455,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
break;
}
- switch (chandef->width) {
- case NL80211_CHAN_WIDTH_5:
- case NL80211_CHAN_WIDTH_10:
- case NL80211_CHAN_WIDTH_20:
- case NL80211_CHAN_WIDTH_20_NOHT:
- case NL80211_CHAN_WIDTH_1:
- case NL80211_CHAN_WIDTH_2:
- case NL80211_CHAN_WIDTH_4:
- case NL80211_CHAN_WIDTH_8:
- case NL80211_CHAN_WIDTH_16:
- /* all checked above */
- break;
- case NL80211_CHAN_WIDTH_320:
- if (chandef->center_freq1 == control_freq + 150 ||
- chandef->center_freq1 == control_freq + 130 ||
- chandef->center_freq1 == control_freq + 110 ||
- chandef->center_freq1 == control_freq + 90 ||
- chandef->center_freq1 == control_freq - 90 ||
- chandef->center_freq1 == control_freq - 110 ||
- chandef->center_freq1 == control_freq - 130 ||
- chandef->center_freq1 == control_freq - 150)
- break;
- fallthrough;
- case NL80211_CHAN_WIDTH_160:
- if (chandef->center_freq1 == control_freq + 70 ||
- chandef->center_freq1 == control_freq + 50 ||
- chandef->center_freq1 == control_freq - 50 ||
- chandef->center_freq1 == control_freq - 70)
- break;
- fallthrough;
- case NL80211_CHAN_WIDTH_80P80:
- case NL80211_CHAN_WIDTH_80:
- if (chandef->center_freq1 == control_freq + 30 ||
- chandef->center_freq1 == control_freq - 30)
- break;
- fallthrough;
- case NL80211_CHAN_WIDTH_40:
- if (chandef->center_freq1 == control_freq + 10 ||
- chandef->center_freq1 == control_freq - 10)
- break;
- fallthrough;
- default:
+ if (!cfg80211_chandef_valid_control_freq(chandef, control_freq))
return false;
- }
if (!cfg80211_valid_center_freq(chandef->center_freq1, chandef->width))
return false;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2225f5d0b124..e15cd26f3a79 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -339,7 +339,20 @@ static int validate_uhr_capa(const struct nlattr *attr,
const u8 *data = nla_data(attr);
unsigned int len = nla_len(attr);
- return ieee80211_uhr_capa_size_ok(data, len, false);
+ if (!ieee80211_uhr_capa_size_ok(data, len, false))
+ return -EINVAL;
+ return 0;
+}
+
+static int validate_uhr_operation(const struct nlattr *attr,
+ struct netlink_ext_ack *extack)
+{
+ const u8 *data = nla_data(attr);
+ unsigned int len = nla_len(attr);
+
+ if (!ieee80211_uhr_oper_size_ok(data, len, false))
+ return -EINVAL;
+ return 0;
}
/* policy for the attributes */
@@ -947,6 +960,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_UHR_CAPABILITY] =
NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_capa, 255),
[NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG },
+ [NL80211_ATTR_UHR_OPERATION] =
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_operation),
};
/* policy for the key attributes */
@@ -3619,6 +3634,9 @@ static int _nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
case NL80211_CHAN_HT20:
case NL80211_CHAN_HT40PLUS:
case NL80211_CHAN_HT40MINUS:
+ if (chandef->chan->band == NL80211_BAND_60GHZ ||
+ chandef->chan->band == NL80211_BAND_S1GHZ)
+ return -EINVAL;
cfg80211_chandef_create(chandef, chandef->chan,
chantype);
/* user input for center_freq is incorrect */
@@ -5825,7 +5843,7 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
*/
BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
nla_for_each_nested(tx_rates, attrs[attr], rem) {
- enum nl80211_band band = nla_type(tx_rates);
+ int band = nla_type(tx_rates);
int err;
if (band < 0 || band >= NUM_NL80211_BANDS)
@@ -6499,16 +6517,6 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
return -EINVAL;
}
- cap = cfg80211_find_ext_elem(WLAN_EID_EXT_UHR_OPER, ies, ies_len);
- if (cap) {
- if (!cap->datalen)
- return -EINVAL;
- params->uhr_oper = (void *)(cap->data + 1);
- if (!ieee80211_uhr_oper_size_ok((const u8 *)params->uhr_oper,
- cap->datalen - 1, true))
- return -EINVAL;
- }
-
return 0;
}
@@ -6950,6 +6958,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out;
+ if (info->attrs[NL80211_ATTR_UHR_OPERATION])
+ params->uhr_oper = nla_data(info->attrs[NL80211_ATTR_UHR_OPERATION]);
+
err = nl80211_validate_ap_phy_operation(params);
if (err)
goto out;
@@ -10694,7 +10705,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
nla_for_each_nested(attr,
info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
tmp) {
- enum nl80211_band band = nla_type(attr);
+ int band = nla_type(attr);
if (band < 0 || band >= NUM_NL80211_BANDS) {
err = -EINVAL;
diff --git a/net/wireless/of.c b/net/wireless/of.c
index 60a864465331..99acbea3beee 100644
--- a/net/wireless/of.c
+++ b/net/wireless/of.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/of.h>
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index c85eaa583a46..df29048a0449 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
* Radiotap parser
*
* Copyright 2007 Andy Green <andy@warmcat.com>
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See COPYING for more details.
*/
#include <linux/kernel.h>
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 1c5c38d18feb..20bba7e491c5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
@@ -6,18 +7,6 @@
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2017 Intel Deutschland GmbH
* Copyright (C) 2018 - 2026 Intel Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index e1b211c4f75c..fc31c5f9a61a 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: ISC */
#ifndef __NET_WIRELESS_REG_H
#define __NET_WIRELESS_REG_H
@@ -6,18 +7,6 @@
/*
* Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
* Copyright (C) 2019, 2023 Intel Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum ieee80211_regd_source {
diff --git a/net/wireless/trace.c b/net/wireless/trace.c
index 95f997fad755..7cb93acf1a8f 100644
--- a/net/wireless/trace.c
+++ b/net/wireless/trace.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#ifndef __CHECKER__
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 7b8e94214b07..c19dece2bc6e 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* This file implement the Wireless Extensions core API.
*
@@ -5,8 +6,6 @@
* Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright (C) 2024 Intel Corporation
- *
- * (As all part of the Linux kernel, this file is GPL)
*/
#include <linux/kernel.h>
#include <linux/netdevice.h>
diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c
index 37d1147019c2..ce9022843dfd 100644
--- a/net/wireless/wext-priv.c
+++ b/net/wireless/wext-priv.c
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* This file implement the Wireless Extensions priv API.
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
- *
- * (As all part of the Linux kernel, this file is GPL)
*/
#include <linux/slab.h>
#include <linux/wireless.h>
diff --git a/net/wireless/wext-proc.c b/net/wireless/wext-proc.c
index cadcf8613af2..be6b2b695bf9 100644
--- a/net/wireless/wext-proc.c
+++ b/net/wireless/wext-proc.c
@@ -1,10 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* This file implement the Wireless Extensions proc API.
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
- *
- * (As all part of the Linux kernel, this file is GPL)
*/
/*