mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-20 09:26:28 +00:00
mac80211: Update to version 5.15-rc6-1
The removed patches were applied upstream. The Cisco Aironet 802.11b driver was removed from backports, remove it also from OpenWrt. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
parent
cfe0eb7485
commit
0a274d67b8
@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=mac80211
|
||||
|
||||
PKG_VERSION:=5.14.13-1
|
||||
PKG_VERSION:=5.15-rc6-1
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.14.13/
|
||||
PKG_HASH:=042aef20caf17ef649502d5f2e744a7676abe7faed18de83c96f37bc029635fe
|
||||
PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15-rc6/
|
||||
PKG_HASH:=9282612c4c02ef9fc9d74405303033f6b53914cd63d631eef0f43155fcd38932
|
||||
|
||||
PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)
|
||||
@ -23,7 +23,6 @@ PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_DRIVERS = \
|
||||
adm8211 \
|
||||
airo \
|
||||
hermes hermes-pci hermes-pcmcia hermes-plx\
|
||||
lib80211 \
|
||||
mac80211-hwsim \
|
||||
@ -174,18 +173,6 @@ define KernelPackage/adm8211
|
||||
AUTOLOAD:=$(call AutoProbe,adm8211)
|
||||
endef
|
||||
|
||||
define KernelPackage/airo
|
||||
$(call KernelPackage/mac80211/Default)
|
||||
TITLE:=Cisco Aironet driver
|
||||
DEPENDS+=@PCI_SUPPORT +@DRIVER_WEXT_SUPPORT +kmod-cfg80211 @TARGET_x86 @BROKEN
|
||||
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/cisco/airo.ko
|
||||
AUTOLOAD:=$(call AutoProbe,airo)
|
||||
endef
|
||||
|
||||
define KernelPackage/airo/description
|
||||
Kernel support for Cisco Aironet cards
|
||||
endef
|
||||
|
||||
define KernelPackage/hermes
|
||||
$(call KernelPackage/mac80211/Default)
|
||||
TITLE:=Hermes 802.11b chipset support
|
||||
@ -406,8 +393,6 @@ endif
|
||||
|
||||
config-$(call config_package,lib80211) += LIB80211 LIB80211_CRYPT_WEP LIB80211_CRYPT_CCMP LIB80211_CRYPT_TKIP
|
||||
|
||||
config-$(call config_package,airo) += AIRO
|
||||
|
||||
config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM
|
||||
config-$(call config_package,mt7601u) += MT7601U
|
||||
config-y += WL_MEDIATEK
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/net/wireless/reg.c
|
||||
+++ b/net/wireless/reg.c
|
||||
@@ -3292,6 +3292,8 @@ void regulatory_hint_country_ie(struct w
|
||||
@@ -3299,6 +3299,8 @@ void regulatory_hint_country_ie(struct w
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request = NULL, *lr;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
/* IE len must be evenly divisible by 2 */
|
||||
if (country_ie_len & 0x01)
|
||||
return;
|
||||
@@ -3543,6 +3545,7 @@ static bool is_wiphy_all_set_reg_flag(en
|
||||
@@ -3550,6 +3552,7 @@ static bool is_wiphy_all_set_reg_flag(en
|
||||
|
||||
void regulatory_hint_disconnect(void)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath10k/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
|
||||
@@ -85,6 +85,12 @@ config ATH10K_TRACING
|
||||
@@ -86,6 +86,12 @@ config ATH10K_TRACING
|
||||
help
|
||||
Select this to ath10k use tracing infrastructure.
|
||||
|
||||
|
@ -85,7 +85,7 @@ v13:
|
||||
create mode 100644 drivers/net/wireless/ath/ath10k/leds.h
|
||||
--- a/drivers/net/wireless/ath/ath10k/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
|
||||
@@ -70,6 +70,16 @@ config ATH10K_DEBUGFS
|
||||
@@ -71,6 +71,16 @@ config ATH10K_DEBUGFS
|
||||
|
||||
If unsure, say Y to make it easier to debug problems.
|
||||
|
||||
|
@ -20,8 +20,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
+ struct completion *completion;
|
||||
};
|
||||
|
||||
static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
|
||||
@@ -636,6 +637,8 @@ static void brcmf_fw_request_done(const
|
||||
#ifdef CONFIG_EFI
|
||||
@@ -653,6 +654,8 @@ static void brcmf_fw_request_done(const
|
||||
fwctx->req = NULL;
|
||||
}
|
||||
fwctx->done(fwctx->dev, ret, fwctx->req);
|
||||
@ -30,16 +30,16 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
kfree(fwctx);
|
||||
}
|
||||
|
||||
@@ -660,6 +663,8 @@ int brcmf_fw_get_firmwares(struct device
|
||||
@@ -693,6 +696,8 @@ int brcmf_fw_get_firmwares(struct device
|
||||
{
|
||||
struct brcmf_fw_item *first = &req->items[0];
|
||||
struct brcmf_fw *fwctx;
|
||||
+ struct completion completion;
|
||||
+ unsigned long time_left;
|
||||
char *alt_path;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
|
||||
@@ -676,6 +681,9 @@ int brcmf_fw_get_firmwares(struct device
|
||||
@@ -710,6 +715,9 @@ int brcmf_fw_get_firmwares(struct device
|
||||
fwctx->dev = dev;
|
||||
fwctx->req = req;
|
||||
fwctx->done = fw_cb;
|
||||
@ -47,9 +47,9 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
+ init_completion(&completion);
|
||||
+ fwctx->completion = &completion;
|
||||
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, first->path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
@@ -683,6 +691,12 @@ int brcmf_fw_get_firmwares(struct device
|
||||
/* First try alternative board-specific path if any */
|
||||
alt_path = brcm_alt_fw_path(first->path, fwctx->req->board_type);
|
||||
@@ -726,6 +734,12 @@ int brcmf_fw_get_firmwares(struct device
|
||||
if (ret < 0)
|
||||
brcmf_fw_request_done(NULL, fwctx);
|
||||
|
||||
|
@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -2966,6 +2966,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
|
||||
@@ -2974,6 +2974,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
|
||||
* preference in cfg struct to apply this to
|
||||
* FW later while initializing the dongle
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -2913,6 +2913,63 @@ done:
|
||||
@@ -2921,6 +2921,63 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
@ -64,7 +64,7 @@
|
||||
brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
@@ -3013,6 +3070,7 @@ static s32 brcmf_inform_single_bss(struc
|
||||
@@ -3021,6 +3078,7 @@ static s32 brcmf_inform_single_bss(struc
|
||||
struct brcmu_chan ch;
|
||||
u16 channel;
|
||||
u32 freq;
|
||||
@ -72,7 +72,7 @@
|
||||
u16 notify_capability;
|
||||
u16 notify_interval;
|
||||
u8 *notify_ie;
|
||||
@@ -3037,6 +3095,17 @@ static s32 brcmf_inform_single_bss(struc
|
||||
@@ -3045,6 +3103,17 @@ static s32 brcmf_inform_single_bss(struc
|
||||
band = NL80211_BAND_5GHZ;
|
||||
|
||||
freq = ieee80211_channel_to_frequency(channel, band);
|
||||
@ -90,7 +90,7 @@
|
||||
bss_data.chan = ieee80211_get_channel(wiphy, freq);
|
||||
bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
|
||||
bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
|
||||
@@ -5565,6 +5634,7 @@ static struct cfg80211_ops brcmf_cfg8021
|
||||
@@ -5573,6 +5642,7 @@ static struct cfg80211_ops brcmf_cfg8021
|
||||
.leave_ibss = brcmf_cfg80211_leave_ibss,
|
||||
.get_station = brcmf_cfg80211_get_station,
|
||||
.dump_station = brcmf_cfg80211_dump_station,
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -431,43 +431,6 @@ USB_VL600=
|
||||
@@ -421,43 +421,6 @@ USB_VL600=
|
||||
USB_NET_CH9200=
|
||||
USB_NET_AQC111=
|
||||
USB_RTL8153_ECM=
|
||||
@ -192,7 +192,7 @@
|
||||
select BRCMUTIL
|
||||
--- a/Kconfig.local
|
||||
+++ b/Kconfig.local
|
||||
@@ -1297,117 +1297,6 @@ config BACKPORTED_USB_NET_AQC111
|
||||
@@ -1267,117 +1267,6 @@ config BACKPORTED_USB_NET_AQC111
|
||||
config BACKPORTED_USB_RTL8153_ECM
|
||||
tristate
|
||||
default USB_RTL8153_ECM
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -325,6 +325,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
@@ -315,6 +315,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
RT2X00_LIB_CRYPTO=
|
||||
RT2X00_LIB_LEDS=
|
||||
RT2X00_LIB_DEBUGFS=
|
||||
|
@ -2,7 +2,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -1306,7 +1306,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
@@ -1314,7 +1314,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
sdata->vif.bss_conf.ftmr_params = NULL;
|
||||
|
||||
__sta_info_flush(sdata, true);
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2487,7 +2487,7 @@ static int ieee80211_scan(struct wiphy *
|
||||
@@ -2495,7 +2495,7 @@ static int ieee80211_scan(struct wiphy *
|
||||
* the frames sent while scanning on other channel will be
|
||||
* lost)
|
||||
*/
|
||||
|
@ -1,492 +0,0 @@
|
||||
From 0d2ab3aea50bb02ff0c9c3d53c7b2b4b21cdd59d Mon Sep 17 00:00:00 2001
|
||||
From: John Crispin <john@phrozen.org>
|
||||
Date: Fri, 2 Jul 2021 19:44:07 +0200
|
||||
Subject: [PATCH] nl80211: add support for BSS coloring
|
||||
|
||||
This patch adds support for BSS color collisions to the wireless subsystem.
|
||||
Add the required functionality to nl80211 that will notify about color
|
||||
collisions, triggering the color change and notifying when it is completed.
|
||||
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Link: https://lore.kernel.org/r/500b3582aec8fe2c42ef46f3117b148cb7cbceb5.1625247619.git.lorenzo@kernel.org
|
||||
[remove unnecessary NULL initialisation]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
include/net/cfg80211.h | 92 ++++++++++++++++++++
|
||||
include/uapi/linux/nl80211.h | 43 ++++++++++
|
||||
net/wireless/nl80211.c | 157 +++++++++++++++++++++++++++++++++++
|
||||
net/wireless/rdev-ops.h | 13 +++
|
||||
net/wireless/trace.h | 46 ++++++++++
|
||||
5 files changed, 351 insertions(+)
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -1258,6 +1258,27 @@ struct cfg80211_csa_settings {
|
||||
};
|
||||
|
||||
/**
|
||||
+ * struct cfg80211_color_change_settings - color change settings
|
||||
+ *
|
||||
+ * Used for bss color change
|
||||
+ *
|
||||
+ * @beacon_color_change: beacon data while performing the color countdown
|
||||
+ * @counter_offsets_beacon: offsets of the counters within the beacon (tail)
|
||||
+ * @counter_offsets_presp: offsets of the counters within the probe response
|
||||
+ * @beacon_next: beacon data to be used after the color change
|
||||
+ * @count: number of beacons until the color change
|
||||
+ * @color: the color used after the change
|
||||
+ */
|
||||
+struct cfg80211_color_change_settings {
|
||||
+ struct cfg80211_beacon_data beacon_color_change;
|
||||
+ u16 counter_offset_beacon;
|
||||
+ u16 counter_offset_presp;
|
||||
+ struct cfg80211_beacon_data beacon_next;
|
||||
+ u8 count;
|
||||
+ u8 color;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct iface_combination_params - input parameters for interface combinations
|
||||
*
|
||||
* Used to pass interface combination parameters
|
||||
@@ -4000,6 +4021,8 @@ struct mgmt_frame_regs {
|
||||
* given TIDs. This callback may sleep.
|
||||
*
|
||||
* @set_sar_specs: Update the SAR (TX power) settings.
|
||||
+ *
|
||||
+ * @color_change: Initiate a color change.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
@@ -4327,6 +4350,9 @@ struct cfg80211_ops {
|
||||
const u8 *peer, u8 tids);
|
||||
int (*set_sar_specs)(struct wiphy *wiphy,
|
||||
struct cfg80211_sar_specs *sar);
|
||||
+ int (*color_change)(struct wiphy *wiphy,
|
||||
+ struct net_device *dev,
|
||||
+ struct cfg80211_color_change_settings *params);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -8226,4 +8252,70 @@ void cfg80211_update_owe_info_event(stru
|
||||
*/
|
||||
void cfg80211_bss_flush(struct wiphy *wiphy);
|
||||
|
||||
+/**
|
||||
+ * cfg80211_bss_color_notify - notify about bss color event
|
||||
+ * @dev: network device
|
||||
+ * @gfp: allocation flags
|
||||
+ * @cmd: the actual event we want to notify
|
||||
+ * @count: the number of TBTTs until the color change happens
|
||||
+ * @color_bitmap: representations of the colors that the local BSS is aware of
|
||||
+ */
|
||||
+int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
|
||||
+ enum nl80211_commands cmd, u8 count,
|
||||
+ u64 color_bitmap);
|
||||
+
|
||||
+/**
|
||||
+ * cfg80211_obss_color_collision_notify - notify about bss color collision
|
||||
+ * @dev: network device
|
||||
+ * @color_bitmap: representations of the colors that the local BSS is aware of
|
||||
+ */
|
||||
+static inline int cfg80211_obss_color_collision_notify(struct net_device *dev,
|
||||
+ u64 color_bitmap)
|
||||
+{
|
||||
+ return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||
+ NL80211_CMD_OBSS_COLOR_COLLISION,
|
||||
+ 0, color_bitmap);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * cfg80211_color_change_started_notify - notify color change start
|
||||
+ * @dev: the device on which the color is switched
|
||||
+ * @count: the number of TBTTs until the color change happens
|
||||
+ *
|
||||
+ * Inform the userspace about the color change that has started.
|
||||
+ */
|
||||
+static inline int cfg80211_color_change_started_notify(struct net_device *dev,
|
||||
+ u8 count)
|
||||
+{
|
||||
+ return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||
+ NL80211_CMD_COLOR_CHANGE_STARTED,
|
||||
+ count, 0);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * cfg80211_color_change_aborted_notify - notify color change abort
|
||||
+ * @dev: the device on which the color is switched
|
||||
+ *
|
||||
+ * Inform the userspace about the color change that has aborted.
|
||||
+ */
|
||||
+static inline int cfg80211_color_change_aborted_notify(struct net_device *dev)
|
||||
+{
|
||||
+ return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||
+ NL80211_CMD_COLOR_CHANGE_ABORTED,
|
||||
+ 0, 0);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * cfg80211_color_change_notify - notify color change completion
|
||||
+ * @dev: the device on which the color was switched
|
||||
+ *
|
||||
+ * Inform the userspace about the color change that has completed.
|
||||
+ */
|
||||
+static inline int cfg80211_color_change_notify(struct net_device *dev)
|
||||
+{
|
||||
+ return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||
+ NL80211_CMD_COLOR_CHANGE_COMPLETED,
|
||||
+ 0, 0);
|
||||
+}
|
||||
+
|
||||
#endif /* __NET_CFG80211_H */
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -1185,6 +1185,21 @@
|
||||
* passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
|
||||
* specify the wiphy index to be applied to.
|
||||
*
|
||||
+ * @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever
|
||||
+ * mac80211/drv detects a bss color collision.
|
||||
+ *
|
||||
+ * @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that
|
||||
+ * userspace wants to change the BSS color.
|
||||
+ *
|
||||
+ * @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has
|
||||
+ * started
|
||||
+ *
|
||||
+ * @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has
|
||||
+ * been aborted
|
||||
+ *
|
||||
+ * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
|
||||
+ * has completed
|
||||
+ *
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@@ -1417,6 +1432,14 @@ enum nl80211_commands {
|
||||
|
||||
NL80211_CMD_SET_SAR_SPECS,
|
||||
|
||||
+ NL80211_CMD_OBSS_COLOR_COLLISION,
|
||||
+
|
||||
+ NL80211_CMD_COLOR_CHANGE_REQUEST,
|
||||
+
|
||||
+ NL80211_CMD_COLOR_CHANGE_STARTED,
|
||||
+ NL80211_CMD_COLOR_CHANGE_ABORTED,
|
||||
+ NL80211_CMD_COLOR_CHANGE_COMPLETED,
|
||||
+
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@@ -2560,6 +2583,16 @@ enum nl80211_commands {
|
||||
* disassoc events to indicate that an immediate reconnect to the AP
|
||||
* is desired.
|
||||
*
|
||||
+ * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
|
||||
+ * %NL80211_CMD_OBSS_COLOR_COLLISION event.
|
||||
+ *
|
||||
+ * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
|
||||
+ * until the color switch event.
|
||||
+ * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
|
||||
+ * switching to
|
||||
+ * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
|
||||
+ * information for the time while performing a color switch.
|
||||
+ *
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3057,6 +3090,12 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_DISABLE_HE,
|
||||
|
||||
+ NL80211_ATTR_OBSS_COLOR_BITMAP,
|
||||
+
|
||||
+ NL80211_ATTR_COLOR_CHANGE_COUNT,
|
||||
+ NL80211_ATTR_COLOR_CHANGE_COLOR,
|
||||
+ NL80211_ATTR_COLOR_CHANGE_ELEMS,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@@ -5953,6 +5992,9 @@ enum nl80211_feature_flags {
|
||||
* frame protection for all management frames exchanged during the
|
||||
* negotiation and range measurement procedure.
|
||||
*
|
||||
+ * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
|
||||
+ * detection and change announcemnts.
|
||||
+ *
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@@ -6017,6 +6059,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_SECURE_LTF,
|
||||
NL80211_EXT_FEATURE_SECURE_RTT,
|
||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
||||
+ NL80211_EXT_FEATURE_BSS_COLOR,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -776,6 +776,10 @@ static const struct nla_policy nl80211_p
|
||||
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
|
||||
[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
|
||||
[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
|
||||
+ [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
|
||||
+ [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
|
||||
+ [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
|
||||
+ [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -14823,6 +14827,106 @@ bad_tid_conf:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
|
||||
+{
|
||||
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
+ struct cfg80211_color_change_settings params = {};
|
||||
+ struct net_device *dev = info->user_ptr[1];
|
||||
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
+ struct nlattr **tb;
|
||||
+ u16 offset;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!rdev->ops->color_change)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
+ NL80211_EXT_FEATURE_BSS_COLOR))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (wdev->iftype != NL80211_IFTYPE_AP)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
|
||||
+ !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
|
||||
+ !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
|
||||
+ params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
|
||||
+
|
||||
+ err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_next);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
|
||||
+ if (!tb)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ err = nla_parse_nested(tb, NL80211_ATTR_MAX,
|
||||
+ info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
|
||||
+ nl80211_policy, info->extack);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+
|
||||
+ err = nl80211_parse_beacon(rdev, tb, ¶ms.beacon_color_change);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
|
||||
+ if (offset >= params.beacon_color_change.tail_len) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (params.beacon_color_change.tail[offset] != params.count) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ params.counter_offset_beacon = offset;
|
||||
+
|
||||
+ if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
|
||||
+ if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
|
||||
+ sizeof(u16)) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
|
||||
+ if (offset >= params.beacon_color_change.probe_resp_len) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (params.beacon_color_change.probe_resp[offset] !=
|
||||
+ params.count) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ params.counter_offset_presp = offset;
|
||||
+ }
|
||||
+
|
||||
+ wdev_lock(wdev);
|
||||
+ err = rdev_color_change(rdev, dev, ¶ms);
|
||||
+ wdev_unlock(wdev);
|
||||
+
|
||||
+out:
|
||||
+ kfree(tb);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
#define NL80211_FLAG_NEED_WIPHY 0x01
|
||||
#define NL80211_FLAG_NEED_NETDEV 0x02
|
||||
#define NL80211_FLAG_NEED_RTNL 0x04
|
||||
@@ -15823,6 +15927,14 @@ static const struct genl_small_ops nl802
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
+ {
|
||||
+ .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
|
||||
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
+ .doit = nl80211_color_change,
|
||||
+ .flags = GENL_UNS_ADMIN_PERM,
|
||||
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
+ NL80211_FLAG_NEED_RTNL,
|
||||
+ },
|
||||
};
|
||||
|
||||
static struct genl_family nl80211_fam __genl_ro_after_init = {
|
||||
@@ -17454,6 +17566,51 @@ void cfg80211_ch_switch_started_notify(s
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
|
||||
|
||||
+int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
|
||||
+ enum nl80211_commands cmd, u8 count,
|
||||
+ u64 color_bitmap)
|
||||
+{
|
||||
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
+ struct wiphy *wiphy = wdev->wiphy;
|
||||
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
+ struct sk_buff *msg;
|
||||
+ void *hdr;
|
||||
+
|
||||
+ ASSERT_WDEV_LOCK(wdev);
|
||||
+
|
||||
+ trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
|
||||
+
|
||||
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
||||
+ if (!msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
|
||||
+ if (!hdr)
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
|
||||
+ nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
|
||||
+ nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
|
||||
+ color_bitmap, NL80211_ATTR_PAD))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ genlmsg_end(msg, hdr);
|
||||
+
|
||||
+ return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
|
||||
+ msg, 0, NL80211_MCGRP_MLME, gfp);
|
||||
+
|
||||
+nla_put_failure:
|
||||
+ nlmsg_free(msg);
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+EXPORT_SYMBOL(cfg80211_bss_color_notify);
|
||||
+
|
||||
void
|
||||
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
--- a/net/wireless/rdev-ops.h
|
||||
+++ b/net/wireless/rdev-ops.h
|
||||
@@ -1368,4 +1368,17 @@ static inline int rdev_set_sar_specs(str
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static inline int rdev_color_change(struct cfg80211_registered_device *rdev,
|
||||
+ struct net_device *dev,
|
||||
+ struct cfg80211_color_change_settings *params)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ trace_rdev_color_change(&rdev->wiphy, dev, params);
|
||||
+ ret = rdev->ops->color_change(&rdev->wiphy, dev, params);
|
||||
+ trace_rdev_return_int(&rdev->wiphy, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#endif /* __CFG80211_RDEV_OPS */
|
||||
--- a/net/wireless/trace.h
|
||||
+++ b/net/wireless/trace.h
|
||||
@@ -3597,6 +3597,52 @@ TRACE_EVENT(rdev_set_sar_specs,
|
||||
WIPHY_PR_ARG, __entry->type, __entry->num)
|
||||
);
|
||||
|
||||
+TRACE_EVENT(rdev_color_change,
|
||||
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
||||
+ struct cfg80211_color_change_settings *params),
|
||||
+ TP_ARGS(wiphy, netdev, params),
|
||||
+ TP_STRUCT__entry(
|
||||
+ WIPHY_ENTRY
|
||||
+ NETDEV_ENTRY
|
||||
+ __field(u8, count)
|
||||
+ __field(u16, bcn_ofs)
|
||||
+ __field(u16, pres_ofs)
|
||||
+ ),
|
||||
+ TP_fast_assign(
|
||||
+ WIPHY_ASSIGN;
|
||||
+ NETDEV_ASSIGN;
|
||||
+ __entry->count = params->count;
|
||||
+ __entry->bcn_ofs = params->counter_offset_beacon;
|
||||
+ __entry->pres_ofs = params->counter_offset_presp;
|
||||
+ ),
|
||||
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
|
||||
+ ", count: %u",
|
||||
+ WIPHY_PR_ARG, NETDEV_PR_ARG,
|
||||
+ __entry->count)
|
||||
+);
|
||||
+
|
||||
+TRACE_EVENT(cfg80211_bss_color_notify,
|
||||
+ TP_PROTO(struct net_device *netdev,
|
||||
+ enum nl80211_commands cmd,
|
||||
+ u8 count, u64 color_bitmap),
|
||||
+ TP_ARGS(netdev, cmd, count, color_bitmap),
|
||||
+ TP_STRUCT__entry(
|
||||
+ NETDEV_ENTRY
|
||||
+ __field(enum nl80211_bss_scan_width, cmd)
|
||||
+ __field(u8, count)
|
||||
+ __field(u64, color_bitmap)
|
||||
+ ),
|
||||
+ TP_fast_assign(
|
||||
+ NETDEV_ASSIGN;
|
||||
+ __entry->cmd = cmd;
|
||||
+ __entry->count = count;
|
||||
+ __entry->color_bitmap = color_bitmap;
|
||||
+ ),
|
||||
+ TP_printk(NETDEV_PR_FMT ", cmd: %x, count: %u, bitmap: %llx",
|
||||
+ NETDEV_PR_ARG, __entry->cmd, __entry->count,
|
||||
+ __entry->color_bitmap)
|
||||
+);
|
||||
+
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
@ -1,524 +0,0 @@
|
||||
From: John Crispin <john@phrozen.org>
|
||||
Date: Fri, 2 Jul 2021 19:44:08 +0200
|
||||
Subject: [PATCH] mac80211: add support for BSS color change
|
||||
|
||||
The color change announcement is very similar to how CSA works where
|
||||
we have an IE that includes a counter. When the counter hits 0, the new
|
||||
color is applied via an updated beacon.
|
||||
|
||||
This patch makes the CSA counter functionality reusable, rather than
|
||||
implementing it again. This also allows for future reuse incase support
|
||||
for other counter IEs gets added.
|
||||
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Link: https://lore.kernel.org/r/057c1e67b82bee561ea44ce6a45a8462d3da6995.1625247619.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1715,6 +1715,10 @@ enum ieee80211_offload_flags {
|
||||
* protected by fq->lock.
|
||||
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
|
||||
* &enum ieee80211_offload_flags.
|
||||
+ * @color_change_active: marks whether a color change is ongoing. Internally it is
|
||||
+ * write-protected by sdata_lock and local->mtx so holding either is fine
|
||||
+ * for read access.
|
||||
+ * @color_change_color: the bss color that will be used after the change.
|
||||
*/
|
||||
struct ieee80211_vif {
|
||||
enum nl80211_iftype type;
|
||||
@@ -1743,6 +1747,9 @@ struct ieee80211_vif {
|
||||
|
||||
bool txqs_stopped[IEEE80211_NUM_ACS];
|
||||
|
||||
+ bool color_change_active;
|
||||
+ u8 color_change_color;
|
||||
+
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
};
|
||||
@@ -5016,6 +5023,16 @@ void ieee80211_csa_finish(struct ieee802
|
||||
bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
+ * ieee80211_color_change_finish - notify mac80211 about color change
|
||||
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
+ *
|
||||
+ * After a color change announcement was scheduled and the counter in this
|
||||
+ * announcement hits 1, this function must be called by the driver to
|
||||
+ * notify mac80211 that the color can be changed
|
||||
+ */
|
||||
+void ieee80211_color_change_finish(struct ieee80211_vif *vif);
|
||||
+
|
||||
+/**
|
||||
* ieee80211_proberesp_get - retrieve a Probe Response template
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
@@ -6780,6 +6797,18 @@ ieee80211_get_unsol_bcast_probe_resp_tmp
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
+ * ieeee80211_obss_color_collision_notify - notify userland about a BSS color
|
||||
+ * collision.
|
||||
+ *
|
||||
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
+ * @color_bitmap: a 64 bit bitmap representing the colors that the local BSS is
|
||||
+ * aware of.
|
||||
+ */
|
||||
+void
|
||||
+ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
|
||||
+ u64 color_bitmap);
|
||||
+
|
||||
+/**
|
||||
* ieee80211_is_tx_data - check if frame is a data frame
|
||||
*
|
||||
* The function is used to check if a frame is a data frame. Frames with
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -828,9 +828,11 @@ static int ieee80211_set_monitor_channel
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||
- const u8 *resp, size_t resp_len,
|
||||
- const struct ieee80211_csa_settings *csa)
|
||||
+static int
|
||||
+ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||
+ const u8 *resp, size_t resp_len,
|
||||
+ const struct ieee80211_csa_settings *csa,
|
||||
+ const struct ieee80211_color_change_settings *cca)
|
||||
{
|
||||
struct probe_resp *new, *old;
|
||||
|
||||
@@ -850,6 +852,8 @@ static int ieee80211_set_probe_resp(stru
|
||||
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp,
|
||||
csa->n_counter_offsets_presp *
|
||||
sizeof(new->cntdwn_counter_offsets[0]));
|
||||
+ else if (cca)
|
||||
+ new->cntdwn_counter_offsets[0] = cca->counter_offset_presp;
|
||||
|
||||
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
|
||||
if (old)
|
||||
@@ -955,7 +959,8 @@ static int ieee80211_set_ftm_responder_p
|
||||
|
||||
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_beacon_data *params,
|
||||
- const struct ieee80211_csa_settings *csa)
|
||||
+ const struct ieee80211_csa_settings *csa,
|
||||
+ const struct ieee80211_color_change_settings *cca)
|
||||
{
|
||||
struct beacon_data *new, *old;
|
||||
int new_head_len, new_tail_len;
|
||||
@@ -1004,6 +1009,9 @@ static int ieee80211_assign_beacon(struc
|
||||
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon,
|
||||
csa->n_counter_offsets_beacon *
|
||||
sizeof(new->cntdwn_counter_offsets[0]));
|
||||
+ } else if (cca) {
|
||||
+ new->cntdwn_current_counter = cca->count;
|
||||
+ new->cntdwn_counter_offsets[0] = cca->counter_offset_beacon;
|
||||
}
|
||||
|
||||
/* copy in head */
|
||||
@@ -1020,7 +1028,7 @@ static int ieee80211_assign_beacon(struc
|
||||
memcpy(new->tail, old->tail, new_tail_len);
|
||||
|
||||
err = ieee80211_set_probe_resp(sdata, params->probe_resp,
|
||||
- params->probe_resp_len, csa);
|
||||
+ params->probe_resp_len, csa, cca);
|
||||
if (err < 0) {
|
||||
kfree(new);
|
||||
return err;
|
||||
@@ -1175,7 +1183,7 @@ static int ieee80211_start_ap(struct wip
|
||||
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
|
||||
sdata->vif.bss_conf.beacon_tx_rate = params->beacon_rate;
|
||||
|
||||
- err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
||||
+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
changed |= err;
|
||||
@@ -1230,17 +1238,17 @@ static int ieee80211_change_beacon(struc
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
- /* don't allow changing the beacon while CSA is in place - offset
|
||||
+ /* don't allow changing the beacon while a countdown is in place - offset
|
||||
* of channel switch counter may change
|
||||
*/
|
||||
- if (sdata->vif.csa_active)
|
||||
+ if (sdata->vif.csa_active || sdata->vif.color_change_active)
|
||||
return -EBUSY;
|
||||
|
||||
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||
if (!old)
|
||||
return -ENOENT;
|
||||
|
||||
- err = ieee80211_assign_beacon(sdata, params, NULL);
|
||||
+ err = ieee80211_assign_beacon(sdata, params, NULL, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
ieee80211_bss_info_change_notify(sdata, err);
|
||||
@@ -3155,7 +3163,7 @@ static int ieee80211_set_after_csa_beaco
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||
- NULL);
|
||||
+ NULL, NULL);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
|
||||
@@ -3321,7 +3329,7 @@ static int ieee80211_set_csa_beacon(stru
|
||||
csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
|
||||
csa.count = params->count;
|
||||
|
||||
- err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa);
|
||||
+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL);
|
||||
if (err < 0) {
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
return err;
|
||||
@@ -3410,6 +3418,15 @@ static int ieee80211_set_csa_beacon(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
|
||||
+{
|
||||
+ sdata->vif.color_change_active = false;
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+
|
||||
+ cfg80211_color_change_aborted_notify(sdata->dev);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params)
|
||||
@@ -3478,6 +3495,10 @@ __ieee80211_channel_switch(struct wiphy
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* if there is a color change in progress, abort it */
|
||||
+ if (sdata->vif.color_change_active)
|
||||
+ ieee80211_color_change_abort(sdata);
|
||||
+
|
||||
err = ieee80211_set_csa_beacon(sdata, params, &changed);
|
||||
if (err) {
|
||||
ieee80211_vif_unreserve_chanctx(sdata);
|
||||
@@ -4129,6 +4150,196 @@ static int ieee80211_set_sar_specs(struc
|
||||
return local->ops->set_sar_specs(&local->hw, sar);
|
||||
}
|
||||
|
||||
+static int
|
||||
+ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
+ u32 *changed)
|
||||
+{
|
||||
+ switch (sdata->vif.type) {
|
||||
+ case NL80211_IFTYPE_AP: {
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||
+ NULL, NULL);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ *changed |= ret;
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct cfg80211_color_change_settings *params,
|
||||
+ u32 *changed)
|
||||
+{
|
||||
+ struct ieee80211_color_change_settings color_change = {};
|
||||
+ int err;
|
||||
+
|
||||
+ switch (sdata->vif.type) {
|
||||
+ case NL80211_IFTYPE_AP:
|
||||
+ sdata->u.ap.next_beacon =
|
||||
+ cfg80211_beacon_dup(¶ms->beacon_next);
|
||||
+ if (!sdata->u.ap.next_beacon)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (params->count <= 1)
|
||||
+ break;
|
||||
+
|
||||
+ color_change.counter_offset_beacon =
|
||||
+ params->counter_offset_beacon;
|
||||
+ color_change.counter_offset_presp =
|
||||
+ params->counter_offset_presp;
|
||||
+ color_change.count = params->count;
|
||||
+
|
||||
+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change,
|
||||
+ NULL, &color_change);
|
||||
+ if (err < 0) {
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ return err;
|
||||
+ }
|
||||
+ *changed |= err;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
|
||||
+ u8 color, int enable, u32 changed)
|
||||
+{
|
||||
+ sdata->vif.bss_conf.he_bss_color.color = color;
|
||||
+ sdata->vif.bss_conf.he_bss_color.enabled = enable;
|
||||
+ changed |= BSS_CHANGED_HE_BSS_COLOR;
|
||||
+
|
||||
+ ieee80211_bss_info_change_notify(sdata, changed);
|
||||
+}
|
||||
+
|
||||
+static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
+{
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ u32 changed = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ sdata_assert_lock(sdata);
|
||||
+ lockdep_assert_held(&local->mtx);
|
||||
+
|
||||
+ sdata->vif.color_change_active = false;
|
||||
+
|
||||
+ err = ieee80211_set_after_color_change_beacon(sdata, &changed);
|
||||
+ if (err) {
|
||||
+ cfg80211_color_change_aborted_notify(sdata->dev);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ ieee80211_color_change_bss_config_notify(sdata,
|
||||
+ sdata->vif.color_change_color,
|
||||
+ 1, changed);
|
||||
+ cfg80211_color_change_notify(sdata->dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void ieee80211_color_change_finalize_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *sdata =
|
||||
+ container_of(work, struct ieee80211_sub_if_data,
|
||||
+ color_change_finalize_work);
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+
|
||||
+ sdata_lock(sdata);
|
||||
+ mutex_lock(&local->mtx);
|
||||
+
|
||||
+ /* AP might have been stopped while waiting for the lock. */
|
||||
+ if (!sdata->vif.color_change_active)
|
||||
+ goto unlock;
|
||||
+
|
||||
+ if (!ieee80211_sdata_running(sdata))
|
||||
+ goto unlock;
|
||||
+
|
||||
+ ieee80211_color_change_finalize(sdata);
|
||||
+
|
||||
+unlock:
|
||||
+ mutex_unlock(&local->mtx);
|
||||
+ sdata_unlock(sdata);
|
||||
+}
|
||||
+
|
||||
+void ieee80211_color_change_finish(struct ieee80211_vif *vif)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
+
|
||||
+ ieee80211_queue_work(&sdata->local->hw,
|
||||
+ &sdata->color_change_finalize_work);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(ieee80211_color_change_finish);
|
||||
+
|
||||
+void
|
||||
+ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
|
||||
+ u64 color_bitmap)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
+
|
||||
+ if (sdata->vif.color_change_active || sdata->vif.csa_active)
|
||||
+ return;
|
||||
+
|
||||
+ cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(ieeee80211_obss_color_collision_notify);
|
||||
+
|
||||
+static int
|
||||
+ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
|
||||
+ struct cfg80211_color_change_settings *params)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ u32 changed = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ sdata_assert_lock(sdata);
|
||||
+
|
||||
+ mutex_lock(&local->mtx);
|
||||
+
|
||||
+ /* don't allow another color change if one is already active or if csa
|
||||
+ * is active
|
||||
+ */
|
||||
+ if (sdata->vif.color_change_active || sdata->vif.csa_active) {
|
||||
+ err = -EBUSY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ err = ieee80211_set_color_change_beacon(sdata, params, &changed);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+
|
||||
+ sdata->vif.color_change_active = true;
|
||||
+ sdata->vif.color_change_color = params->color;
|
||||
+
|
||||
+ cfg80211_color_change_started_notify(sdata->dev, params->count);
|
||||
+
|
||||
+ if (changed)
|
||||
+ ieee80211_color_change_bss_config_notify(sdata, 0, 0, changed);
|
||||
+ else
|
||||
+ /* if the beacon didn't change, we can finalize immediately */
|
||||
+ ieee80211_color_change_finalize(sdata);
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&local->mtx);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@@ -4232,4 +4443,5 @@ const struct cfg80211_ops mac80211_confi
|
||||
.set_tid_config = ieee80211_set_tid_config,
|
||||
.reset_tid_config = ieee80211_reset_tid_config,
|
||||
.set_sar_specs = ieee80211_set_sar_specs,
|
||||
+ .color_change = ieee80211_color_change,
|
||||
};
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -248,6 +248,12 @@ struct ieee80211_csa_settings {
|
||||
u8 count;
|
||||
};
|
||||
|
||||
+struct ieee80211_color_change_settings {
|
||||
+ u16 counter_offset_beacon;
|
||||
+ u16 counter_offset_presp;
|
||||
+ u8 count;
|
||||
+};
|
||||
+
|
||||
struct beacon_data {
|
||||
u8 *head, *tail;
|
||||
int head_len, tail_len;
|
||||
@@ -927,6 +933,8 @@ struct ieee80211_sub_if_data {
|
||||
bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
|
||||
struct cfg80211_chan_def csa_chandef;
|
||||
|
||||
+ struct work_struct color_change_finalize_work;
|
||||
+
|
||||
struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
|
||||
struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */
|
||||
|
||||
@@ -1891,6 +1899,9 @@ void ieee80211_csa_finalize_work(struct
|
||||
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params);
|
||||
|
||||
+/* color change handling */
|
||||
+void ieee80211_color_change_finalize_work(struct work_struct *work);
|
||||
+
|
||||
/* interface handling */
|
||||
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
|
||||
NETIF_F_HW_CSUM | NETIF_F_SG | \
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -462,6 +462,7 @@ static void ieee80211_do_stop(struct iee
|
||||
sdata_unlock(sdata);
|
||||
|
||||
cancel_work_sync(&sdata->csa_finalize_work);
|
||||
+ cancel_work_sync(&sdata->color_change_finalize_work);
|
||||
|
||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||
|
||||
@@ -1608,6 +1609,7 @@ static void ieee80211_setup_sdata(struct
|
||||
INIT_WORK(&sdata->work, ieee80211_iface_work);
|
||||
INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
|
||||
INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
|
||||
+ INIT_WORK(&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work);
|
||||
INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
|
||||
INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -4796,11 +4796,11 @@ static int ieee80211_beacon_add_tim(stru
|
||||
static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
{
|
||||
+ u8 *beacon_data, count, max_count = 1;
|
||||
struct probe_resp *resp;
|
||||
- u8 *beacon_data;
|
||||
size_t beacon_data_len;
|
||||
+ u16 *bcn_offsets;
|
||||
int i;
|
||||
- u8 count = beacon->cntdwn_current_counter;
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
@@ -4820,21 +4820,27 @@ static void ieee80211_set_beacon_cntdwn(
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
- for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) {
|
||||
- resp = rcu_dereference(sdata->u.ap.probe_resp);
|
||||
+ resp = rcu_dereference(sdata->u.ap.probe_resp);
|
||||
|
||||
- if (beacon->cntdwn_counter_offsets[i]) {
|
||||
- if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >=
|
||||
- beacon_data_len)) {
|
||||
+ bcn_offsets = beacon->cntdwn_counter_offsets;
|
||||
+ count = beacon->cntdwn_current_counter;
|
||||
+ if (sdata->vif.csa_active)
|
||||
+ max_count = IEEE80211_MAX_CNTDWN_COUNTERS_NUM;
|
||||
+
|
||||
+ for (i = 0; i < max_count; ++i) {
|
||||
+ if (bcn_offsets[i]) {
|
||||
+ if (WARN_ON_ONCE(bcn_offsets[i] >= beacon_data_len)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
-
|
||||
- beacon_data[beacon->cntdwn_counter_offsets[i]] = count;
|
||||
+ beacon_data[bcn_offsets[i]] = count;
|
||||
}
|
||||
|
||||
- if (sdata->vif.type == NL80211_IFTYPE_AP && resp)
|
||||
- resp->data[resp->cntdwn_counter_offsets[i]] = count;
|
||||
+ if (sdata->vif.type == NL80211_IFTYPE_AP && resp) {
|
||||
+ u16 *resp_offsets = resp->cntdwn_counter_offsets;
|
||||
+
|
||||
+ resp->data[resp_offsets[i]] = count;
|
||||
+ }
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -5044,6 +5050,7 @@ __ieee80211_beacon_get(struct ieee80211_
|
||||
if (offs) {
|
||||
offs->tim_offset = beacon->head_len;
|
||||
offs->tim_length = skb->len - beacon->head_len;
|
||||
+ offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
|
||||
|
||||
/* for AP the csa offsets are from tail */
|
||||
csa_off_base = skb->len;
|
@ -1,112 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 23 Aug 2021 20:02:38 +0200
|
||||
Subject: [PATCH] ieee80211: add TWT element definitions
|
||||
|
||||
Introduce TWT definitions and TWT Information element structure
|
||||
in ieee80211.h
|
||||
|
||||
Tested-by: Peter Chiu <chui-hao.chiu@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/71d8b581fe4b5abc5b92f8d77ac2de3e2f7591b6.1629741512.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/linux/ieee80211.h
|
||||
+++ b/include/linux/ieee80211.h
|
||||
@@ -1088,6 +1088,48 @@ struct ieee80211_ext {
|
||||
} u;
|
||||
} __packed __aligned(2);
|
||||
|
||||
+#define IEEE80211_TWT_CONTROL_NDP BIT(0)
|
||||
+#define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1)
|
||||
+#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3)
|
||||
+#define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4)
|
||||
+#define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5)
|
||||
+
|
||||
+#define IEEE80211_TWT_REQTYPE_REQUEST BIT(0)
|
||||
+#define IEEE80211_TWT_REQTYPE_SETUP_CMD GENMASK(3, 1)
|
||||
+#define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4)
|
||||
+#define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5)
|
||||
+#define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6)
|
||||
+#define IEEE80211_TWT_REQTYPE_FLOWID GENMASK(9, 7)
|
||||
+#define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP GENMASK(14, 10)
|
||||
+#define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15)
|
||||
+
|
||||
+enum ieee80211_twt_setup_cmd {
|
||||
+ TWT_SETUP_CMD_REQUEST,
|
||||
+ TWT_SETUP_CMD_SUGGEST,
|
||||
+ TWT_SETUP_CMD_DEMAND,
|
||||
+ TWT_SETUP_CMD_GROUPING,
|
||||
+ TWT_SETUP_CMD_ACCEPT,
|
||||
+ TWT_SETUP_CMD_ALTERNATE,
|
||||
+ TWT_SETUP_CMD_DICTATE,
|
||||
+ TWT_SETUP_CMD_REJECT,
|
||||
+};
|
||||
+
|
||||
+struct ieee80211_twt_params {
|
||||
+ __le16 req_type;
|
||||
+ __le64 twt;
|
||||
+ u8 min_twt_dur;
|
||||
+ __le16 mantissa;
|
||||
+ u8 channel;
|
||||
+} __packed;
|
||||
+
|
||||
+struct ieee80211_twt_setup {
|
||||
+ u8 dialog_token;
|
||||
+ u8 element_id;
|
||||
+ u8 length;
|
||||
+ u8 control;
|
||||
+ u8 params[];
|
||||
+} __packed;
|
||||
+
|
||||
struct ieee80211_mgmt {
|
||||
__le16 frame_control;
|
||||
__le16 duration;
|
||||
@@ -1252,6 +1294,10 @@ struct ieee80211_mgmt {
|
||||
__le16 toa_error;
|
||||
u8 variable[0];
|
||||
} __packed ftm;
|
||||
+ struct {
|
||||
+ u8 action_code;
|
||||
+ u8 variable[];
|
||||
+ } __packed s1g;
|
||||
} u;
|
||||
} __packed action;
|
||||
} u;
|
||||
@@ -2881,6 +2927,7 @@ enum ieee80211_eid {
|
||||
WLAN_EID_AID_RESPONSE = 211,
|
||||
WLAN_EID_S1G_BCN_COMPAT = 213,
|
||||
WLAN_EID_S1G_SHORT_BCN_INTERVAL = 214,
|
||||
+ WLAN_EID_S1G_TWT = 216,
|
||||
WLAN_EID_S1G_CAPABILITIES = 217,
|
||||
WLAN_EID_VENDOR_SPECIFIC = 221,
|
||||
WLAN_EID_QOS_PARAMETER = 222,
|
||||
@@ -2950,6 +2997,7 @@ enum ieee80211_category {
|
||||
WLAN_CATEGORY_FST = 18,
|
||||
WLAN_CATEGORY_UNPROT_DMG = 20,
|
||||
WLAN_CATEGORY_VHT = 21,
|
||||
+ WLAN_CATEGORY_S1G = 22,
|
||||
WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
|
||||
WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
|
||||
};
|
||||
@@ -3023,6 +3071,20 @@ enum ieee80211_key_len {
|
||||
WLAN_KEY_LEN_BIP_GMAC_256 = 32,
|
||||
};
|
||||
|
||||
+enum ieee80211_s1g_actioncode {
|
||||
+ WLAN_S1G_AID_SWITCH_REQUEST,
|
||||
+ WLAN_S1G_AID_SWITCH_RESPONSE,
|
||||
+ WLAN_S1G_SYNC_CONTROL,
|
||||
+ WLAN_S1G_STA_INFO_ANNOUNCE,
|
||||
+ WLAN_S1G_EDCA_PARAM_SET,
|
||||
+ WLAN_S1G_EL_OPERATION,
|
||||
+ WLAN_S1G_TWT_SETUP,
|
||||
+ WLAN_S1G_TWT_TEARDOWN,
|
||||
+ WLAN_S1G_SECT_GROUP_ID_LIST,
|
||||
+ WLAN_S1G_SECT_ID_FEEDBACK,
|
||||
+ WLAN_S1G_TWT_INFORMATION = 11,
|
||||
+};
|
||||
+
|
||||
#define IEEE80211_WEP_IV_LEN 4
|
||||
#define IEEE80211_WEP_ICV_LEN 4
|
||||
#define IEEE80211_CCMP_HDR_LEN 8
|
@ -1,604 +0,0 @@
|
||||
From f5a4c24e689f54e66201f04d343bdd2e8a1d7923 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 23 Aug 2021 20:02:39 +0200
|
||||
Subject: [PATCH] mac80211: introduce individual TWT support in AP mode
|
||||
|
||||
Introduce TWT action frames parsing support to mac80211.
|
||||
Currently just individual TWT agreement are support in AP mode.
|
||||
Whenever the AP receives a TWT action frame from an associated client,
|
||||
after performing sanity checks, it will notify the underlay driver with
|
||||
requested parameters in order to check if they are supported and if there
|
||||
is enough room for a new agreement. The driver is expected to set the
|
||||
agreement result and report it to mac80211.
|
||||
|
||||
Drivers supporting this have two new callbacks:
|
||||
- add_twt_setup (mandatory)
|
||||
- twt_teardown_request (optional)
|
||||
|
||||
mac80211 will send an action frame reply according to the result
|
||||
reported by the driver.
|
||||
|
||||
Tested-by: Peter Chiu <chui-hao.chiu@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/257512f2e22ba42b9f2624942a128dd8f141de4b.1629741512.git.lorenzo@kernel.org
|
||||
[use le16p_replace_bits(), minor cleanups, use (void *) casts,
|
||||
fix to use ieee80211_get_he_iftype_cap() correctly]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
include/net/mac80211.h | 12 +++
|
||||
net/mac80211/driver-ops.h | 36 ++++++++
|
||||
net/mac80211/ieee80211_i.h | 6 ++
|
||||
net/mac80211/iface.c | 41 +++++++++
|
||||
net/mac80211/rx.c | 73 +++++++++++++++
|
||||
net/mac80211/s1g.c | 180 +++++++++++++++++++++++++++++++++++++
|
||||
net/mac80211/status.c | 17 +++-
|
||||
net/mac80211/trace.h | 67 ++++++++++++++
|
||||
8 files changed, 430 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -3930,6 +3930,13 @@ struct ieee80211_prep_tx_info {
|
||||
* @set_sar_specs: Update the SAR (TX power) settings.
|
||||
* @sta_set_decap_offload: Called to notify the driver when a station is allowed
|
||||
* to use rx decapsulation offload
|
||||
+ * @add_twt_setup: Update hw with TWT agreement parameters received from the peer.
|
||||
+ * This callback allows the hw to check if requested parameters
|
||||
+ * are supported and if there is enough room for a new agreement.
|
||||
+ * The hw is expected to set agreement result in the req_type field of
|
||||
+ * twt structure.
|
||||
+ * @twt_teardown_request: Update the hw with TWT teardown request received
|
||||
+ * from the peer.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@@ -4253,6 +4260,11 @@ struct ieee80211_ops {
|
||||
void (*sta_set_decap_offload)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enabled);
|
||||
+ void (*add_twt_setup)(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ struct ieee80211_twt_setup *twt);
|
||||
+ void (*twt_teardown_request)(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_sta *sta, u8 flowid);
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1447,4 +1447,40 @@ static inline void drv_sta_set_decap_off
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
+static inline void drv_add_twt_setup(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ struct ieee80211_twt_setup *twt)
|
||||
+{
|
||||
+ struct ieee80211_twt_params *twt_agrt;
|
||||
+
|
||||
+ might_sleep();
|
||||
+
|
||||
+ if (!check_sdata_in_driver(sdata))
|
||||
+ return;
|
||||
+
|
||||
+ twt_agrt = (void *)twt->params;
|
||||
+
|
||||
+ trace_drv_add_twt_setup(local, sta, twt, twt_agrt);
|
||||
+ local->ops->add_twt_setup(&local->hw, sta, twt);
|
||||
+ trace_drv_return_void(local);
|
||||
+}
|
||||
+
|
||||
+static inline void drv_twt_teardown_request(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ u8 flowid)
|
||||
+{
|
||||
+ might_sleep();
|
||||
+ if (!check_sdata_in_driver(sdata))
|
||||
+ return;
|
||||
+
|
||||
+ if (!local->ops->twt_teardown_request)
|
||||
+ return;
|
||||
+
|
||||
+ trace_drv_twt_teardown_request(local, sta, flowid);
|
||||
+ local->ops->twt_teardown_request(&local->hw, sta, flowid);
|
||||
+ trace_drv_return_void(local);
|
||||
+}
|
||||
+
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -949,6 +949,7 @@ struct ieee80211_sub_if_data {
|
||||
|
||||
struct work_struct work;
|
||||
struct sk_buff_head skb_queue;
|
||||
+ struct sk_buff_head status_queue;
|
||||
|
||||
u8 needed_rx_chains;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
@@ -2083,6 +2084,11 @@ ieee80211_he_op_ie_to_bss_conf(struct ie
|
||||
|
||||
/* S1G */
|
||||
void ieee80211_s1g_sta_rate_init(struct sta_info *sta);
|
||||
+bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb);
|
||||
+void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sk_buff *skb);
|
||||
+void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sk_buff *skb);
|
||||
|
||||
/* Spectrum management */
|
||||
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -552,6 +552,7 @@ static void ieee80211_do_stop(struct iee
|
||||
*/
|
||||
ieee80211_free_keys(sdata, true);
|
||||
skb_queue_purge(&sdata->skb_queue);
|
||||
+ skb_queue_purge(&sdata->status_queue);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
@@ -1055,6 +1056,7 @@ int ieee80211_add_virtual_monitor(struct
|
||||
}
|
||||
|
||||
skb_queue_head_init(&sdata->skb_queue);
|
||||
+ skb_queue_head_init(&sdata->status_queue);
|
||||
INIT_WORK(&sdata->work, ieee80211_iface_work);
|
||||
|
||||
return 0;
|
||||
@@ -1459,6 +1461,16 @@ static void ieee80211_iface_process_skb(
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
+ } else if (ieee80211_is_action(mgmt->frame_control) &&
|
||||
+ mgmt->u.action.category == WLAN_CATEGORY_S1G) {
|
||||
+ switch (mgmt->u.action.u.s1g.action_code) {
|
||||
+ case WLAN_S1G_TWT_TEARDOWN:
|
||||
+ case WLAN_S1G_TWT_SETUP:
|
||||
+ ieee80211_s1g_rx_twt_action(sdata, skb);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
} else if (ieee80211_is_ext(mgmt->frame_control)) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_sta_rx_queued_ext(sdata, skb);
|
||||
@@ -1514,6 +1526,24 @@ static void ieee80211_iface_process_skb(
|
||||
}
|
||||
}
|
||||
|
||||
+static void ieee80211_iface_process_status(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
+
|
||||
+ if (ieee80211_is_action(mgmt->frame_control) &&
|
||||
+ mgmt->u.action.category == WLAN_CATEGORY_S1G) {
|
||||
+ switch (mgmt->u.action.u.s1g.action_code) {
|
||||
+ case WLAN_S1G_TWT_TEARDOWN:
|
||||
+ case WLAN_S1G_TWT_SETUP:
|
||||
+ ieee80211_s1g_status_twt_action(sdata, skb);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void ieee80211_iface_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata =
|
||||
@@ -1543,6 +1573,16 @@ static void ieee80211_iface_work(struct
|
||||
kcov_remote_stop();
|
||||
}
|
||||
|
||||
+ /* process status queue */
|
||||
+ while ((skb = skb_dequeue(&sdata->status_queue))) {
|
||||
+ kcov_remote_start_common(skb_get_kcov_handle(skb));
|
||||
+
|
||||
+ ieee80211_iface_process_status(sdata, skb);
|
||||
+ kfree_skb(skb);
|
||||
+
|
||||
+ kcov_remote_stop();
|
||||
+ }
|
||||
+
|
||||
/* then other type-dependent work */
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@@ -1606,6 +1646,7 @@ static void ieee80211_setup_sdata(struct
|
||||
}
|
||||
|
||||
skb_queue_head_init(&sdata->skb_queue);
|
||||
+ skb_queue_head_init(&sdata->status_queue);
|
||||
INIT_WORK(&sdata->work, ieee80211_iface_work);
|
||||
INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
|
||||
INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -3211,6 +3211,68 @@ ieee80211_rx_h_mgmt_check(struct ieee802
|
||||
return RX_CONTINUE;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+ieee80211_process_rx_twt_action(struct ieee80211_rx_data *rx)
|
||||
+{
|
||||
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)rx->skb->data;
|
||||
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
+ struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
+ const struct ieee80211_sta_he_cap *hecap;
|
||||
+ struct ieee80211_supported_band *sband;
|
||||
+
|
||||
+ /* TWT actions are only supported in AP for the moment */
|
||||
+ if (sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!rx->local->ops->add_twt_setup)
|
||||
+ return false;
|
||||
+
|
||||
+ sband = rx->local->hw.wiphy->bands[status->band];
|
||||
+ hecap = ieee80211_get_he_iftype_cap(sband,
|
||||
+ ieee80211_vif_type_p2p(&sdata->vif));
|
||||
+ if (!hecap)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!(hecap->he_cap_elem.mac_cap_info[0] &
|
||||
+ IEEE80211_HE_MAC_CAP0_TWT_RES))
|
||||
+ return false;
|
||||
+
|
||||
+ if (!rx->sta)
|
||||
+ return false;
|
||||
+
|
||||
+ switch (mgmt->u.action.u.s1g.action_code) {
|
||||
+ case WLAN_S1G_TWT_SETUP: {
|
||||
+ struct ieee80211_twt_setup *twt;
|
||||
+
|
||||
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE +
|
||||
+ 1 + /* action code */
|
||||
+ sizeof(struct ieee80211_twt_setup) +
|
||||
+ 2 /* TWT req_type agrt */)
|
||||
+ break;
|
||||
+
|
||||
+ twt = (void *)mgmt->u.action.u.s1g.variable;
|
||||
+ if (twt->element_id != WLAN_EID_S1G_TWT)
|
||||
+ break;
|
||||
+
|
||||
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE +
|
||||
+ 4 + /* action code + token + tlv */
|
||||
+ twt->length)
|
||||
+ break;
|
||||
+
|
||||
+ return true; /* queue the frame */
|
||||
+ }
|
||||
+ case WLAN_S1G_TWT_TEARDOWN:
|
||||
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + 2)
|
||||
+ break;
|
||||
+
|
||||
+ return true; /* queue the frame */
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static ieee80211_rx_result debug_noinline
|
||||
ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
@@ -3490,6 +3552,17 @@ ieee80211_rx_h_action(struct ieee80211_r
|
||||
!mesh_path_sel_is_hwmp(sdata))
|
||||
break;
|
||||
goto queue;
|
||||
+ case WLAN_CATEGORY_S1G:
|
||||
+ switch (mgmt->u.action.u.s1g.action_code) {
|
||||
+ case WLAN_S1G_TWT_SETUP:
|
||||
+ case WLAN_S1G_TWT_TEARDOWN:
|
||||
+ if (ieee80211_process_rx_twt_action(rx))
|
||||
+ goto queue;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
}
|
||||
|
||||
return RX_CONTINUE;
|
||||
--- a/net/mac80211/s1g.c
|
||||
+++ b/net/mac80211/s1g.c
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
+#include "driver-ops.h"
|
||||
|
||||
void ieee80211_s1g_sta_rate_init(struct sta_info *sta)
|
||||
{
|
||||
@@ -14,3 +15,182 @@ void ieee80211_s1g_sta_rate_init(struct
|
||||
sta->rx_stats.last_rate =
|
||||
STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G);
|
||||
}
|
||||
+
|
||||
+bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
+
|
||||
+ if (likely(!ieee80211_is_action(mgmt->frame_control)))
|
||||
+ return false;
|
||||
+
|
||||
+ if (likely(mgmt->u.action.category != WLAN_CATEGORY_S1G))
|
||||
+ return false;
|
||||
+
|
||||
+ return mgmt->u.action.u.s1g.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;
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ struct ieee80211_mgmt *mgmt;
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
|
||||
+ if (!skb)
|
||||
+ return;
|
||||
+
|
||||
+ skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
+ mgmt = skb_put_zero(skb, len);
|
||||
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
+ IEEE80211_STYPE_ACTION);
|
||||
+ memcpy(mgmt->da, da, ETH_ALEN);
|
||||
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
||||
+ 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);
|
||||
+
|
||||
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
+ IEEE80211_TX_INTFL_MLME_CONN_TX |
|
||||
+ IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
+ ieee80211_tx_skb(sdata, skb);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata,
|
||||
+ const u8 *da, const u8 *bssid, u8 flowid)
|
||||
+{
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ struct ieee80211_mgmt *mgmt;
|
||||
+ struct sk_buff *skb;
|
||||
+ u8 *id;
|
||||
+
|
||||
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
|
||||
+ IEEE80211_MIN_ACTION_SIZE + 2);
|
||||
+ if (!skb)
|
||||
+ return;
|
||||
+
|
||||
+ skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
+ mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE + 2);
|
||||
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
+ IEEE80211_STYPE_ACTION);
|
||||
+ memcpy(mgmt->da, da, ETH_ALEN);
|
||||
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
||||
+ 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;
|
||||
+ *id = flowid;
|
||||
+
|
||||
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
+ IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
+ ieee80211_tx_skb(sdata, skb);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+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_params *twt_agrt = (void *)twt->params;
|
||||
+
|
||||
+ twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST);
|
||||
+
|
||||
+ /* broadcast TWT not supported yet */
|
||||
+ if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) {
|
||||
+ le16p_replace_bits(&twt_agrt->req_type,
|
||||
+ TWT_SETUP_CMD_REJECT,
|
||||
+ IEEE80211_TWT_REQTYPE_SETUP_CMD);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ drv_add_twt_setup(sdata->local, sdata, &sta->sta, twt);
|
||||
+out:
|
||||
+ ieee80211_s1g_send_twt_setup(sdata, mgmt->sa, sdata->vif.addr, twt);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ieee80211_s1g_rx_twt_teardown(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sta_info *sta, struct sk_buff *skb)
|
||||
+{
|
||||
+ 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]);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+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_params *twt_agrt = (void *)twt->params;
|
||||
+ u8 flowid = le16_get_bits(twt_agrt->req_type,
|
||||
+ IEEE80211_TWT_REQTYPE_FLOWID);
|
||||
+
|
||||
+ drv_twt_teardown_request(sdata->local, sdata, &sta->sta, flowid);
|
||||
+
|
||||
+ ieee80211_s1g_send_twt_teardown(sdata, mgmt->sa, sdata->vif.addr,
|
||||
+ flowid);
|
||||
+}
|
||||
+
|
||||
+void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ struct sta_info *sta;
|
||||
+
|
||||
+ mutex_lock(&local->sta_mtx);
|
||||
+
|
||||
+ sta = sta_info_get_bss(sdata, mgmt->sa);
|
||||
+ if (!sta)
|
||||
+ goto out;
|
||||
+
|
||||
+ switch (mgmt->u.action.u.s1g.action_code) {
|
||||
+ case WLAN_S1G_TWT_SETUP:
|
||||
+ ieee80211_s1g_rx_twt_setup(sdata, sta, skb);
|
||||
+ break;
|
||||
+ case WLAN_S1G_TWT_TEARDOWN:
|
||||
+ ieee80211_s1g_rx_twt_teardown(sdata, sta, skb);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&local->sta_mtx);
|
||||
+}
|
||||
+
|
||||
+void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ struct sta_info *sta;
|
||||
+
|
||||
+ mutex_lock(&local->sta_mtx);
|
||||
+
|
||||
+ sta = sta_info_get_bss(sdata, mgmt->da);
|
||||
+ if (!sta)
|
||||
+ goto out;
|
||||
+
|
||||
+ switch (mgmt->u.action.u.s1g.action_code) {
|
||||
+ case WLAN_S1G_TWT_SETUP:
|
||||
+ /* process failed twt setup frames */
|
||||
+ ieee80211_s1g_tx_twt_setup_fail(sdata, sta, skb);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&local->sta_mtx);
|
||||
+}
|
||||
--- a/net/mac80211/status.c
|
||||
+++ b/net/mac80211/status.c
|
||||
@@ -705,13 +705,26 @@ static void ieee80211_report_used_skb(st
|
||||
/* Check to see if packet is a TDLS teardown packet */
|
||||
if (ieee80211_is_data(hdr->frame_control) &&
|
||||
(ieee80211_get_tdls_action(skb, hdr_size) ==
|
||||
- WLAN_TDLS_TEARDOWN))
|
||||
+ WLAN_TDLS_TEARDOWN)) {
|
||||
ieee80211_tdls_td_tx_handle(local, sdata, skb,
|
||||
info->flags);
|
||||
- else
|
||||
+ } else if (ieee80211_s1g_is_twt_setup(skb)) {
|
||||
+ if (!acked) {
|
||||
+ struct sk_buff *qskb;
|
||||
+
|
||||
+ qskb = skb_clone(skb, GFP_ATOMIC);
|
||||
+ if (qskb) {
|
||||
+ skb_queue_tail(&sdata->status_queue,
|
||||
+ qskb);
|
||||
+ ieee80211_queue_work(&local->hw,
|
||||
+ &sdata->work);
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
ieee80211_mgd_conn_tx_status(sdata,
|
||||
hdr->frame_control,
|
||||
acked);
|
||||
+ }
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2825,6 +2825,73 @@ DEFINE_EVENT(sta_flag_evt, drv_sta_set_d
|
||||
TP_ARGS(local, sdata, sta, enabled)
|
||||
);
|
||||
|
||||
+TRACE_EVENT(drv_add_twt_setup,
|
||||
+ TP_PROTO(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ struct ieee80211_twt_setup *twt,
|
||||
+ struct ieee80211_twt_params *twt_agrt),
|
||||
+
|
||||
+ TP_ARGS(local, sta, twt, twt_agrt),
|
||||
+
|
||||
+ TP_STRUCT__entry(
|
||||
+ LOCAL_ENTRY
|
||||
+ STA_ENTRY
|
||||
+ __field(u8, dialog_token)
|
||||
+ __field(u8, control)
|
||||
+ __field(__le16, req_type)
|
||||
+ __field(__le64, twt)
|
||||
+ __field(u8, duration)
|
||||
+ __field(__le16, mantissa)
|
||||
+ __field(u8, channel)
|
||||
+ ),
|
||||
+
|
||||
+ TP_fast_assign(
|
||||
+ LOCAL_ASSIGN;
|
||||
+ STA_ASSIGN;
|
||||
+ __entry->dialog_token = twt->dialog_token;
|
||||
+ __entry->control = twt->control;
|
||||
+ __entry->req_type = twt_agrt->req_type;
|
||||
+ __entry->twt = twt_agrt->twt;
|
||||
+ __entry->duration = twt_agrt->min_twt_dur;
|
||||
+ __entry->mantissa = twt_agrt->mantissa;
|
||||
+ __entry->channel = twt_agrt->channel;
|
||||
+ ),
|
||||
+
|
||||
+ TP_printk(
|
||||
+ LOCAL_PR_FMT STA_PR_FMT
|
||||
+ " token:%d control:0x%02x req_type:0x%04x"
|
||||
+ " twt:%llu duration:%d mantissa:%d channel:%d",
|
||||
+ LOCAL_PR_ARG, STA_PR_ARG, __entry->dialog_token,
|
||||
+ __entry->control, le16_to_cpu(__entry->req_type),
|
||||
+ le64_to_cpu(__entry->twt), __entry->duration,
|
||||
+ le16_to_cpu(__entry->mantissa), __entry->channel
|
||||
+ )
|
||||
+);
|
||||
+
|
||||
+TRACE_EVENT(drv_twt_teardown_request,
|
||||
+ TP_PROTO(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sta *sta, u8 flowid),
|
||||
+
|
||||
+ TP_ARGS(local, sta, flowid),
|
||||
+
|
||||
+ TP_STRUCT__entry(
|
||||
+ LOCAL_ENTRY
|
||||
+ STA_ENTRY
|
||||
+ __field(u8, flowid)
|
||||
+ ),
|
||||
+
|
||||
+ TP_fast_assign(
|
||||
+ LOCAL_ASSIGN;
|
||||
+ STA_ASSIGN;
|
||||
+ __entry->flowid = flowid;
|
||||
+ ),
|
||||
+
|
||||
+ TP_printk(
|
||||
+ LOCAL_PR_FMT STA_PR_FMT " flowid:%d",
|
||||
+ LOCAL_PR_ARG, STA_PR_ARG, __entry->flowid
|
||||
+ )
|
||||
+);
|
||||
+
|
||||
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
@ -87,7 +87,7 @@
|
||||
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1428,6 +1428,7 @@ struct ieee80211_local {
|
||||
@@ -1429,6 +1429,7 @@ struct ieee80211_local {
|
||||
int dynamic_ps_forced_timeout;
|
||||
|
||||
int user_power_level; /* in dBm, for all interfaces */
|
||||
|
Loading…
x
Reference in New Issue
Block a user