mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
Aside from various small improvements/cleanups, not much:
- cfg80211/mac80211: S1G and UHR improvements - hwsim: incumbent signal report test support -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmm7sb4ACgkQ10qiO8sP aAD+iQ/+IYWmM1Z/Iu6eZZx/VPrc4Xnj/8UgbalyjetyLRYFNEvawFSdutqZ23uI FO7vYbzGXMtAlt7fjmxVKMiN4aoX+rISRjG5cnH1qPpeVO8w9fnOZyqmNUFJFboN ibpr4dqPIS2qZDKegvOa9JO+8KkkPerPWl608eOzXPxoZaZAMnXOhWuV4cWdvuTT vEnL+Ma4ckkOV6QdBFazYaxAyTt3Mpqj5ULodixtKPMdgB3P+6mAVipp/icE5R1P R/Vd7Fn+0r7wb/4+1S6DcCBvT6V6Ui94bIRF9DB5LGG/9iLPrGYRD52qQpetzXzA Si238bs7qi/6t6Q5tfzK1LZVnzZXTUqcWGS6ba4JiMxrLTAK1AEmcLved6A48ywt YH9zImLRBRMSANbH27BoWvijT5YZGMetH06cTdFmZ8MMGoYV7CWBxVOaIroH7WMx exMnWEcX6PUVMtlIR4FTGwX/nalGbvnBtoMv9ei3NRb2Dkart8OFT6vIDfy6TBnD BzAUE3pDAW3I7ukbLQGJ3mmanZpHtF/Xgfr5Y9EbZHPjtC08l7cwdd2zn0n3Q2qu JGlzZiut6sJTfnRESbUvJ6fnCMdGARpQxq6p2At3njJW0sncvyV9WFKh4A+ReaDr PQ24fgapG5PNEISevO+/FV1z2qZ0+IbHSmcH+BIoktBnPUBLZFo= =cLVw -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
9ac76f3d0b
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, 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, 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_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) {
|
||||
|
|
|
|||
|
|
@ -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)) &&
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)) &&
|
||||
|
|
|
|||
|
|
@ -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 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
|
|||
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 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -325,6 +325,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.
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 (skb->len < IEEE80211_MIN_ACTION_SIZE(ftm))
|
||||
return false;
|
||||
|
||||
if (!ieee80211_is_public_action((void *)mgmt, skb->len))
|
||||
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;
|
||||
|
||||
return false;
|
||||
return mgmt->u.action.action_code == WLAN_PUB_ACTION_FTM_RESPONSE;
|
||||
}
|
||||
|
||||
struct element {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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, ¶ms);
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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,24 +239,45 @@ 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,
|
||||
_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 = req;
|
||||
struct ieee80211_chanctx_user_iter iter;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
*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)
|
||||
{
|
||||
const struct ieee80211_chan_req *ret;
|
||||
struct ieee80211_chan_req tmp2;
|
||||
|
||||
*tmp = (struct ieee80211_chan_req){
|
||||
.oper = ctx->conf.def,
|
||||
.ap = ctx->conf.ap,
|
||||
};
|
||||
|
||||
ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
*tmp = *ret;
|
||||
return tmp;
|
||||
return _ieee80211_chanctx_compatible(local, NULL, ctx, req, tmp);
|
||||
}
|
||||
|
||||
static const struct ieee80211_chan_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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 __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 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 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_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 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 \
|
||||
__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 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 \
|
||||
|
|
|
|||
|
|
@ -3766,12 +3766,11 @@ void ieee80211_chandef_downgrade(struct cfg80211_chan_def *c,
|
|||
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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/module.h>
|
||||
|
||||
#ifndef __CHECKER__
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user