diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 7b93f8024..715e851a1 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=5.10.42-1 -PKG_RELEASE:=3 -PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.10.42/ -PKG_HASH:=6876520105240844fdb32d1dcdf2bfdea291a37a96f16c892fda3776ba714fcb +PKG_VERSION:=5.15.8-1 +PKG_RELEASE:=2 +PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.8/ +PKG_HASH:=9f71b659c034f19d156532ec780fcb606cee3c4ccc42e2f8ef18dd3e9f1b6820 PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) @@ -23,7 +23,6 @@ PKG_MAINTAINER:=Felix Fietkau PKG_DRIVERS = \ adm8211 \ - airo \ hermes hermes-pci hermes-pcmcia hermes-plx\ lib80211 \ mac80211-hwsim \ @@ -84,7 +83,6 @@ config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE config-$(call config_package,mac80211) += MAC80211 config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH -config-$(CONFIG_PACKAGE_MAC80211_NSS_SUPPORT) += MAC80211_NSS_SUPPORT include ath.mk include broadcom.mk @@ -99,7 +97,7 @@ PKG_CONFIG_DEPENDS += \ define KernelPackage/cfg80211 $(call KernelPackage/mac80211/Default) TITLE:=cfg80211 - wireless configuration API - DEPENDS+= +iw +iwinfo +wireless-regdb + DEPENDS+= +iw +iwinfo +wireless-regdb +USE_RFKILL:kmod-rfkill ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) FILES:= \ $(PKG_BUILD_DIR)/compat/compat.ko \ @@ -128,7 +126,7 @@ define KernelPackage/mac80211 $(call KernelPackage/mac80211/Default) TITLE:=Linux 802.11 Wireless Networking Stack # +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c - DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common +PACKAGE_kmod-qca-nss-drv:kmod-qca-nss-drv +PACKAGE_kmod-qca-nss-drv-64:kmod-qca-nss-drv-64 + DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common KCONFIG:=\ CONFIG_AVERAGE=y FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko @@ -138,14 +136,6 @@ endef define KernelPackage/mac80211/config if PACKAGE_kmod-mac80211 - - if PACKAGE_kmod-qca-nss-drv||PACKAGE_kmod-qca-nss-drv-64 - config PACKAGE_MAC80211_NSS_SUPPORT - bool "Enable NSS support for IPQ platform" - default y - help - This option enables support for NSS in boards. - endif config PACKAGE_MAC80211_DEBUGFS bool "Export mac80211 internals in DebugFS" @@ -183,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 @@ -415,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 @@ -451,8 +427,7 @@ endif MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \ $(KERNEL_MAKE_FLAGS) \ - EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES) \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv" \ + EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES)" \ KLIB_BUILD="$(LINUX_DIR)" \ MODPROBE=true \ KLIB=$(TARGET_MODULES_DIR) \ diff --git a/package/kernel/mac80211/ath.mk b/package/kernel/mac80211/ath.mk index ebd47f89d..bf2da0ae8 100644 --- a/package/kernel/mac80211/ath.mk +++ b/package/kernel/mac80211/ath.mk @@ -12,7 +12,6 @@ PKG_CONFIG_DEPENDS += \ CONFIG_ATH9K_TX99 \ CONFIG_ATH10K_LEDS \ CONFIG_ATH10K_THERMAL \ - CONFIG_ATH11K_MEM_PROFILE_512M \ CONFIG_ATH_USER_REGD ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS @@ -55,7 +54,6 @@ config-$(CONFIG_ATH9K_TX99) += ATH9K_TX99 config-$(CONFIG_ATH9K_UBNTHSR) += ATH9K_UBNTHSR config-$(CONFIG_ATH10K_LEDS) += ATH10K_LEDS config-$(CONFIG_ATH10K_THERMAL) += ATH10K_THERMAL -config-$(CONFIG_ATH11K_MEM_PROFILE_512M) += ATH11K_MEM_PROFILE_512M config-$(call config_package,ath9k-htc) += ATH9K_HTC config-$(call config_package,ath10k) += ATH10K ATH10K_PCI @@ -319,11 +317,6 @@ define KernelPackage/ath11k/config depends on PACKAGE_kmod-ath11k default y if TARGET_ipq807x - config ATH11K_MEM_PROFILE_512M - bool "Enable 512MB profile" - depends on PACKAGE_kmod-ath11k - default y if TARGET_ipq807x_generic_DEVICE_redmi_ax6 || TARGET_ipq807x_generic_DEVICE_xiaomi_ax3600 || TARGET_ipq807x_generic_DEVICE_zte_mf269 - endef define KernelPackage/ath11k-ahb diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index a27b0e104..d74a2e006 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -52,6 +52,8 @@ drv_mac80211_init_device_config() { he_spr_sr_control \ he_twt_required config_add_int \ + beamformer_antennas \ + beamformee_antennas \ vht_max_a_mpdu_len_exp \ vht_max_mpdu \ vht_link_adapt \ @@ -147,6 +149,9 @@ mac80211_hostapd_setup_base() { [ "$noscan" -gt 0 ] && hostapd_noscan=1 [ "$tx_burst" = 0 ] && tx_burst= + chan_ofs=0 + [ "$band" = "6g" ] && chan_ofs=1 + ieee80211n=1 ht_capab= case "$htmode" in @@ -154,7 +159,7 @@ mac80211_hostapd_setup_base() { HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160) case "$hwmode" in a) - case "$(( ($channel / 4) % 2 ))" in + case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in 1) ht_capab="[HT40+]";; 0) ht_capab="[HT40-]";; esac @@ -223,8 +228,6 @@ mac80211_hostapd_setup_base() { enable_ac=0 vht_oper_chwidth=0 vht_center_seg0= - chan_ofs=0 - [ "$band" = "6g" ] && chan_ofs=1 idx="$channel" case "$htmode" in @@ -292,6 +295,8 @@ mac80211_hostapd_setup_base() { mu_beamformee:1 \ vht_txop_ps:1 \ htc_vht:1 \ + beamformee_antennas:4 \ + beamformer_antennas:4 \ rx_antenna_pattern:1 \ tx_antenna_pattern:1 \ vht_max_a_mpdu_len_exp:7 \ @@ -332,6 +337,18 @@ mac80211_hostapd_setup_base() { RX-STBC-123:0x700:0x300:1 \ RX-STBC-1234:0x700:0x400:1 \ + [ "$(($vht_cap & 0x800))" -gt 0 -a "$su_beamformer" -gt 0 ] && { + cap_ant="$(( ( ($vht_cap >> 16) & 3 ) + 1 ))" + [ "$cap_ant" -gt "$beamformer_antennas" ] && cap_ant="$beamformer_antennas" + [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[SOUNDING-DIMENSION-$cap_ant]" + } + + [ "$(($vht_cap & 0x1000))" -gt 0 -a "$su_beamformee" -gt 0 ] && { + cap_ant="$(( ( ($vht_cap >> 13) & 3 ) + 1 ))" + [ "$cap_ant" -gt "$beamformee_antennas" ] && cap_ant="$beamformee_antennas" + [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[BF-ANTENNA-$cap_ant]" + } + # supported Channel widths vht160_hw=0 [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \ @@ -624,7 +641,7 @@ mac80211_iw_interface_add() { rc="$?" } - [ "$rc" != 0 ] && wireless_setup_failed INTERFACE_CREATION_FAILED + [ "$rc" != 0 ] && echo "Failed to create interface $ifname" return $rc } @@ -859,6 +876,7 @@ mac80211_setup_adhoc() { mcval= [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" + iw dev "$ifname" set type ibss iw dev "$ifname" ibss join "$ssid" $freq $iw_htmode fixed-freq $bssid \ beacon-interval $beacon_int \ ${brstr:+basic-rates $brstr} \ diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh index c9d24c8e1..4c5981850 100644 --- a/package/kernel/mac80211/files/lib/wifi/mac80211.sh +++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh @@ -176,7 +176,7 @@ detect_mac80211() { set wireless.radio${devidx}.htmode=$htmode set wireless.radio${devidx}.disabled=0 set wireless.radio${devidx}.country=US - + set wireless.default_radio${devidx}=wifi-iface set wireless.default_radio${devidx}.device=radio${devidx} set wireless.default_radio${devidx}.network=lan diff --git a/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch b/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch deleted file mode 100644 index d1d6c9e2e..000000000 --- a/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: Christian Lamparter -Date: Sat, 16 Nov 2019 19:25:24 +0100 -Subject: [PATCH] owl_loader: compatibility patch - -This patch includes OpenWrt specific changes that are -not included in the upstream owl-loader. - -This includes a platform data handling changes for ar71xx. - -Signed-off-by: Christian Lamparter - ---- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c -+++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c -@@ -103,6 +103,7 @@ static void owl_fw_cb(const struct firmw - { - struct pci_dev *pdev = (struct pci_dev *)context; - struct owl_ctx *ctx = (struct owl_ctx *)pci_get_drvdata(pdev); -+ struct ath9k_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct pci_bus *bus; - - complete(&ctx->eeprom_load); -@@ -118,6 +119,16 @@ static void owl_fw_cb(const struct firmw - goto release; - } - -+ if (pdata) { -+ memcpy(pdata->eeprom_data, fw->data, fw->size); -+ -+ /* -+ * eeprom has been successfully loaded - pass the data to ath9k -+ * but remove the eeprom_name, so it doesn't try to load it too. -+ */ -+ pdata->eeprom_name = NULL; -+ } -+ - if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size)) - goto release; - -@@ -137,8 +148,14 @@ release: - static const char *owl_get_eeprom_name(struct pci_dev *pdev) - { - struct device *dev = &pdev->dev; -+ struct ath9k_platform_data *pdata; - char *eeprom_name; - -+ /* try the existing platform data first */ -+ pdata = dev_get_platdata(dev); -+ if (pdata && pdata->eeprom_name) -+ return pdata->eeprom_name; -+ - dev_dbg(dev, "using auto-generated eeprom filename\n"); - - eeprom_name = devm_kzalloc(dev, EEPROM_FILENAME_LEN, GFP_KERNEL); diff --git a/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch index db10c4510..eacc72776 100644 --- a/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch +++ b/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch @@ -14,7 +14,7 @@ CFLAGS_trace.o := -I$(src) --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -316,14 +316,7 @@ void _ath_dbg(struct ath_common *common, +@@ -317,14 +317,7 @@ void _ath_dbg(struct ath_common *common, #endif /* CPTCFG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ diff --git a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch index 3c9180b11..506beb79c 100644 --- a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch @@ -37,7 +37,7 @@ for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!wiphy->bands[band]) continue; -@@ -378,6 +387,9 @@ ath_reg_apply_ir_flags(struct wiphy *wip +@@ -379,6 +388,9 @@ ath_reg_apply_ir_flags(struct wiphy *wip { struct ieee80211_supported_band *sband; @@ -47,7 +47,7 @@ sband = wiphy->bands[NL80211_BAND_2GHZ]; if (!sband) return; -@@ -407,6 +419,9 @@ static void ath_reg_apply_radar_flags(st +@@ -408,6 +420,9 @@ static void ath_reg_apply_radar_flags(st struct ieee80211_channel *ch; unsigned int i; @@ -57,7 +57,7 @@ if (!wiphy->bands[NL80211_BAND_5GHZ]) return; -@@ -639,6 +654,10 @@ ath_regd_init_wiphy(struct ath_regulator +@@ -640,6 +655,10 @@ ath_regd_init_wiphy(struct ath_regulator const struct ieee80211_regdomain *regd; wiphy->reg_notifier = reg_notifier; @@ -82,7 +82,7 @@ help --- a/local-symbols +++ b/local-symbols -@@ -86,6 +86,7 @@ ADM8211= +@@ -76,6 +76,7 @@ ADM8211= ATH_COMMON= WLAN_VENDOR_ATH= ATH_DEBUG= diff --git a/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch index c6dc184e2..833e2411c 100644 --- a/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch +++ b/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch @@ -1,6 +1,6 @@ --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -3252,6 +3252,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; -@@ -3503,6 +3505,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) { diff --git a/package/kernel/mac80211/patches/ath/406-ath_relax_default_regd.patch b/package/kernel/mac80211/patches/ath/406-ath_relax_default_regd.patch index 35b0f2b76..ee4e46134 100644 --- a/package/kernel/mac80211/patches/ath/406-ath_relax_default_regd.patch +++ b/package/kernel/mac80211/patches/ath/406-ath_relax_default_regd.patch @@ -39,7 +39,7 @@ bool ath_is_world_regd(struct ath_regulatory *reg) { return is_wwr_sku(ath_regd_get_eepromRD(reg)); -@@ -658,6 +666,9 @@ ath_regd_init_wiphy(struct ath_regulator +@@ -659,6 +667,9 @@ ath_regd_init_wiphy(struct ath_regulator if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) return 0; diff --git a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch index 9ce44fd28..0886fd688 100644 --- a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch +++ b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch @@ -37,7 +37,7 @@ void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); --- a/local-symbols +++ b/local-symbols -@@ -145,6 +145,7 @@ ATH10K_SNOC= +@@ -135,6 +135,7 @@ ATH10K_SNOC= ATH10K_DEBUG= ATH10K_DEBUGFS= ATH10K_SPECTRAL= diff --git a/package/kernel/mac80211/patches/ath10k/120-ath10k-fetch-calibration-data-via-nvmem-subsystem.patch b/package/kernel/mac80211/patches/ath10k/120-ath10k-fetch-calibration-data-via-nvmem-subsystem.patch new file mode 100644 index 000000000..6728a69ef --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/120-ath10k-fetch-calibration-data-via-nvmem-subsystem.patch @@ -0,0 +1,162 @@ +From e2333703373e8b81294da5d1c73c30154f75b082 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 15 Oct 2021 18:56:33 +0200 +Subject: [PATCH] ath10k: fetch (pre-)calibration data via nvmem subsystem + +On most embedded ath10k devices (like range extenders, +routers, accesspoints, ...) the calibration data is +stored in a easily accessible MTD partitions named +"ART", "caldata", "calibration", etc... + +Since commit 4b361cfa8624 ("mtd: core: add OTP nvmem provider support"): +MTD partitions and portions of them can be specified +as potential nvmem-cells which are accessible through +the nvmem subsystem. + +This feature - together with an nvmem cell definition either +in the platform data or via device-tree allows drivers to get +the (pre-)calibration data which is required for initializing +the WIFI. + +Tested with Netgear EX6150v2 (IPQ4018) + +Cc: Robert Marko +Cc: Thibaut Varene +Signed-off-by: Christian Lamparter +--- +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + + #include "core.h" +@@ -935,7 +936,8 @@ static int ath10k_core_get_board_id_from + } + + if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || +- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) ++ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE || ++ ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM) + bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID; + else + bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID; +@@ -1726,7 +1728,8 @@ static int ath10k_download_and_run_otp(s + + /* As of now pre-cal is valid for 10_4 variants */ + if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || +- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) ++ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE || ++ ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM) + bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; + + ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); +@@ -1853,6 +1856,39 @@ out_free: + return ret; + } + ++static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name) ++{ ++ struct nvmem_cell *cell; ++ void *buf; ++ size_t len; ++ int ret; ++ ++ cell = devm_nvmem_cell_get(ar->dev, cell_name); ++ if (IS_ERR(cell)) { ++ ret = PTR_ERR(cell); ++ return ret; ++ } ++ ++ buf = nvmem_cell_read(cell, &len); ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ ++ if (ar->hw_params.cal_data_len != len) { ++ kfree(buf); ++ ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n", ++ cell_name, len, ar->hw_params.cal_data_len); ++ return -EMSGSIZE; ++ } ++ ++ ret = ath10k_download_board_data(ar, buf, len); ++ kfree(buf); ++ if (ret) ++ ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n", ++ cell_name, ret); ++ ++ return ret; ++} ++ + int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file) + { +@@ -2087,6 +2123,18 @@ static int ath10k_core_pre_cal_download( + { + int ret; + ++ ret = ath10k_download_cal_nvmem(ar, "pre-calibration"); ++ if (ret == 0) { ++ ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM; ++ goto success; ++ } else if (ret == -EPROBE_DEFER) { ++ return ret; ++ } ++ ++ ath10k_dbg(ar, ATH10K_DBG_BOOT, ++ "boot did not find a pre-calibration nvmem-cell, try file next: %d\n", ++ ret); ++ + ret = ath10k_download_cal_file(ar, ar->pre_cal_file); + if (ret == 0) { + ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE; +@@ -2153,6 +2201,18 @@ static int ath10k_download_cal_data(stru + "pre cal download procedure failed, try cal file: %d\n", + ret); + ++ ret = ath10k_download_cal_nvmem(ar, "calibration"); ++ if (ret == 0) { ++ ar->cal_mode = ATH10K_CAL_MODE_NVMEM; ++ goto done; ++ } else if (ret == -EPROBE_DEFER) { ++ return ret; ++ } ++ ++ ath10k_dbg(ar, ATH10K_DBG_BOOT, ++ "boot did not find a calibration nvmem-cell, try file next: %d\n", ++ ret); ++ + ret = ath10k_download_cal_file(ar, ar->cal_file); + if (ret == 0) { + ar->cal_mode = ATH10K_CAL_MODE_FILE; +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -877,8 +877,10 @@ enum ath10k_cal_mode { + ATH10K_CAL_MODE_FILE, + ATH10K_CAL_MODE_OTP, + ATH10K_CAL_MODE_DT, ++ ATH10K_CAL_MODE_NVMEM, + ATH10K_PRE_CAL_MODE_FILE, + ATH10K_PRE_CAL_MODE_DT, ++ ATH10K_PRE_CAL_MODE_NVMEM, + ATH10K_CAL_MODE_EEPROM, + }; + +@@ -898,10 +900,14 @@ static inline const char *ath10k_cal_mod + return "otp"; + case ATH10K_CAL_MODE_DT: + return "dt"; ++ case ATH10K_CAL_MODE_NVMEM: ++ return "nvmem"; + case ATH10K_PRE_CAL_MODE_FILE: + return "pre-cal-file"; + case ATH10K_PRE_CAL_MODE_DT: + return "pre-cal-dt"; ++ case ATH10K_PRE_CAL_MODE_NVMEM: ++ return "pre-cal-nvmem"; + case ATH10K_CAL_MODE_EEPROM: + return "eeprom"; + } diff --git a/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch index e004acc34..710cd4526 100644 --- a/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch @@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -3189,6 +3189,16 @@ int ath10k_core_register(struct ath10k * +@@ -3412,6 +3412,16 @@ int ath10k_core_register(struct ath10k * queue_work(ar->workqueue, &ar->register_work); diff --git a/package/kernel/mac80211/patches/ath10k/922-ath10k-increase-rx-buffer-size-to-2048.patch b/package/kernel/mac80211/patches/ath10k/922-ath10k-increase-rx-buffer-size-to-2048.patch deleted file mode 100644 index 8f7a60eec..000000000 --- a/package/kernel/mac80211/patches/ath10k/922-ath10k-increase-rx-buffer-size-to-2048.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Linus Lüssing -Date: Wed, 5 Feb 2020 20:10:43 +0100 -Subject: ath10k: increase rx buffer size to 2048 - -Before, only frames with a maximum size of 1528 bytes could be -transmitted between two 802.11s nodes. - -For batman-adv for instance, which adds its own header to each frame, -we typically need an MTU of at least 1532 bytes to be able to transmit -without fragmentation. - -This patch now increases the maxmimum frame size from 1528 to 1656 -bytes. - -Tested with two ath10k devices in 802.11s mode, as well as with -batman-adv on top of 802.11s with forwarding disabled. - -Fix originally found and developed by Ben Greear. - -Link: https://github.com/greearb/ath10k-ct/issues/89 -Link: https://github.com/greearb/ath10k-ct/commit/9e5ab25027e0971fa24ccf93373324c08c4e992d -Cc: Ben Greear -Signed-off-by: Linus Lüssing - -Forwarded: https://patchwork.kernel.org/patch/11367055/ - ---- a/drivers/net/wireless/ath/ath10k/htt.h -+++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -2243,7 +2243,7 @@ struct htt_rx_chan_info { - * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size, - * rounded up to a cache line size. - */ --#define HTT_RX_BUF_SIZE 1920 -+#define HTT_RX_BUF_SIZE 2048 - #define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) - - /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle diff --git a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch index 74b3292e0..b60db1946 100644 --- a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch +++ b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -9708,6 +9708,21 @@ static int ath10k_mac_init_rd(struct ath +@@ -9843,6 +9843,21 @@ static int ath10k_mac_init_rd(struct ath return 0; } @@ -22,7 +22,7 @@ int ath10k_mac_register(struct ath10k *ar) { static const u32 cipher_suites[] = { -@@ -10057,6 +10072,12 @@ int ath10k_mac_register(struct ath10k *a +@@ -10195,6 +10210,12 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; diff --git a/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch index fa007e73a..65d67b2e0 100644 --- a/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch +++ b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -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. @@ -114,7 +114,7 @@ v13: ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o --- a/local-symbols +++ b/local-symbols -@@ -146,6 +146,7 @@ ATH10K_DEBUG= +@@ -136,6 +136,7 @@ ATH10K_DEBUG= ATH10K_DEBUGFS= ATH10K_SPECTRAL= ATH10K_THERMAL= @@ -124,7 +124,7 @@ v13: WCN36XX= --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -25,6 +25,7 @@ +@@ -26,6 +26,7 @@ #include "testmode.h" #include "wmi-ops.h" #include "coredump.h" @@ -132,7 +132,7 @@ v13: unsigned int ath10k_debug_mask; EXPORT_SYMBOL(ath10k_debug_mask); -@@ -61,6 +62,7 @@ static const struct ath10k_hw_params ath +@@ -62,6 +63,7 @@ static const struct ath10k_hw_params ath .dev_id = QCA988X_2_0_DEVICE_ID, .bus = ATH10K_BUS_PCI, .name = "qca988x hw2.0", @@ -140,7 +140,7 @@ v13: .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, -@@ -130,6 +132,7 @@ static const struct ath10k_hw_params ath +@@ -133,6 +135,7 @@ static const struct ath10k_hw_params ath .dev_id = QCA9887_1_0_DEVICE_ID, .bus = ATH10K_BUS_PCI, .name = "qca9887 hw1.0", @@ -148,7 +148,7 @@ v13: .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, -@@ -335,6 +338,7 @@ static const struct ath10k_hw_params ath +@@ -344,6 +347,7 @@ static const struct ath10k_hw_params ath .dev_id = QCA99X0_2_0_DEVICE_ID, .bus = ATH10K_BUS_PCI, .name = "qca99x0 hw2.0", @@ -156,7 +156,7 @@ v13: .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .otp_exe_param = 0x00000700, -@@ -375,6 +379,7 @@ static const struct ath10k_hw_params ath +@@ -385,6 +389,7 @@ static const struct ath10k_hw_params ath .dev_id = QCA9984_1_0_DEVICE_ID, .bus = ATH10K_BUS_PCI, .name = "qca9984/qca9994 hw1.0", @@ -164,7 +164,7 @@ v13: .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, -@@ -422,6 +427,7 @@ static const struct ath10k_hw_params ath +@@ -433,6 +438,7 @@ static const struct ath10k_hw_params ath .dev_id = QCA9888_2_0_DEVICE_ID, .bus = ATH10K_BUS_PCI, .name = "qca9888 hw2.0", @@ -172,7 +172,7 @@ v13: .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, -@@ -2904,6 +2910,10 @@ int ath10k_core_start(struct ath10k *ar, +@@ -3127,6 +3133,10 @@ int ath10k_core_start(struct ath10k *ar, goto err_hif_stop; } @@ -183,7 +183,7 @@ v13: return 0; err_hif_stop: -@@ -3162,9 +3172,18 @@ static void ath10k_core_register_work(st +@@ -3385,9 +3395,18 @@ static void ath10k_core_register_work(st goto err_spectral_destroy; } @@ -202,7 +202,7 @@ v13: err_spectral_destroy: ath10k_spectral_destroy(ar); err_debug_destroy: -@@ -3210,6 +3229,8 @@ void ath10k_core_unregister(struct ath10 +@@ -3433,6 +3452,8 @@ void ath10k_core_unregister(struct ath10 if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) return; @@ -221,7 +221,7 @@ v13: #include "htt.h" #include "htc.h" -@@ -1237,6 +1238,13 @@ struct ath10k { +@@ -1256,6 +1257,13 @@ struct ath10k { } testmode; struct { @@ -467,7 +467,7 @@ v13: static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -7468,6 +7468,49 @@ ath10k_wmi_op_gen_peer_set_param(struct +@@ -7472,6 +7472,49 @@ ath10k_wmi_op_gen_peer_set_param(struct return skb; } @@ -517,7 +517,7 @@ v13: static struct sk_buff * ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, enum wmi_sta_ps_mode psmode) -@@ -9156,6 +9199,9 @@ static const struct wmi_ops wmi_ops = { +@@ -9160,6 +9203,9 @@ static const struct wmi_ops wmi_ops = { .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, .gen_echo = ath10k_wmi_op_gen_echo, @@ -527,7 +527,7 @@ v13: /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9226,6 +9272,8 @@ static const struct wmi_ops wmi_10_1_ops +@@ -9230,6 +9276,8 @@ static const struct wmi_ops wmi_10_1_ops .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, .gen_echo = ath10k_wmi_op_gen_echo, @@ -536,7 +536,7 @@ v13: /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9298,6 +9346,8 @@ static const struct wmi_ops wmi_10_2_ops +@@ -9302,6 +9350,8 @@ static const struct wmi_ops wmi_10_2_ops .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, @@ -545,7 +545,7 @@ v13: /* .gen_pdev_enable_adaptive_cca not implemented */ }; -@@ -9369,6 +9419,8 @@ static const struct wmi_ops wmi_10_2_4_o +@@ -9373,6 +9423,8 @@ static const struct wmi_ops wmi_10_2_4_o ath10k_wmi_op_gen_pdev_enable_adaptive_cca, .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, .gen_bb_timing = ath10k_wmi_10_2_4_op_gen_bb_timing, @@ -554,7 +554,7 @@ v13: /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9450,6 +9502,8 @@ static const struct wmi_ops wmi_10_4_ops +@@ -9454,6 +9506,8 @@ static const struct wmi_ops wmi_10_4_ops .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info, .gen_echo = ath10k_wmi_op_gen_echo, .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, @@ -565,7 +565,7 @@ v13: int ath10k_wmi_attach(struct ath10k *ar) --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h -@@ -3027,6 +3027,41 @@ enum wmi_10_4_feature_mask { +@@ -3030,6 +3030,41 @@ enum wmi_10_4_feature_mask { }; diff --git a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch index 6da7bfa72..da31ad578 100644 --- a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch +++ b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch @@ -16,9 +16,9 @@ Signed-off-by: Mathias Kresin --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -1290,6 +1290,10 @@ struct ath10k { - bool coex_support; - int coex_gpio_pin; +@@ -1312,6 +1312,10 @@ struct ath10k { + s32 tx_power_2g_limit; + s32 tx_power_5g_limit; +#ifdef CPTCFG_MAC80211_LEDS + const char *led_default_trigger; @@ -42,7 +42,7 @@ Signed-off-by: Mathias Kresin if (ret) --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -10074,7 +10074,7 @@ int ath10k_mac_register(struct ath10k *a +@@ -10212,7 +10212,7 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; #ifdef CPTCFG_MAC80211_LEDS diff --git a/package/kernel/mac80211/patches/ath10k/980-ath10k-fix-max-antenna-gain-unit.patch b/package/kernel/mac80211/patches/ath10k/980-ath10k-fix-max-antenna-gain-unit.patch deleted file mode 100644 index e951e011e..000000000 --- a/package/kernel/mac80211/patches/ath10k/980-ath10k-fix-max-antenna-gain-unit.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Sven Eckelmann -Date: Tue, 11 Jun 2019 13:58:35 +0200 -Subject: ath10k: fix max antenna gain unit - -Most of the txpower for the ath10k firmware is stored as twicepower (0.5 dB -steps). This isn't the case for max_antenna_gain - which is still expected -by the firmware as dB. - -The firmware is converting it from dB to the internal (twicepower) -representation when it calculates the limits of a channel. This can be seen -in tpc_stats when configuring "12" as max_antenna_gain. Instead of the -expected 12 (6 dB), the tpc_stats shows 24 (12 dB). - -Tested on QCA9888 and IPQ4019 with firmware 10.4-3.5.3-00057. - -Fixes: 02256930d9b8 ("ath10k: use proper tx power unit") -Signed-off-by: Sven Eckelmann - -Forwarded: https://patchwork.kernel.org/patch/10986723/ - ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1038,7 +1038,7 @@ static int ath10k_monitor_vdev_start(str - arg.channel.min_power = 0; - arg.channel.max_power = channel->max_power * 2; - arg.channel.max_reg_power = channel->max_reg_power * 2; -- arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; -+ arg.channel.max_antenna_gain = channel->max_antenna_gain; - - reinit_completion(&ar->vdev_setup_done); - reinit_completion(&ar->vdev_delete_done); -@@ -1484,7 +1484,7 @@ static int ath10k_vdev_start_restart(str - arg.channel.min_power = 0; - arg.channel.max_power = chandef->chan->max_power * 2; - arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; -- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; -+ arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; - - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - arg.ssid = arvif->u.ap.ssid; -@@ -3255,7 +3255,7 @@ static int ath10k_update_channel_list(st - ch->min_power = 0; - ch->max_power = channel->max_power * 2; - ch->max_reg_power = channel->max_reg_power * 2; -- ch->max_antenna_gain = channel->max_antenna_gain * 2; -+ ch->max_antenna_gain = channel->max_antenna_gain; - ch->reg_class_id = 0; /* FIXME */ - - /* FIXME: why use only legacy modes, why not any diff --git a/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch index a149ce121..a45addf11 100644 --- a/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch +++ b/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch @@ -28,7 +28,7 @@ Forwarded: no --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1006,6 +1006,40 @@ static inline int ath10k_vdev_setup_sync +@@ -1021,6 +1021,40 @@ static inline int ath10k_vdev_setup_sync return ar->last_wmi_vdev_start_status; } @@ -69,7 +69,7 @@ Forwarded: no static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) { struct cfg80211_chan_def *chandef = NULL; -@@ -1038,7 +1072,8 @@ static int ath10k_monitor_vdev_start(str +@@ -1053,7 +1087,8 @@ static int ath10k_monitor_vdev_start(str arg.channel.min_power = 0; arg.channel.max_power = channel->max_power * 2; arg.channel.max_reg_power = channel->max_reg_power * 2; @@ -79,7 +79,7 @@ Forwarded: no reinit_completion(&ar->vdev_setup_done); reinit_completion(&ar->vdev_delete_done); -@@ -1484,7 +1519,8 @@ static int ath10k_vdev_start_restart(str +@@ -1499,7 +1534,8 @@ static int ath10k_vdev_start_restart(str arg.channel.min_power = 0; arg.channel.max_power = chandef->chan->max_power * 2; arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; @@ -89,7 +89,7 @@ Forwarded: no if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { arg.ssid = arvif->u.ap.ssid; -@@ -3255,7 +3291,8 @@ static int ath10k_update_channel_list(st +@@ -3427,7 +3463,8 @@ static int ath10k_update_channel_list(st ch->min_power = 0; ch->max_power = channel->max_power * 2; ch->max_reg_power = channel->max_reg_power * 2; diff --git a/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch b/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch new file mode 100644 index 000000000..e14329cce --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch @@ -0,0 +1,37 @@ +From 22fb5991a44c78ff18ec0082dc90c809356eb893 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 27 Sep 2020 19:23:35 +0200 +Subject: [PATCH 1/2] ath10k: Try to get mac-address from dts + +Most of embedded device that have the ath10k wifi integrated store the +mac-address in nvmem partitions. Try to fetch the mac-address using the +standard 'of_get_mac_address' than in all the check also try to fetch the +address using the nvmem api searching for a defined 'mac-address' cell. +Mac-address defined in the dts have priority than any other address found. + +Tested-on: QCA9984 hw1.0 PCI 10.4 + +Signed-off-by: Ansuel Smith +--- + drivers/net/wireless/ath/ath10k/core.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3303,6 +3304,8 @@ static int ath10k_core_probe_fw(struct a + + device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr)); + ++ of_get_mac_address(ar->dev->of_node, ar->mac_addr); ++ + ret = ath10k_core_init_firmware_features(ar); + if (ret) { + ath10k_err(ar, "fatal problem with firmware features: %d\n", diff --git a/package/kernel/mac80211/patches/ath/990-ath10k-small-buffers.patch b/package/kernel/mac80211/patches/ath10k/990-ath10k-small-buffers.patch similarity index 100% rename from package/kernel/mac80211/patches/ath/990-ath10k-small-buffers.patch rename to package/kernel/mac80211/patches/ath10k/990-ath10k-small-buffers.patch diff --git a/package/kernel/mac80211/patches/ath10k/999-ath10k-Enable-802.11-encap-offload-in-tx-path.patch b/package/kernel/mac80211/patches/ath10k/999-ath10k-Enable-802.11-encap-offload-in-tx-path.patch deleted file mode 100644 index 65e40444d..000000000 --- a/package/kernel/mac80211/patches/ath10k/999-ath10k-Enable-802.11-encap-offload-in-tx-path.patch +++ /dev/null @@ -1,337 +0,0 @@ ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -35,6 +35,7 @@ static bool uart_print; - static bool skip_otp; - static bool rawmode; - static bool fw_diag_log; -+static bool ethernetmode = true; - - unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) | - BIT(ATH10K_FW_CRASH_DUMP_CE_DATA); -@@ -47,6 +48,7 @@ module_param(skip_otp, bool, 0644); - module_param(rawmode, bool, 0644); - module_param(fw_diag_log, bool, 0644); - module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444); -+module_param(ethernetmode, bool, 0644); - - MODULE_PARM_DESC(debug_mask, "Debugging mask"); - MODULE_PARM_DESC(uart_print, "Uart target debugging"); -@@ -55,6 +57,7 @@ MODULE_PARM_DESC(cryptmode, "Crypto mode - MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath"); - MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file"); - MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging"); -+MODULE_PARM_DESC(ethernetmode, "Use ethernet frame datapath"); - - static const struct ath10k_hw_params ath10k_hw_params_list[] = { - { -@@ -3135,6 +3138,14 @@ static void ath10k_core_register_work(st - /* peer stats are enabled by default */ - set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags); - -+ if (ethernetmode && rawmode) { -+ ath10k_err(ar, "invalid configuration, ethernet and rawmode data path can not coexist\n"); -+ status = -EINVAL; -+ goto err; -+ } -+ -+ ar->ethernetmode = ethernetmode; -+ - status = ath10k_core_probe_fw(ar); - if (status) { - ath10k_err(ar, "could not probe fw (%d)\n", status); ---- a/drivers/net/wireless/ath/ath10k/core.h -+++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -113,6 +113,7 @@ enum ath10k_skb_flags { - ATH10K_SKB_F_QOS = BIT(4), - ATH10K_SKB_F_RAW_TX = BIT(5), - ATH10K_SKB_F_NOACK_TID = BIT(6), -+ ATH10K_SKB_F_HW_80211_ENCAP = BIT(7), - }; - - struct ath10k_skb_cb { -@@ -1294,6 +1295,8 @@ struct ath10k { - const char *led_default_trigger; - #endif - -+ bool ethernetmode; -+ - /* must be last */ - u8 drv_priv[] __aligned(sizeof(void *)); - }; ---- a/drivers/net/wireless/ath/ath10k/htt_tx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c -@@ -1187,6 +1187,10 @@ static u8 ath10k_htt_tx_get_tid(struct s - struct ieee80211_hdr *hdr = (void *)skb->data; - struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); - -+ /* Firmware takes care of tid classification for ethernet format */ -+ if (cb->flags & ATH10K_SKB_F_HW_80211_ENCAP) -+ return skb->priority & IEEE80211_QOS_CTL_TID_MASK; -+ - if (!is_eth && ieee80211_is_mgmt(hdr->frame_control)) - return HTT_DATA_TX_EXT_TID_MGMT; - else if (cb->flags & ATH10K_SKB_F_QOS) -@@ -1434,15 +1438,17 @@ static int ath10k_htt_tx_32(struct ath10 - txbuf_paddr = htt->txbuf.paddr + - (sizeof(struct ath10k_htt_txbuf_32) * msdu_id); - -- if ((ieee80211_is_action(hdr->frame_control) || -- ieee80211_is_deauth(hdr->frame_control) || -- ieee80211_is_disassoc(hdr->frame_control)) && -- ieee80211_has_protected(hdr->frame_control)) { -- skb_put(msdu, IEEE80211_CCMP_MIC_LEN); -- } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && -- txmode == ATH10K_HW_TXRX_RAW && -- ieee80211_has_protected(hdr->frame_control)) { -- skb_put(msdu, IEEE80211_CCMP_MIC_LEN); -+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) { -+ if ((ieee80211_is_action(hdr->frame_control) || -+ ieee80211_is_deauth(hdr->frame_control) || -+ ieee80211_is_disassoc(hdr->frame_control)) && -+ ieee80211_has_protected(hdr->frame_control)) { -+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN); -+ } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && -+ txmode == ATH10K_HW_TXRX_RAW && -+ ieee80211_has_protected(hdr->frame_control)) { -+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN); -+ } - } - - skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -3573,12 +3573,16 @@ ath10k_mac_tx_h_get_txmode(struct ath10k - struct sk_buff *skb) - { - const struct ieee80211_hdr *hdr = (void *)skb->data; -+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); - __le16 fc = hdr->frame_control; - - if (!vif || vif->type == NL80211_IFTYPE_MONITOR) - return ATH10K_HW_TXRX_RAW; - -+ if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) -+ return ATH10K_HW_TXRX_ETHERNET; -+ - if (ieee80211_is_mgmt(fc)) - return ATH10K_HW_TXRX_MGMT; - -@@ -3736,6 +3740,15 @@ static void ath10k_mac_tx_h_fill_cb(stru - bool noack = false; - - cb->flags = 0; -+ cb->vif = vif; -+ cb->txq = txq; -+ cb->airtime_est = airtime; -+ -+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { -+ cb->flags |= ATH10K_SKB_F_HW_80211_ENCAP; -+ return; -+ } -+ - if (!ath10k_tx_h_use_hwcrypto(vif, skb)) - cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; - -@@ -3774,9 +3787,6 @@ static void ath10k_mac_tx_h_fill_cb(stru - cb->flags |= ATH10K_SKB_F_RAW_TX; - } - -- cb->vif = vif; -- cb->txq = txq; -- cb->airtime_est = airtime; - if (sta) { - arsta = (struct ath10k_sta *)sta->drv_priv; - spin_lock_bh(&ar->data_lock); -@@ -3892,6 +3902,9 @@ static int ath10k_mac_tx(struct ath10k * - const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); - int ret; - -+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) -+ goto skip_encap; -+ - /* We should disable CCK RATE due to P2P */ - if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) - ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n"); -@@ -3915,6 +3928,7 @@ static int ath10k_mac_tx(struct ath10k * - } - } - -+skip_encap: - if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { - if (!ath10k_mac_tx_frm_has_freq(ar)) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n", -@@ -3964,6 +3978,7 @@ void ath10k_offchan_tx_work(struct work_ - int ret; - unsigned long time_left; - bool tmp_peer_created = false; -+ struct ieee80211_tx_info *info; - - /* FW requirement: We must create a peer before FW will send out - * an offchannel frame. Otherwise the frame will be stuck and -@@ -3983,8 +3998,14 @@ void ath10k_offchan_tx_work(struct work_ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n", - skb, skb->len); - -- hdr = (struct ieee80211_hdr *)skb->data; -- peer_addr = ieee80211_get_DA(hdr); -+ info = IEEE80211_SKB_CB(skb); -+ -+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { -+ peer_addr = skb->data; -+ } else { -+ hdr = (struct ieee80211_hdr *)skb->data; -+ peer_addr = ieee80211_get_DA(hdr); -+ } - - spin_lock_bh(&ar->data_lock); - vdev_id = ar->scan.vdev_id; -@@ -4517,7 +4538,7 @@ static void ath10k_mac_op_tx(struct ieee - struct ieee80211_vif *vif = info->control.vif; - struct ieee80211_sta *sta = control->sta; - struct ieee80211_txq *txq = NULL; -- struct ieee80211_hdr *hdr = (void *)skb->data; -+ struct ieee80211_hdr *hdr; - enum ath10k_hw_txrx_mode txmode; - enum ath10k_mac_tx_path txpath; - bool is_htt; -@@ -4537,7 +4558,6 @@ static void ath10k_mac_op_tx(struct ieee - - if (is_htt) { - spin_lock_bh(&ar->htt.tx_lock); -- is_presp = ieee80211_is_probe_resp(hdr->frame_control); - - ret = ath10k_htt_tx_inc_pending(htt); - if (ret) { -@@ -4548,14 +4568,19 @@ static void ath10k_mac_op_tx(struct ieee - return; - } - -- ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp); -- if (ret) { -- ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n", -- ret); -- ath10k_htt_tx_dec_pending(htt); -- spin_unlock_bh(&ar->htt.tx_lock); -- ieee80211_free_txskb(ar->hw, skb); -- return; -+ if (is_mgmt) { -+ hdr = (struct ieee80211_hdr *)skb->data; -+ is_presp = ieee80211_is_probe_resp(hdr->frame_control); -+ -+ ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp); -+ if (ret) { -+ ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n", -+ ret); -+ ath10k_htt_tx_dec_pending(htt); -+ spin_unlock_bh(&ar->htt.tx_lock); -+ ieee80211_free_txskb(ar->hw, skb); -+ return; -+ } - } - spin_unlock_bh(&ar->htt.tx_lock); - } -@@ -5378,6 +5403,36 @@ static int ath10k_mac_set_txbf_conf(stru - ar->wmi.vdev_param->txbf, value); - } - -+static void ath10k_mac_op_update_vif_offload(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif) -+{ -+ struct ath10k *ar = hw->priv; -+ struct ath10k_vif *arvif = (void *)vif->drv_priv; -+ -+ u32 vdev_param, param_value; -+ int ret; -+ -+ vdev_param = ar->wmi.vdev_param->tx_encap_type; -+ if (!ar->ethernetmode || -+ (vif->type != NL80211_IFTYPE_STATION && -+ vif->type != NL80211_IFTYPE_AP)) -+ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; -+ -+ if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) -+ param_value = ATH10K_HW_TXRX_ETHERNET; -+ else -+ param_value = ATH10K_HW_TXRX_NATIVE_WIFI; -+ -+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, -+ param_value); -+ -+ if (ret) { -+ ath10k_info(ar, "failed to set vdev %i TX encapsulation: %d\n", -+ arvif->vdev_id, ret); -+ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; -+ } -+} -+ - /* - * TODO: - * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE, -@@ -5571,15 +5626,7 @@ static int ath10k_add_interface(struct i - - arvif->def_wep_key_idx = -1; - -- vdev_param = ar->wmi.vdev_param->tx_encap_type; -- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, -- ATH10K_HW_TXRX_NATIVE_WIFI); -- /* 10.X firmware does not support this VDEV parameter. Do not warn */ -- if (ret && ret != -EOPNOTSUPP) { -- ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n", -- arvif->vdev_id, ret); -- goto err_vdev_delete; -- } -+ ath10k_mac_op_update_vif_offload(hw, vif); - - /* Configuring number of spatial stream for monitor interface is causing - * target assert in qca9888 and qca6174. -@@ -9260,6 +9307,7 @@ static const struct ieee80211_ops ath10k - .config = ath10k_config, - .add_interface = ath10k_add_interface, - .remove_interface = ath10k_remove_interface, -+ .update_vif_offload = ath10k_mac_op_update_vif_offload, - .configure_filter = ath10k_configure_filter, - .bss_info_changed = ath10k_bss_info_changed, - .set_coverage_class = ath10k_mac_op_set_coverage_class, -@@ -9886,6 +9934,9 @@ int ath10k_mac_register(struct ath10k *a - ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); - ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); - -+ if(ar->ethernetmode) -+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); -+ - if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) - ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL); - ---- a/drivers/net/wireless/ath/ath10k/txrx.c -+++ b/drivers/net/wireless/ath/ath10k/txrx.c -@@ -50,6 +50,7 @@ int ath10k_txrx_tx_unref(struct ath10k_h - struct ath10k_skb_cb *skb_cb; - struct ath10k_txq *artxq; - struct sk_buff *msdu; -+ struct ieee80211_vif *vif; - u8 flags; - - ath10k_dbg(ar, ATH10K_DBG_HTT, -@@ -80,6 +81,8 @@ int ath10k_txrx_tx_unref(struct ath10k_h - } - - flags = skb_cb->flags; -+ vif = skb_cb->vif; -+ - ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - ath10k_htt_tx_dec_pending(htt); - if (htt->num_pending_tx == 0) -@@ -130,7 +133,11 @@ int ath10k_txrx_tx_unref(struct ath10k_h - info->status.is_valid_ack_signal = true; - } - -- ieee80211_tx_status(htt->ar->hw, msdu); -+ if (flags & ATH10K_SKB_F_HW_80211_ENCAP) -+ ieee80211_tx_status_8023(htt->ar->hw, vif, msdu); -+ else -+ ieee80211_tx_status(htt->ar->hw, msdu); -+ - /* we do not own the msdu anymore */ - - return 0; diff --git a/package/kernel/mac80211/patches/ath11k/001-v5.11-ath11k-search-DT-for-qcom-ath11k-calibration-variant.patch b/package/kernel/mac80211/patches/ath11k/001-v5.11-ath11k-search-DT-for-qcom-ath11k-calibration-variant.patch deleted file mode 100644 index d71ba4049..000000000 --- a/package/kernel/mac80211/patches/ath11k/001-v5.11-ath11k-search-DT-for-qcom-ath11k-calibration-variant.patch +++ /dev/null @@ -1,144 +0,0 @@ -From da4ccc477bb46cc518991828ae8ac79e856f92ab Mon Sep 17 00:00:00 2001 -From: Sven Eckelmann -Date: Thu, 15 Oct 2020 15:15:01 +0200 -Subject: [PATCH] ath11k: search DT for qcom,ath11k-calibration-variant - -Board Data File (BDF) is loaded upon driver boot-up procedure. The right -board data file is identified on IPQ6018 using bus, qmi-chip-id and -qmi-board-id. - -The problem, however, can occur when the (default) board data file cannot -fulfill with the vendor requirements and it is necessary to use a different -board data file. - -This problem was already solved on ath10k by adding a ",variant=.*" at the -end of the board name. The same functionality must also be provided for -ath11k. - -The device tree requires an additional string to define the variant name - - wifi@c000000 { - status = "okay"; - qcom,ath11k-calibration-variant = "Cigtech-WF-188"; - }; - -This would create the boarddata identifier for the board-2.bin search - - * bus=ahb,qmi-chip-id=0,qmi-board-id=18,variant=Cigtech-WF-188 - -Signed-off-by: Sven Eckelmann -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20201015131501.1939685-2-sven@narfation.org ---- - drivers/net/wireless/ath/ath11k/core.c | 35 ++++++++++++++++++++++++-- - drivers/net/wireless/ath/ath11k/core.h | 1 + - drivers/net/wireless/ath/ath11k/qmi.c | 5 ++++ - drivers/net/wireless/ath/ath11k/qmi.h | 2 ++ - 4 files changed, 41 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include "core.h" - #include "dp_tx.h" - #include "dp_rx.h" -@@ -141,14 +142,44 @@ static const struct ath11k_hw_params ath - }, - }; - -+int ath11k_core_check_dt(struct ath11k_base *ab) -+{ -+ size_t max_len = sizeof(ab->qmi.target.bdf_ext); -+ const char *variant = NULL; -+ struct device_node *node; -+ -+ node = ab->dev->of_node; -+ if (!node) -+ return -ENOENT; -+ -+ of_property_read_string(node, "qcom,ath11k-calibration-variant", -+ &variant); -+ if (!variant) -+ return -ENODATA; -+ -+ if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0) -+ ath11k_dbg(ab, ATH11K_DBG_BOOT, -+ "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", -+ variant); -+ -+ return 0; -+} -+ - static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, - size_t name_len) - { -+ /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ -+ char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; -+ -+ if (ab->qmi.target.bdf_ext[0] != '\0') -+ scnprintf(variant, sizeof(variant), ",variant=%s", -+ ab->qmi.target.bdf_ext); -+ - scnprintf(name, name_len, -- "bus=%s,qmi-chip-id=%d,qmi-board-id=%d", -+ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", - ath11k_bus_str(ab->hif.bus), - ab->qmi.target.chip_id, -- ab->qmi.target.board_id); -+ ab->qmi.target.board_id, variant); - - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name); - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -886,6 +886,7 @@ void ath11k_core_free(struct ath11k_base - int ath11k_core_fetch_bdf(struct ath11k_base *ath11k, - struct ath11k_board_data *bd); - void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd); -+int ath11k_core_check_dt(struct ath11k_base *ath11k); - - void ath11k_core_halt(struct ath11k *ar); - ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -1815,6 +1815,7 @@ static int ath11k_qmi_request_target_cap - struct qmi_wlanfw_cap_resp_msg_v01 resp; - struct qmi_txn txn = {}; - int ret = 0; -+ int r; - - memset(&req, 0, sizeof(req)); - memset(&resp, 0, sizeof(resp)); -@@ -1880,6 +1881,10 @@ static int ath11k_qmi_request_target_cap - ab->qmi.target.fw_build_timestamp, - ab->qmi.target.fw_build_id); - -+ r = ath11k_core_check_dt(ab); -+ if (r) -+ ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n"); -+ - out: - return ret; - } ---- a/drivers/net/wireless/ath/ath11k/qmi.h -+++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -24,6 +24,7 @@ - #define ATH11K_QMI_RESP_LEN_MAX 8192 - #define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 32 - #define ATH11K_QMI_CALDB_SIZE 0x480000 -+#define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20 - - #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 - #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 -@@ -101,6 +102,7 @@ struct target_info { - u32 fw_version; - char fw_build_timestamp[ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1]; - char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1]; -+ char bdf_ext[ATH11K_QMI_BDF_EXT_STR_LENGTH]; - }; - - struct m3_mem_region { diff --git a/package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch b/package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch deleted file mode 100644 index a6351e5c8..000000000 --- a/package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 4b965be536eefdd16ca0a88120fee23f5b92cd16 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Mon, 8 Feb 2021 13:32:11 +0200 -Subject: ath11k: Update tx descriptor search index properly - -Tx descriptor search index field should be updated with hw peer id -and not by AST Hash as per the HW/FW recommendation. Incorrect search -index causes throughput degradation in all scenario for all the -platforms. so updated the search index field with hw peer id, which -is a common change applicable for all the platforms. Also no need of these -configuration for non station type. seen 10% throughput increase in WDS -traffic with this change. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01492-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Karthikeyan Periyasamy -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/1612410960-9120-1-git-send-email-periyasa@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/core.h | 1 + - drivers/net/wireless/ath/ath11k/dp_rx.c | 8 ++++++-- - drivers/net/wireless/ath/ath11k/dp_tx.c | 1 + - drivers/net/wireless/ath/ath11k/hal_tx.c | 2 ++ - drivers/net/wireless/ath/ath11k/hal_tx.h | 1 + - drivers/net/wireless/ath/ath11k/peer.c | 9 +++++++-- - drivers/net/wireless/ath/ath11k/peer.h | 3 ++- - 7 files changed, 20 insertions(+), 5 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -193,6 +193,7 @@ struct ath11k_vif { - u32 beacon_interval; - u32 dtim_period; - u16 ast_hash; -+ u16 ast_idx; - u16 tcl_metadata; - u8 hal_addr_search_flags; - u8 search_type; ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1648,6 +1648,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s - u8 mac_addr[ETH_ALEN]; - u16 peer_mac_h16; - u16 ast_hash; -+ u16 hw_peer_id; - - ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type); - -@@ -1668,7 +1669,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s - resp->peer_map_ev.info1); - ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, - peer_mac_h16, mac_addr); -- ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0); -+ ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0); - break; - case HTT_T2H_MSG_TYPE_PEER_MAP2: - vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID, -@@ -1681,7 +1682,10 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s - peer_mac_h16, mac_addr); - ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, - resp->peer_map_ev.info2); -- ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash); -+ hw_peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID, -+ resp->peer_map_ev.info1); -+ ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, -+ hw_peer_id); - break; - case HTT_T2H_MSG_TYPE_PEER_UNMAP: - case HTT_T2H_MSG_TYPE_PEER_UNMAP2: ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -165,6 +165,7 @@ tcl_ring_sel: - ti.pkt_offset = 0; - ti.lmac_id = ar->lmac_id; - ti.bss_ast_hash = arvif->ast_hash; -+ ti.bss_ast_idx = arvif->ast_idx; - ti.dscp_tid_tbl_idx = 0; - - if (skb->ip_summed == CHECKSUM_PARTIAL && ---- a/drivers/net/wireless/ath/ath11k/hal_tx.c -+++ b/drivers/net/wireless/ath/ath11k/hal_tx.c -@@ -71,6 +71,8 @@ void ath11k_hal_tx_cmd_desc_setup(struct - tcl_cmd->info3 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_DSCP_TID_TABLE_IDX, - ti->dscp_tid_tbl_idx) | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_SEARCH_INDEX, -+ ti->bss_ast_idx) | -+ FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_CACHE_SET_NUM, - ti->bss_ast_hash); - tcl_cmd->info4 = 0; - } ---- a/drivers/net/wireless/ath/ath11k/hal_tx.h -+++ b/drivers/net/wireless/ath/ath11k/hal_tx.h -@@ -29,6 +29,7 @@ struct hal_tx_info { - u32 flags1; /* %HAL_TCL_DATA_CMD_INFO2_ */ - u16 addr_search_flags; /* %HAL_TCL_DATA_CMD_INFO0_ADDR(X/Y)_ */ - u16 bss_ast_hash; -+ u16 bss_ast_idx; - u8 tid; - u8 search_type; /* %HAL_TX_ADDR_SEARCH_ */ - u8 lmac_id; ---- a/drivers/net/wireless/ath/ath11k/peer.c -+++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -118,7 +118,7 @@ exit: - } - - void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, -- u8 *mac_addr, u16 ast_hash) -+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) - { - struct ath11k_peer *peer; - -@@ -132,6 +132,7 @@ void ath11k_peer_map_event(struct ath11k - peer->vdev_id = vdev_id; - peer->peer_id = peer_id; - peer->ast_hash = ast_hash; -+ peer->hw_peer_id = hw_peer_id; - ether_addr_copy(peer->addr, mac_addr); - list_add(&peer->list, &ab->peers); - wake_up(&ab->peer_mapping_wq); -@@ -309,7 +310,11 @@ int ath11k_peer_create(struct ath11k *ar - - peer->pdev_idx = ar->pdev_idx; - peer->sta = sta; -- arvif->ast_hash = peer->ast_hash; -+ -+ if (arvif->vif->type == NL80211_IFTYPE_STATION) { -+ arvif->ast_hash = peer->ast_hash; -+ arvif->ast_idx = peer->hw_peer_id; -+ } - - peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; - peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; ---- a/drivers/net/wireless/ath/ath11k/peer.h -+++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -14,6 +14,7 @@ struct ath11k_peer { - int peer_id; - u16 ast_hash; - u8 pdev_idx; -+ u16 hw_peer_id; - - /* protected by ab->data_lock */ - struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; -@@ -31,7 +32,7 @@ struct ath11k_peer { - - void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); - void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, -- u8 *mac_addr, u16 ast_hash); -+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); - struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, - const u8 *addr); - struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, diff --git a/package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch b/package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch deleted file mode 100644 index 1522273e5..000000000 --- a/package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cf8480d338a1b9156121e5e035e6b9721db4332a Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Mon, 11 Jan 2021 19:49:30 +0200 -Subject: ath11k: remove duplicate function declaration - -Removed the duplicated peer related function declaration -from core.h since those functions are already declared in peer.h - -Founded in code review. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01492-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Karthikeyan Periyasamy -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/1608304793-20612-1-git-send-email-periyasa@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/core.h | 8 -------- - 1 file changed, 8 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -868,14 +868,6 @@ extern const struct service_to_pipe ath1 - extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[]; - extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[]; - --void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); --void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, -- u8 *mac_addr, u16 ast_hash); --struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, -- const u8 *addr); --struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, -- const u8 *addr); --struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, int peer_id); - int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab); - int ath11k_core_pre_init(struct ath11k_base *ab); - int ath11k_core_init(struct ath11k_base *ath11k); diff --git a/package/kernel/mac80211/patches/ath11k/004-v5.12-ath11k-fix-ZERO-address-in-probe-request.patch b/package/kernel/mac80211/patches/ath11k/004-v5.12-ath11k-fix-ZERO-address-in-probe-request.patch deleted file mode 100644 index 60ce26768..000000000 --- a/package/kernel/mac80211/patches/ath11k/004-v5.12-ath11k-fix-ZERO-address-in-probe-request.patch +++ /dev/null @@ -1,38 +0,0 @@ -From fa7572c2cfe081dff82f884fa05f1b067d4beaaa Mon Sep 17 00:00:00 2001 -From: Carl Huang -Date: Fri, 6 Nov 2020 08:55:48 +0200 -Subject: ath11k: fix ZERO address in probe request - -Host needs to pass at least on bssid with all 0xff to firmware in -WMI_START_SCAN_CMDID, otherwise the bssid and receiver address -in probe requeste are all ZEROs. - -This also fixed some hidden AP connection issue because some AP -doesn't respond to probe request which receiver address are all -ZEROs. - -Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 - -Signed-off-by: Carl Huang -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20201012101733.24137-1-cjhuang@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/wmi.c | 5 +++++ - 1 file changed, 5 insertions(+) - -(limited to 'drivers/net/wireless/ath/ath11k') - ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1946,6 +1946,11 @@ void ath11k_wmi_start_scan_init(struct a - WMI_SCAN_EVENT_DEQUEUED; - arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT; - arg->num_bssid = 1; -+ -+ /* fill bssid_list[0] with 0xff, otherwise bssid and RA will be -+ * ZEROs in probe request -+ */ -+ eth_broadcast_addr(arg->bssid_list[0].addr); - } - - static inline void diff --git a/package/kernel/mac80211/patches/ath11k/005-v5.13-ath11k-Fix-sounding-dimension-config-in-HE-cap.patch b/package/kernel/mac80211/patches/ath11k/005-v5.13-ath11k-Fix-sounding-dimension-config-in-HE-cap.patch deleted file mode 100644 index d843465c3..000000000 --- a/package/kernel/mac80211/patches/ath11k/005-v5.13-ath11k-Fix-sounding-dimension-config-in-HE-cap.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 096b625fab8f9d88d9b436288a64b70080219d4b Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Wed, 17 Feb 2021 11:45:45 +0200 -Subject: ath11k: Fix sounding dimension config in HE cap - -Number of Sounding dimensions config received from firmware for -bandwidth above 80MHz is cleared, and proper value is not set again. -So not resetting it to accept the config from firmware. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01689-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Lavanya Suresh -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/1613460136-7170-1-git-send-email-lavaks@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/mac.c | 2 -- - 1 file changed, 2 deletions(-) - -(limited to 'drivers/net/wireless/ath/ath11k') - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3744,8 +3744,6 @@ static int ath11k_mac_copy_he_cap(struct - - he_cap_elem->phy_cap_info[5] &= - ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; -- he_cap_elem->phy_cap_info[5] &= -- ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK; - he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1; - - switch (i) { diff --git a/package/kernel/mac80211/patches/ath11k/006-v5.13-ath11k-Update-signal-filled-flag-during-sta_statistics-drv-op.patch b/package/kernel/mac80211/patches/ath11k/006-v5.13-ath11k-Update-signal-filled-flag-during-sta_statistics-drv-op.patch deleted file mode 100644 index c948a348d..000000000 --- a/package/kernel/mac80211/patches/ath11k/006-v5.13-ath11k-Update-signal-filled-flag-during-sta_statistics-drv-op.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f277eb0500b4ee1cbe9db8615761f19b5a5520c9 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Wed, 24 Feb 2021 14:32:41 +0530 -Subject: ath11k: Update signal filled flag during sta_statistics drv op - -Currently, though the peer rssi information is updated to station dump -from driver sta_statistics mac op, the info doesn't get updated -since the NL80211_STA_INFO_SIGNAL filled flag is not set in station -info. Hence update this flag while filling the rssi info. - -Tested on: IPQ8074 WLAN.HK.2.1.0.1-01213-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Sriram R -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20210224090241.3098-1-srirrama@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/mac.c | 1 + - 1 file changed, 1 insertion(+) - -(limited to 'drivers/net/wireless/ath/ath11k') - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5898,6 +5898,7 @@ static void ath11k_mac_op_sta_statistics - - /* TODO: Use real NF instead of default one. */ - sinfo->signal = arsta->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); - } - - static const struct ieee80211_ops ath11k_ops = { diff --git a/package/kernel/mac80211/patches/ath11k/007-ath11k-switch-to-using-ieee80211_tx_status_ext.patch b/package/kernel/mac80211/patches/ath11k/007-ath11k-switch-to-using-ieee80211_tx_status_ext.patch deleted file mode 100644 index 4cf5709f2..000000000 --- a/package/kernel/mac80211/patches/ath11k/007-ath11k-switch-to-using-ieee80211_tx_status_ext.patch +++ /dev/null @@ -1,143 +0,0 @@ -From patchwork Sun Apr 4 12:52:33 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Pradeep Kumar Chitrapu -X-Patchwork-Id: 12182277 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham - autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 2BB7BC433B4 - for ; - Sun, 4 Apr 2021 12:52:56 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id EE74761041 - for ; - Sun, 4 Apr 2021 12:52:55 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S229983AbhDDMw7 (ORCPT - ); - Sun, 4 Apr 2021 08:52:59 -0400 -Received: from so254-9.mailgun.net ([198.61.254.9]:17051 "EHLO - so254-9.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S229483AbhDDMw6 (ORCPT - ); - Sun, 4 Apr 2021 08:52:58 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1617540774; h=References: In-Reply-To: Message-Id: Date: - Subject: Cc: To: From: Sender; - bh=/GXnwqptt6p6CF8Ju3RWi0Vi/H9CAhjNh6c9swux4qw=; - b=tGeZoN0fcpg6Yz7zhTvx3F8v6K2l45+2zEn+LVCMOnofEU6UylvRzwgYQscWV2SyAdcdXAJl - YXfiqu86NFyKeSOy0HwUljtRSv5W0TsrnwrhcTPepD+mqig74O7HV9ApkX70bWbxQ5SFsEcs - Q8AizUlCnS3Z8p8yj23M+tyFRtg= -X-Mailgun-Sending-Ip: 198.61.254.9 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n01.prod.us-west-2.postgun.com with SMTP id - 6069b69cf34440a9d4cbfce8 (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Sun, 04 Apr 2021 12:52:44 - GMT -Sender: pradeepc=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id 26F3CC43462; Sun, 4 Apr 2021 12:52:44 +0000 (UTC) -Received: from pradeepc2-linux.qualcomm.com (i-global254.qualcomm.com - [199.106.103.254]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: pradeepc) - by smtp.codeaurora.org (Postfix) with ESMTPSA id B5E48C433C6; - Sun, 4 Apr 2021 12:52:42 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org B5E48C433C6 -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=pradeepc@codeaurora.org -From: Pradeep Kumar Chitrapu -To: ath11k@lists.infradead.org -Cc: linux-wireless@vger.kernel.org, - Pradeep Kumar Chitrapu , - Miles Hu , - John Crispin -Subject: [PATCH v9 1/3] ath11k: switch to using ieee80211_tx_status_ext() -Date: Sun, 4 Apr 2021 05:52:33 -0700 -Message-Id: <20210404125235.5589-2-pradeepc@codeaurora.org> -X-Mailer: git-send-email 2.17.1 -In-Reply-To: <20210404125235.5589-1-pradeepc@codeaurora.org> -References: <20210404125235.5589-1-pradeepc@codeaurora.org> -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -This allows us to pass HE rates down into the stack. - -Co-developed-by: Miles Hu -Signed-off-by: Miles Hu -Signed-off-by: John Crispin -Signed-off-by: Pradeep Kumar Chitrapu ---- - drivers/net/wireless/ath/ath11k/dp_tx.c | 31 ++++++++++++++++++++----- - 1 file changed, 25 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c -index 8bba5234f81f..f0a2e87b2454 100644 ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -417,9 +417,13 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, - struct sk_buff *msdu, - struct hal_tx_status *ts) - { -+ struct ieee80211_tx_status status = { 0 }; - struct ath11k_base *ab = ar->ab; - struct ieee80211_tx_info *info; - struct ath11k_skb_cb *skb_cb; -+ struct ath11k_peer *peer; -+ struct ath11k_sta *arsta; -+ struct rate_info rate; - - if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { - /* Must not happen */ -@@ -483,13 +487,28 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, - ath11k_dp_tx_cache_peer_stats(ar, msdu, ts); - } - -- /* NOTE: Tx rate status reporting. Tx completion status does not have -- * necessary information (for example nss) to build the tx rate. -- * Might end up reporting it out-of-band from HTT stats. -- */ -- -- ieee80211_tx_status(ar->hw, msdu); -+ spin_lock_bh(&ab->base_lock); -+ peer = ath11k_peer_find_by_id(ab, ts->peer_id); -+ if (!peer || !peer->sta) { -+ ath11k_dbg(ab, ATH11K_DBG_DATA, -+ "dp_tx: failed to find the peer with peer_id %d\n", -+ ts->peer_id); -+ spin_unlock_bh(&ab->base_lock); -+ dev_kfree_skb_any(msdu); -+ goto exit; -+ } -+ arsta = (struct ath11k_sta *)peer->sta->drv_priv; -+ status.sta = peer->sta; -+ status.skb = msdu; -+ status.info = info; -+ rate = arsta->last_txrate; -+ status.rate = &rate; -+ -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); - -+ ieee80211_tx_status_ext(ar->hw, &status); -+ return; - exit: - rcu_read_unlock(); - } diff --git a/package/kernel/mac80211/patches/ath11k/008-ath11k-decode-HE-status-tlv.patch b/package/kernel/mac80211/patches/ath11k/008-ath11k-decode-HE-status-tlv.patch deleted file mode 100644 index 429c9f5aa..000000000 --- a/package/kernel/mac80211/patches/ath11k/008-ath11k-decode-HE-status-tlv.patch +++ /dev/null @@ -1,496 +0,0 @@ -From patchwork Sun Apr 4 12:52:34 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Pradeep Kumar Chitrapu -X-Patchwork-Id: 12182281 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham - autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id E3203C433B4 - for ; - Sun, 4 Apr 2021 12:53:09 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id AE37B611CC - for ; - Sun, 4 Apr 2021 12:53:09 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S230377AbhDDMxH (ORCPT - ); - Sun, 4 Apr 2021 08:53:07 -0400 -Received: from so254-9.mailgun.net ([198.61.254.9]:62724 "EHLO - so254-9.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S230214AbhDDMxG (ORCPT - ); - Sun, 4 Apr 2021 08:53:06 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1617540782; h=References: In-Reply-To: Message-Id: Date: - Subject: Cc: To: From: Sender; - bh=52aLQBi4pTxsSaRgMTF2reTfBgzIt+ifJ5UPtdC+HEc=; - b=HJAZiJ/uoeNzd/a5ksLJBM18zUZq5nyjVMEjYLaiuAUii2puX7B0nY9FcKPXUzbsbN+NnxUq - p11ACR8WmoIFXL6m+jCP7UOrP/bhPO3tFWq1VTNUn5V7p/CA85dBhrPxy8SBAmZqiGk9KiSX - DvEjrVEM57Ob9lvFR0y7IIUgs8Q= -X-Mailgun-Sending-Ip: 198.61.254.9 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n06.prod.us-west-2.postgun.com with SMTP id - 6069b69cfebcffa80f0a68f4 (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Sun, 04 Apr 2021 12:52:44 - GMT -Sender: pradeepc=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id DB600C433C6; Sun, 4 Apr 2021 12:52:44 +0000 (UTC) -Received: from pradeepc2-linux.qualcomm.com (i-global254.qualcomm.com - [199.106.103.254]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: pradeepc) - by smtp.codeaurora.org (Postfix) with ESMTPSA id 69338C433CA; - Sun, 4 Apr 2021 12:52:43 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 69338C433CA -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=pradeepc@codeaurora.org -From: Pradeep Kumar Chitrapu -To: ath11k@lists.infradead.org -Cc: linux-wireless@vger.kernel.org, - Pradeep Kumar Chitrapu , - Miles Hu -Subject: [PATCH v9 2/3] ath11k: decode HE status tlv -Date: Sun, 4 Apr 2021 05:52:34 -0700 -Message-Id: <20210404125235.5589-3-pradeepc@codeaurora.org> -X-Mailer: git-send-email 2.17.1 -In-Reply-To: <20210404125235.5589-1-pradeepc@codeaurora.org> -References: <20210404125235.5589-1-pradeepc@codeaurora.org> -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -Add new bitmasks and macro definitions required for parsing HE -status tlvs. Decode HE status tlvs, which will used in dumping -ppdu stats as well as updating radiotap headers. - -Co-developed-by: Miles Hu -Signed-off-by: Miles Hu -Signed-off-by: Pradeep Kumar Chitrapu ---- - drivers/net/wireless/ath/ath11k/dp_rx.c | 99 ++++++++++++--- - drivers/net/wireless/ath/ath11k/hal_desc.h | 1 + - drivers/net/wireless/ath/ath11k/hal_rx.h | 135 ++++++++++++++++++++- - 3 files changed, 214 insertions(+), 21 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2362,7 +2362,7 @@ static void ath11k_dp_rx_deliver_msdu(st - char tid[32]; - - status = IEEE80211_SKB_RXCB(msdu); -- if (status->encoding == RX_ENC_HE) { -+ if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE)) { - he = skb_push(msdu, sizeof(known)); - memcpy(he, &known, sizeof(known)); - status->flag |= RX_FLAG_RADIOTAP_HE; -@@ -4692,7 +4692,7 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11 - struct ieee80211_rx_status *rxs) - { - struct sk_buff *msdu, *mpdu_buf, *prev_buf; -- u32 decap_format, wifi_hdr_len; -+ u32 decap_format; - struct hal_rx_desc *rx_desc; - char *hdr_desc; - u8 *dest; -@@ -4729,38 +4729,27 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11 - - skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN); - } else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) { -- __le16 qos_field; - u8 qos_pkt = 0; - - rx_desc = (struct hal_rx_desc *)head_msdu->data; - hdr_desc = ath11k_dp_rxdesc_get_80211hdr(rx_desc); - - /* Base size */ -- wifi_hdr_len = sizeof(struct ieee80211_hdr_3addr); - wh = (struct ieee80211_hdr_3addr *)hdr_desc; - - if (ieee80211_is_data_qos(wh->frame_control)) { -- struct ieee80211_qos_hdr *qwh = -- (struct ieee80211_qos_hdr *)hdr_desc; -- -- qos_field = qwh->qos_ctrl; - qos_pkt = 1; - } - msdu = head_msdu; - - while (msdu) { -- rx_desc = (struct hal_rx_desc *)msdu->data; -- hdr_desc = ath11k_dp_rxdesc_get_80211hdr(rx_desc); -- -+ ath11k_dp_rx_msdus_set_payload(msdu); - if (qos_pkt) { - dest = skb_push(msdu, sizeof(__le16)); - if (!dest) - goto err_merge_fail; -- memcpy(dest, hdr_desc, wifi_hdr_len); -- memcpy(dest + wifi_hdr_len, -- (u8 *)&qos_field, sizeof(__le16)); -+ memcpy(dest, hdr_desc, sizeof(struct ieee80211_qos_hdr)); - } -- ath11k_dp_rx_msdus_set_payload(msdu); - prev_buf = msdu; - msdu = msdu->next; - } -@@ -4790,8 +4779,83 @@ err_merge_fail: - return NULL; - } - -+static void -+ath11k_dp_rx_update_radiotap_he(struct hal_rx_mon_ppdu_info *rx_status, -+ u8 *rtap_buf) -+{ -+ u32 rtap_len = 0; -+ -+ put_unaligned_le16(rx_status->he_data1, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data2, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data3, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data4, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data5, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data6, &rtap_buf[rtap_len]); -+} -+ -+static void -+ath11k_dp_rx_update_radiotap_he_mu(struct hal_rx_mon_ppdu_info *rx_status, -+ u8 *rtap_buf) -+{ -+ u32 rtap_len = 0; -+ -+ put_unaligned_le16(rx_status->he_flags1, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_flags2, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[0]; -+ rtap_len += 1; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[1]; -+ rtap_len += 1; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[2]; -+ rtap_len += 1; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[3]; -+} -+ -+static void ath11k_update_radiotap(struct hal_rx_mon_ppdu_info *ppduinfo, -+ struct sk_buff *mon_skb, -+ struct ieee80211_rx_status *rxs) -+{ -+ u8 *ptr = NULL; -+ -+ if (ppduinfo->he_mu_flags) { -+ rxs->flag |= RX_FLAG_RADIOTAP_HE_MU; -+ rxs->encoding = RX_ENC_HE; -+ ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he_mu)); -+ ath11k_dp_rx_update_radiotap_he_mu(ppduinfo, ptr); -+ } -+ if (ppduinfo->he_flags) { -+ rxs->flag |= RX_FLAG_RADIOTAP_HE; -+ rxs->encoding = RX_ENC_HE; -+ ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he)); -+ ath11k_dp_rx_update_radiotap_he(ppduinfo, ptr); -+ } -+ -+ rxs->flag |= RX_FLAG_MACTIME_START; -+ rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -+ rxs->nss = ppduinfo->nss; -+ -+ rxs->mactime = ppduinfo->tsft; -+} -+ - static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id, - struct sk_buff *head_msdu, -+ struct hal_rx_mon_ppdu_info *ppduinfo, - struct sk_buff *tail_msdu, - struct napi_struct *napi) - { -@@ -4821,8 +4885,7 @@ static int ath11k_dp_rx_mon_deliver(stru - } else { - rxs->flag |= RX_FLAG_ALLOW_SAME_PN; - } -- rxs->flag |= RX_FLAG_ONLY_MONITOR; -- -+ ath11k_update_radiotap(ppduinfo, mon_skb, rxs); - status = IEEE80211_SKB_RXCB(mon_skb); - *status = *rxs; - -@@ -4898,6 +4961,7 @@ static void ath11k_dp_rx_mon_dest_proces - } - if (head_msdu && tail_msdu) { - ath11k_dp_rx_mon_deliver(ar, dp->mac_id, head_msdu, -+ &pmon->mon_ppdu_info, - tail_msdu, napi); - rx_mon_stats->dest_mpdu_done++; - } -@@ -4944,6 +5008,8 @@ static void ath11k_dp_rx_mon_status_proc - while (!skb_queue_empty(&pmon->rx_status_q)) { - status_skb = skb_dequeue(&pmon->rx_status_q); - -+ memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info)); -+ - tlv_status = ath11k_hal_rx_parse_mon_status(ar->ab, ppdu_info, - status_skb); - if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) { ---- a/drivers/net/wireless/ath/ath11k/hal_desc.h -+++ b/drivers/net/wireless/ath/ath11k/hal_desc.h -@@ -474,6 +474,7 @@ enum hal_tlv_tag { - - #define HAL_TLV_HDR_TAG GENMASK(9, 1) - #define HAL_TLV_HDR_LEN GENMASK(25, 10) -+#define HAL_TLV_USR_ID GENMASK(31, 26) - - #define HAL_TLV_ALIGN 4 - ---- a/drivers/net/wireless/ath/ath11k/hal_rx.h -+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h -@@ -77,6 +77,36 @@ enum hal_rx_mon_status { - HAL_RX_MON_STATUS_BUF_DONE, - }; - -+struct hal_rx_user_status { -+ u32 mcs:4, -+ nss:3, -+ ofdma_info_valid:1, -+ dl_ofdma_ru_start_index:7, -+ dl_ofdma_ru_width:7, -+ dl_ofdma_ru_size:8; -+ u32 ul_ofdma_user_v0_word0; -+ u32 ul_ofdma_user_v0_word1; -+ u32 ast_index; -+ u32 tid; -+ u16 tcp_msdu_count; -+ u16 udp_msdu_count; -+ u16 other_msdu_count; -+ u16 frame_control; -+ u8 frame_control_info_valid; -+ u8 data_sequence_control_info_valid; -+ u16 first_data_seq_ctrl; -+ u32 preamble_type; -+ u16 ht_flags; -+ u16 vht_flags; -+ u16 he_flags; -+ u8 rs_flags; -+ u32 mpdu_cnt_fcs_ok; -+ u32 mpdu_cnt_fcs_err; -+ u32 mpdu_fcs_ok_bitmap[8]; -+ u32 mpdu_ok_byte_count; -+ u32 mpdu_err_byte_count; -+}; -+ - struct hal_rx_mon_ppdu_info { - u32 ppdu_id; - u32 ppdu_ts; -@@ -93,16 +123,58 @@ struct hal_rx_mon_ppdu_info { - u8 mcs; - u8 nss; - u8 bw; -+ u8 vht_flag_values1; -+ u8 vht_flag_values2; -+ u8 vht_flag_values3[4]; -+ u8 vht_flag_values4; -+ u8 vht_flag_values5; -+ u16 vht_flag_values6; - u8 is_stbc; - u8 gi; - u8 ldpc; - u8 beamformed; - u8 rssi_comb; - u8 tid; -+ u16 ht_flags; -+ u16 vht_flags; -+ u16 he_flags; -+ u16 he_mu_flags; - u8 dcm; - u8 ru_alloc; - u8 reception_type; -+ u64 tsft; - u64 rx_duration; -+ u16 frame_control; -+ u32 ast_index; -+ u8 rs_fcs_err; -+ u8 rs_flags; -+ u8 cck_flag; -+ u8 ofdm_flag; -+ u8 ulofdma_flag; -+ u8 frame_control_info_valid; -+ u16 he_per_user_1; -+ u16 he_per_user_2; -+ u8 he_per_user_position; -+ u8 he_per_user_known; -+ u16 he_flags1; -+ u16 he_flags2; -+ u8 he_RU[4]; -+ u16 he_data1; -+ u16 he_data2; -+ u16 he_data3; -+ u16 he_data4; -+ u16 he_data5; -+ u16 he_data6; -+ u32 ppdu_len; -+ u32 prev_ppdu_id; -+ u32 device_id; -+ u16 first_data_seq_ctrl; -+ u8 monitor_direct_used; -+ u8 data_sequence_control_info_valid; -+ u8 ltf_size; -+ u8 rxpcu_filter_pass; -+ char rssi_chain[8][8]; -+ struct hal_rx_user_status userstats; - }; - - #define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0) -@@ -135,6 +207,9 @@ struct hal_rx_ppdu_start { - #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0) - #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16) - -+#define HAL_RX_PPDU_END_USER_STATS_RSVD2_6_MPDU_OK_BYTE_COUNT GENMASK(24, 0) -+#define HAL_RX_PPDU_END_USER_STATS_RSVD2_8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0) -+ - struct hal_rx_ppdu_end_user_stats { - __le32 rsvd0[2]; - __le32 info0; -@@ -149,6 +224,16 @@ struct hal_rx_ppdu_end_user_stats { - __le32 rsvd2[11]; - } __packed; - -+struct hal_rx_ppdu_end_user_stats_ext { -+ u32 info0; -+ u32 info1; -+ u32 info2; -+ u32 info3; -+ u32 info4; -+ u32 info5; -+ u32 info6; -+} __packed; -+ - #define HAL_RX_HT_SIG_INFO_INFO0_MCS GENMASK(6, 0) - #define HAL_RX_HT_SIG_INFO_INFO0_BW BIT(7) - -@@ -197,25 +282,62 @@ enum hal_rx_vht_sig_a_gi_setting { - HAL_RX_VHT_SIG_A_SHORT_GI_AMBIGUITY = 3, - }; - -+#define HAL_RX_SU_MU_CODING_LDPC 0x01 -+ -+#define HE_GI_0_8 0 -+#define HE_GI_0_4 1 -+#define HE_GI_1_6 2 -+#define HE_GI_3_2 3 -+ -+#define HE_LTF_1_X 0 -+#define HE_LTF_2_X 1 -+#define HE_LTF_4_X 2 -+#define HE_LTF_UNKNOWN 3 -+ - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS GENMASK(6, 3) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM BIT(7) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW GENMASK(20, 19) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE GENMASK(22, 21) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS GENMASK(25, 23) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_BSS_COLOR GENMASK(13, 8) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_SPATIAL_REUSE GENMASK(18, 15) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_FORMAT_IND BIT(0) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_BEAM_CHANGE BIT(1) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_DL_UL_FLAG BIT(2) - -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXOP_DURATION GENMASK(6, 0) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING BIT(7) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_LDPC_EXTRA BIT(8) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC BIT(9) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF BIT(10) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_FACTOR GENMASK(12, 11) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_PE_DISAM BIT(13) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_DOPPLER_IND BIT(15) - - struct hal_rx_he_sig_a_su_info { - __le32 info0; - __le32 info1; - } __packed; - --#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW GENMASK(17, 15) --#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_CP_LTF_SIZE GENMASK(24, 23) -- -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_UL_FLAG BIT(1) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_MCS_OF_SIGB GENMASK(3, 1) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_DCM_OF_SIGB BIT(4) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_BSS_COLOR GENMASK(10, 5) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_SPATIAL_REUSE GENMASK(14, 11) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW GENMASK(17, 15) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_NUM_SIGB_SYMB GENMASK(21, 18) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_COMP_MODE_SIGB BIT(22) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_CP_LTF_SIZE GENMASK(24, 23) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_DOPPLER_INDICATION BIT(25) -+ -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_TXOP_DURATION GENMASK(6, 0) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_CODING BIT(7) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_NUM_LTF_SYMB GENMASK(10, 8) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_LDPC_EXTRA BIT(11) - #define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_STBC BIT(12) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_TXBF BIT(10) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_PKT_EXT_FACTOR GENMASK(14, 13) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_PKT_EXT_PE_DISAM BIT(15) - - struct hal_rx_he_sig_a_mu_dl_info { - __le32 info0; -@@ -228,6 +350,7 @@ struct hal_rx_he_sig_b1_mu_info { - __le32 info0; - } __packed; - -+#define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_ID GENMASK(10, 0) - #define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS GENMASK(18, 15) - #define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING BIT(20) - #define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS GENMASK(31, 29) -@@ -236,6 +359,7 @@ struct hal_rx_he_sig_b2_mu_info { - __le32 info0; - } __packed; - -+#define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_ID GENMASK(10, 0) - #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_NSTS GENMASK(13, 11) - #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF BIT(19) - #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS GENMASK(18, 15) -@@ -254,10 +378,13 @@ struct hal_rx_phyrx_rssi_legacy_info { - } __packed; - - #define HAL_RX_MPDU_INFO_INFO0_PEERID GENMASK(31, 16) -+#define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0) - struct hal_rx_mpdu_info { - __le32 rsvd0; - __le32 info0; -- __le32 rsvd1[21]; -+ __le32 rsvd1[11]; -+ __le32 info1; -+ __le32 rsvd2[9]; - } __packed; - - #define HAL_RX_PPDU_END_DURATION GENMASK(23, 0) diff --git a/package/kernel/mac80211/patches/ath11k/009-ath11k-Avoid-memcpy-over-reading-of-he_cap.patch b/package/kernel/mac80211/patches/ath11k/009-ath11k-Avoid-memcpy-over-reading-of-he_cap.patch deleted file mode 100644 index 78ef0d680..000000000 --- a/package/kernel/mac80211/patches/ath11k/009-ath11k-Avoid-memcpy-over-reading-of-he_cap.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c8bcd82a4efd053cdd5ce515a8b0003011a5f756 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 16 Jun 2021 12:54:10 -0700 -Subject: [PATCH] ath11k: Avoid memcpy() over-reading of he_cap - -In preparation for FORTIFY_SOURCE performing compile-time and run-time -field bounds checking for memcpy(), memmove(), and memset(), avoid -intentionally writing across neighboring array fields. - -Since peer_he_cap_{mac,phy}info and he_cap_elem.{mac,phy}_cap_info are not -the same sizes, memcpy() was reading beyond field boundaries. Instead, -correctly cap the copy length and pad out any difference in size -(peer_he_cap_macinfo is 8 bytes whereas mac_cap_info is 6, and -peer_he_cap_phyinfo is 12 bytes whereas phy_cap_info is 11). - -Signed-off-by: Kees Cook -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20210616195410.1232119-1-keescook@chromium.org ---- - drivers/net/wireless/ath/ath11k/mac.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index eb52332dbe3f13..e9b3689331ec2a 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1314,10 +1314,16 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, - - arg->he_flag = true; - -- memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info, -- sizeof(arg->peer_he_cap_macinfo)); -- memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info, -- sizeof(arg->peer_he_cap_phyinfo)); -+ memcpy_and_pad(&arg->peer_he_cap_macinfo, -+ sizeof(arg->peer_he_cap_macinfo), -+ he_cap->he_cap_elem.mac_cap_info, -+ sizeof(he_cap->he_cap_elem.mac_cap_info), -+ 0); -+ memcpy_and_pad(&arg->peer_he_cap_phyinfo, -+ sizeof(arg->peer_he_cap_phyinfo), -+ he_cap->he_cap_elem.phy_cap_info, -+ sizeof(he_cap->he_cap_elem.phy_cap_info), -+ 0); - arg->peer_he_ops = vif->bss_conf.he_oper.params; - - /* the top most byte is used to indicate BSS color info */ \ No newline at end of file diff --git a/package/kernel/mac80211/patches/ath11k/010-ath11k-translate-HE-status-to-radiotap-format.patch b/package/kernel/mac80211/patches/ath11k/010-ath11k-translate-HE-status-to-radiotap-format.patch deleted file mode 100644 index 09e18f3a2..000000000 --- a/package/kernel/mac80211/patches/ath11k/010-ath11k-translate-HE-status-to-radiotap-format.patch +++ /dev/null @@ -1,758 +0,0 @@ -From patchwork Sun Apr 4 12:52:35 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Pradeep Kumar Chitrapu -X-Patchwork-Id: 12182279 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham - autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 8410EC433ED - for ; - Sun, 4 Apr 2021 12:53:04 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id 4BABB611CC - for ; - Sun, 4 Apr 2021 12:53:04 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S230472AbhDDMxH (ORCPT - ); - Sun, 4 Apr 2021 08:53:07 -0400 -Received: from so254-9.mailgun.net ([198.61.254.9]:17051 "EHLO - so254-9.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S229483AbhDDMxG (ORCPT - ); - Sun, 4 Apr 2021 08:53:06 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1617540782; h=References: In-Reply-To: Message-Id: Date: - Subject: Cc: To: From: Sender; - bh=cf2p38bfxo2Bcdc6lgC2IKZtwOAHsfGlcvwXCZgQWzk=; - b=Sv8xfHpbgoNmqYa0Wo4q3Dx9AdLgN2RlBTUHjzr4KfEuknxPgl1UgNdmvr7VmkMZfPrnncn+ - y2QGaP3tiRW9RZaF3Qr1zKVnrxE2CCunAgtKxIMp2sZ9mRsdwa77nviXwcMeNAmnznwlwVKo - M0hpKCEJlbttKHWPYwwEyyeSX40= -X-Mailgun-Sending-Ip: 198.61.254.9 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n05.prod.us-east-1.postgun.com with SMTP id - 6069b69e8166b7eff749171e (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Sun, 04 Apr 2021 12:52:46 - GMT -Sender: pradeepc=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id 9ED2CC43462; Sun, 4 Apr 2021 12:52:45 +0000 (UTC) -Received: from pradeepc2-linux.qualcomm.com (i-global254.qualcomm.com - [199.106.103.254]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: pradeepc) - by smtp.codeaurora.org (Postfix) with ESMTPSA id 046B9C43461; - Sun, 4 Apr 2021 12:52:43 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 046B9C43461 -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=pradeepc@codeaurora.org -From: Pradeep Kumar Chitrapu -To: ath11k@lists.infradead.org -Cc: linux-wireless@vger.kernel.org, - Pradeep Kumar Chitrapu , - Miles Hu , - Anilkumar Kolli -Subject: [PATCH v9 3/3] ath11k: translate HE status to radiotap format -Date: Sun, 4 Apr 2021 05:52:35 -0700 -Message-Id: <20210404125235.5589-4-pradeepc@codeaurora.org> -X-Mailer: git-send-email 2.17.1 -In-Reply-To: <20210404125235.5589-1-pradeepc@codeaurora.org> -References: <20210404125235.5589-1-pradeepc@codeaurora.org> -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -Translate HE status to radiotap format. This uses HE radiotap -definitions from include/net/ieee80211_radiotap.h. - -Co-developed-by: Miles Hu -Signed-off-by: Miles Hu -Signed-off-by: Anilkumar Kolli -Signed-off-by: Pradeep Kumar Chitrapu ---- - drivers/net/wireless/ath/ath11k/dp_rx.c | 31 +- - drivers/net/wireless/ath/ath11k/hal_rx.c | 470 ++++++++++++++++++++--- - 2 files changed, 438 insertions(+), 63 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -4827,29 +4827,44 @@ ath11k_dp_rx_update_radiotap_he_mu(struc - rtap_buf[rtap_len] = rx_status->he_RU[3]; - } - --static void ath11k_update_radiotap(struct hal_rx_mon_ppdu_info *ppduinfo, -+static void ath11k_update_radiotap(struct ath11k *ar, -+ struct hal_rx_mon_ppdu_info *ppduinfo, - struct sk_buff *mon_skb, - struct ieee80211_rx_status *rxs) - { -+ struct ieee80211_supported_band *sband; - u8 *ptr = NULL; - -+ rxs->flag |= RX_FLAG_MACTIME_START; -+ rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -+ -+ if (ppduinfo->nss) -+ rxs->nss = ppduinfo->nss; -+ - if (ppduinfo->he_mu_flags) { - rxs->flag |= RX_FLAG_RADIOTAP_HE_MU; - rxs->encoding = RX_ENC_HE; - ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he_mu)); - ath11k_dp_rx_update_radiotap_he_mu(ppduinfo, ptr); -- } -- if (ppduinfo->he_flags) { -+ } else if (ppduinfo->he_flags) { - rxs->flag |= RX_FLAG_RADIOTAP_HE; - rxs->encoding = RX_ENC_HE; - ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he)); - ath11k_dp_rx_update_radiotap_he(ppduinfo, ptr); -+ rxs->rate_idx = ppduinfo->rate; -+ } else if (ppduinfo->vht_flags) { -+ rxs->encoding = RX_ENC_VHT; -+ rxs->rate_idx = ppduinfo->rate; -+ } else if (ppduinfo->ht_flags) { -+ rxs->encoding = RX_ENC_HT; -+ rxs->rate_idx = ppduinfo->rate; -+ } else { -+ rxs->encoding = RX_ENC_LEGACY; -+ sband = &ar->mac.sbands[rxs->band]; -+ rxs->rate_idx = ath11k_mac_hw_rate_to_idx(sband, ppduinfo->rate, -+ ppduinfo->cck_flag); - } - -- rxs->flag |= RX_FLAG_MACTIME_START; -- rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -- rxs->nss = ppduinfo->nss; -- - rxs->mactime = ppduinfo->tsft; - } - -@@ -4885,7 +4900,7 @@ static int ath11k_dp_rx_mon_deliver(stru - } else { - rxs->flag |= RX_FLAG_ALLOW_SAME_PN; - } -- ath11k_update_radiotap(ppduinfo, mon_skb, rxs); -+ ath11k_update_radiotap(ar, ppduinfo, mon_skb, rxs); - status = IEEE80211_SKB_RXCB(mon_skb); - *status = *rxs; - ---- a/drivers/net/wireless/ath/ath11k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -454,10 +454,12 @@ void ath11k_hal_reo_status_queue_stats(s - desc->info0)); - ath11k_dbg(ab, ATH11k_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n", - desc->pn[0], desc->pn[1], desc->pn[2], desc->pn[3]); -- ath11k_dbg(ab, ATH11k_DBG_HAL, "last_rx: enqueue_tstamp %08x dequeue_tstamp %08x\n", -+ ath11k_dbg(ab, ATH11k_DBG_HAL, -+ "last_rx: enqueue_tstamp %08x dequeue_tstamp %08x\n", - desc->last_rx_enqueue_timestamp, - desc->last_rx_dequeue_timestamp); -- ath11k_dbg(ab, ATH11k_DBG_HAL, "rx_bitmap [%08x %08x %08x %08x %08x %08x %08x %08x]\n", -+ ath11k_dbg(ab, ATH11k_DBG_HAL, -+ "rx_bitmap [%08x %08x %08x %08x %08x %08x %08x %08x]\n", - desc->rx_bitmap[0], desc->rx_bitmap[1], desc->rx_bitmap[2], - desc->rx_bitmap[3], desc->rx_bitmap[4], desc->rx_bitmap[5], - desc->rx_bitmap[6], desc->rx_bitmap[7]); -@@ -838,12 +840,75 @@ void ath11k_hal_reo_hw_setup(struct ath1 - ring_hash_map)); - } - -+#define HAL_MAX_UL_MU_USERS 37 -+static inline void -+ath11k_hal_rx_handle_ofdma_info(void *rx_tlv, -+ struct hal_rx_user_status *rx_user_status) -+{ -+ struct hal_rx_ppdu_end_user_stats *ppdu_end_user = -+ (struct hal_rx_ppdu_end_user_stats *)rx_tlv; -+ -+ rx_user_status->ul_ofdma_user_v0_word0 = __le32_to_cpu(ppdu_end_user->info6); -+ -+ rx_user_status->ul_ofdma_user_v0_word1 = __le32_to_cpu(ppdu_end_user->rsvd2[10]); -+} -+ -+static inline void -+ath11k_hal_rx_populate_byte_count(void *rx_tlv, void *ppduinfo, -+ struct hal_rx_user_status *rx_user_status) -+{ -+ struct hal_rx_ppdu_end_user_stats *ppdu_end_user = -+ (struct hal_rx_ppdu_end_user_stats *)rx_tlv; -+ -+ rx_user_status->mpdu_ok_byte_count = -+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_RSVD2_6_MPDU_OK_BYTE_COUNT, -+ __le32_to_cpu(ppdu_end_user->rsvd2[6])); -+ rx_user_status->mpdu_err_byte_count = -+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_RSVD2_8_MPDU_ERR_BYTE_COUNT, -+ __le32_to_cpu(ppdu_end_user->rsvd2[8])); -+} -+ -+static inline void -+ath11k_hal_rx_populate_mu_user_info(void *rx_tlv, struct hal_rx_mon_ppdu_info *ppdu_info, -+ struct hal_rx_user_status *rx_user_status) -+{ -+ rx_user_status->ast_index = ppdu_info->ast_index; -+ rx_user_status->tid = ppdu_info->tid; -+ rx_user_status->tcp_msdu_count = -+ ppdu_info->tcp_msdu_count; -+ rx_user_status->udp_msdu_count = -+ ppdu_info->udp_msdu_count; -+ rx_user_status->other_msdu_count = -+ ppdu_info->other_msdu_count; -+ rx_user_status->frame_control = ppdu_info->frame_control; -+ rx_user_status->frame_control_info_valid = -+ ppdu_info->frame_control_info_valid; -+ rx_user_status->data_sequence_control_info_valid = -+ ppdu_info->data_sequence_control_info_valid; -+ rx_user_status->first_data_seq_ctrl = -+ ppdu_info->first_data_seq_ctrl; -+ rx_user_status->preamble_type = ppdu_info->preamble_type; -+ rx_user_status->ht_flags = ppdu_info->ht_flags; -+ rx_user_status->vht_flags = ppdu_info->vht_flags; -+ rx_user_status->he_flags = ppdu_info->he_flags; -+ rx_user_status->rs_flags = ppdu_info->rs_flags; -+ -+ rx_user_status->mpdu_cnt_fcs_ok = -+ ppdu_info->num_mpdu_fcs_ok; -+ rx_user_status->mpdu_cnt_fcs_err = -+ ppdu_info->num_mpdu_fcs_err; -+ -+ ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status); -+} -+ - static enum hal_rx_mon_status - ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, - struct hal_rx_mon_ppdu_info *ppdu_info, -- u32 tlv_tag, u8 *tlv_data) -+ u32 tlv_tag, u8 *tlv_data, u32 userid) - { -- u32 info0, info1; -+ u32 info0, info1, value; -+ u8 he_dcm = 0, he_stbc = 0; -+ u16 he_gi = 0, he_ltf = 0; - - switch (tlv_tag) { - case HAL_RX_PPDU_START: { -@@ -864,6 +929,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - info0 = __le32_to_cpu(eu_stats->info0); - info1 = __le32_to_cpu(eu_stats->info1); - -+ ppdu_info->ast_index = -+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX, -+ __le32_to_cpu(eu_stats->info2)); - ppdu_info->tid = - ffs(FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP, - __le32_to_cpu(eu_stats->info6))) - 1; -@@ -887,6 +955,44 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - ppdu_info->num_mpdu_fcs_err = - FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR, - info0); -+ switch (ppdu_info->preamble_type) { -+ case HAL_RX_PREAMBLE_11N: -+ ppdu_info->ht_flags = 1; -+ break; -+ case HAL_RX_PREAMBLE_11AC: -+ ppdu_info->vht_flags = 1; -+ break; -+ case HAL_RX_PREAMBLE_11AX: -+ ppdu_info->he_flags = 1; -+ break; -+ default: -+ break; -+ } -+ -+ if (userid < HAL_MAX_UL_MU_USERS) { -+ struct hal_rx_user_status *rxuser_stats = -+ &ppdu_info->userstats; -+ -+ ath11k_hal_rx_handle_ofdma_info(tlv_data, rxuser_stats); -+ ath11k_hal_rx_populate_mu_user_info(tlv_data, ppdu_info, -+ rxuser_stats); -+ } -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[0] = -+ __le32_to_cpu(eu_stats->rsvd1[0]); -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[1] = -+ __le32_to_cpu(eu_stats->rsvd1[1]); -+ -+ break; -+ } -+ case HAL_RX_PPDU_END_USER_STATS_EXT: { -+ struct hal_rx_ppdu_end_user_stats_ext *eu_stats = -+ (struct hal_rx_ppdu_end_user_stats_ext *)tlv_data; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[2] = eu_stats->info1; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[3] = eu_stats->info2; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[4] = eu_stats->info3; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[5] = eu_stats->info4; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[6] = eu_stats->info5; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[7] = eu_stats->info6; - break; - } - case HAL_PHYRX_HT_SIG: { -@@ -985,50 +1091,151 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - else - ppdu_info->reception_type = - HAL_RX_RECEPTION_TYPE_MU_MIMO; -+ ppdu_info->vht_flag_values5 = group_id; -+ ppdu_info->vht_flag_values3[0] = (((ppdu_info->mcs) << 4) | -+ ppdu_info->nss); -+ ppdu_info->vht_flag_values2 = ppdu_info->bw; -+ ppdu_info->vht_flag_values4 = -+ FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING, info1); - break; - } - case HAL_PHYRX_HE_SIG_A_SU: { - struct hal_rx_he_sig_a_su_info *he_sig_a = - (struct hal_rx_he_sig_a_su_info *)tlv_data; -- u32 nsts, cp_ltf, dcm; - -+ ppdu_info->he_flags = 1; - info0 = __le32_to_cpu(he_sig_a->info0); - info1 = __le32_to_cpu(he_sig_a->info1); - -- ppdu_info->mcs = -- FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS, -- info0); -- ppdu_info->bw = -- FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW, -- info0); -- ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING, info0); -- ppdu_info->is_stbc = info1 & -- HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC; -- ppdu_info->beamformed = info1 & -- HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF; -- dcm = info0 & HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM; -- cp_ltf = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE, -- info0); -- nsts = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS, info0); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_FORMAT_IND, info0); - -- switch (cp_ltf) { -+ if (value == 0) -+ ppdu_info->he_data1 = IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG; -+ else -+ ppdu_info->he_data1 = IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU; -+ -+ ppdu_info->he_data1 |= -+ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN; -+ -+ ppdu_info->he_data2 |= -+ IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_BSS_COLOR, info0); -+ ppdu_info->he_data3 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_BEAM_CHANGE, info0); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_DL_UL_FLAG, info0); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_UL_DL, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS, info0); -+ ppdu_info->mcs = value; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS, value); -+ -+ he_dcm = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM, info0); -+ ppdu_info->dcm = he_dcm; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM, he_dcm); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING, info1); -+ ppdu_info->ldpc = (value == HAL_RX_SU_MU_CODING_LDPC) ? 1 : 0; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_CODING, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_LDPC_EXTRA, info1); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG, value); -+ he_stbc = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC, info1); -+ ppdu_info->is_stbc = he_stbc; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_STBC, he_stbc); -+ -+ /* data4 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_SPATIAL_REUSE, info0); -+ ppdu_info->he_data4 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE, value); -+ -+ /* data5 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW, info0); -+ ppdu_info->bw = value; -+ ppdu_info->he_data5 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE, info0); -+ switch (value) { - case 0: -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_1_X; -+ break; - case 1: -- ppdu_info->gi = HAL_RX_GI_0_8_US; -- break; -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_2_X; -+ break; - case 2: -- ppdu_info->gi = HAL_RX_GI_1_6_US; -- break; -+ he_gi = HE_GI_1_6; -+ he_ltf = HE_LTF_2_X; -+ break; - case 3: -- if (dcm && ppdu_info->is_stbc) -- ppdu_info->gi = HAL_RX_GI_0_8_US; -- else -- ppdu_info->gi = HAL_RX_GI_3_2_US; -- break; -+ if (he_dcm && he_stbc) { -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_4_X; -+ } else { -+ he_gi = HE_GI_3_2; -+ he_ltf = HE_LTF_4_X; -+ } -+ break; - } -+ ppdu_info->gi = he_gi; -+ he_gi = (he_gi != 0) ? he_gi - 1 : 0; -+ ppdu_info->he_data5 |= FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_GI, he_gi); -+ ppdu_info->ltf_size = he_ltf; -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE, -+ (he_ltf == HE_LTF_4_X) ? he_ltf - 1 : he_ltf); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS, info0); -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_FACTOR, info1); -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF, info1); -+ ppdu_info->beamformed = value; -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_TXBF, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_PE_DISAM, info1); -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG, value); -+ -+ /* data6 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS, info0); -+ value++; -+ ppdu_info->nss = value; -+ ppdu_info->he_data6 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA6_NSTS, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_DOPPLER_IND, info1); -+ ppdu_info->he_data6 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA6_DOPPLER, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXOP_DURATION, info1); -+ ppdu_info->he_data6 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA6_TXOP, value); - -- ppdu_info->nss = nsts + 1; -- ppdu_info->dcm = dcm; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU; - break; - } -@@ -1036,29 +1243,142 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - struct hal_rx_he_sig_a_mu_dl_info *he_sig_a_mu_dl = - (struct hal_rx_he_sig_a_mu_dl_info *)tlv_data; - -- u32 cp_ltf; -- - info0 = __le32_to_cpu(he_sig_a_mu_dl->info0); - info1 = __le32_to_cpu(he_sig_a_mu_dl->info1); - -- ppdu_info->bw = -- FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW, -- info0); -- cp_ltf = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_CP_LTF_SIZE, -- info0); -+ ppdu_info->he_mu_flags = 1; -+ -+ ppdu_info->he_data1 = IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU; -+ ppdu_info->he_data1 |= -+ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN; -+ -+ ppdu_info->he_data2 = -+ IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN; -+ -+ /*data3*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_BSS_COLOR, info0); -+ ppdu_info->he_data3 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_UL_FLAG, info0); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_UL_DL, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_LDPC_EXTRA, info1); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_STBC, info1); -+ he_stbc = value; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_STBC, value); -+ -+ /*data4*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_SPATIAL_REUSE, info0); -+ ppdu_info->he_data4 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE, value); -+ -+ /*data5*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW, info0); -+ ppdu_info->bw = value; -+ ppdu_info->he_data5 = -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC, value); - -- switch (cp_ltf) { -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_CP_LTF_SIZE, info0); -+ switch (value) { - case 0: -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_4_X; -+ break; - case 1: -- ppdu_info->gi = HAL_RX_GI_0_8_US; -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_2_X; - break; - case 2: -- ppdu_info->gi = HAL_RX_GI_1_6_US; -+ he_gi = HE_GI_1_6; -+ he_ltf = HE_LTF_2_X; - break; - case 3: -- ppdu_info->gi = HAL_RX_GI_3_2_US; -+ he_gi = HE_GI_3_2; -+ he_ltf = HE_LTF_4_X; - break; - } -+ ppdu_info->gi = he_gi; -+ he_gi = (he_gi != 0) ? he_gi - 1 : 0; -+ ppdu_info->he_data5 |= FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_GI, he_gi); -+ ppdu_info->ltf_size = he_ltf; -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE, -+ (he_ltf == HE_LTF_4_X) ? he_ltf - 1 : he_ltf); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_NUM_LTF_SYMB, info1); -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_PKT_EXT_FACTOR, -+ info1); -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_PKT_EXT_PE_DISAM, -+ info1); -+ ppdu_info->he_data5 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG, value); -+ -+ /*data6*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_DOPPLER_INDICATION, -+ info0); -+ ppdu_info->he_data6 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA6_DOPPLER, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_TXOP_DURATION, info1); -+ ppdu_info->he_data6 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA6_TXOP, value); -+ -+ /* HE-MU Flags */ -+ /* HE-MU-flags1 */ -+ ppdu_info->he_flags1 = -+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN | -+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN | -+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN | -+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN | -+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_MCS_OF_SIGB, info0); -+ ppdu_info->he_flags1 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN, -+ value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_DCM_OF_SIGB, info0); -+ ppdu_info->he_flags1 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN, -+ value); -+ -+ /* HE-MU-flags2 */ -+ ppdu_info->he_flags2 = -+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW, info0); -+ ppdu_info->he_flags2 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW, -+ value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_COMP_MODE_SIGB, info0); -+ ppdu_info->he_flags2 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP, value); -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_NUM_SIGB_SYMB, info0); -+ value = value - 1; -+ ppdu_info->he_flags2 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS, -+ value); - - ppdu_info->is_stbc = info1 & - HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_STBC; -@@ -1075,6 +1395,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - ru_tones = FIELD_GET(HAL_RX_HE_SIG_B1_MU_INFO_INFO0_RU_ALLOCATION, - info0); - ppdu_info->ru_alloc = ath11k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones); -+ ppdu_info->he_RU[0] = ru_tones; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO; - break; - } -@@ -1084,14 +1405,25 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - - info0 = __le32_to_cpu(he_sig_b2_mu->info0); - -+ ppdu_info->he_data1 |= IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN; -+ - ppdu_info->mcs = -- FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS, -- info0); -+ FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS, info0); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS, ppdu_info->mcs); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING, info0); -+ ppdu_info->ldpc = value; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_CODING, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_ID, info0); -+ ppdu_info->he_data4 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID, value); -+ - ppdu_info->nss = -- FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS, -- info0) + 1; -- ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING, -- info0); -+ FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS, info0) + 1; - break; - } - case HAL_PHYRX_HE_SIG_B2_OFDMA: { -@@ -1100,17 +1432,40 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - - info0 = __le32_to_cpu(he_sig_b2_ofdma->info0); - -+ ppdu_info->he_data1 |= -+ IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN | -+ IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN; -+ -+ /* HE-data2 */ -+ ppdu_info->he_data2 |= IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN; -+ - ppdu_info->mcs = - FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS, - info0); -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS, ppdu_info->mcs); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_DCM, info0); -+ he_dcm = value; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM, value); -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING, info0); -+ ppdu_info->ldpc = value; -+ ppdu_info->he_data3 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_CODING, value); -+ -+ /* HE-data4 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_ID, info0); -+ ppdu_info->he_data4 |= -+ FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID, value); -+ - ppdu_info->nss = - FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_NSTS, - info0) + 1; - ppdu_info->beamformed = -- info0 & -- HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF; -- ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING, -- info0); -+ info0 & HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA; - break; - } -@@ -1144,6 +1499,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - ppdu_info->rx_duration = - FIELD_GET(HAL_RX_PPDU_END_DURATION, - __le32_to_cpu(ppdu_rx_duration->info0)); -+ ppdu_info->tsft = __le32_to_cpu(ppdu_rx_duration->rsvd0[1]); -+ ppdu_info->tsft = (ppdu_info->tsft << 32) | -+ __le32_to_cpu(ppdu_rx_duration->rsvd0[0]); - break; - } - case HAL_DUMMY: -@@ -1167,12 +1525,14 @@ ath11k_hal_rx_parse_mon_status(struct at - enum hal_rx_mon_status hal_status = HAL_RX_MON_STATUS_BUF_DONE; - u16 tlv_tag; - u16 tlv_len; -+ u32 tlv_userid = 0; - u8 *ptr = skb->data; - - do { - tlv = (struct hal_tlv_hdr *)ptr; - tlv_tag = FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl); - tlv_len = FIELD_GET(HAL_TLV_HDR_LEN, tlv->tl); -+ tlv_userid = FIELD_GET(HAL_TLV_USR_ID, tlv->tl); - ptr += sizeof(*tlv); - - /* The actual length of PPDU_END is the combined length of many PHY -@@ -1184,7 +1544,7 @@ ath11k_hal_rx_parse_mon_status(struct at - tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview); - - hal_status = ath11k_hal_rx_parse_mon_status_tlv(ab, ppdu_info, -- tlv_tag, ptr); -+ tlv_tag, ptr, tlv_userid); - ptr += tlv_len; - ptr = PTR_ALIGN(ptr, HAL_TLV_ALIGN); - diff --git a/package/kernel/mac80211/patches/ath11k/011-ath11k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch b/package/kernel/mac80211/patches/ath11k/011-ath11k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch deleted file mode 100644 index f26e71642..000000000 --- a/package/kernel/mac80211/patches/ath11k/011-ath11k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch +++ /dev/null @@ -1,437 +0,0 @@ -From patchwork Tue Jul 20 21:31:46 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Jouni Malinen -X-Patchwork-Id: 12389427 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT - autolearn=unavailable autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id AE5DFC07E95 - for ; - Tue, 20 Jul 2021 21:32:35 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id 8BCA960E0B - for ; - Tue, 20 Jul 2021 21:32:35 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S232037AbhGTUvp (ORCPT - ); - Tue, 20 Jul 2021 16:51:45 -0400 -Received: from so254-9.mailgun.net ([198.61.254.9]:51945 "EHLO - so254-9.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S233404AbhGTUvb (ORCPT - ); - Tue, 20 Jul 2021 16:51:31 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1626816727; h=Content-Transfer-Encoding: MIME-Version: - Message-Id: Date: Subject: Cc: To: From: Sender; - bh=0NKtP900YLYCGbw3/GGjWWripcJNlTdjFgNVgginJt0=; - b=abeQRnEIETDnBog8B8jC5dz4L/CByAwwAd4rRXQWAhj3mrSD3aI8lXlncgB6UaxCJ7IxwD7n - Jd43kUakxtbNRc2ljAhNOBgnVzUYc34DC9P8+cZCUyohmRMATXg9kMszaiWSrlwKfnFbNmhy - bB2QJmD4AKn90qUvNto1Rmu6PRY= -X-Mailgun-Sending-Ip: 198.61.254.9 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n07.prod.us-east-1.postgun.com with SMTP id - 60f740d4290ea35ee6638a2d (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Tue, 20 Jul 2021 21:32:04 - GMT -Sender: jouni=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id 72C9CC43460; Tue, 20 Jul 2021 21:32:03 +0000 (UTC) -Received: from jouni.codeaurora.org (85-76-67-217-nat.elisa-mobile.fi - [85.76.67.217]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: jouni) - by smtp.codeaurora.org (Postfix) with ESMTPSA id 07C11C433F1; - Tue, 20 Jul 2021 21:32:00 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 07C11C433F1 -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=jouni@codeaurora.org -From: Jouni Malinen -To: Kalle Valo -Cc: ath11k@lists.infradead.org, linux-wireless@vger.kernel.org, - Sathishkumar Muruganandam , - Jouni Malinen -Subject: [PATCH 1/2] ath11k: fix 4-addr tx failure for AP and STA modes -Date: Wed, 21 Jul 2021 00:31:46 +0300 -Message-Id: <20210720213147.90042-1-jouni@codeaurora.org> -X-Mailer: git-send-email 2.25.1 -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -From: Sathishkumar Muruganandam - -Ath11k FW requires peer parameter WMI_PEER_USE_4ADDR to be set for -4-addr peers allowing 4-address frame transmission to those peers. - -Add ath11k driver callback for sta_set_4addr() to queue new workq -set_4addr_wk only once based on new boolean, use_4addr_set. - -sta_set_4addr() will be called during 4-addr STA association cases -applicable for both AP and STA modes. - -In ath11k_sta_set_4addr_wk(), - -AP mode: - WMI_PEER_USE_4ADDR will be set for the corresponding - associated 4-addr STA(s) - -STA mode: - WMI_PEER_USE_4ADDR will be set for the AP to which the - 4-addr STA got associated. - -Tested-on: IPQ8074 WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Sathishkumar Muruganandam -Signed-off-by: Jouni Malinen ---- - drivers/net/wireless/ath/ath11k/core.h | 3 ++ - drivers/net/wireless/ath/ath11k/mac.c | 48 ++++++++++++++++++++++++-- - 2 files changed, 49 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 018fb2385f2a..11c8dffd0236 100644 ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -362,6 +362,7 @@ struct ath11k_sta { - enum hal_pn_type pn_type; - - struct work_struct update_wk; -+ struct work_struct set_4addr_wk; - struct rate_info txrate; - struct rate_info last_txrate; - u64 rx_duration; -@@ -374,6 +375,8 @@ struct ath11k_sta { - /* protected by conf_mutex */ - bool aggr_mode; - #endif -+ -+ bool use_4addr_set; - }; - - #define ATH11K_MIN_5G_FREQ 4150 -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index e9b3689331ec..d42637ecbf1e 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3155,6 +3155,31 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) - mutex_unlock(&ar->conf_mutex); - } - -+static void ath11k_sta_set_4addr_wk(struct work_struct *wk) -+{ -+ struct ath11k *ar; -+ struct ath11k_vif *arvif; -+ struct ath11k_sta *arsta; -+ struct ieee80211_sta *sta; -+ int ret = 0; -+ -+ arsta = container_of(wk, struct ath11k_sta, set_4addr_wk); -+ sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); -+ arvif = arsta->arvif; -+ ar = arvif->ar; -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "setting USE_4ADDR for peer %pM\n", sta->addr); -+ -+ ret = ath11k_wmi_set_peer_param(ar, sta->addr, -+ arvif->vdev_id, -+ WMI_PEER_USE_4ADDR, 1); -+ -+ if (ret) -+ ath11k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n", -+ sta->addr, ret); -+} -+ - static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif, - struct ieee80211_sta *sta) - { -@@ -3234,11 +3259,13 @@ static int ath11k_mac_station_add(struct ath11k *ar, - } - - if (ieee80211_vif_is_mesh(vif)) { -+ ath11k_dbg(ab, ATH11K_DBG_MAC, -+ "setting USE_4ADDR for mesh STA %pM\n", sta->addr); - ret = ath11k_wmi_set_peer_param(ar, sta->addr, - arvif->vdev_id, - WMI_PEER_USE_4ADDR, 1); - if (ret) { -- ath11k_warn(ab, "failed to STA %pM 4addr capability: %d\n", -+ ath11k_warn(ab, "failed to set mesh STA %pM 4addr capability: %d\n", - sta->addr, ret); - goto free_tx_stats; - } -@@ -3291,8 +3318,10 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, - - /* cancel must be done outside the mutex to avoid deadlock */ - if ((old_state == IEEE80211_STA_NONE && -- new_state == IEEE80211_STA_NOTEXIST)) -+ new_state == IEEE80211_STA_NOTEXIST)) { - cancel_work_sync(&arsta->update_wk); -+ cancel_work_sync(&arsta->set_4addr_wk); -+ } - - mutex_lock(&ar->conf_mutex); - -@@ -3301,6 +3330,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, - memset(arsta, 0, sizeof(*arsta)); - arsta->arvif = arvif; - INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk); -+ INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk); - - ret = ath11k_mac_station_add(ar, vif, sta); - if (ret) -@@ -3395,6 +3425,19 @@ static int ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw, - return ret; - } - -+static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta, bool enabled) -+{ -+ struct ath11k *ar = hw->priv; -+ struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; -+ -+ if (enabled && !arsta->use_4addr_set) { -+ ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk); -+ arsta->use_4addr_set = true; -+ } -+} -+ - static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, -@@ -6180,6 +6223,7 @@ static const struct ieee80211_ops ath11k_ops = { - .cancel_hw_scan = ath11k_mac_op_cancel_hw_scan, - .set_key = ath11k_mac_op_set_key, - .sta_state = ath11k_mac_op_sta_state, -+ .sta_set_4addr = ath11k_mac_op_sta_set_4addr, - .sta_set_txpwr = ath11k_mac_op_sta_set_txpwr, - .sta_rc_update = ath11k_mac_op_sta_rc_update, - .conf_tx = ath11k_mac_op_conf_tx, - -From patchwork Tue Jul 20 21:31:47 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Jouni Malinen -X-Patchwork-Id: 12389429 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT - autolearn=unavailable autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 25420C07E9B - for ; - Tue, 20 Jul 2021 21:33:45 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id 01B6660E0B - for ; - Tue, 20 Jul 2021 21:33:44 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S231676AbhGTUw7 (ORCPT - ); - Tue, 20 Jul 2021 16:52:59 -0400 -Received: from so254-9.mailgun.net ([198.61.254.9]:51945 "EHLO - so254-9.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S234001AbhGTUvt (ORCPT - ); - Tue, 20 Jul 2021 16:51:49 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1626816747; h=Content-Transfer-Encoding: MIME-Version: - References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: - Sender; bh=pTgIsAFvKI5zaKS8j6HkCt9Dr4xbghRAApcXu+jUG8M=; - b=ZAAksGTytroGGn4JtQ3J6nCBuDx5xyVpnhflyyy4ZihH6zkONxlfFzdmrU9OAB7jqgetM0bw - aodI6LSEYmEo+yYTMvYfRD+vtYNqbnEtj3Er8kXZA+EaraVr1rhQNUCootlK9BaqAyA+ckoS - iUediQZtUI3serWUbPDTPAUCDn8= -X-Mailgun-Sending-Ip: 198.61.254.9 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n01.prod.us-east-1.postgun.com with SMTP id - 60f740d74815712f3a66316d (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Tue, 20 Jul 2021 21:32:07 - GMT -Sender: jouni=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id AE3D3C43217; Tue, 20 Jul 2021 21:32:06 +0000 (UTC) -Received: from jouni.codeaurora.org (85-76-67-217-nat.elisa-mobile.fi - [85.76.67.217]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: jouni) - by smtp.codeaurora.org (Postfix) with ESMTPSA id BA686C433D3; - Tue, 20 Jul 2021 21:32:04 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org BA686C433D3 -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=jouni@codeaurora.org -From: Jouni Malinen -To: Kalle Valo -Cc: ath11k@lists.infradead.org, linux-wireless@vger.kernel.org, - Karthikeyan Periyasamy , - Jouni Malinen -Subject: [PATCH 2/2] ath11k: fix 4addr multicast packet tx -Date: Wed, 21 Jul 2021 00:31:47 +0300 -Message-Id: <20210720213147.90042-2-jouni@codeaurora.org> -X-Mailer: git-send-email 2.25.1 -In-Reply-To: <20210720213147.90042-1-jouni@codeaurora.org> -References: <20210720213147.90042-1-jouni@codeaurora.org> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -From: Karthikeyan Periyasamy - -In 4addr, AP wired backbone to STA wired backbone ping fails due to ARP -request not getting answered. Here 4addr ARP multicast packet is sent in -3addr, so that 4addr STA not honouring the 3addr ARP multicast packet. -Fix this issue by sending out multicast packet in 4addr format, firmware -expects peer meta flag instead of vdev meta flag in Tx descriptor. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01641-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Karthikeyan Periyasamy -Signed-off-by: Jouni Malinen ---- - drivers/net/wireless/ath/ath11k/core.h | 1 + - drivers/net/wireless/ath/ath11k/dp_tx.c | 12 ++++++++++-- - drivers/net/wireless/ath/ath11k/dp_tx.h | 2 +- - drivers/net/wireless/ath/ath11k/mac.c | 6 +++++- - drivers/net/wireless/ath/ath11k/peer.c | 11 +++++++++++ - 5 files changed, 28 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 11c8dffd0236..6a6cabdd3e30 100644 ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -377,6 +377,7 @@ struct ath11k_sta { - #endif - - bool use_4addr_set; -+ u16 tcl_metadata; - }; - - #define ATH11K_MIN_5G_FREQ 4150 -diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c -index 8bba5234f81f..3acdd4050d5b 100644 ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -78,7 +78,7 @@ enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher) - } - - int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, -- struct sk_buff *skb) -+ struct ath11k_sta *arsta, struct sk_buff *skb) - { - struct ath11k_base *ab = ar->ab; - struct ath11k_dp *dp = &ab->dp; -@@ -145,7 +145,15 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, - FIELD_PREP(DP_TX_DESC_ID_MSDU_ID, ret) | - FIELD_PREP(DP_TX_DESC_ID_POOL_ID, pool_id); - ti.encap_type = ath11k_dp_tx_get_encap_type(arvif, skb); -- ti.meta_data_flags = arvif->tcl_metadata; -+ -+ if (ieee80211_has_a4(hdr->frame_control) && -+ is_multicast_ether_addr(hdr->addr3) && arsta && -+ arsta->use_4addr_set) { -+ ti.meta_data_flags = arsta->tcl_metadata; -+ ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_TO_FW, 1); -+ } else { -+ ti.meta_data_flags = arvif->tcl_metadata; -+ } - - if (ti.encap_type == HAL_TCL_ENCAP_TYPE_RAW) { - if (skb_cb->flags & ATH11K_SKB_CIPHER_SET) { -diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h -index f8a9f9c8e444..698b907b878d 100644 ---- a/drivers/net/wireless/ath/ath11k/dp_tx.h -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h -@@ -17,7 +17,7 @@ struct ath11k_dp_htt_wbm_tx_status { - - int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab); - int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, -- struct sk_buff *skb); -+ struct ath11k_sta *arsta, struct sk_buff *skb); - void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id); - int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid, - enum hal_reo_cmd_type type, -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index d42637ecbf1e..e8da4af82221 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4356,6 +4356,7 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw, - struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_key_conf *key = info->control.hw_key; -+ struct ath11k_sta *arsta = NULL; - u32 info_flags = info->flags; - bool is_prb_rsp; - int ret; -@@ -4381,7 +4382,10 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw, - return; - } - -- ret = ath11k_dp_tx(ar, arvif, skb); -+ if (control->sta) -+ arsta = (struct ath11k_sta *)control->sta->drv_priv; -+ -+ ret = ath11k_dp_tx(ar, arvif, arsta, skb); - if (ret) { - ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret); - ieee80211_free_txskb(ar->hw, skb); -diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c -index f49abefa9618..85471f8b3563 100644 ---- a/drivers/net/wireless/ath/ath11k/peer.c -+++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -251,6 +251,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, - struct ieee80211_sta *sta, struct peer_create_params *param) - { - struct ath11k_peer *peer; -+ struct ath11k_sta *arsta; - int ret; - - lockdep_assert_held(&ar->conf_mutex); -@@ -319,6 +320,16 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, - peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; - peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; - -+ if (sta) { -+ arsta = (struct ath11k_sta *)sta->drv_priv; -+ arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) | -+ FIELD_PREP(HTT_TCL_META_DATA_PEER_ID, -+ peer->peer_id); -+ -+ /* set HTT extension valid bit to 0 by default */ -+ arsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; -+ } -+ - ar->num_peers++; - - spin_unlock_bh(&ar->ab->base_lock); diff --git a/package/kernel/mac80211/patches/ath11k/012-ath11k-set-register-access-length-for-MHI-driver.patch b/package/kernel/mac80211/patches/ath11k/012-ath11k-set-register-access-length-for-MHI-driver.patch deleted file mode 100644 index 40942e4bb..000000000 --- a/package/kernel/mac80211/patches/ath11k/012-ath11k-set-register-access-length-for-MHI-driver.patch +++ /dev/null @@ -1,31 +0,0 @@ -From fb359946c3effad77a3ac8ebc943ea5cac22d335 Mon Sep 17 00:00:00 2001 -From: Bhaumik Bhatt -Date: Thu, 6 May 2021 12:51:43 -0700 -Subject: [PATCH] ath11k: set register access length for MHI driver - -MHI driver requires register space length to add range checks and -prevent memory region accesses outside of that for MMIO space. -Set it before registering the MHI controller. - -Signed-off-by: Bhaumik Bhatt -Reviewed-by: Hemant Kumar -Reviewed-by: Manivannan Sadhasivam -Acked-by: Kalle Valo -Link: https://lore.kernel.org/r/1620330705-40192-5-git-send-email-bbhatt@codeaurora.org -Signed-off-by: Manivannan Sadhasivam ---- - drivers/net/wireless/ath/ath11k/mhi.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c -index 27b394d115e26a..e097ae52e25733 100644 ---- a/drivers/net/wireless/ath/ath11k/mhi.c -+++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -330,6 +330,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) - mhi_ctrl->cntrl_dev = ab->dev; - mhi_ctrl->fw_image = ab_pci->amss_path; - mhi_ctrl->regs = ab->mem; -+ mhi_ctrl->reg_len = ab->mem_len; - - ret = ath11k_mhi_get_msi(ab_pci); - if (ret) { diff --git a/package/kernel/mac80211/patches/ath11k/014-ath11k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch b/package/kernel/mac80211/patches/ath11k/014-ath11k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch deleted file mode 100644 index f4ad3c287..000000000 --- a/package/kernel/mac80211/patches/ath11k/014-ath11k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch +++ /dev/null @@ -1,1496 +0,0 @@ -From patchwork Wed Jul 21 17:36:14 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Jouni Malinen -X-Patchwork-Id: 12391753 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham - autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id B4885C12002 - for ; - Wed, 21 Jul 2021 17:37:13 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id 8F9DD6023B - for ; - Wed, 21 Jul 2021 17:37:13 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S229961AbhGUQ4f (ORCPT - ); - Wed, 21 Jul 2021 12:56:35 -0400 -Received: from m43-7.mailgun.net ([69.72.43.7]:31197 "EHLO m43-7.mailgun.net" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S229895AbhGUQ4f (ORCPT ); - Wed, 21 Jul 2021 12:56:35 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1626889031; h=Content-Transfer-Encoding: MIME-Version: - Message-Id: Date: Subject: Cc: To: From: Sender; - bh=d+3K8Rh/ZN2RkI4rs/cFatBAfvEApLmsIaV+mOawdJM=; - b=k75yD6fQg3XH+N8dDPDHjnWyIPRiVa1T+hjCQP2mj72O+GAaIqbIVEfYW/MmoUSDDqNHhqNC - DLMJm4gnndCIc9kZ+sIn4zTzp9QgKJafOLUbpoEf4Vbf2pYUXLCTNG/mnwMMkPrYAsm7rRGU - sKnUkY/D/9mRESn/rHG1TkJlKnA= -X-Mailgun-Sending-Ip: 69.72.43.7 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n06.prod.us-east-1.postgun.com with SMTP id - 60f85b334815712f3ad9d3a6 (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 21 Jul 2021 17:36:51 - GMT -Sender: jouni=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id C4828C43460; Wed, 21 Jul 2021 17:36:50 +0000 (UTC) -Received: from jouni.codeaurora.org (85-76-67-217-nat.elisa-mobile.fi - [85.76.67.217]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: jouni) - by smtp.codeaurora.org (Postfix) with ESMTPSA id 71C64C433F1; - Wed, 21 Jul 2021 17:36:45 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 71C64C433F1 -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=jouni@codeaurora.org -From: Jouni Malinen -To: Kalle Valo -Cc: ath11k@lists.infradead.org, linux-wireless@vger.kernel.org, - Miles Hu , - Aloka Dixit , - Lavanya Suresh , - Pradeep Chitrapu , - Venkateswara Naralasetty , - Jouni Malinen -Subject: [PATCH 1/2] ath11k: add support for setting fixed HE rate/gi/ltf -Date: Wed, 21 Jul 2021 20:36:14 +0300 -Message-Id: <20210721173615.75637-1-jouni@codeaurora.org> -X-Mailer: git-send-email 2.25.1 -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -From: Miles Hu - -Support setting fixed HE rate/gi/ltf values that we are now able to send -to the kernel using nl80211. The added code is reusing parts of the -existing code path already used for HT/VHT. The new helpers are -symmetric to how we do it for HT/VHT. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-00235-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Miles Hu -Co-developed-by: Aloka Dixit -Signed-off-by: Aloka Dixit -Co-developed-by: Lavanya Suresh -Signed-off-by: Lavanya Suresh -Co-developed-by: Pradeep Chitrapu -Signed-off-by: Pradeep Chitrapu -Signed-off-by: Venkateswara Naralasetty -Signed-off-by: Jouni Malinen ---- - drivers/net/wireless/ath/ath11k/mac.c | 586 ++++++++++++++++++++++++-- - drivers/net/wireless/ath/ath11k/wmi.c | 4 +- - drivers/net/wireless/ath/ath11k/wmi.h | 20 + - 3 files changed, 570 insertions(+), 40 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index b9d4e8914482..4dcc1b377642 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -354,6 +354,18 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) - return 1; - } - -+static u32 -+ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) -+{ -+ int nss; -+ -+ for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--) -+ if (he_mcs_mask[nss]) -+ return nss + 1; -+ -+ return 1; -+} -+ - static u8 ath11k_parse_mpdudensity(u8 mpdudensity) - { - /* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": -@@ -1391,6 +1403,14 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar, - arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG; - } - -+ /* As firmware handles this two flags (IEEE80211_HT_CAP_SGI_20 -+ * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, we reset -+ * both flags if guard interval is Default GI -+ */ -+ if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI) -+ arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 | -+ IEEE80211_HT_CAP_SGI_40); -+ - if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) { - if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40)) -@@ -1514,10 +1534,11 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, - struct ath11k_vif *arvif = (void *)vif->drv_priv; - struct cfg80211_chan_def def; - enum nl80211_band band; -- const u16 *vht_mcs_mask; -+ u16 *vht_mcs_mask; - u8 ampdu_factor; - u8 max_nss, vht_mcs; -- int i; -+ int i, vht_nss, nss_idx; -+ bool user_rate_valid = true; - - if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) - return; -@@ -1560,6 +1581,24 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, - if (sta->bandwidth == IEEE80211_STA_RX_BW_160) - arg->bw_160 = true; - -+ vht_nss = ath11k_mac_max_vht_nss(vht_mcs_mask); -+ -+ if (vht_nss > sta->rx_nss) { -+ user_rate_valid = false; -+ for (nss_idx = sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { -+ if (vht_mcs_mask[nss_idx]) { -+ user_rate_valid = true; -+ break; -+ } -+ } -+ } -+ -+ if (!user_rate_valid) { -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "Setting vht range MCS value to peer supported nss:%d for peer %pM\n", -+ sta->rx_nss, sta->addr); -+ vht_mcs_mask[sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; -+ } -+ - /* Calculate peer NSS capability from VHT capabilities if STA - * supports VHT. - */ -@@ -1598,18 +1637,100 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, - /* TODO: rxnss_override */ - } - -+static int ath11k_mac_get_max_he_mcs_map(u16 mcs_map, int nss) -+{ -+ switch ((mcs_map >> (2 * nss)) & 0x3) { -+ case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1; -+ case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1; -+ case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1; -+ } -+ return 0; -+} -+ -+static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set, -+ const u16 he_mcs_limit[NL80211_HE_NSS_MAX]) -+{ -+ int idx_limit; -+ int nss; -+ u16 mcs_map; -+ u16 mcs; -+ -+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) { -+ mcs_map = ath11k_mac_get_max_he_mcs_map(tx_mcs_set, nss) & -+ he_mcs_limit[nss]; -+ -+ if (mcs_map) -+ idx_limit = fls(mcs_map) - 1; -+ else -+ idx_limit = -1; -+ -+ switch (idx_limit) { -+ case 0 ... 7: -+ mcs = IEEE80211_HE_MCS_SUPPORT_0_7; -+ break; -+ case 8: -+ case 9: -+ mcs = IEEE80211_HE_MCS_SUPPORT_0_9; -+ break; -+ case 10: -+ case 11: -+ mcs = IEEE80211_HE_MCS_SUPPORT_0_11; -+ break; -+ default: -+ WARN_ON(1); -+ fallthrough; -+ case -1: -+ mcs = IEEE80211_HE_MCS_NOT_SUPPORTED; -+ break; -+ } -+ -+ tx_mcs_set &= ~(0x3 << (nss * 2)); -+ tx_mcs_set |= mcs << (nss * 2); -+ } -+ -+ return tx_mcs_set; -+} -+ -+static bool -+ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) -+{ -+ int nss; -+ -+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) -+ if (he_mcs_mask[nss]) -+ return false; -+ -+ return true; -+} -+ - static void ath11k_peer_assoc_h_he(struct ath11k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct peer_assoc_params *arg) - { -+ struct ath11k_vif *arvif = (void *)vif->drv_priv; -+ struct cfg80211_chan_def def; - const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; - u8 ampdu_factor; -- u16 v; -+ enum nl80211_band band; -+ u16 *he_mcs_mask; -+ u8 max_nss, he_mcs; -+ u16 he_tx_mcs = 0, v = 0; -+ int i, he_nss, nss_idx; -+ bool user_rate_valid = true; -+ -+ if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) -+ return; - - if (!he_cap->has_he) - return; - -+ band = def.chan->band; -+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; -+ -+ if (ath11k_peer_assoc_h_he_masked(he_mcs_mask)) -+ return; -+ - arg->he_flag = true; - - memcpy_and_pad(&arg->peer_he_cap_macinfo, -@@ -1686,25 +1807,48 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, - if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ) - arg->twt_requester = true; - -+ he_nss = ath11k_mac_max_he_nss(he_mcs_mask); -+ -+ if (he_nss > sta->rx_nss) { -+ user_rate_valid = false; -+ for (nss_idx = sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { -+ if (he_mcs_mask[nss_idx]) { -+ user_rate_valid = true; -+ break; -+ } -+ } -+ } -+ -+ if (!user_rate_valid) { -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "Setting he range MCS value to peer supported nss:%d for peer %pM\n", -+ sta->rx_nss, sta->addr); -+ he_mcs_mask[sta->rx_nss - 1] = he_mcs_mask[he_nss - 1]; -+ } -+ - switch (sta->bandwidth) { - case IEEE80211_STA_RX_BW_160: - if (he_cap->he_cap_elem.phy_cap_info[0] & - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) { - v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80); -+ v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask); - arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v; - - v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80); - arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v; - - arg->peer_he_mcs_count++; -+ he_tx_mcs = v; - } - v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); - arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v; - - v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160); -+ v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask); - arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v; - - arg->peer_he_mcs_count++; -+ if (!he_tx_mcs) -+ he_tx_mcs = v; - fallthrough; - - default: -@@ -1712,11 +1856,34 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, - arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v; - - v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80); -+ v = ath11k_peer_assoc_h_he_limit(v, he_mcs_mask); - arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v; - - arg->peer_he_mcs_count++; -+ if (!he_tx_mcs) -+ he_tx_mcs = v; - break; - } -+ -+ /* Calculate peer NSS capability from HE capabilities if STA -+ * supports HE. -+ */ -+ for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) { -+ he_mcs = he_tx_mcs >> (2 * i) & 3; -+ -+ /* In case of fixed rates, MCS Range in he_tx_mcs might have -+ * unsupported range, with he_mcs_mask set, so check either of them -+ * to find nss. -+ */ -+ if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED || -+ he_mcs_mask[i]) -+ max_nss = i + 1; -+ } -+ arg->peer_nss = min(sta->rx_nss, max_nss); -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "mac he peer %pM nss %d mcs cnt %d\n", -+ sta->addr, arg->peer_nss, arg->peer_he_mcs_count); - } - - static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta, -@@ -1919,6 +2086,7 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, - enum nl80211_band band; - const u8 *ht_mcs_mask; - const u16 *vht_mcs_mask; -+ const u16 *he_mcs_mask; - enum wmi_phy_mode phymode = MODE_UNKNOWN; - - if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) -@@ -1927,10 +2095,12 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, - band = def.chan->band; - ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs; - vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs; -+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; - - switch (band) { - case NL80211_BAND_2GHZ: -- if (sta->he_cap.has_he) { -+ if (sta->he_cap.has_he && -+ !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) - phymode = MODE_11AX_HE80_2G; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) -@@ -1958,7 +2128,8 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, - case NL80211_BAND_5GHZ: - case NL80211_BAND_6GHZ: - /* Check HE first */ -- if (sta->he_cap.has_he) { -+ if (sta->he_cap.has_he && -+ !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) { - phymode = ath11k_mac_get_phymode_he(ar, sta); - } else if (sta->vht_cap.vht_supported && - !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) { -@@ -3184,6 +3355,20 @@ ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar, - return num_rates; - } - -+static int -+ath11k_mac_bitrate_mask_num_he_rates(struct ath11k *ar, -+ enum nl80211_band band, -+ const struct cfg80211_bitrate_mask *mask) -+{ -+ int num_rates = 0; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) -+ num_rates += hweight16(mask->control[band].he_mcs[i]); -+ -+ return num_rates; -+} -+ - static int - ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif, - struct ieee80211_sta *sta, -@@ -3212,6 +3397,10 @@ ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif, - return -EINVAL; - } - -+ /* Avoid updating invalid nss as fixed rate*/ -+ if (nss > sta->rx_nss) -+ return -EINVAL; -+ - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates", - sta->addr); -@@ -3230,6 +3419,57 @@ ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif, - return ret; - } - -+static int -+ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif, -+ struct ieee80211_sta *sta, -+ const struct cfg80211_bitrate_mask *mask, -+ enum nl80211_band band) -+{ -+ struct ath11k *ar = arvif->ar; -+ u8 he_rate, nss; -+ u32 rate_code; -+ int ret, i; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ nss = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) { -+ if (hweight16(mask->control[band].he_mcs[i]) == 1) { -+ nss = i + 1; -+ he_rate = ffs(mask->control[band].he_mcs[i]) - 1; -+ } -+ } -+ -+ if (!nss) { -+ ath11k_warn(ar->ab, "No single HE Fixed rate found to set for %pM", -+ sta->addr); -+ return -EINVAL; -+ } -+ -+ /* Avoid updating invalid nss as fixed rate*/ -+ if (nss > sta->rx_nss) -+ return -EINVAL; -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates", -+ sta->addr); -+ -+ rate_code = ATH11K_HW_RATE_CODE(he_rate, nss - 1, -+ WMI_RATE_PREAMBLE_HE); -+ -+ ret = ath11k_wmi_set_peer_param(ar, sta->addr, -+ arvif->vdev_id, -+ WMI_PEER_PARAM_FIXED_RATE, -+ rate_code); -+ if (ret) -+ ath11k_warn(ar->ab, -+ "failed to update STA %pM Fixed Rate %d: %d\n", -+ sta->addr, rate_code, ret); -+ -+ return ret; -+} -+ - static int ath11k_station_assoc(struct ath11k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, -@@ -3241,7 +3481,7 @@ static int ath11k_station_assoc(struct ath11k *ar, - struct cfg80211_chan_def def; - enum nl80211_band band; - struct cfg80211_bitrate_mask *mask; -- u8 num_vht_rates; -+ u8 num_vht_rates, num_he_rates; - - lockdep_assert_held(&ar->conf_mutex); - -@@ -3267,9 +3507,10 @@ static int ath11k_station_assoc(struct ath11k *ar, - } - - num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask); -+ num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask); - -- /* If single VHT rate is configured (by set_bitrate_mask()), -- * peer_assoc will disable VHT. This is now enabled by a peer specific -+ /* If single VHT/HE rate is configured (by set_bitrate_mask()), -+ * peer_assoc will disable VHT/HE. This is now enabled by a peer specific - * fixed param. - * Note that all other rates and NSS will be disabled for this peer. - */ -@@ -3278,6 +3519,11 @@ static int ath11k_station_assoc(struct ath11k *ar, - band); - if (ret) - return ret; -+ } else if (sta->he_cap.has_he && num_he_rates == 1) { -+ ret = ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, -+ band); -+ if (ret) -+ return ret; - } - - /* Re-assoc is run only to update supported rates for given station. It -@@ -3348,8 +3594,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) - enum nl80211_band band; - const u8 *ht_mcs_mask; - const u16 *vht_mcs_mask; -+ const u16 *he_mcs_mask; - u32 changed, bw, nss, smps; -- int err, num_vht_rates; -+ int err, num_vht_rates, num_he_rates; - const struct cfg80211_bitrate_mask *mask; - struct peer_assoc_params peer_arg; - -@@ -3364,6 +3611,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) - band = def.chan->band; - ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs; - vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs; -+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; - - spin_lock_bh(&ar->data_lock); - -@@ -3379,8 +3627,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) - mutex_lock(&ar->conf_mutex); - - nss = max_t(u32, 1, nss); -- nss = min(nss, max(ath11k_mac_max_ht_nss(ht_mcs_mask), -- ath11k_mac_max_vht_nss(vht_mcs_mask))); -+ nss = min(nss, max(max(ath11k_mac_max_ht_nss(ht_mcs_mask), -+ ath11k_mac_max_vht_nss(vht_mcs_mask)), -+ ath11k_mac_max_he_nss(he_mcs_mask))); - - if (changed & IEEE80211_RC_BW_CHANGED) { - err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, -@@ -3416,6 +3665,8 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) - mask = &arvif->bitrate_mask; - num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, - mask); -+ num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, -+ mask); - - /* Peer_assoc_prepare will reject vht rates in - * bitrate_mask if its not available in range format and -@@ -3431,11 +3682,25 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) - if (sta->vht_cap.vht_supported && num_vht_rates == 1) { - ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, - band); -+ } else if (sta->he_cap.has_he && num_he_rates == 1) { -+ ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, -+ band); - } else { -- /* If the peer is non-VHT or no fixed VHT rate -+ /* If the peer is non-VHT/HE or no fixed VHT/HE rate - * is provided in the new bitrate mask we set the -- * other rates using peer_assoc command. -+ * other rates using peer_assoc command. Also clear -+ * the peer fixed rate settings as it has higher proprity -+ * than peer assoc - */ -+ err = ath11k_wmi_set_peer_param(ar, sta->addr, -+ arvif->vdev_id, -+ WMI_PEER_PARAM_FIXED_RATE, -+ WMI_FIXED_RATE_NONE); -+ if (err) -+ ath11k_warn(ar->ab, -+ "failed to disable peer fixed rate for STA %pM ret %d\n", -+ sta->addr, err); -+ - ath11k_peer_assoc_prepare(ar, arvif->vif, sta, - &peer_arg, true); - -@@ -5045,10 +5310,13 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, - - for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) { - arvif->bitrate_mask.control[i].legacy = 0xffffffff; -+ arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_FORCE_SGI; - memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff, - sizeof(arvif->bitrate_mask.control[i].ht_mcs)); - memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff, - sizeof(arvif->bitrate_mask.control[i].vht_mcs)); -+ memset(arvif->bitrate_mask.control[i].he_mcs, 0xff, -+ sizeof(arvif->bitrate_mask.control[i].he_mcs)); - } - - bit = __ffs64(ab->free_vdev_map); -@@ -6086,9 +6354,26 @@ ath11k_mac_has_single_legacy_rate(struct ath11k *ar, - if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask)) - return false; - -+ if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask)) -+ return false; -+ - return num_rates == 1; - } - -+static __le16 -+ath11k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap) -+{ -+ if (he_cap->he_cap_elem.phy_cap_info[0] & -+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) -+ return he_cap->he_mcs_nss_supp.tx_mcs_80p80; -+ -+ if (he_cap->he_cap_elem.phy_cap_info[0] & -+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) -+ return he_cap->he_mcs_nss_supp.tx_mcs_160; -+ -+ return he_cap->he_mcs_nss_supp.tx_mcs_80; -+} -+ - static bool - ath11k_mac_bitrate_mask_get_single_nss(struct ath11k *ar, - enum nl80211_band band, -@@ -6097,8 +6382,10 @@ ath11k_mac_bitrate_mask_get_single_nss(struct ath11k *ar, - { - struct ieee80211_supported_band *sband = &ar->mac.sbands[band]; - u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); -+ u16 he_mcs_map = 0; - u8 ht_nss_mask = 0; - u8 vht_nss_mask = 0; -+ u8 he_nss_mask = 0; - int i; - - /* No need to consider legacy here. Basic rates are always present -@@ -6125,7 +6412,20 @@ ath11k_mac_bitrate_mask_get_single_nss(struct ath11k *ar, - return false; - } - -- if (ht_nss_mask != vht_nss_mask) -+ he_mcs_map = le16_to_cpu(ath11k_mac_get_tx_mcs_map(&sband->iftype_data->he_cap)); -+ -+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) { -+ if (mask->control[band].he_mcs[i] == 0) -+ continue; -+ -+ if (mask->control[band].he_mcs[i] == -+ ath11k_mac_get_max_he_mcs_map(he_mcs_map, i)) -+ he_nss_mask |= BIT(i); -+ else -+ return false; -+ } -+ -+ if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask) - return false; - - if (ht_nss_mask == 0) -@@ -6172,42 +6472,128 @@ ath11k_mac_get_single_legacy_rate(struct ath11k *ar, - return 0; - } - --static int ath11k_mac_set_fixed_rate_params(struct ath11k_vif *arvif, -- u32 rate, u8 nss, u8 sgi, u8 ldpc) -+static int -+ath11k_mac_set_fixed_rate_GI_LTF(struct ath11k_vif *arvif, u8 he_gi, u8 he_ltf) - { - struct ath11k *ar = arvif->ar; -- u32 vdev_param; - int ret; - -- lockdep_assert_held(&ar->conf_mutex); -+ /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */ -+ if (he_gi && he_gi != 0xFF) -+ he_gi += 1; - -- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02hhx nss %hhu sgi %hhu\n", -- arvif->vdev_id, rate, nss, sgi); -+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -+ WMI_VDEV_PARAM_SGI, he_gi); -+ if (ret) { -+ ath11k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n", -+ he_gi, ret); -+ return ret; -+ } -+ /* start from 1 */ -+ if (he_ltf != 0xFF) -+ he_ltf += 1; - -- vdev_param = WMI_VDEV_PARAM_FIXED_RATE; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -- vdev_param, rate); -+ WMI_VDEV_PARAM_HE_LTF, he_ltf); - if (ret) { -- ath11k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n", -- rate, ret); -+ ath11k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n", -+ he_ltf, ret); - return ret; - } - -- vdev_param = WMI_VDEV_PARAM_NSS; -+ return 0; -+} -+ -+static int -+ath11k_mac_set_auto_rate_GI_LTF(struct ath11k_vif *arvif, u16 he_gi, u8 he_ltf) -+{ -+ struct ath11k *ar = arvif->ar; -+ int ret; -+ u32 he_ar_gi_ltf = 0; -+ -+ if (he_gi != 0xFF) { -+ switch (he_gi) { -+ case NL80211_RATE_INFO_HE_GI_0_8: -+ he_gi = WMI_AUTORATE_800NS_GI; -+ break; -+ case NL80211_RATE_INFO_HE_GI_1_6: -+ he_gi = WMI_AUTORATE_1600NS_GI; -+ break; -+ case NL80211_RATE_INFO_HE_GI_3_2: -+ he_gi = WMI_AUTORATE_3200NS_GI; -+ break; -+ default: -+ ath11k_warn(ar->ab, "Invalid GI\n"); -+ return -EINVAL; -+ } -+ } -+ -+ if (he_ltf != 0xFF) { -+ switch (he_ltf) { -+ case NL80211_RATE_INFO_HE_1XLTF: -+ he_ltf = WMI_HE_AUTORATE_LTF_1X; -+ break; -+ case NL80211_RATE_INFO_HE_2XLTF: -+ he_ltf = WMI_HE_AUTORATE_LTF_2X; -+ break; -+ case NL80211_RATE_INFO_HE_4XLTF: -+ he_ltf = WMI_HE_AUTORATE_LTF_4X; -+ break; -+ default: -+ ath11k_warn(ar->ab, "Invalid LTF\n"); -+ return -EINVAL; -+ } -+ } -+ -+ he_ar_gi_ltf = he_gi | he_ltf; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -- vdev_param, nss); -+ WMI_VDEV_PARAM_AUTORATE_MISC_CFG, -+ he_ar_gi_ltf); - if (ret) { -- ath11k_warn(ar->ab, "failed to set nss param %d: %d\n", -- nss, ret); -+ ath11k_warn(ar->ab, -+ "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n", -+ he_gi, he_ltf, ret); - return ret; - } - -- vdev_param = WMI_VDEV_PARAM_SGI; -+ return 0; -+} -+ -+static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif, -+ u32 rate, u8 nss, u8 sgi, u8 ldpc, -+ u8 he_gi, u8 he_ltf, bool he_fixed_rate) -+{ -+ struct ath11k *ar = arvif->ar; -+ u32 vdev_param; -+ int ret; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "mac set rate params vdev %i, rate:0x%02x, nss:0x%02x, sgi:0x%02x, ldpc:0x%02x\n", -+ arvif->vdev_id, rate, nss, sgi, ldpc); -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "he_gi:0x%02x, he_ltf:0x%02x, he_fixed_rate:%d\n", he_gi, -+ he_ltf, he_fixed_rate); -+ -+ if (!arvif->vif->bss_conf.he_support) { -+ vdev_param = WMI_VDEV_PARAM_FIXED_RATE; -+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -+ vdev_param, rate); -+ if (ret) { -+ ath11k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n", -+ rate, ret); -+ return ret; -+ } -+ } -+ -+ vdev_param = WMI_VDEV_PARAM_NSS; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -- vdev_param, sgi); -+ vdev_param, nss); - if (ret) { -- ath11k_warn(ar->ab, "failed to set sgi param %d: %d\n", -- sgi, ret); -+ ath11k_warn(ar->ab, "failed to set nss param %d: %d\n", -+ nss, ret); - return ret; - } - -@@ -6220,6 +6606,27 @@ static int ath11k_mac_set_fixed_rate_params(struct ath11k_vif *arvif, - return ret; - } - -+ if (arvif->vif->bss_conf.he_support) { -+ if (he_fixed_rate) { -+ ret = ath11k_mac_set_fixed_rate_GI_LTF(arvif, he_gi, -+ he_ltf); -+ } else { -+ ret = ath11k_mac_set_auto_rate_GI_LTF(arvif, he_gi, -+ he_ltf); -+ } -+ if (ret) -+ return ret; -+ } else { -+ vdev_param = WMI_VDEV_PARAM_SGI; -+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -+ vdev_param, sgi); -+ if (ret) { -+ ath11k_warn(ar->ab, "failed to set sgi param %d: %d\n", -+ sgi, ret); -+ return ret; -+ } -+ } -+ - return 0; - } - -@@ -6248,6 +6655,31 @@ ath11k_mac_vht_mcs_range_present(struct ath11k *ar, - return true; - } - -+static bool -+ath11k_mac_he_mcs_range_present(struct ath11k *ar, -+ enum nl80211_band band, -+ const struct cfg80211_bitrate_mask *mask) -+{ -+ int i; -+ u16 he_mcs; -+ -+ for (i = 0; i < NL80211_HE_NSS_MAX; i++) { -+ he_mcs = mask->control[band].he_mcs[i]; -+ -+ switch (he_mcs) { -+ case 0: -+ case BIT(8) - 1: -+ case BIT(10) - 1: -+ case BIT(12) - 1: -+ break; -+ default: -+ return false; -+ } -+ } -+ -+ return true; -+} -+ - static void ath11k_mac_set_bitrate_mask_iter(void *data, - struct ieee80211_sta *sta) - { -@@ -6279,6 +6711,53 @@ static void ath11k_mac_disable_peer_fixed_rate(void *data, - sta->addr, ret); - } - -+static bool -+ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_band band, -+ const struct cfg80211_bitrate_mask *mask) -+{ -+ bool he_fixed_rate = false, vht_fixed_rate = false; -+ struct ath11k_peer *peer, *tmp; -+ const u16 *vht_mcs_mask, *he_mcs_mask; -+ u8 vht_nss, he_nss; -+ bool ret = true; -+ -+ vht_mcs_mask = mask->control[band].vht_mcs; -+ he_mcs_mask = mask->control[band].he_mcs; -+ -+ if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1) -+ vht_fixed_rate = true; -+ -+ if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1) -+ he_fixed_rate = true; -+ -+ if (!vht_fixed_rate && !he_fixed_rate) -+ return true; -+ -+ vht_nss = ath11k_mac_max_vht_nss(vht_mcs_mask); -+ he_nss = ath11k_mac_max_he_nss(he_mcs_mask); -+ -+ rcu_read_lock(); -+ spin_lock_bh(&ar->ab->base_lock); -+ list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { -+ if (peer->sta) { -+ if (vht_fixed_rate && (!peer->sta->vht_cap.vht_supported || -+ peer->sta->rx_nss < vht_nss)) { -+ ret = false; -+ goto exit; -+ } -+ if (he_fixed_rate && (!peer->sta->he_cap.has_he || -+ peer->sta->rx_nss < he_nss)) { -+ ret = false; -+ goto exit; -+ } -+ } -+ } -+exit: -+ spin_unlock_bh(&ar->ab->base_lock); -+ rcu_read_unlock(); -+ return ret; -+} -+ - static int - ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, -@@ -6290,6 +6769,9 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - enum nl80211_band band; - const u8 *ht_mcs_mask; - const u16 *vht_mcs_mask; -+ const u16 *he_mcs_mask; -+ u8 he_ltf = 0; -+ u8 he_gi = 0; - u32 rate; - u8 nss; - u8 sgi; -@@ -6297,6 +6779,7 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - int single_nss; - int ret; - int num_rates; -+ bool he_fixed_rate = false; - - if (ath11k_mac_vif_chan(vif, &def)) - return -EPERM; -@@ -6304,12 +6787,16 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - band = def.chan->band; - ht_mcs_mask = mask->control[band].ht_mcs; - vht_mcs_mask = mask->control[band].vht_mcs; -+ he_mcs_mask = mask->control[band].he_mcs; - ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); - - sgi = mask->control[band].gi; - if (sgi == NL80211_TXRATE_FORCE_LGI) - return -EINVAL; - -+ he_gi = mask->control[band].he_gi; -+ he_ltf = mask->control[band].he_ltf; -+ - /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it - * requires passing atleast one of used basic rates along with them. - * Fixed rate setting across different preambles(legacy, HT, VHT) is -@@ -6333,11 +6820,22 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - &single_nss)) { - rate = WMI_FIXED_RATE_NONE; - nss = single_nss; -+ mutex_lock(&ar->conf_mutex); -+ arvif->bitrate_mask = *mask; -+ ieee80211_iterate_stations_atomic(ar->hw, -+ ath11k_mac_set_bitrate_mask_iter, -+ arvif); -+ mutex_unlock(&ar->conf_mutex); - } else { - rate = WMI_FIXED_RATE_NONE; -+ -+ if (!ath11k_mac_validate_vht_he_fixed_rate_settings(ar, band, mask)) -+ ath11k_warn(ar->ab, -+ "could not update fixed rate settings to all peers due to mcs/nss incompaitiblity\n"); - nss = min_t(u32, ar->num_tx_chains, -- max(ath11k_mac_max_ht_nss(ht_mcs_mask), -- ath11k_mac_max_vht_nss(vht_mcs_mask))); -+ max(max(ath11k_mac_max_ht_nss(ht_mcs_mask), -+ ath11k_mac_max_vht_nss(vht_mcs_mask)), -+ ath11k_mac_max_he_nss(he_mcs_mask))); - - /* If multiple rates across different preambles are given - * we can reconfigure this info with all peers using PEER_ASSOC -@@ -6372,12 +6870,23 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - return -EINVAL; - } - -+ num_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, -+ mask); -+ if (num_rates == 1) -+ he_fixed_rate = true; -+ -+ if (!ath11k_mac_he_mcs_range_present(ar, band, mask) && -+ num_rates > 1) { -+ ath11k_warn(ar->ab, -+ "Setting more than one HE MCS Value in bitrate mask not supported\n"); -+ return -EINVAL; -+ } -+ -+ mutex_lock(&ar->conf_mutex); - ieee80211_iterate_stations_atomic(ar->hw, - ath11k_mac_disable_peer_fixed_rate, - arvif); - -- mutex_lock(&ar->conf_mutex); -- - arvif->bitrate_mask = *mask; - ieee80211_iterate_stations_atomic(ar->hw, - ath11k_mac_set_bitrate_mask_iter, -@@ -6388,9 +6897,10 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, - - mutex_lock(&ar->conf_mutex); - -- ret = ath11k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc); -+ ret = ath11k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi, -+ he_ltf, he_fixed_rate); - if (ret) { -- ath11k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n", -+ ath11k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n", - arvif->vdev_id, ret); - } - -diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c -index e3d11a0a7b7c..330b435e0ed3 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1904,8 +1904,8 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar, - FIELD_PREP(WMI_TLV_LEN, - sizeof(*he_mcs) - TLV_HDR_SIZE); - -- he_mcs->rx_mcs_set = param->peer_he_rx_mcs_set[i]; -- he_mcs->tx_mcs_set = param->peer_he_tx_mcs_set[i]; -+ he_mcs->rx_mcs_set = param->peer_he_tx_mcs_set[i]; -+ he_mcs->tx_mcs_set = param->peer_he_rx_mcs_set[i]; - ptr += sizeof(*he_mcs); - } - -diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h -index 799b3bd96a27..097023a94e06 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -119,6 +119,22 @@ enum { - WMI_HOST_WLAN_2G_5G_CAP = 0x3, - }; - -+/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command. -+ * Used only for HE auto rate mode. -+ */ -+enum { -+ /* HE LTF related configuration */ -+ WMI_HE_AUTORATE_LTF_1X = BIT(0), -+ WMI_HE_AUTORATE_LTF_2X = BIT(1), -+ WMI_HE_AUTORATE_LTF_4X = BIT(2), -+ -+ /* HE GI related configuration */ -+ WMI_AUTORATE_400NS_GI = BIT(8), -+ WMI_AUTORATE_800NS_GI = BIT(9), -+ WMI_AUTORATE_1600NS_GI = BIT(10), -+ WMI_AUTORATE_3200NS_GI = BIT(11), -+}; -+ - /* - * wmi command groups. - */ -@@ -1044,7 +1060,9 @@ enum wmi_tlv_vdev_param { - WMI_VDEV_PARAM_HE_RANGE_EXT, - WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE, - WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME, -+ WMI_VDEV_PARAM_HE_LTF = 0x74, - WMI_VDEV_PARAM_BA_MODE = 0x7e, -+ WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80, - WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87, - WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99, - WMI_VDEV_PARAM_PROTOTYPE = 0x8000, -@@ -3920,7 +3938,9 @@ struct wmi_vht_rate_set { - - struct wmi_he_rate_set { - u32 tlv_header; -+ /* MCS at which the peer can receive */ - u32 rx_mcs_set; -+ /* MCS at which the peer can transmit */ - u32 tx_mcs_set; - } __packed; - - -From patchwork Wed Jul 21 17:36:15 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Jouni Malinen -X-Patchwork-Id: 12391751 -X-Patchwork-Delegate: kvalo@adurom.com -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -X-Spam-Level: -X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, - DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, - MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT - autolearn=unavailable autolearn_force=no version=3.4.0 -Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) - by smtp.lore.kernel.org (Postfix) with ESMTP id ED66CC636C9 - for ; - Wed, 21 Jul 2021 17:37:12 +0000 (UTC) -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by mail.kernel.org (Postfix) with ESMTP id C53B161246 - for ; - Wed, 21 Jul 2021 17:37:12 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S229948AbhGUQ4f (ORCPT - ); - Wed, 21 Jul 2021 12:56:35 -0400 -Received: from m43-7.mailgun.net ([69.72.43.7]:24415 "EHLO m43-7.mailgun.net" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S229767AbhGUQ4f (ORCPT ); - Wed, 21 Jul 2021 12:56:35 -0400 -DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; - q=dns/txt; - s=smtp; t=1626889031; h=Content-Transfer-Encoding: MIME-Version: - References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: - Sender; bh=lF1ojJptZPwZovzBlNtOoNgPKW8QTeEKCq2RB6a8Z+4=; - b=LA2hIcYLsUHpnXbyTqn4yR/XSj5WvrLDmq/6e4pwvapc8zGlom/XbwEhlmuISHZM22tKGL7y - Ya1lvIE0cr6FNosu4biRMmNQM6aNUgZFPyfXIj9zH6PjdTXy5WYzl2AWoU+D+H/erSLWlVHg - p44FuzWsd26CJtrzJ7yvdwUEUa4= -X-Mailgun-Sending-Ip: 69.72.43.7 -X-Mailgun-Sid: - WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= -Received: from smtp.codeaurora.org - (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by - smtp-out-n04.prod.us-east-1.postgun.com with SMTP id - 60f85b341dd16c87882bae14 (version=TLS1.2, - cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 21 Jul 2021 17:36:52 - GMT -Sender: jouni=codeaurora.org@mg.codeaurora.org -Received: by smtp.codeaurora.org (Postfix, from userid 1001) - id D2AA2C433F1; Wed, 21 Jul 2021 17:36:51 +0000 (UTC) -Received: from jouni.codeaurora.org (85-76-67-217-nat.elisa-mobile.fi - [85.76.67.217]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - (Authenticated sender: jouni) - by smtp.codeaurora.org (Postfix) with ESMTPSA id 45C92C4338A; - Wed, 21 Jul 2021 17:36:49 +0000 (UTC) -DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 45C92C4338A -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - dmarc=none (p=none dis=none) header.from=codeaurora.org -Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; - spf=fail smtp.mailfrom=jouni@codeaurora.org -From: Jouni Malinen -To: Kalle Valo -Cc: ath11k@lists.infradead.org, linux-wireless@vger.kernel.org, - P Praneesh , - Ganesh Sesetti , - Sathishkumar Muruganandam , - Jouni Malinen -Subject: [PATCH 2/2] ath11k: add support for 80P80 and 160 MHz bandwidth -Date: Wed, 21 Jul 2021 20:36:15 +0300 -Message-Id: <20210721173615.75637-2-jouni@codeaurora.org> -X-Mailer: git-send-email 2.25.1 -In-Reply-To: <20210721173615.75637-1-jouni@codeaurora.org> -References: <20210721173615.75637-1-jouni@codeaurora.org> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless@vger.kernel.org - -From: P Praneesh - -For 160 MHz, nss_ratio_enabled flag is added to indicate firmware -supports sending NSS ratio information from firmware as a part of -service ready ext event. Extract this NSS ratio info from service -ready ext event and save this information in ath11k_pdev_cap to -calculate NSS ratio. - -Current firmware configurations support two types of NSS ratio -which is WMI_NSS_RATIO_1_NSS for QCN9074 and WMI_NSS_RATIO_1BY2_NSS -for IPQ8074. Based on this two configuration, max supported -NSS getting calculated. - -Move ath11k_peer_assoc_h_phymode() before ath11k_peer_assoc_h_vht() -to get arg->peer_phymode updated. - -Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1-00097-QCAHKSWPL_SILICONZ-1 -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01467-QCAHKSWPL_SILICONZ-1 - -Co-developed-by: Ganesh Sesetti -Signed-off-by: Ganesh Sesetti -Co-developed-by: Sathishkumar Muruganandam -Signed-off-by: Sathishkumar Muruganandam -Signed-off-by: P Praneesh -Signed-off-by: Jouni Malinen ---- - drivers/net/wireless/ath/ath11k/core.h | 2 + - drivers/net/wireless/ath/ath11k/mac.c | 94 ++++++++++++++++++++++---- - drivers/net/wireless/ath/ath11k/mac.h | 3 + - drivers/net/wireless/ath/ath11k/wmi.c | 20 +++++- - drivers/net/wireless/ath/ath11k/wmi.h | 30 ++++++++ - 5 files changed, 135 insertions(+), 14 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 0ad5a935b52b..c73001014795 100644 ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -593,6 +593,8 @@ struct ath11k_pdev_cap { - u32 tx_chain_mask_shift; - u32 rx_chain_mask_shift; - struct ath11k_band_cap band[NUM_NL80211_BANDS]; -+ bool nss_ratio_enabled; -+ u8 nss_ratio_info; - }; - - struct ath11k_pdev { -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index 4dcc1b377642..11d919d3c23e 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1525,6 +1525,33 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set, - return tx_mcs_set; - } - -+static u8 ath11k_get_nss_160mhz(struct ath11k *ar, -+ u8 max_nss) -+{ -+ u8 nss_ratio_info = ar->pdev->cap.nss_ratio_info; -+ u8 max_sup_nss = 0; -+ -+ switch (nss_ratio_info) { -+ case WMI_NSS_RATIO_1BY2_NSS: -+ max_sup_nss = max_nss >> 1; -+ break; -+ case WMI_NSS_RATIO_3BY4_NSS: -+ ath11k_warn(ar->ab, "WMI_NSS_RATIO_3BY4_NSS not supported\n"); -+ break; -+ case WMI_NSS_RATIO_1_NSS: -+ max_sup_nss = max_nss; -+ break; -+ case WMI_NSS_RATIO_2_NSS: -+ ath11k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n"); -+ break; -+ default: -+ ath11k_warn(ar->ab, "invalid nss ratio received from fw\n"); -+ break; -+ } -+ -+ return max_sup_nss; -+} -+ - static void ath11k_peer_assoc_h_vht(struct ath11k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, -@@ -1539,6 +1566,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, - u8 max_nss, vht_mcs; - int i, vht_nss, nss_idx; - bool user_rate_valid = true; -+ u32 rx_nss, tx_nss, nss_160; - - if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) - return; -@@ -1631,10 +1659,29 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, - /* TODO: Check */ - arg->tx_max_mcs_nss = 0xFF; - -- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n", -- sta->addr, arg->peer_max_mpdu, arg->peer_flags); -+ if (arg->peer_phymode == MODE_11AC_VHT160 || -+ arg->peer_phymode == MODE_11AC_VHT80_80) { -+ tx_nss = ath11k_get_nss_160mhz(ar, max_nss); -+ rx_nss = min(arg->peer_nss, tx_nss); -+ arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE; -+ -+ if (!rx_nss) { -+ ath11k_warn(ar->ab, "invalid max_nss\n"); -+ return; -+ } -+ -+ if (arg->peer_phymode == MODE_11AC_VHT160) -+ nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ, rx_nss - 1); -+ else -+ nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ, rx_nss - 1); - -- /* TODO: rxnss_override */ -+ arg->peer_bw_rxnss_override |= nss_160; -+ } -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n", -+ sta->addr, arg->peer_max_mpdu, arg->peer_flags, -+ arg->peer_bw_rxnss_override); - } - - static int ath11k_mac_get_max_he_mcs_map(u16 mcs_map, int nss) -@@ -1718,6 +1765,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, - u16 he_tx_mcs = 0, v = 0; - int i, he_nss, nss_idx; - bool user_rate_valid = true; -+ u32 rx_nss, tx_nss, nss_160; - - if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) - return; -@@ -1881,9 +1929,30 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, - } - arg->peer_nss = min(sta->rx_nss, max_nss); - -+ if (arg->peer_phymode == MODE_11AX_HE160 || -+ arg->peer_phymode == MODE_11AX_HE80_80) { -+ tx_nss = ath11k_get_nss_160mhz(ar, max_nss); -+ rx_nss = min(arg->peer_nss, tx_nss); -+ arg->peer_bw_rxnss_override = ATH11K_BW_NSS_MAP_ENABLE; -+ -+ if (!rx_nss) { -+ ath11k_warn(ar->ab, "invalid max_nss\n"); -+ return; -+ } -+ -+ if (arg->peer_phymode == MODE_11AX_HE160) -+ nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ, rx_nss - 1); -+ else -+ nss_160 = FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ, rx_nss - 1); -+ -+ arg->peer_bw_rxnss_override |= nss_160; -+ } -+ - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -- "mac he peer %pM nss %d mcs cnt %d\n", -- sta->addr, arg->peer_nss, arg->peer_he_mcs_count); -+ "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n", -+ sta->addr, arg->peer_nss, -+ arg->peer_he_mcs_count, -+ arg->peer_bw_rxnss_override); - } - - static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta, -@@ -2171,11 +2240,11 @@ static void ath11k_peer_assoc_prepare(struct ath11k *ar, - ath11k_peer_assoc_h_basic(ar, vif, sta, arg); - ath11k_peer_assoc_h_crypto(ar, vif, sta, arg); - ath11k_peer_assoc_h_rates(ar, vif, sta, arg); -+ ath11k_peer_assoc_h_phymode(ar, vif, sta, arg); - ath11k_peer_assoc_h_ht(ar, vif, sta, arg); - ath11k_peer_assoc_h_vht(ar, vif, sta, arg); - ath11k_peer_assoc_h_he(ar, vif, sta, arg); - ath11k_peer_assoc_h_qos(ar, vif, sta, arg); -- ath11k_peer_assoc_h_phymode(ar, vif, sta, arg); - ath11k_peer_assoc_h_smps(sta, arg); - - /* TODO: amsdu_disable req? */ -@@ -4371,11 +4440,6 @@ ath11k_create_vht_cap(struct ath11k *ar, u32 rate_cap_tx_chainmask, - - ath11k_set_vht_txbf_cap(ar, &vht_cap.cap); - -- /* TODO: Enable back VHT160 mode once association issues are fixed */ -- /* Disabling VHT160 and VHT80+80 modes */ -- vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; -- vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160; -- - rxmcs_map = 0; - txmcs_map = 0; - for (i = 0; i < 8; i++) { -@@ -7244,7 +7308,9 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar) - combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40) | -- BIT(NL80211_CHAN_WIDTH_80); -+ BIT(NL80211_CHAN_WIDTH_80) | -+ BIT(NL80211_CHAN_WIDTH_80P80) | -+ BIT(NL80211_CHAN_WIDTH_160); - - ar->hw->wiphy->iface_combinations = combinations; - ar->hw->wiphy->n_iface_combinations = 1; -@@ -7383,6 +7449,10 @@ static int __ath11k_mac_register(struct ath11k *ar) - ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); - ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); - ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); -+ -+ if (cap->nss_ratio_enabled) -+ ieee80211_hw_set(ar->hw, SUPPORTS_VHT_EXT_NSS_BW); -+ - if (ht_cap & WMI_HT_CAP_ENABLED) { - ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION); - ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW); -diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h -index 4bc59bdaf244..254ca4acc8e8 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.h -+++ b/drivers/net/wireless/ath/ath11k/mac.h -@@ -115,6 +115,9 @@ struct ath11k_generic_iter { - #define WMI_MAX_SPATIAL_STREAM 3 - - #define ATH11K_CHAN_WIDTH_NUM 8 -+#define ATH11K_BW_NSS_MAP_ENABLE BIT(31) -+#define ATH11K_PEER_RX_NSS_160MHZ GENMASK(2, 0) -+#define ATH11K_PEER_RX_NSS_80_80MHZ GENMASK(5, 3) - - #define ATH11K_OBSS_PD_MAX_THRESHOLD -82 - #define ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62 -diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c -index 330b435e0ed3..7ac84ac86aab 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -360,6 +360,10 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle, - pdev_cap->he_mcs = mac_phy_caps->he_supp_mcs_5g; - pdev_cap->tx_chain_mask = mac_phy_caps->tx_chain_mask_5g; - pdev_cap->rx_chain_mask = mac_phy_caps->rx_chain_mask_5g; -+ pdev_cap->nss_ratio_enabled = -+ WMI_NSS_RATIO_ENABLE_DISABLE_GET(mac_phy_caps->nss_ratio); -+ pdev_cap->nss_ratio_info = -+ WMI_NSS_RATIO_INFO_GET(mac_phy_caps->nss_ratio); - } else { - return -EINVAL; - } -@@ -783,14 +787,26 @@ int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id) - static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan, - struct wmi_vdev_start_req_arg *arg) - { -+ u32 center_freq1 = arg->channel.band_center_freq1; -+ - memset(chan, 0, sizeof(*chan)); - - chan->mhz = arg->channel.freq; - chan->band_center_freq1 = arg->channel.band_center_freq1; -- if (arg->channel.mode == MODE_11AC_VHT80_80) -+ -+ if (arg->channel.mode == MODE_11AX_HE160) { -+ if (arg->channel.freq > arg->channel.band_center_freq1) -+ chan->band_center_freq1 = center_freq1 + 40; -+ else -+ chan->band_center_freq1 = center_freq1 - 40; -+ -+ chan->band_center_freq2 = arg->channel.band_center_freq1; -+ -+ } else if (arg->channel.mode == MODE_11AC_VHT80_80) { - chan->band_center_freq2 = arg->channel.band_center_freq2; -- else -+ } else { - chan->band_center_freq2 = 0; -+ } - - chan->info |= FIELD_PREP(WMI_CHAN_INFO_MODE, arg->channel.mode); - if (arg->channel.passive) -diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h -index 097023a94e06..fb27a8d0f0fd 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2146,6 +2146,24 @@ enum wmi_direct_buffer_module { - WMI_DIRECT_BUF_MAX - }; - -+/* enum wmi_nss_ratio - NSS ratio received from FW during service ready ext -+ * event -+ * WMI_NSS_RATIO_1BY2_NSS -Max nss of 160MHz is equals to half of the max nss -+ * of 80MHz -+ * WMI_NSS_RATIO_3BY4_NSS - Max nss of 160MHz is equals to 3/4 of the max nss -+ * of 80MHz -+ * WMI_NSS_RATIO_1_NSS - Max nss of 160MHz is equals to the max nss of 80MHz -+ * WMI_NSS_RATIO_2_NSS - Max nss of 160MHz is equals to two times the max -+ * nss of 80MHz -+ */ -+ -+enum wmi_nss_ratio { -+ WMI_NSS_RATIO_1BY2_NSS = 0x0, -+ WMI_NSS_RATIO_3BY4_NSS = 0x1, -+ WMI_NSS_RATIO_1_NSS = 0x2, -+ WMI_NSS_RATIO_2_NSS = 0x3, -+}; -+ - struct wmi_host_pdev_band_to_mac { - u32 pdev_id; - u32 start_freq; -@@ -2390,6 +2408,12 @@ struct wmi_hw_mode_capabilities { - } __packed; - - #define WMI_MAX_HECAP_PHY_SIZE (3) -+#define WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS BIT(0) -+#define WMI_NSS_RATIO_ENABLE_DISABLE_GET(_val) \ -+ FIELD_GET(WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS, _val) -+#define WMI_NSS_RATIO_INFO_BITPOS GENMASK(4, 1) -+#define WMI_NSS_RATIO_INFO_GET(_val) \ -+ FIELD_GET(WMI_NSS_RATIO_INFO_BITPOS, _val) - - struct wmi_mac_phy_capabilities { - u32 hw_mode_id; -@@ -2423,6 +2447,12 @@ struct wmi_mac_phy_capabilities { - u32 he_cap_info_2g_ext; - u32 he_cap_info_5g_ext; - u32 he_cap_info_internal; -+ u32 wireless_modes; -+ u32 low_2ghz_chan_freq; -+ u32 high_2ghz_chan_freq; -+ u32 low_5ghz_chan_freq; -+ u32 high_5ghz_chan_freq; -+ u32 nss_ratio; - } __packed; - - struct wmi_hal_reg_capabilities_ext { diff --git a/package/kernel/mac80211/patches/ath11k/015-ath11k-Enable-radar-detection-for-160MHz-secondary-segment.patch b/package/kernel/mac80211/patches/ath11k/015-ath11k-Enable-radar-detection-for-160MHz-secondary-segment.patch deleted file mode 100644 index fe0d6f614..000000000 --- a/package/kernel/mac80211/patches/ath11k/015-ath11k-Enable-radar-detection-for-160MHz-secondary-segment.patch +++ /dev/null @@ -1,37 +0,0 @@ -WMI_CHAN_INFO_DFS_FREQ2 needs to be set in wmi vdev start command chan -info parameter, to enable radar detection for secondary segment in 160MHz. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01717-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Lavanya Suresh ---- -v2: -* Rebased on latest ath.git - ---- - drivers/net/wireless/ath/ath11k/mac.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index b391169..a650d95 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5096,13 +5096,15 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, - arg.channel.chan_radar = - !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); - -+ arg.channel.freq2_radar = -+ !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); -+ - arg.channel.passive = arg.channel.chan_radar; - - spin_lock_bh(&ab->base_lock); - arg.regdomain = ar->ab->dfs_region; - spin_unlock_bh(&ab->base_lock); - -- /* TODO: Notify if secondary 80Mhz also needs radar detection */ - if (he_support) { - ret = ath11k_set_he_mu_sounding_mode(ar, arvif); - if (ret) { --- -2.7.4 \ No newline at end of file diff --git a/package/kernel/mac80211/patches/ath11k/017-ath11k-Fix-an-error-handling-path-in-ath11k-core_fetch-board-data-api-n.patch b/package/kernel/mac80211/patches/ath11k/017-ath11k-Fix-an-error-handling-path-in-ath11k-core_fetch-board-data-api-n.patch deleted file mode 100644 index 67f43eeae..000000000 --- a/package/kernel/mac80211/patches/ath11k/017-ath11k-Fix-an-error-handling-path-in-ath11k-core_fetch-board-data-api-n.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 515bda1d1e51c64edf2a384a58801f85a80a3f2d Mon Sep 17 00:00:00 2001 -From: Christophe JAILLET -Date: Sat, 22 May 2021 11:50:54 +0200 -Subject: ath11k: Fix an error handling path in - ath11k_core_fetch_board_data_api_n() - -All error paths but this one 'goto err' in order to release some -resources. -Fix this. - -Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") -Signed-off-by: Christophe JAILLET -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/e959eb544f3cb04258507d8e25a6f12eab126bde.1621676864.git.christophe.jaillet@wanadoo.fr ---- - drivers/net/wireless/ath/ath11k/core.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c -index 4a1051418f33a..969bf1a590d99 100644 ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -532,7 +532,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, - if (len < ALIGN(ie_len, 4)) { - ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n", - ie_id, ie_len, len); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err; - } - - switch (ie_id) { --- -cgit 1.2.3-1.el7 diff --git a/package/kernel/mac80211/patches/ath11k/018-ath11k-send-beacon-template-after-vdev-startrestart-during-csa.patch b/package/kernel/mac80211/patches/ath11k/018-ath11k-send-beacon-template-after-vdev-startrestart-during-csa.patch deleted file mode 100644 index 4b34eaa37..000000000 --- a/package/kernel/mac80211/patches/ath11k/018-ath11k-send-beacon-template-after-vdev-startrestart-during-csa.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 979ebc54cf13bd1e3eb6e21766d208d5de984fb8 Mon Sep 17 00:00:00 2001 -From: Seevalamuthu Mariappan -Date: Tue, 25 May 2021 15:30:28 +0200 -Subject: ath11k: send beacon template after vdev_start/restart during csa - -Firmware has added assert if beacon template is received after -vdev_down. Firmware expects beacon template after vdev_start -and before vdev_up. This change is needed to support MBSSID EMA -cases in firmware. - -Hence, Change the sequence in ath11k as expected from firmware. -This new change is not causing any issues with older -firmware. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1.r3-00011-QCAHKSWPL_SILICONZ-1 -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1.r4-00008-QCAHKSWPL_SILICONZ-1 - -Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") -Signed-off-by: Seevalamuthu Mariappan -[sven@narfation.org: added tested-on/fixes information] -Signed-off-by: Sven Eckelmann -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20210525133028.2805615-1-sven@narfation.org ---- - drivers/net/wireless/ath/ath11k/mac.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index 9d0ff150ec30f..eb52332dbe3f1 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5379,11 +5379,6 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, - if (WARN_ON(!arvif->is_up)) - continue; - -- ret = ath11k_mac_setup_bcn_tmpl(arvif); -- if (ret) -- ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -- ret); -- - ret = ath11k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def); - if (ret) { - ath11k_warn(ab, "failed to restart vdev %d: %d\n", -@@ -5391,6 +5386,11 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, - continue; - } - -+ ret = ath11k_mac_setup_bcn_tmpl(arvif); -+ if (ret) -+ ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -+ ret); -+ - ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); - if (ret) { --- -cgit 1.2.3-1.el7 diff --git a/package/kernel/mac80211/patches/ath11k/033-ath11k-fix-for-peer-memory-corruption.patch b/package/kernel/mac80211/patches/ath11k/033-ath11k-fix-for-peer-memory-corruption.patch deleted file mode 100644 index af130a1c7..000000000 --- a/package/kernel/mac80211/patches/ath11k/033-ath11k-fix-for-peer-memory-corruption.patch +++ /dev/null @@ -1,103 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1463,11 +1463,9 @@ struct htt_ppdu_stats_info *ath11k_dp_ht - { - struct htt_ppdu_stats_info *ppdu_info; - -- spin_lock_bh(&ar->data_lock); - if (!list_empty(&ar->ppdu_stats_info)) { - list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) { - if (ppdu_info->ppdu_id == ppdu_id) { -- spin_unlock_bh(&ar->data_lock); - return ppdu_info; - } - } -@@ -1481,16 +1479,13 @@ struct htt_ppdu_stats_info *ath11k_dp_ht - kfree(ppdu_info); - } - } -- spin_unlock_bh(&ar->data_lock); - - ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_ATOMIC); - if (!ppdu_info) - return NULL; - -- spin_lock_bh(&ar->data_lock); - list_add_tail(&ppdu_info->list, &ar->ppdu_stats_info); - ar->ppdu_stat_list_depth++; -- spin_unlock_bh(&ar->data_lock); - - return ppdu_info; - } -@@ -1522,8 +1517,10 @@ static int ath11k_htt_pull_ppdu_stats(st - ath11k_htt_ppdu_pktlog_process(ar, (u8 *)skb->data, DP_RX_BUFFER_SIZE); - } - -+ spin_lock_bh(&ar->data_lock); - ppdu_info = ath11k_dp_htt_get_ppdu_desc(ar, ppdu_id); - if (!ppdu_info) { -+ spin_unlock_bh(&ar->data_lock); - ret = -EINVAL; - goto exit; - } -@@ -1533,10 +1530,12 @@ static int ath11k_htt_pull_ppdu_stats(st - ath11k_htt_tlv_ppdu_stats_parse, - (void *)ppdu_info); - if (ret) { -+ spin_unlock_bh(&ar->data_lock); - ath11k_warn(ab, "Failed to parse tlv %d\n", ret); - goto exit; - } - -+ spin_unlock_bh(&ar->data_lock); - exit: - rcu_read_unlock(); - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -2755,22 +2755,28 @@ static int ath11k_clear_peer_keys(struct - int ret; - int i; - u32 flags = 0; -+ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; - - lockdep_assert_held(&ar->conf_mutex); - - spin_lock_bh(&ab->base_lock); - peer = ath11k_peer_find(ab, arvif->vdev_id, addr); -- spin_unlock_bh(&ab->base_lock); -- -- if (!peer) -+ if (!peer) { -+ spin_unlock_bh(&ab->base_lock); - return -ENOENT; -+ } -+ for (i = 0; i < ARRAY_SIZE(keys); i++) { -+ keys[i]= peer->keys[i]; -+ peer->keys[i]= NULL; -+ } -+ spin_unlock_bh(&ab->base_lock); - -- for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { -- if (!peer->keys[i]) -+ for (i = 0; i < ARRAY_SIZE(keys); i++) { -+ if (!keys[i]) - continue; - - /* key flags are not required to delete the key */ -- ret = ath11k_install_key(arvif, peer->keys[i], -+ ret = ath11k_install_key(arvif, keys[i], - DISABLE_KEY, addr, flags); - if (ret < 0 && first_errno == 0) - first_errno = ret; -@@ -2778,10 +2784,6 @@ static int ath11k_clear_peer_keys(struct - if (ret < 0) - ath11k_warn(ab, "failed to remove peer key %d: %d\n", - i, ret); -- -- spin_lock_bh(&ab->base_lock); -- peer->keys[i] = NULL; -- spin_unlock_bh(&ab->base_lock); - } - - return first_errno; \ No newline at end of file diff --git a/package/kernel/mac80211/patches/ath11k/100-ath11k-load-appropriate-board-data-from-board-id.patch b/package/kernel/mac80211/patches/ath11k/100-ath11k-load-appropriate-board-data-from-board-id.patch deleted file mode 100644 index 2ab24b053..000000000 --- a/package/kernel/mac80211/patches/ath11k/100-ath11k-load-appropriate-board-data-from-board-id.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 89aec0a67ee30cd11762aede86b3edfdb2433663 Mon Sep 17 00:00:00 2001 -From: Venkateswara Naralasetty -Date: Thu, 2 Jul 2020 12:04:34 +0530 -Subject: [PATCH] ath11k: load appropriate board data based on board id - -This patch adds support to read board id from dts and load -appropriate board data. - -Adding the patch which was removed as a part of commit id - -Ib950b3271fede9ccf7d53fe9629c38ee729a0ef5 - -Signed-off-by: Venkateswara Naralasetty -Signed-off-by: Lavanya Suresh ---- - drivers/net/wireless/ath/ath11k/qmi.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -1811,9 +1811,11 @@ static int ath11k_qmi_assign_target_mem_ - - static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) - { -+ struct device *dev = ab->dev; - struct qmi_wlanfw_cap_req_msg_v01 req; - struct qmi_wlanfw_cap_resp_msg_v01 resp; - struct qmi_txn txn = {}; -+ unsigned int board_id; - int ret = 0; - int r; - -@@ -1853,10 +1855,13 @@ static int ath11k_qmi_request_target_cap - ab->qmi.target.chip_family = resp.chip_info.chip_family; - } - -- if (resp.board_info_valid) -+ if (!of_property_read_u32(dev->of_node, "qcom,board_id", &board_id) && board_id != 0xFF) { -+ ab->qmi.target.board_id = board_id; -+ } else if (resp.board_info_valid) { - ab->qmi.target.board_id = resp.board_info.board_id; -- else -+ } else { - ab->qmi.target.board_id = 0xFF; -+ } - - if (resp.soc_info_valid) - ab->qmi.target.soc_id = resp.soc_info.soc_id; diff --git a/package/kernel/mac80211/patches/ath11k/101-ath11k-add-support-for-channel-rx-tx-time-in-survey-dump.patch b/package/kernel/mac80211/patches/ath11k/101-ath11k-add-support-for-channel-rx-tx-time-in-survey-dump.patch deleted file mode 100644 index dfb00e1ed..000000000 --- a/package/kernel/mac80211/patches/ath11k/101-ath11k-add-support-for-channel-rx-tx-time-in-survey-dump.patch +++ /dev/null @@ -1,54 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1333,6 +1333,7 @@ int ath11k_wmi_pdev_bss_chan_info_reques - WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST) | - FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->req_type = type; -+ cmd->pdev_id = ar->pdev->pdev_id; - - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI bss chan info req type %d\n", type); -@@ -3122,7 +3123,7 @@ ath11k_wmi_copy_resource_config(struct w - wmi_cfg->bpf_instruction_size = tg_cfg->bpf_instruction_size; - wmi_cfg->max_bssid_rx_filters = tg_cfg->max_bssid_rx_filters; - wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id; -- wmi_cfg->flag1 = tg_cfg->atf_config; -+ wmi_cfg->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; - wmi_cfg->peer_map_unmap_v2_support = tg_cfg->peer_map_unmap_v2_support; - wmi_cfg->sched_params = tg_cfg->sched_params; - wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2219,6 +2219,8 @@ struct wmi_init_cmd { - u32 num_host_mem_chunks; - } __packed; - -+#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) -+ - struct wmi_resource_config { - u32 tlv_header; - u32 num_vdevs; -@@ -2935,6 +2937,7 @@ struct wmi_pdev_bss_chan_info_req_cmd { - u32 tlv_header; - /* ref wmi_bss_chan_info_req_type */ - u32 req_type; -+ u32 pdev_id; - } __packed; - - struct wmi_ap_ps_peer_cmd { -@@ -4028,7 +4031,6 @@ struct wmi_vdev_stopped_event { - } __packed; - - struct wmi_pdev_bss_chan_info_event { -- u32 pdev_id; - u32 freq; /* Units in MHz */ - u32 noise_floor; /* units are dBm */ - /* rx clear - how often the channel was unused */ -@@ -4046,6 +4048,7 @@ struct wmi_pdev_bss_chan_info_event { - /*rx_cycle cnt for my bss in 64bits format */ - u32 rx_bss_cycle_count_low; - u32 rx_bss_cycle_count_high; -+ u32 pdev_id; - } __packed; - - #define WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS 0 diff --git a/package/kernel/mac80211/patches/ath11k/143-ath11k-disabling-credit-flow-for-ath11k.patch b/package/kernel/mac80211/patches/ath11k/143-ath11k-disabling-credit-flow-for-ath11k.patch deleted file mode 100644 index c2947d852..000000000 --- a/package/kernel/mac80211/patches/ath11k/143-ath11k-disabling-credit-flow-for-ath11k.patch +++ /dev/null @@ -1,439 +0,0 @@ -From 929e141221444868ee98f253717479e5dd333102 Mon Sep 17 00:00:00 2001 -From: Maharaja Kennadyrajan -Date: Fri, 19 Mar 2021 14:45:37 +0530 -Subject: [PATCH] ath11k: register copy engine send completion callback - -Register send completion callback for copy engine-0 (CE0) -for the function ath11k_htc_tx_completion_handler(). -This callback will be used for freeing the skbs allocated -by the ath11k_htc_send() from the below functions: -ath11k_htc_connect_service() & ath11k_htc_start(). - -Signed-off-by: Maharaja Kennadyrajan ---- - drivers/net/wireless/ath/ath11k/ce.c | 33 +++++++++++---- - drivers/net/wireless/ath/ath11k/ce.h | 3 +- - drivers/net/wireless/ath/ath11k/core.c | 2 + - drivers/net/wireless/ath/ath11k/htc.c | 75 ++++++++++++++++++++++++---------- - drivers/net/wireless/ath/ath11k/htc.h | 4 ++ - drivers/net/wireless/ath/ath11k/hw.h | 1 + - drivers/net/wireless/ath/ath11k/wmi.c | 54 +++++++++++++++++++++--- - drivers/net/wireless/ath/ath11k/wmi.h | 1 + - 8 files changed, 138 insertions(+), 35 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/ce.c -+++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -14,6 +14,7 @@ const struct ce_attr ath11k_host_ce_conf - .src_nentries = 16, - .src_sz_max = 2048, - .dest_nentries = 0, -+ .send_cb = ath11k_htc_tx_completion_handler, - }, - - /* CE1: target->host HTT + HTC control */ -@@ -40,6 +41,7 @@ const struct ce_attr ath11k_host_ce_conf - .src_nentries = 32, - .src_sz_max = 2048, - .dest_nentries = 0, -+ .send_cb = ath11k_htc_tx_completion_handler, - }, - - /* CE4: host->target HTT */ -@@ -73,6 +75,7 @@ const struct ce_attr ath11k_host_ce_conf - .src_nentries = 32, - .src_sz_max = 2048, - .dest_nentries = 0, -+ .send_cb = ath11k_htc_tx_completion_handler, - }, - - /* CE8: target autonomous hif_memcpy */ -@@ -89,6 +92,7 @@ const struct ce_attr ath11k_host_ce_conf - .src_nentries = 32, - .src_sz_max = 2048, - .dest_nentries = 0, -+ .send_cb = ath11k_htc_tx_completion_handler, - }, - - /* CE10: target->host HTT */ -@@ -116,6 +120,7 @@ const struct ce_attr ath11k_host_ce_conf - .src_nentries = 16, - .src_sz_max = 2048, - .dest_nentries = 0, -+ .send_cb = ath11k_htc_tx_completion_handler, - }, - - /* CE1: target->host HTT + HTC control */ -@@ -142,6 +147,7 @@ const struct ce_attr ath11k_host_ce_conf - .src_nentries = 32, - .src_sz_max = 2048, - .dest_nentries = 0, -+ .send_cb = ath11k_htc_tx_completion_handler, - }, - - /* CE4: host->target HTT */ -@@ -436,19 +442,33 @@ err_unlock: - return skb; - } - --static void ath11k_ce_send_done_cb(struct ath11k_ce_pipe *pipe) -+static void ath11k_ce_tx_process_cb(struct ath11k_ce_pipe *pipe) - { - struct ath11k_base *ab = pipe->ab; - struct sk_buff *skb; -+ struct sk_buff_head list; - -+ __skb_queue_head_init(&list); - while (!IS_ERR(skb = ath11k_ce_completed_send_next(pipe))) { - if (!skb) - continue; - - dma_unmap_single(ab->dev, ATH11K_SKB_CB(skb)->paddr, skb->len, - DMA_TO_DEVICE); -- dev_kfree_skb_any(skb); -+ if ((!pipe->send_cb) || ab->hw_params.credit_flow) { -+ dev_kfree_skb_any(skb); -+ continue; -+ } -+ -+ __skb_queue_tail(&list, skb); - } -+ -+ while ((skb = __skb_dequeue(&list))) { -+ ath11k_dbg(ab, ATH11K_DBG_AHB, "tx ce pipe %d len %d\n", -+ pipe->pipe_num, skb->len); -+ pipe->send_cb(ab, skb); -+ } -+ - } - - static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_id, -@@ -582,7 +602,7 @@ static int ath11k_ce_alloc_pipe(struct a - pipe->attr_flags = attr->flags; - - if (attr->src_nentries) { -- pipe->send_cb = ath11k_ce_send_done_cb; -+ pipe->send_cb = attr->send_cb; - nentries = roundup_pow_of_two(attr->src_nentries); - desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_SRC); - ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz); -@@ -613,9 +633,10 @@ static int ath11k_ce_alloc_pipe(struct a - void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id) - { - struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id]; -+ const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id]; - -- if (pipe->send_cb) -- pipe->send_cb(pipe); -+ if (attr->src_nentries) -+ ath11k_ce_tx_process_cb(pipe); - - if (pipe->recv_cb) - ath11k_ce_recv_process_cb(pipe); -@@ -624,9 +645,10 @@ void ath11k_ce_per_engine_service(struct - void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id) - { - struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id]; -+ const struct ce_attr *attr = &ab->hw_params.host_ce_config[pipe_id]; - -- if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && pipe->send_cb) -- pipe->send_cb(pipe); -+ if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && attr->src_nentries) -+ ath11k_ce_tx_process_cb(pipe); - } - EXPORT_SYMBOL(ath11k_ce_per_engine_service); - ---- a/drivers/net/wireless/ath/ath11k/ce.h -+++ b/drivers/net/wireless/ath/ath11k/ce.h -@@ -101,6 +101,7 @@ struct ce_attr { - unsigned int dest_nentries; - - void (*recv_cb)(struct ath11k_base *, struct sk_buff *); -+ void (*send_cb)(struct ath11k_base *, struct sk_buff *); - }; - - #define CE_DESC_RING_ALIGN 8 -@@ -154,7 +155,7 @@ struct ath11k_ce_pipe { - unsigned int buf_sz; - unsigned int rx_buf_needed; - -- void (*send_cb)(struct ath11k_ce_pipe *); -+ void (*send_cb)(struct ath11k_base *, struct sk_buff *); - void (*recv_cb)(struct ath11k_base *, struct sk_buff *); - - struct tasklet_struct intr_tq; ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -41,6 +41,7 @@ static const struct ath11k_hw_params ath - .max_radios = 3, - .bdf_addr = 0x4B0C0000, - .hw_ops = &ipq8074_ops, -+ .credit_flow = false, - .ring_mask = &ath11k_hw_ring_mask_ipq8074, - .internal_sleep_clock = false, - .regs = &ipq8074_regs, -@@ -78,6 +79,7 @@ static const struct ath11k_hw_params ath - .max_radios = 2, - .bdf_addr = 0x4ABC0000, - .hw_ops = &ipq6018_ops, -+ .credit_flow = false, - .ring_mask = &ath11k_hw_ring_mask_ipq8074, - .internal_sleep_clock = false, - .regs = &ipq8074_regs, ---- a/drivers/net/wireless/ath/ath11k/htc.c -+++ b/drivers/net/wireless/ath/ath11k/htc.c -@@ -86,8 +86,7 @@ int ath11k_htc_send(struct ath11k_htc *h - } - - skb_push(skb, sizeof(struct ath11k_htc_hdr)); -- -- if (ep->tx_credit_flow_enabled) { -+ if (ab->hw_params.credit_flow && ep->tx_credit_flow_enabled) { - credits = DIV_ROUND_UP(skb->len, htc->target_credit_size); - spin_lock_bh(&htc->tx_lock); - if (ep->tx_credits < credits) { -@@ -112,7 +111,11 @@ int ath11k_htc_send(struct ath11k_htc *h - ret = dma_mapping_error(dev, skb_cb->paddr); - if (ret) { - ret = -EIO; -- goto err_credits; -+ if (ab->hw_params.credit_flow) -+ goto err_credits; -+ -+ else -+ goto err_pull; - } - - ret = ath11k_ce_send(htc->ab, skb, ep->ul_pipe_id, ep->eid); -@@ -124,14 +127,13 @@ int ath11k_htc_send(struct ath11k_htc *h - err_unmap: - dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); - err_credits: -- if (ep->tx_credit_flow_enabled) { -+ if (ab->hw_params.credit_flow && ep->tx_credit_flow_enabled) { - spin_lock_bh(&htc->tx_lock); - ep->tx_credits += credits; - ath11k_dbg(ab, ATH11K_DBG_HTC, - "htc ep %d reverted %d credits back (total %d)\n", - eid, credits, ep->tx_credits); - spin_unlock_bh(&htc->tx_lock); -- - if (ep->ep_ops.ep_tx_credits) - ep->ep_ops.ep_tx_credits(htc->ab); - } -@@ -200,24 +202,25 @@ static int ath11k_htc_process_trailer(st - status = -EINVAL; - break; - } -- -- switch (record->hdr.id) { -- case ATH11K_HTC_RECORD_CREDITS: -- len = sizeof(struct ath11k_htc_credit_report); -- if (record->hdr.len < len) { -- ath11k_warn(ab, "Credit report too long\n"); -- status = -EINVAL; -+ if(ab->hw_params.credit_flow) { -+ switch (record->hdr.id) { -+ case ATH11K_HTC_RECORD_CREDITS: -+ len = sizeof(struct ath11k_htc_credit_report); -+ if (record->hdr.len < len) { -+ ath11k_warn(ab, "Credit report too long\n"); -+ status = -EINVAL; -+ break; -+ } -+ ath11k_htc_process_credit_report(htc, -+ record->credit_report, -+ record->hdr.len, -+ src_eid); -+ break; -+ default: -+ ath11k_warn(ab, "Unhandled record: id:%d length:%d\n", -+ record->hdr.id, record->hdr.len); - break; - } -- ath11k_htc_process_credit_report(htc, -- record->credit_report, -- record->hdr.len, -- src_eid); -- break; -- default: -- ath11k_warn(ab, "Unhandled record: id:%d length:%d\n", -- record->hdr.id, record->hdr.len); -- break; - } - - if (status) -@@ -231,6 +234,29 @@ static int ath11k_htc_process_trailer(st - return status; - } - -+void ath11k_htc_tx_completion_handler(struct ath11k_base *ab, -+ struct sk_buff *skb) -+{ -+ struct ath11k_htc *htc = &ab->htc; -+ struct ath11k_htc_ep *ep; -+ u8 eid = ATH11K_HTC_EP_UNUSED; -+ -+ eid = ATH11K_SKB_CB(skb)->eid; -+ if (eid >= ATH11K_HTC_EP_COUNT) -+ return; -+ -+ spin_lock_bh(&htc->tx_lock); -+ ep = &htc->endpoint[eid]; -+ if (!ep->ep_ops.ep_tx_complete) { -+ dev_kfree_skb_any(skb); -+ spin_unlock_bh(&htc->tx_lock); -+ return; -+ } -+ spin_unlock_bh(&htc->tx_lock); -+ -+ ep->ep_ops.ep_tx_complete(htc->ab, skb); -+} -+ - void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, - struct sk_buff *skb) - { -@@ -584,6 +610,11 @@ int ath11k_htc_connect_service(struct at - disable_credit_flow_ctrl = true; - } - -+ if (!ab->hw_params.credit_flow) { -+ flags |= ATH11K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL; -+ disable_credit_flow_ctrl = true; -+ } -+ - req_msg->flags_len = FIELD_PREP(HTC_SVC_MSG_CONNECTIONFLAGS, flags); - req_msg->msg_svc_id |= FIELD_PREP(HTC_SVC_MSG_SERVICE_ID, - conn_req->service_id); -@@ -708,6 +739,8 @@ int ath11k_htc_start(struct ath11k_htc * - msg = (struct ath11k_htc_setup_complete_extended *)skb->data; - msg->msg_id = FIELD_PREP(HTC_MSG_MESSAGEID, - ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID); -+ if (!ab->hw_params.credit_flow) -+ msg->flags |= ATH11K_GLOBAL_DISABLE_CREDIT_FLOW; - - ath11k_dbg(ab, ATH11K_DBG_HTC, "HTC is using TX credit flow control\n"); - ---- a/drivers/net/wireless/ath/ath11k/htc.h -+++ b/drivers/net/wireless/ath/ath11k/htc.h -@@ -114,6 +114,8 @@ struct ath11k_htc_conn_svc_resp { - u32 svc_meta_pad; - } __packed; - -+#define ATH11K_GLOBAL_DISABLE_CREDIT_FLOW BIT(1) -+ - struct ath11k_htc_setup_complete_extended { - u32 msg_id; - u32 flags; -@@ -309,5 +311,7 @@ int ath11k_htc_send(struct ath11k_htc *h - struct sk_buff *ath11k_htc_alloc_skb(struct ath11k_base *ar, int size); - void ath11k_htc_rx_completion_handler(struct ath11k_base *ar, - struct sk_buff *skb); -+void ath11k_htc_tx_completion_handler(struct ath11k_base *ab, -+ struct sk_buff *skb); - - #endif ---- a/drivers/net/wireless/ath/ath11k/hw.h -+++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -156,6 +156,7 @@ struct ath11k_hw_params { - bool htt_peer_map_v2; - bool tcl_0_only; - u8 spectral_fft_sz; -+ bool credit_flow; - - u16 interface_modes; - bool supports_monitor; ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -261,20 +261,35 @@ int ath11k_wmi_cmd_send(struct ath11k_pd - { - struct ath11k_wmi_base *wmi_sc = wmi->wmi_ab; - int ret = -EOPNOTSUPP; -+ struct ath11k_base *ab = wmi_sc->ab; - - might_sleep(); - -- wait_event_timeout(wmi_sc->tx_credits_wq, ({ -- ret = ath11k_wmi_cmd_send_nowait(wmi, skb, cmd_id); -+ if (ab->hw_params.credit_flow) { -+ wait_event_timeout(wmi_sc->tx_credits_wq, ({ -+ ret = ath11k_wmi_cmd_send_nowait(wmi, skb, cmd_id); -+ -+ if (ret && test_bit(ATH11K_FLAG_CRASH_FLUSH, &wmi_sc->ab->dev_flags)) -+ ret = -ESHUTDOWN; - -- if (ret && test_bit(ATH11K_FLAG_CRASH_FLUSH, &wmi_sc->ab->dev_flags)) -- ret = -ESHUTDOWN; -+ (ret != -EAGAIN); -+ }), WMI_SEND_TIMEOUT_HZ); -+ } else { -+ wait_event_timeout(wmi->tx_ce_desc_wq, ({ -+ ret = ath11k_wmi_cmd_send_nowait(wmi, skb, cmd_id); - -- (ret != -EAGAIN); -- }), WMI_SEND_TIMEOUT_HZ); -+ if (ret && test_bit(ATH11K_FLAG_CRASH_FLUSH, &wmi_sc->ab->dev_flags)) -+ ret = -ESHUTDOWN; -+ -+ (ret != -ENOBUFS); -+ }), WMI_SEND_TIMEOUT_HZ); -+ } - - if (ret == -EAGAIN) - ath11k_warn(wmi_sc->ab, "wmi command %d timeout\n", cmd_id); -+ if (ret == -ENOBUFS) -+ ath11k_warn(wmi_sc->ab, "ce desc not available for wmi command %d\n", -+ cmd_id); - - return ret; - } -@@ -5328,6 +5343,32 @@ static void ath11k_wmi_op_ep_tx_credits( - static void ath11k_wmi_htc_tx_complete(struct ath11k_base *ab, - struct sk_buff *skb) - { -+ struct ath11k_pdev_wmi *wmi; -+ u32 i; -+ u8 wmi_ep_count; -+ u8 eid = ATH11K_HTC_EP_UNUSED; -+ -+ eid = ATH11K_SKB_CB(skb)->eid; -+ if (eid >= ATH11K_HTC_EP_COUNT) -+ goto out; -+ -+ wmi_ep_count = ab->htc.wmi_ep_count; -+ if (wmi_ep_count > ab->hw_params.max_radios) -+ goto out; -+ -+ dev_kfree_skb(skb); -+ -+ for (i = 0; i < ab->htc.wmi_ep_count; i++) { -+ if (ab->wmi_ab.wmi[i].eid == eid) { -+ wmi = &ab->wmi_ab.wmi[i]; -+ break; -+ } -+ } -+ -+ wake_up(&wmi->tx_ce_desc_wq); -+ -+ return; -+out: - dev_kfree_skb(skb); - } - -@@ -6545,6 +6586,7 @@ static int ath11k_connect_pdev_htc_servi - ab->wmi_ab.wmi_endpoint_id[pdev_idx] = conn_resp.eid; - ab->wmi_ab.wmi[pdev_idx].eid = conn_resp.eid; - ab->wmi_ab.max_msg_len[pdev_idx] = conn_resp.max_msg_len; -+ init_waitqueue_head(&ab->wmi_ab.wmi[pdev_idx].tx_ce_desc_wq); - - return 0; - } ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2446,6 +2446,7 @@ struct ath11k_pdev_wmi { - enum ath11k_htc_ep_id eid; - const struct wmi_peer_flags_map *peer_flags; - u32 rx_decap_mode; -+ wait_queue_head_t tx_ce_desc_wq; - }; - - struct vdev_create_params { diff --git a/package/kernel/mac80211/patches/ath11k/191-ath11k-add-mgmt-and-data-ack-rssi.patch b/package/kernel/mac80211/patches/ath11k/191-ath11k-add-mgmt-and-data-ack-rssi.patch deleted file mode 100644 index 9f7828658..000000000 --- a/package/kernel/mac80211/patches/ath11k/191-ath11k-add-mgmt-and-data-ack-rssi.patch +++ /dev/null @@ -1,102 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6278,6 +6278,8 @@ static int __ath11k_mac_register(struct - - ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations; - -+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); -+ - ar->hw->queues = ATH11K_HW_MAX_QUEUES; - ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; - ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -3143,7 +3143,8 @@ ath11k_wmi_copy_resource_config(struct w - wmi_cfg->bpf_instruction_size = tg_cfg->bpf_instruction_size; - wmi_cfg->max_bssid_rx_filters = tg_cfg->max_bssid_rx_filters; - wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id; -- wmi_cfg->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; -+ wmi_cfg->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 | -+ WMI_RSRC_CFG_FLAG1_ACK_RSSI; - wmi_cfg->peer_map_unmap_v2_support = tg_cfg->peer_map_unmap_v2_support; - wmi_cfg->sched_params = tg_cfg->sched_params; - wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; -@@ -4344,32 +4345,35 @@ static int ath11k_pull_mgmt_rx_params_tl - return 0; - } - --static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, -- u32 status) -+static int wmi_process_mgmt_tx_comp(struct ath11k *ar, struct wmi_mgmt_tx_compl_event *tx_compl_param) - { - struct sk_buff *msdu; - struct ieee80211_tx_info *info; - struct ath11k_skb_cb *skb_cb; - - spin_lock_bh(&ar->txmgmt_idr_lock); -- msdu = idr_find(&ar->txmgmt_idr, desc_id); -+ msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id); - - if (!msdu) { - ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n", -- desc_id); -+ tx_compl_param->desc_id); - spin_unlock_bh(&ar->txmgmt_idr_lock); - return -ENOENT; - } - -- idr_remove(&ar->txmgmt_idr, desc_id); -+ idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id); - spin_unlock_bh(&ar->txmgmt_idr_lock); - - skb_cb = ATH11K_SKB_CB(msdu); - dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - - info = IEEE80211_SKB_CB(msdu); -- if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) -+ if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !tx_compl_param->status) -+ { - info->flags |= IEEE80211_TX_STAT_ACK; -+ info->status.ack_signal = tx_compl_param->ack_rssi; -+ info->status.is_valid_ack_signal = true; -+ } - - ieee80211_tx_status_irqsafe(ar->hw, msdu); - -@@ -4405,6 +4409,7 @@ static int ath11k_pull_mgmt_tx_compl_par - param->pdev_id = ev->pdev_id; - param->desc_id = ev->desc_id; - param->status = ev->status; -+ param->ack_rssi = ev->ack_rssi; - - kfree(tb); - return 0; -@@ -5798,8 +5803,7 @@ static void ath11k_mgmt_tx_compl_event(s - goto exit; - } - -- wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id, -- tx_compl_param.status); -+ wmi_process_mgmt_tx_comp(ar, &tx_compl_param); - - ath11k_dbg(ab, ATH11K_DBG_MGMT, - "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2220,6 +2220,7 @@ struct wmi_init_cmd { - } __packed; - - #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) -+#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) - - struct wmi_resource_config { - u32 tlv_header; -@@ -4337,6 +4338,8 @@ struct wmi_mgmt_tx_compl_event { - u32 desc_id; - u32 status; - u32 pdev_id; -+ u32 ppdu_id; -+ u32 ack_rssi; - } __packed; - - struct wmi_scan_event { diff --git a/package/kernel/mac80211/patches/ath11k/237-001-ath11k-Disable-unused-CE8-interrupts.patch b/package/kernel/mac80211/patches/ath11k/237-001-ath11k-Disable-unused-CE8-interrupts.patch deleted file mode 100644 index 68527785a..000000000 --- a/package/kernel/mac80211/patches/ath11k/237-001-ath11k-Disable-unused-CE8-interrupts.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b71cab89b4be24528db1f4641825d2a0fd5f8efe Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Mon, 14 Dec 2020 19:05:02 +0530 -Subject: [PATCH] ath11k: Disable unused CE8 interrupts - -Host driver doesn't need to process CE8 interrupts (used -by target independently) - -The volume of interrupts is huge within short interval, - CPU0 CPU1 CPU2 CPU3 -14022188 0 0 0 GIC 71 Edge ce8 - -Hence disable these interrupts. - -Signed-off-by: Sriram R -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath11k/ce.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/ath11k/ce.c -+++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -80,7 +80,7 @@ const struct ce_attr ath11k_host_ce_conf - - /* CE8: target autonomous hif_memcpy */ - { -- .flags = CE_ATTR_FLAGS, -+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, - .src_nentries = 0, - .src_sz_max = 0, - .dest_nentries = 0, diff --git a/package/kernel/mac80211/patches/ath11k/302-ath11k-tx-mgmt-cleanup-fix.patch b/package/kernel/mac80211/patches/ath11k/302-ath11k-tx-mgmt-cleanup-fix.patch deleted file mode 100644 index 4b861318d..000000000 --- a/package/kernel/mac80211/patches/ath11k/302-ath11k-tx-mgmt-cleanup-fix.patch +++ /dev/null @@ -1,102 +0,0 @@ -From de7df710540275b29231a989a3a65af9f6cf7659 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Wed, 31 Mar 2021 07:59:52 +0530 -Subject: [PATCH] ath11k: Avoid NULL ptr access during mgmt tx cleanup - -Currently skb_cb values such as ar,vif is not filled during -WMI mgmt tx. Though this is generally not used during callback, -On interface removal, the remaining idr cleanup callback -uses the ar ptr from skb_cb from mgmt txmgmt_idr. Hence -fill them during tx call for proper usage. - -Also free the skb which is missing currently in these -callbacks. - -Crash_info: - -[19282.489476] Unable to handle kernel NULL pointer dereference at virtual address 00000000 -[19282.489515] pgd = 91eb8000 -[19282.496702] [00000000] *pgd=00000000 -[19282.502524] Internal error: Oops: 5 [#1] PREEMPT SMP ARM -[19282.783728] PC is at ath11k_mac_vif_txmgmt_idr_remove+0x28/0xd8 [ath11k] -[19282.789170] LR is at idr_for_each+0xa0/0xc8 - -Signed-off-by: Sriram R ---- - drivers/net/wireless/ath/ath11k/mac.c | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5691,23 +5691,36 @@ static int __ath11k_set_antenna(struct a - return 0; - } - --int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) -+static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id) - { -- struct sk_buff *msdu = skb; -+ struct sk_buff *msdu; - struct ieee80211_tx_info *info; -- struct ath11k *ar = ctx; -- struct ath11k_base *ab = ar->ab; - - spin_lock_bh(&ar->txmgmt_idr_lock); -- idr_remove(&ar->txmgmt_idr, buf_id); -+ msdu = idr_remove(&ar->txmgmt_idr, buf_id); - spin_unlock_bh(&ar->txmgmt_idr_lock); -- dma_unmap_single(ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len, -+ -+ /* msdu is already removed if msdu is NULL, -+ * if msdu is not NULL we free the skb below and -+ * idr wont be seen if any concurent tx completion happen -+ */ -+ if (!msdu) -+ return; -+ -+ dma_unmap_single(ar->ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len, - DMA_TO_DEVICE); - - info = IEEE80211_SKB_CB(msdu); - memset(&info->status, 0, sizeof(info->status)); - - ieee80211_free_txskb(ar->hw, msdu); -+} -+ -+int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) -+{ -+ struct ath11k *ar = ctx; -+ -+ ath11k_mac_tx_mgmt_free(ar, buf_id); - - return 0; - } -@@ -5716,17 +5729,10 @@ static int ath11k_mac_vif_txmgmt_idr_rem - { - struct ieee80211_vif *vif = ctx; - struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb); -- struct sk_buff *msdu = skb; - struct ath11k *ar = skb_cb->ar; -- struct ath11k_base *ab = ar->ab; - -- if (skb_cb->vif == vif) { -- spin_lock_bh(&ar->txmgmt_idr_lock); -- idr_remove(&ar->txmgmt_idr, buf_id); -- spin_unlock_bh(&ar->txmgmt_idr_lock); -- dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, -- DMA_TO_DEVICE); -- } -+ if (skb_cb->vif == vif) -+ ath11k_mac_tx_mgmt_free(ar, buf_id); - - return 0; - } -@@ -5767,6 +5773,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct - } - - ATH11K_SKB_CB(skb)->paddr = paddr; -+ ATH11K_SKB_CB(skb)->vif = arvif->vif; -+ ATH11K_SKB_CB(skb)->ar = ar; - - if (ieee80211_is_qos_nullfunc(hdr->frame_control)) { - ret = ath11k_wmi_qos_null_send(ar, arvif->vdev_id, buf_id, skb); diff --git a/package/kernel/mac80211/patches/ath11k/314-002-ath11k-fix-ce-dp-address-alignment.patch b/package/kernel/mac80211/patches/ath11k/314-002-ath11k-fix-ce-dp-address-alignment.patch deleted file mode 100644 index 18d61e23f..000000000 --- a/package/kernel/mac80211/patches/ath11k/314-002-ath11k-fix-ce-dp-address-alignment.patch +++ /dev/null @@ -1,129 +0,0 @@ -From: Karthikeyan Periyasamy -Date: Thu, 3 Jun 2021 15:07:12 +0530 -Subject: [PATCH] ath11k: fix CE and DP address alignment - -srng dma address and virtual address should be aligned with byte instead -of pointer type. Alignment should be based on dma address instead -of virtual address. Also CE dma allocations are freed with unaligned -address instead of aligned address. so corrected all address alignment. - -Signed-off-by: Karthikeyan Periyasamy ---- - ---- a/drivers/net/wireless/ath/ath11k/ce.c -+++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -559,6 +559,7 @@ ath11k_ce_alloc_ring(struct ath11k_base - { - struct ath11k_ce_ring *ce_ring; - dma_addr_t base_addr; -+ unsigned long off; - - ce_ring = kzalloc(struct_size(ce_ring, skb, nentries), GFP_KERNEL); - if (ce_ring == NULL) -@@ -581,12 +582,13 @@ ath11k_ce_alloc_ring(struct ath11k_base - - ce_ring->base_addr_ce_space_unaligned = base_addr; - -- ce_ring->base_addr_owner_space = PTR_ALIGN( -- ce_ring->base_addr_owner_space_unaligned, -- CE_DESC_RING_ALIGN); -- ce_ring->base_addr_ce_space = ALIGN( -- ce_ring->base_addr_ce_space_unaligned, -+ ce_ring->base_addr_ce_space = (dma_addr_t) ALIGN( -+ (unsigned long)ce_ring->base_addr_ce_space_unaligned, - CE_DESC_RING_ALIGN); -+ off = (unsigned long)ce_ring->base_addr_ce_space - -+ (unsigned long)ce_ring->base_addr_ce_space_unaligned; -+ ce_ring->base_addr_owner_space = (void *) -+ ((unsigned long)ce_ring->base_addr_owner_space_unaligned + off); - - return ce_ring; - } -@@ -935,8 +937,8 @@ void ath11k_ce_free_pipes(struct ath11k_ - dma_free_coherent(ab->dev, - pipe->src_ring->nentries * desc_sz + - CE_DESC_RING_ALIGN, -- pipe->src_ring->base_addr_owner_space, -- pipe->src_ring->base_addr_ce_space); -+ pipe->src_ring->base_addr_owner_space_unaligned, -+ pipe->src_ring->base_addr_ce_space_unaligned); - kfree(pipe->src_ring); - pipe->src_ring = NULL; - } -@@ -946,8 +948,8 @@ void ath11k_ce_free_pipes(struct ath11k_ - dma_free_coherent(ab->dev, - pipe->dest_ring->nentries * desc_sz + - CE_DESC_RING_ALIGN, -- pipe->dest_ring->base_addr_owner_space, -- pipe->dest_ring->base_addr_ce_space); -+ pipe->src_ring->base_addr_owner_space_unaligned, -+ pipe->src_ring->base_addr_ce_space_unaligned); - kfree(pipe->dest_ring); - pipe->dest_ring = NULL; - } -@@ -958,8 +960,8 @@ void ath11k_ce_free_pipes(struct ath11k_ - dma_free_coherent(ab->dev, - pipe->status_ring->nentries * desc_sz + - CE_DESC_RING_ALIGN, -- pipe->status_ring->base_addr_owner_space, -- pipe->status_ring->base_addr_ce_space); -+ pipe->src_ring->base_addr_owner_space_unaligned, -+ pipe->src_ring->base_addr_ce_space_unaligned); - kfree(pipe->status_ring); - pipe->status_ring = NULL; - } ---- a/drivers/net/wireless/ath/ath11k/ce.h -+++ b/drivers/net/wireless/ath/ath11k/ce.h -@@ -129,7 +129,7 @@ struct ath11k_ce_ring { - /* Host address space */ - void *base_addr_owner_space_unaligned; - /* CE address space */ -- u32 base_addr_ce_space_unaligned; -+ dma_addr_t base_addr_ce_space_unaligned; - - /* Actual start of descriptors. - * Aligned to descriptor-size boundary. -@@ -139,7 +139,7 @@ struct ath11k_ce_ring { - void *base_addr_owner_space; - - /* CE address space */ -- u32 base_addr_ce_space; -+ dma_addr_t base_addr_ce_space; - - /* HAL ring id */ - u32 hal_ring_id; ---- a/drivers/net/wireless/ath/ath11k/dp.c -+++ b/drivers/net/wireless/ath/ath11k/dp.c -@@ -222,6 +222,7 @@ int ath11k_dp_srng_setup(struct ath11k_b - int entry_sz = ath11k_hal_srng_get_entrysize(ab, type); - int max_entries = ath11k_hal_srng_get_max_entries(ab, type); - int ret; -+ unsigned long off; - - if (max_entries < 0 || entry_sz < 0) - return -EINVAL; -@@ -236,9 +237,10 @@ int ath11k_dp_srng_setup(struct ath11k_b - if (!ring->vaddr_unaligned) - return -ENOMEM; - -- ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN); -- ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr - -- (unsigned long)ring->vaddr_unaligned); -+ ring->paddr = (dma_addr_t) ALIGN((unsigned long)ring->paddr_unaligned, -+ HAL_RING_BASE_ALIGN); -+ off = (unsigned long)ring->paddr - (unsigned long)ring->paddr_unaligned; -+ ring->vaddr = (u32 *) ((unsigned long)ring->vaddr_unaligned + off); - - params.ring_base_vaddr = ring->vaddr; - params.ring_base_paddr = ring->paddr; ---- a/drivers/net/wireless/ath/ath11k/hal.h -+++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -19,7 +19,7 @@ struct ath11k_base; - #define HAL_NUM_MPDU_LINKS_PER_QUEUE_DESC 12 - #define HAL_MAX_AVAIL_BLK_RES 3 - --#define HAL_RING_BASE_ALIGN 8 -+#define HAL_RING_BASE_ALIGN 32 - - #define HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX 32704 - /* TODO: Check with hw team on the supported scatter buf size */ diff --git a/package/kernel/mac80211/patches/ath11k/802-ath11k-small-tx-queue.patch b/package/kernel/mac80211/patches/ath11k/802-ath11k-small-tx-queue.patch deleted file mode 100644 index dff7da31d..000000000 --- a/package/kernel/mac80211/patches/ath11k/802-ath11k-small-tx-queue.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/hw.h -+++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -64,7 +64,7 @@ - #define TARGET_RX_BATCHMODE 1 - - #define ATH11K_HW_MAX_QUEUES 4 --#define ATH11K_QUEUE_LEN 4096 -+#define ATH11K_QUEUE_LEN 2048 - - #define ATH11k_HW_RATECODE_CCK_SHORT_PREAM_MASK 0x4 - ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -1885,6 +1885,8 @@ static int ath11k_qmi_request_target_cap - ab->qmi.target.fw_version, - ab->qmi.target.fw_build_timestamp, - ab->qmi.target.fw_build_id); -+ -+ ath11k_info(ab, "joba-1 patch V2: ATH11K_QUEUE_LEN=%d", ATH11K_QUEUE_LEN); - - r = ath11k_core_check_dt(ab); - if (r) diff --git a/package/kernel/mac80211/patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch b/package/kernel/mac80211/patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch deleted file mode 100644 index d5fab8b23..000000000 --- a/package/kernel/mac80211/patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1593,9 +1593,9 @@ static void ath11k_peer_assoc_h_phymode( - } else if (sta->vht_cap.vht_supported && - !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) -- phymode = MODE_11AC_VHT40; -+ phymode = MODE_11AC_VHT40_2G; - else -- phymode = MODE_11AC_VHT20; -+ phymode = MODE_11AC_VHT20_2G; - } else if (sta->ht_cap.ht_supported && - !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) -@@ -3552,6 +3552,9 @@ static void ath11k_mac_setup_ht_vht_cap( - *ht_cap_info = ht_cap; - band->ht_cap = ath11k_create_ht_cap(ar, ht_cap, - rate_cap_rx_chainmask); -+ -+ band->vht_cap = ath11k_create_vht_cap(ar, rate_cap_tx_chainmask, -+ rate_cap_rx_chainmask); - } - - if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP && !ar->supports_6ghz) { ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -346,6 +346,8 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(st - * handled. - */ - if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_2G_CAP) { -+ pdev_cap->vht_cap = mac_phy_caps->vht_cap_info_2g; -+ pdev_cap->vht_mcs = mac_phy_caps->vht_supp_mcs_2g; - pdev_cap->tx_chain_mask = mac_phy_caps->tx_chain_mask_2g; - pdev_cap->rx_chain_mask = mac_phy_caps->rx_chain_mask_2g; - } else if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_5G_CAP) { diff --git a/package/kernel/mac80211/patches/ath11k/998-ath11k-Enable-512MB-profile-in-ath11k.patch b/package/kernel/mac80211/patches/ath11k/998-ath11k-Enable-512MB-profile-in-ath11k.patch deleted file mode 100644 index 1ba61da64..000000000 --- a/package/kernel/mac80211/patches/ath11k/998-ath11k-Enable-512MB-profile-in-ath11k.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 1b402e444ff99efe84d09a084b96c39826783a8e Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Thu, 10 Sep 2020 13:33:55 +0530 -Subject: [PATCH] ath11k: Enable 512MB profile in ath11k - -Below changes are made to enable 512MB mem mode in ath11k - * Makefile changes to implement compilation flag when - 512MB mem profile is configured. - * Enabling 512MB mem profile by default from Makefile - for IPQ5018. This can be removed later once - 512MB profile config is supported. - * Update target_mem_mode, number of stations, peer and vap - during compile time - -Signed-off-by: Ramya Gnanasekar ---- - drivers/net/wireless/ath/ath11k/Kconfig | 7 +++++++ - drivers/net/wireless/ath/ath11k/hw.h | 14 +++++++++++--- - drivers/net/wireless/ath/ath11k/qmi.c | 2 +- - drivers/net/wireless/ath/ath11k/qmi.h | 6 +++++- - 4 files changed, 24 insertions(+), 5 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/Kconfig -+++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -60,3 +60,10 @@ config ATH11K_SPECTRAL - Enable ath11k spectral scan support - - Say Y to enable access to the FFT/spectral data via debugfs. -+ -+config ATH11K_MEM_PROFILE_512M -+ bool "ath11k enable 512MB memory profile" -+ depends on ATH11K -+ default n -+ help -+ Enables 512MB memory profile for ath11k ---- a/drivers/net/wireless/ath/ath11k/hw.h -+++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -9,11 +9,30 @@ - #include "wmi.h" - - /* Target configuration defines */ -+#ifdef CPTCFG_ATH11K_MEM_PROFILE_512M - -+#define TARGET_NUM_VDEVS 8 -+#define TARGET_NUM_PEERS_PDEV (128 + TARGET_NUM_VDEVS) -+/* Max num of stations (per radio) */ -+#define TARGET_NUM_STATIONS 128 -+#define ATH11K_QMI_TARGET_MEM_MODE ATH11K_QMI_TARGET_MEM_MODE_512M -+#define ATH11K_DP_TX_COMP_RING_SIZE 8192 -+#define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 512 -+#define ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE 128 -+#define ATH11K_DP_RXDMA_MONITOR_DST_RING_SIZE 128 -+#else - /* Num VDEVS per radio */ - #define TARGET_NUM_VDEVS (16 + 1) - - #define TARGET_NUM_PEERS_PDEV (512 + TARGET_NUM_VDEVS) -+/* Max num of stations (per radio) */ -+#define TARGET_NUM_STATIONS 512 -+#define ATH11K_QMI_TARGET_MEM_MODE ATH11K_QMI_TARGET_MEM_MODE_DEFAULT -+#define ATH11K_DP_TX_COMP_RING_SIZE 32768 -+#define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 1024 -+#define ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE 4096 -+#define ATH11K_DP_RXDMA_MONITOR_DST_RING_SIZE 2048 -+#endif - - /* Num of peers for Single Radio mode */ - #define TARGET_NUM_PEERS_SINGLE (TARGET_NUM_PEERS_PDEV) -@@ -24,9 +43,6 @@ - /* Num of peers for DBS_SBS */ - #define TARGET_NUM_PEERS_DBS_SBS (3 * TARGET_NUM_PEERS_PDEV) - --/* Max num of stations (per radio) */ --#define TARGET_NUM_STATIONS 512 -- - #define TARGET_NUM_PEERS(x) TARGET_NUM_PEERS_##x - #define TARGET_NUM_PEER_KEYS 2 - #define TARGET_NUM_TIDS(x) (2 * TARGET_NUM_PEERS(x) + \ ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2675,7 +2675,7 @@ int ath11k_qmi_init_service(struct ath11 - memset(&ab->qmi.target_mem, 0, sizeof(struct target_mem_chunk)); - ab->qmi.ab = ab; - -- ab->qmi.target_mem_mode = ATH11K_QMI_TARGET_MEM_MODE_DEFAULT; -+ ab->qmi.target_mem_mode = ATH11K_QMI_TARGET_MEM_MODE; - ret = qmi_handle_init(&ab->qmi.handle, ATH11K_QMI_RESP_LEN_MAX, - &ath11k_qmi_ops, ath11k_qmi_msg_handlers); - if (ret < 0) { ---- a/drivers/net/wireless/ath/ath11k/qmi.h -+++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -33,10 +33,14 @@ - - #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 - #define ATH11K_FIRMWARE_MODE_OFF 4 --#define ATH11K_QMI_TARGET_MEM_MODE_DEFAULT 0 - - struct ath11k_base; - -+enum ath11k_target_mem_mode { -+ ATH11K_QMI_TARGET_MEM_MODE_DEFAULT = 0, -+ ATH11K_QMI_TARGET_MEM_MODE_512M, -+}; -+ - enum ath11k_qmi_file_type { - ATH11K_QMI_FILE_TYPE_BDF_GOLDEN, - ATH11K_QMI_FILE_TYPE_CALDATA, ---- a/local-symbols -+++ b/local-symbols -@@ -153,6 +153,7 @@ WCN36XX_DEBUGFS= - ATH11K= - ATH11K_AHB= - ATH11K_PCI= -+ATH11K_MEM_PROFILE_512M= - ATH11K_DEBUG= - ATH11K_DEBUGFS= - ATH11K_TRACING= ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -734,6 +734,8 @@ struct ath11k_base { - u32 num_db_cap; - - struct timer_list mon_reap_timer; -+ atomic_t num_max_allowed; -+ - /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); - }; ---- a/drivers/net/wireless/ath/ath11k/dp.h -+++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -174,8 +174,9 @@ struct ath11k_pdev_dp { - - #define DP_WBM_RELEASE_RING_SIZE 64 - #define DP_TCL_DATA_RING_SIZE 512 --#define DP_TX_COMP_RING_SIZE 32768 -+#define DP_TX_COMP_RING_SIZE ATH11K_DP_TX_COMP_RING_SIZE - #define DP_TX_IDR_SIZE DP_TX_COMP_RING_SIZE -+#define DP_TX_COMP_MAX_ALLOWED ((DP_TX_COMP_RING_SIZE << 1)/3) - #define DP_TCL_CMD_RING_SIZE 32 - #define DP_TCL_STATUS_RING_SIZE 32 - #define DP_REO_DST_RING_MAX 4 -@@ -188,9 +189,9 @@ struct ath11k_pdev_dp { - #define DP_RXDMA_BUF_RING_SIZE 4096 - #define DP_RXDMA_REFILL_RING_SIZE 2048 - #define DP_RXDMA_ERR_DST_RING_SIZE 1024 --#define DP_RXDMA_MON_STATUS_RING_SIZE 1024 --#define DP_RXDMA_MONITOR_BUF_RING_SIZE 4096 --#define DP_RXDMA_MONITOR_DST_RING_SIZE 2048 -+#define DP_RXDMA_MON_STATUS_RING_SIZE ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE -+#define DP_RXDMA_MONITOR_BUF_RING_SIZE ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE -+#define DP_RXDMA_MONITOR_DST_RING_SIZE ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE - #define DP_RXDMA_MONITOR_DESC_RING_SIZE 4096 - - #define DP_RX_BUFFER_SIZE 2048 ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -262,6 +262,7 @@ tcl_ring_sel: - skb->data, skb->len); - - atomic_inc(&ar->dp.num_tx_pending); -+ atomic_inc(&ab->num_max_allowed); - - return 0; - -@@ -308,6 +309,7 @@ static void ath11k_dp_tx_free_txbuf(stru - ar = ab->pdevs[mac_id].ar; - if (atomic_dec_and_test(&ar->dp.num_tx_pending)) - wake_up(&ar->dp.tx_empty_waitq); -+ atomic_dec(&ab->num_max_allowed); - } - - static void -@@ -339,6 +341,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct - - if (atomic_dec_and_test(&ar->dp.num_tx_pending)) - wake_up(&ar->dp.tx_empty_waitq); -+ atomic_dec(&ab->num_max_allowed); - - dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - -@@ -619,6 +622,7 @@ void ath11k_dp_tx_completion_handler(str - wake_up(&ar->dp.tx_empty_waitq); - - ath11k_dp_tx_complete_msdu(ar, msdu, &ts); -+ atomic_dec(&ab->num_max_allowed); - } - } - diff --git a/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch index 9dbe047c9..35ed6ea55 100644 --- a/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch @@ -18,7 +18,7 @@ goto end; --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -1964,7 +1964,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) +@@ -1963,7 +1963,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) } if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + @@ -27,7 +27,7 @@ ah->opmode == NL80211_IFTYPE_MESH_POINT) { u64 tsf = ath5k_hw_get_tsf64(ah); u32 tsftu = TSF_TO_TU(tsf); -@@ -2050,7 +2050,7 @@ ath5k_beacon_update_timers(struct ath5k_ +@@ -2049,7 +2049,7 @@ ath5k_beacon_update_timers(struct ath5k_ intval = ah->bintval & AR5K_BEACON_PERIOD; if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs @@ -36,7 +36,7 @@ intval /= ATH_BCBUF; /* staggered multi-bss beacons */ if (intval < 15) ATH5K_WARN(ah, "intval %u is too low, min 15\n", -@@ -2516,6 +2516,7 @@ static const struct ieee80211_iface_limi +@@ -2515,6 +2515,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_MESH_POINT) | #endif BIT(NL80211_IFTYPE_AP) }, diff --git a/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch index 92fb90c16..a63f0c881 100644 --- a/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch +++ b/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch @@ -130,7 +130,7 @@ drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ /* Antenna Control */ --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru +@@ -465,6 +465,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru return -EINVAL; } diff --git a/package/kernel/mac80211/patches/ath9k/040-ath9k-support-DT-ieee80211-freq-limit-property-to-li.patch b/package/kernel/mac80211/patches/ath9k/040-ath9k-support-DT-ieee80211-freq-limit-property-to-li.patch new file mode 100644 index 000000000..7d4468176 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/040-ath9k-support-DT-ieee80211-freq-limit-property-to-li.patch @@ -0,0 +1,28 @@ +From 03469e79fee9e8e908dae3bd1a80bcd9a66f2a88 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Mon, 11 Oct 2021 18:18:00 +0300 +Subject: ath9k: support DT ieee80211-freq-limit property to limit channels + +The common DT property can be used to limit the available channels +but ath9k has to manually call wiphy_read_of_freq_limits(). + +I would have put this into ath9k_of_init(). But it didn't work there. +The reason is that in ath9k_of_init() the channels and bands are not yet +registered in the wiphy struct. So there isn't any channel to flag as +disabled. + +Signed-off-by: Christian Lamparter +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20211009212847.1781986-1-chunkeey@gmail.com +--- +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1038,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + ++ wiphy_read_of_freq_limits(hw->wiphy); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) diff --git a/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch index d648a3a3e..3a0171d4a 100644 --- a/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch +++ b/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1435,8 +1435,12 @@ static bool ath9k_hw_set_reset(struct at +@@ -1434,8 +1434,12 @@ static bool ath9k_hw_set_reset(struct at if (!AR_SREV_9100(ah)) REG_WRITE(ah, AR_RC, 0); diff --git a/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch b/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch index 5f265b84c..53b7ba08b 100644 --- a/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch +++ b/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc +@@ -1311,39 +1311,56 @@ void ath9k_hw_get_delta_slope_vals(struc *coef_exponent = coef_exp - 16; } @@ -94,7 +94,7 @@ Signed-off-by: Felix Fietkau return true; } -@@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at +@@ -1396,24 +1413,24 @@ static bool ath9k_hw_set_reset(struct at rst_flags |= AR_RTC_RC_MAC_COLD; } diff --git a/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch b/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch index 3eb57bb1c..7405e594f 100644 --- a/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch +++ b/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -48,7 +48,7 @@ int ath9k_modparam_nohwcrypt; +@@ -47,7 +47,7 @@ int ath9k_modparam_nohwcrypt; module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); diff --git a/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch index 17dd8f659..b355e8372 100644 --- a/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch @@ -1,10 +1,10 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -830,6 +830,7 @@ static const struct ieee80211_iface_limi +@@ -826,6 +826,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_AP) }, { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, }; - #ifdef CPTCFG_WIRELESS_WDS + #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT diff --git a/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch b/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch index ea94b5238..284c88ff4 100644 --- a/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch +++ b/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch @@ -14,7 +14,7 @@ Signed-off-by: David Bauer --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -927,6 +927,7 @@ static void ath9k_set_hw_capab(struct at +@@ -907,6 +907,7 @@ static void ath9k_set_hw_capab(struct at ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); @@ -22,7 +22,7 @@ Signed-off-by: David Bauer if (ath9k_ps_enable) ieee80211_hw_set(hw, SUPPORTS_PS); -@@ -939,9 +940,6 @@ static void ath9k_set_hw_capab(struct at +@@ -919,9 +920,6 @@ static void ath9k_set_hw_capab(struct at IEEE80211_RADIOTAP_MCS_HAVE_STBC; } diff --git a/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch index b9c784eb2..6ab7972b5 100644 --- a/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch +++ b/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1143,25 +1143,25 @@ static int __init ath9k_init(void) +@@ -1122,25 +1122,25 @@ static int __init ath9k_init(void) { int error; diff --git a/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch index 75b48b480..fda050a8f 100644 --- a/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch +++ b/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -403,13 +403,8 @@ static void ath9k_hw_init_config(struct +@@ -402,13 +402,8 @@ static void ath9k_hw_init_config(struct ah->config.rx_intr_mitigation = true; diff --git a/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch index 113c35625..a085e3a1f 100644 --- a/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch +++ b/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -663,6 +663,7 @@ int ath9k_hw_init(struct ath_hw *ah) +@@ -662,6 +662,7 @@ int ath9k_hw_init(struct ath_hw *ah) /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ switch (ah->hw_version.devid) { diff --git a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch index 5fd5c73a2..c16123782 100644 --- a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru +@@ -843,6 +843,9 @@ static inline int ath9k_dump_btcoex(stru #ifdef CPTCFG_MAC80211_LEDS void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); @@ -10,7 +10,7 @@ #else static inline void ath_init_leds(struct ath_softc *sc) { -@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc +@@ -979,6 +982,13 @@ void ath_ant_comb_scan(struct ath_softc #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ @@ -24,7 +24,7 @@ struct ath_softc { struct ieee80211_hw *hw; struct device *dev; -@@ -1033,9 +1043,8 @@ struct ath_softc { +@@ -1032,9 +1042,8 @@ struct ath_softc { spinlock_t chan_lock; #ifdef CPTCFG_MAC80211_LEDS @@ -181,7 +181,7 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1055,7 +1055,7 @@ int ath9k_init_device(u16 devid, struct +@@ -1032,7 +1032,7 @@ int ath9k_init_device(u16 devid, struct #ifdef CPTCFG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ diff --git a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch index f93a6fe5c..5b64f560f 100644 --- a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -84,7 +84,7 @@ bool reset_power_on; bool htc_reset_init; -@@ -1076,6 +1084,7 @@ void ath9k_hw_check_nav(struct ath_hw *a +@@ -1077,6 +1085,7 @@ void ath9k_hw_check_nav(struct ath_hw *a bool ath9k_hw_check_alive(struct ath_hw *ah); bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); @@ -94,7 +94,7 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1883,6 +1883,20 @@ u32 ath9k_hw_get_tsf_offset(struct times +@@ -1881,6 +1881,20 @@ u32 ath9k_hw_get_tsf_offset(struct times } EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); @@ -115,7 +115,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata, bool fastcc) { -@@ -2091,6 +2105,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -2089,6 +2103,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ar9003_hw_disable_phy_restart(ah); ath9k_hw_apply_gpio_override(ah); @@ -125,9 +125,9 @@ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -531,6 +531,11 @@ irqreturn_t ath_isr(int irq, void *dev) - if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) +@@ -538,6 +538,11 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_HANDLED; + } + if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) { + status |= ATH9K_INT_FATAL; diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch index 0d938a373..ef4e65987 100644 --- a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -818,7 +818,8 @@ static void ath9k_init_txpower_limits(st +@@ -814,7 +814,8 @@ static void ath9k_init_txpower_limits(st if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); @@ -65,7 +65,7 @@ } static const struct ieee80211_iface_limit if_limits[] = { -@@ -1015,6 +1016,18 @@ static void ath9k_set_hw_capab(struct at +@@ -992,6 +993,18 @@ static void ath9k_set_hw_capab(struct at wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); } @@ -84,9 +84,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -1060,6 +1073,8 @@ int ath9k_init_device(u16 devid, struct - ARRAY_SIZE(ath9k_tpt_blink)); - #endif +@@ -1039,6 +1052,8 @@ int ath9k_init_device(u16 devid, struct + + wiphy_read_of_freq_limits(hw->wiphy); + ath_get_initial_entropy(sc); + @@ -110,7 +110,7 @@ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -1349,9 +1349,30 @@ void ar5008_hw_init_rate_txpower(struct +@@ -1340,9 +1340,30 @@ void ar5008_hw_init_rate_txpower(struct } } @@ -141,7 +141,7 @@ static const u32 ar5416_cca_regs[6] = { AR_PHY_CCA, AR_PHY_CH1_CCA, -@@ -1366,6 +1387,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ +@@ -1357,6 +1378,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ if (ret) return ret; diff --git a/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch index 93eee34b6..23a81864f 100644 --- a/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch +++ b/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -248,6 +248,19 @@ void ath9k_hw_get_channel_centers(struct +@@ -247,6 +247,19 @@ void ath9k_hw_get_channel_centers(struct centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); } @@ -20,7 +20,7 @@ /******************/ /* Chip Revisions */ /******************/ -@@ -1455,6 +1468,9 @@ static bool ath9k_hw_set_reset(struct at +@@ -1454,6 +1467,9 @@ static bool ath9k_hw_set_reset(struct at udelay(50); } @@ -30,7 +30,7 @@ return true; } -@@ -1554,6 +1570,9 @@ static bool ath9k_hw_chip_reset(struct a +@@ -1553,6 +1569,9 @@ static bool ath9k_hw_chip_reset(struct a ar9003_hw_internal_regulator_apply(ah); ath9k_hw_init_pll(ah, chan); @@ -40,7 +40,7 @@ return true; } -@@ -1861,8 +1880,14 @@ static int ath9k_hw_do_fastcc(struct ath +@@ -1859,8 +1878,14 @@ static int ath9k_hw_do_fastcc(struct ath if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); @@ -55,7 +55,7 @@ return -EINVAL; } -@@ -2116,6 +2141,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -2114,6 +2139,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ath9k_hw_set_radar_params(ah); } diff --git a/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch index 466767adb..854bb3659 100644 --- a/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch +++ b/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -978,55 +978,6 @@ static bool ar5008_hw_ani_control_new(st +@@ -969,55 +969,6 @@ static bool ar5008_hw_ani_control_new(st * on == 0 means more noise imm */ u32 on = param ? 1 : 0; diff --git a/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch index 88198a456..78206d286 100644 --- a/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch +++ b/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau #include "common.h" #include "debug.h" -@@ -990,6 +991,14 @@ struct ath_led { +@@ -989,6 +990,14 @@ struct ath_led { struct led_classdev cdev; }; @@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau struct ath_softc { struct ieee80211_hw *hw; struct device *dev; -@@ -1045,6 +1054,9 @@ struct ath_softc { +@@ -1044,6 +1053,9 @@ struct ath_softc { #ifdef CPTCFG_MAC80211_LEDS const char *led_default_trigger; struct list_head leds; diff --git a/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch index 83076b8ae..716e09f35 100644 --- a/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch +++ b/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -1056,6 +1056,7 @@ struct ath_softc { +@@ -1055,6 +1055,7 @@ struct ath_softc { struct list_head leds; #ifdef CONFIG_GPIOLIB struct ath9k_gpio_chip *gpiochip; diff --git a/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch b/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch deleted file mode 100644 index 7d3a334c4..000000000 --- a/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -627,6 +627,12 @@ static int ath9k_of_init(struct ath_soft - - ath_dbg(common, CONFIG, "parsing configuration from OF node\n"); - -+ if (of_property_read_bool(np, "qca,disable-2ghz")) -+ ah->disable_2ghz = true; -+ -+ if (of_property_read_bool(np, "qca,disable-5ghz")) -+ ah->disable_5ghz = true; -+ - if (of_property_read_bool(np, "qca,no-eeprom")) { - /* ath9k-eeprom--.bin */ - scnprintf(eeprom_name, sizeof(eeprom_name), diff --git a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch index cd2bdbf1a..cb6374feb 100644 --- a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch +++ b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch @@ -339,7 +339,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); -@@ -652,6 +653,7 @@ void ath_reset_work(struct work_struct * +@@ -659,6 +660,7 @@ void ath_reset_work(struct work_struct * static int ath9k_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; @@ -347,7 +347,7 @@ struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; -@@ -730,6 +732,11 @@ static int ath9k_start(struct ieee80211_ +@@ -737,6 +739,11 @@ static int ath9k_start(struct ieee80211_ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } @@ -371,7 +371,7 @@ --- a/local-symbols +++ b/local-symbols -@@ -113,6 +113,7 @@ ATH9K_WOW= +@@ -103,6 +103,7 @@ ATH9K_WOW= ATH9K_RFKILL= ATH9K_CHANNEL_CONTEXT= ATH9K_PCOEM= diff --git a/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch b/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch index 8fd6e4409..7ce8bc5b8 100644 --- a/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch +++ b/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch @@ -16,7 +16,7 @@ static const struct platform_device_id ath9k_platform_id_table[] = { { -@@ -69,6 +77,242 @@ static const struct ath_bus_ops ath_ahb_ +@@ -69,6 +77,236 @@ static const struct ath_bus_ops ath_ahb_ .eeprom_read = ath_ahb_eeprom_read, }; @@ -218,12 +218,6 @@ + else + pdata->led_pin = -1; + -+ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz")) -+ pdata->disable_2ghz = true; -+ -+ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz")) -+ pdata->disable_5ghz = true; -+ + if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo")) + pdata->tx_gain_buffalo = true; + @@ -259,7 +253,7 @@ static int ath_ahb_probe(struct platform_device *pdev) { void __iomem *mem; -@@ -80,6 +324,17 @@ static int ath_ahb_probe(struct platform +@@ -80,6 +318,17 @@ static int ath_ahb_probe(struct platform int ret = 0; struct ath_hw *ah; char hw_name[64]; @@ -277,7 +271,7 @@ if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "no platform data specified\n"); -@@ -122,13 +377,16 @@ static int ath_ahb_probe(struct platform +@@ -122,13 +371,16 @@ static int ath_ahb_probe(struct platform sc->mem = mem; sc->irq = irq; @@ -295,7 +289,7 @@ if (ret) { dev_err(&pdev->dev, "failed to initialize device\n"); goto err_irq; -@@ -159,6 +417,9 @@ static int ath_ahb_remove(struct platfor +@@ -159,6 +411,9 @@ static int ath_ahb_remove(struct platfor free_irq(sc->irq, sc); ieee80211_free_hw(sc->hw); } @@ -305,7 +299,7 @@ return 0; } -@@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr +@@ -168,6 +423,9 @@ static struct platform_driver ath_ahb_dr .remove = ath_ahb_remove, .driver = { .name = "ath9k", @@ -325,7 +319,7 @@ #include "common.h" #include "debug.h" -@@ -1012,6 +1013,9 @@ struct ath_softc { +@@ -1011,6 +1012,9 @@ struct ath_softc { struct ath_hw *sc_ah; void __iomem *mem; int irq; diff --git a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch index 8e0041e3e..80e0dc4c5 100644 --- a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch +++ b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -654,6 +654,12 @@ static int ath9k_of_init(struct ath_soft +@@ -644,6 +644,12 @@ static int ath9k_of_init(struct ath_soft return 0; } @@ -13,7 +13,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -757,6 +763,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -747,6 +753,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_hw; diff --git a/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch b/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch new file mode 100644 index 000000000..a250d2318 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch @@ -0,0 +1,154 @@ +From dab16ef495dbb3cabb355b6c80f0771a4a25e35d Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 20 Aug 2021 22:44:52 +0200 +Subject: [PATCH] ath9k: fetch calibration data via nvmem subsystem + +On most embedded ath9k devices (like range extenders, +routers, accesspoints, ...) the calibration data is +stored in a MTD partitions named "ART", or "caldata"/ +"calibration". + +Ever since commit +4b361cfa8624 ("mtd: core: add OTP nvmem provider support") +all MTD partitions are all automatically available through +the nvmem subsystem. This allows drivers like ath9k to read +the necessary data without needing any userspace helpers +that would do this extraction. + +Signed-off-by: Christian Lamparter +--- + +includes: + +From 57671351379b2051cfb07fc14e0bead9916a0880 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Mon, 11 Oct 2021 18:18:01 +0300 +Subject: ath9k: fix an IS_ERR() vs NULL check + +The devm_kmemdup() function doesn't return error pointers, it returns +NULL on error. + +Fixes: eb3a97a69be8 ("ath9k: fetch calibration data via nvmem subsystem") +Signed-off-by: Dan Carpenter +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20211011123533.GA15188@kili + +--- + +--- a/drivers/net/wireless/ath/ath9k/eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom.c +@@ -135,13 +135,23 @@ static bool ath9k_hw_nvram_read_firmware + offset, data); + } + ++static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset, ++ u16 *data) ++{ ++ return ath9k_hw_nvram_read_array(ah->nvmem_blob, ++ ah->nvmem_blob_len / sizeof(u16), ++ offset, data); ++} ++ + bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) + { + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_platform_data *pdata = ah->dev->platform_data; + bool ret; + +- if (ah->eeprom_blob) ++ if (ah->nvmem_blob) ++ ret = ath9k_hw_nvram_read_nvmem(ah, off, data); ++ else if (ah->eeprom_blob) + ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data); + else if (pdata && !pdata->use_eeprom) + ret = ath9k_hw_nvram_read_pdata(pdata, off, data); +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -988,6 +988,8 @@ struct ath_hw { + bool disable_5ghz; + + const struct firmware *eeprom_blob; ++ u16 *nvmem_blob; /* devres managed */ ++ size_t nvmem_blob_len; + + struct ath_dynack dynack; + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -568,6 +569,57 @@ static void ath9k_eeprom_release(struct + release_firmware(sc->sc_ah->eeprom_blob); + } + ++static int ath9k_nvmem_request_eeprom(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ struct nvmem_cell *cell; ++ void *buf; ++ size_t len; ++ int err; ++ ++ cell = devm_nvmem_cell_get(sc->dev, "calibration"); ++ if (IS_ERR(cell)) { ++ err = PTR_ERR(cell); ++ ++ /* nvmem cell might not be defined, or the nvmem ++ * subsystem isn't included. In this case, follow ++ * the established "just return 0;" convention of ++ * ath9k_init_platform to say: ++ * "All good. Nothing to see here. Please go on." ++ */ ++ if (err == -ENOENT || err == -EOPNOTSUPP) ++ return 0; ++ ++ return err; ++ } ++ ++ buf = nvmem_cell_read(cell, &len); ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ ++ /* run basic sanity checks on the returned nvram cell length. ++ * That length has to be a multiple of a "u16" (i.e.: & 1). ++ * Furthermore, it has to be more than "let's say" 512 bytes ++ * but less than the maximum of AR9300_EEPROM_SIZE (16kb). ++ */ ++ if (((len & 1) == 1) || (len < 512) || (len >= AR9300_EEPROM_SIZE)) { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ /* devres manages the calibration values release on shutdown */ ++ ah->nvmem_blob = (u16 *)devm_kmemdup(sc->dev, buf, len, GFP_KERNEL); ++ kfree(buf); ++ if (!ah->nvmem_blob) ++ return -ENOMEM; ++ ++ ah->nvmem_blob_len = len; ++ ah->ah_flags &= ~AH_USE_EEPROM; ++ ah->ah_flags |= AH_NO_EEP_SWAP; ++ ++ return 0; ++} ++ + static int ath9k_init_platform(struct ath_softc *sc) + { + struct ath9k_platform_data *pdata = sc->dev->platform_data; +@@ -710,6 +762,10 @@ static int ath9k_init_softc(u16 devid, s + if (ret) + return ret; + ++ ret = ath9k_nvmem_request_eeprom(sc); ++ if (ret) ++ return ret; ++ + if (ath9k_led_active_high != -1) + ah->config.led_active_high = ath9k_led_active_high == 1; + diff --git a/package/kernel/mac80211/patches/ath9k/601-v5.16-ath9k-owl-loader-fetch-pci-init-values-through-nvmem.patch b/package/kernel/mac80211/patches/ath9k/601-v5.16-ath9k-owl-loader-fetch-pci-init-values-through-nvmem.patch new file mode 100644 index 000000000..62c561d61 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/601-v5.16-ath9k-owl-loader-fetch-pci-init-values-through-nvmem.patch @@ -0,0 +1,181 @@ +From 9bf31835f11aa3c4fe5a9c1f7462c199c5d8e7ca Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 21 Aug 2021 00:22:39 +0200 +Subject: [PATCH] ath9k: owl-loader: fetch pci init values through nvmem + +extends the owl loader to fetch important pci initialization +values - which are stored together with the calibration data - +through the nvmem subsystem. + +This allows for much faster WIFI/ath9k initializations on devices +that do not require to perform any post-processing (like XOR'ing/ +reversal or unpacking) since no userspace helper is required. + +Signed-off-by: Christian Lamparter +--- + .../wireless/ath/ath9k/ath9k_pci_owl_loader.c | 105 +++++++++++++----- + 1 file changed, 76 insertions(+), 29 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c ++++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c +@@ -19,9 +19,14 @@ + #include + #include + #include ++#include ++#include + + struct owl_ctx { ++ struct pci_dev *pdev; + struct completion eeprom_load; ++ struct work_struct work; ++ struct nvmem_cell *cell; + }; + + #define EEPROM_FILENAME_LEN 100 +@@ -42,6 +47,12 @@ static int ath9k_pci_fixup(struct pci_de + u32 bar0; + bool swap_needed = false; + ++ /* also note that we are doing *u16 operations on the file */ ++ if (cal_len > 4096 || cal_len < 0x200 || (cal_len & 1) == 1) { ++ dev_err(&pdev->dev, "eeprom has an invalid size.\n"); ++ return -EINVAL; ++ } ++ + if (*cal_data != AR5416_EEPROM_MAGIC) { + if (*cal_data != swab16(AR5416_EEPROM_MAGIC)) { + dev_err(&pdev->dev, "invalid calibration data\n"); +@@ -99,38 +110,31 @@ static int ath9k_pci_fixup(struct pci_de + return 0; + } + +-static void owl_fw_cb(const struct firmware *fw, void *context) ++static void owl_rescan(struct pci_dev *pdev) + { +- struct pci_dev *pdev = (struct pci_dev *)context; +- struct owl_ctx *ctx = (struct owl_ctx *)pci_get_drvdata(pdev); +- struct pci_bus *bus; +- +- complete(&ctx->eeprom_load); +- +- if (!fw) { +- dev_err(&pdev->dev, "no eeprom data received.\n"); +- goto release; +- } +- +- /* also note that we are doing *u16 operations on the file */ +- if (fw->size > 4096 || fw->size < 0x200 || (fw->size & 1) == 1) { +- dev_err(&pdev->dev, "eeprom file has an invalid size.\n"); +- goto release; +- } +- +- if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size)) +- goto release; ++ struct pci_bus *bus = pdev->bus; + + pci_lock_rescan_remove(); +- bus = pdev->bus; + pci_stop_and_remove_bus_device(pdev); + /* the device should come back with the proper + * ProductId. But we have to initiate a rescan. + */ + pci_rescan_bus(bus); + pci_unlock_rescan_remove(); ++} ++ ++static void owl_fw_cb(const struct firmware *fw, void *context) ++{ ++ struct owl_ctx *ctx = (struct owl_ctx *)context; ++ ++ complete(&ctx->eeprom_load); + +-release: ++ if (fw) { ++ ath9k_pci_fixup(ctx->pdev, (const u16 *)fw->data, fw->size); ++ owl_rescan(ctx->pdev); ++ } else { ++ dev_err(&ctx->pdev->dev, "no eeprom data received.\n"); ++ } + release_firmware(fw); + } + +@@ -152,6 +156,43 @@ static const char *owl_get_eeprom_name(s + return eeprom_name; + } + ++static void owl_nvmem_work(struct work_struct *work) ++{ ++ struct owl_ctx *ctx = container_of(work, struct owl_ctx, work); ++ void *buf; ++ size_t len; ++ ++ complete(&ctx->eeprom_load); ++ ++ buf = nvmem_cell_read(ctx->cell, &len); ++ if (!IS_ERR(buf)) { ++ ath9k_pci_fixup(ctx->pdev, buf, len); ++ kfree(buf); ++ owl_rescan(ctx->pdev); ++ } else { ++ dev_err(&ctx->pdev->dev, "no nvmem data received.\n"); ++ } ++} ++ ++static int owl_nvmem_probe(struct owl_ctx *ctx) ++{ ++ int err; ++ ++ ctx->cell = devm_nvmem_cell_get(&ctx->pdev->dev, "calibration"); ++ if (IS_ERR(ctx->cell)) { ++ err = PTR_ERR(ctx->cell); ++ if (err == -ENOENT || err == -EOPNOTSUPP) ++ return 1; /* not present, try firmware_request */ ++ ++ return err; ++ } ++ ++ INIT_WORK(&ctx->work, owl_nvmem_work); ++ schedule_work(&ctx->work); ++ ++ return 0; ++} ++ + static int owl_probe(struct pci_dev *pdev, + const struct pci_device_id *id) + { +@@ -164,21 +205,27 @@ static int owl_probe(struct pci_dev *pde + + pcim_pin_device(pdev); + +- eeprom_name = owl_get_eeprom_name(pdev); +- if (!eeprom_name) { +- dev_err(&pdev->dev, "no eeprom filename found.\n"); +- return -ENODEV; +- } +- + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + init_completion(&ctx->eeprom_load); ++ ctx->pdev = pdev; + + pci_set_drvdata(pdev, ctx); ++ ++ err = owl_nvmem_probe(ctx); ++ if (err <= 0) ++ return err; ++ ++ eeprom_name = owl_get_eeprom_name(pdev); ++ if (!eeprom_name) { ++ dev_err(&pdev->dev, "no eeprom filename found.\n"); ++ return -ENODEV; ++ } ++ + err = request_firmware_nowait(THIS_MODULE, true, eeprom_name, +- &pdev->dev, GFP_KERNEL, pdev, owl_fw_cb); ++ &pdev->dev, GFP_KERNEL, ctx, owl_fw_cb); + if (err) + dev_err(&pdev->dev, "failed to request caldata (%d).\n", err); + diff --git a/package/kernel/mac80211/patches/ath9k/999-ath9k-fix-5.15.patch b/package/kernel/mac80211/patches/ath9k/999-ath9k-fix-5.15.patch deleted file mode 100644 index 58acd03af..000000000 --- a/package/kernel/mac80211/patches/ath9k/999-ath9k-fix-5.15.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -646,11 +646,13 @@ - ah->ah_flags &= ~AH_USE_EEPROM; - ah->ah_flags |= AH_NO_EEP_SWAP; - } -- -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) -+ of_get_mac_address(np, common->macaddr); -+#else - mac = of_get_mac_address(np); - if (!IS_ERR(mac)) - ether_addr_copy(common->macaddr, mac); -- -+#endif - return 0; - } - diff --git a/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch index 52ae7a8eb..5dc04ecc8 100644 --- a/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch +++ b/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch @@ -42,7 +42,7 @@ if (wl->radio_enabled != phy->radio_on) { if (wl->radio_enabled) { -@@ -5176,6 +5173,47 @@ static int b43_op_get_survey(struct ieee +@@ -5175,6 +5172,47 @@ static int b43_op_get_survey(struct ieee return 0; } @@ -90,7 +90,7 @@ static const struct ieee80211_ops b43_hw_ops = { .tx = b43_op_tx, .conf_tx = b43_op_conf_tx, -@@ -5197,6 +5235,8 @@ static const struct ieee80211_ops b43_hw +@@ -5196,6 +5234,8 @@ static const struct ieee80211_ops b43_hw .sw_scan_complete = b43_op_sw_scan_complete_notifier, .get_survey = b43_op_get_survey, .rfkill_poll = b43_rfkill_poll, @@ -99,7 +99,7 @@ }; /* Hard-reset the chip. Do not call this directly. -@@ -5498,6 +5538,8 @@ static int b43_one_core_attach(struct b4 +@@ -5497,6 +5537,8 @@ static int b43_one_core_attach(struct b4 if (!wldev) goto out; @@ -108,7 +108,7 @@ wldev->use_pio = b43_modparam_pio; wldev->dev = dev; wldev->wl = wl; -@@ -5592,6 +5634,9 @@ static struct b43_wl *b43_wireless_init( +@@ -5588,6 +5630,9 @@ static struct b43_wl *b43_wireless_init( wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); diff --git a/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch index c9730e29f..aa890ce0f 100644 --- a/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch +++ b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -13,15 +13,15 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c -@@ -431,6 +431,7 @@ struct brcmf_fw { +@@ -429,6 +429,7 @@ struct brcmf_fw { struct brcmf_fw_request *req; u32 curpos; void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); + struct completion *completion; }; - static void brcmf_fw_request_done(const struct firmware *fw, void *ctx); -@@ -638,6 +639,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 kfree(fwctx); } -@@ -662,6 +665,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)); -@@ -678,6 +683,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 + init_completion(&completion); + fwctx->completion = &completion; - ret = request_firmware_nowait(THIS_MODULE, true, first->path, - fwctx->dev, GFP_KERNEL, fwctx, -@@ -685,6 +693,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); diff --git a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch index e640849e6..88465f256 100644 --- a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2958,6 +2958,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 */ diff --git a/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch b/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch index 9658bda1c..835c870a6 100644 --- a/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch +++ b/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch @@ -12,9 +12,9 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c -@@ -12,6 +12,36 @@ - #include "common.h" - #include "of.h" +@@ -58,6 +58,36 @@ static int brcmf_of_get_country_codes(st + return 0; + } +/* TODO: FIXME: Use DT */ +static void brcmf_of_probe_cc(struct device *dev, @@ -49,12 +49,12 @@ Signed-off-by: Rafał Miłecki void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, struct brcmf_mp_device *settings) { -@@ -43,6 +73,8 @@ void brcmf_of_probe(struct device *dev, +@@ -90,6 +120,8 @@ void brcmf_of_probe(struct device *dev, of_node_put(root); } + brcmf_of_probe_cc(dev, settings); + - if (!np || bus_type != BRCMF_BUSTYPE_SDIO || - !of_device_is_compatible(np, "brcm,bcm4329-fmac")) + if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) return; + diff --git a/package/kernel/mac80211/patches/brcm/998-survey.patch b/package/kernel/mac80211/patches/brcm/998-survey.patch index 9e9f4bbf8..a5efc0801 100644 --- a/package/kernel/mac80211/patches/brcm/998-survey.patch +++ b/package/kernel/mac80211/patches/brcm/998-survey.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2910,6 +2910,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) { -@@ -3005,6 +3062,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; -@@ -3029,6 +3087,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()); -@@ -5515,6 +5584,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, @@ -100,7 +100,7 @@ .add_key = brcmf_cfg80211_add_key, --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1356,6 +1356,8 @@ int brcmf_attach(struct device *dev) +@@ -1361,6 +1361,8 @@ int brcmf_attach(struct device *dev) /* Link to bus module */ drvr->hdrlen = 0; @@ -109,7 +109,7 @@ /* Attach and link in the protocol */ ret = brcmf_proto_attach(drvr); -@@ -1438,6 +1440,12 @@ void brcmf_detach(struct device *dev) +@@ -1443,6 +1445,12 @@ void brcmf_detach(struct device *dev) if (drvr == NULL) return; diff --git a/package/kernel/mac80211/patches/build/003-remove_bogus_modparams.patch b/package/kernel/mac80211/patches/build/003-remove_bogus_modparams.patch index 8fa465a7e..aa26c8cb2 100644 --- a/package/kernel/mac80211/patches/build/003-remove_bogus_modparams.patch +++ b/package/kernel/mac80211/patches/build/003-remove_bogus_modparams.patch @@ -1,6 +1,6 @@ --- a/compat/main.c +++ b/compat/main.c -@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL"); +@@ -19,31 +19,6 @@ MODULE_LICENSE("GPL"); #error "You need a CPTCFG_VERSION" #endif diff --git a/package/kernel/mac80211/patches/build/004-kconfig_backport_fix.patch b/package/kernel/mac80211/patches/build/004-kconfig_backport_fix.patch deleted file mode 100644 index 2c9572ec9..000000000 --- a/package/kernel/mac80211/patches/build/004-kconfig_backport_fix.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/backport-include/linux/kconfig.h -+++ b/backport-include/linux/kconfig.h -@@ -5,6 +5,8 @@ - #include_next - #endif - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -+ - #ifndef __ARG_PLACEHOLDER_1 - #define __ARG_PLACEHOLDER_1 0, - #define config_enabled(cfg) _config_enabled(cfg) -@@ -16,6 +18,7 @@ - * 3.1 - 3.3 had a broken version of this, so undef - * (they didn't have __ARG_PLACEHOLDER_1) - */ -+ - #undef IS_ENABLED - #define IS_ENABLED(option) \ - (config_enabled(option) || config_enabled(option##_MODULE)) -@@ -31,6 +34,8 @@ - #undef IS_BUILTIN - #define IS_BUILTIN(option) config_enabled(option) - -+#endif -+ - #ifndef IS_REACHABLE - /* - * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled diff --git a/package/kernel/mac80211/patches/build/010-disable_rfkill.patch b/package/kernel/mac80211/patches/build/010-disable_rfkill.patch deleted file mode 100644 index d5253063c..000000000 --- a/package/kernel/mac80211/patches/build/010-disable_rfkill.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/backport-include/linux/rfkill.h -+++ b/backport-include/linux/rfkill.h -@@ -2,6 +2,12 @@ - #define __COMPAT_RFKILL_H - #include - -+#undef CONFIG_RFKILL -+#undef CONFIG_RFKILL_FULL -+#undef CONFIG_RFKILL_LEDS -+#undef CONFIG_RFKILL_MODULE -+#undef CONFIG_RFKILL_FULL_MODULE -+ - #if LINUX_VERSION_IS_GEQ(3,10,0) - #include_next - #else diff --git a/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch index ff2ce2071..3967d73fa 100644 --- a/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch +++ b/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch @@ -1,9 +1,9 @@ --- a/local-symbols +++ b/local-symbols -@@ -437,43 +437,6 @@ USB_SIERRA_NET= - USB_VL600= +@@ -421,43 +421,6 @@ USB_VL600= USB_NET_CH9200= USB_NET_AQC111= + USB_RTL8153_ECM= -SSB_POSSIBLE= -SSB= -SSB_SPROM= @@ -192,10 +192,10 @@ select BRCMUTIL --- a/Kconfig.local +++ b/Kconfig.local -@@ -1315,117 +1315,6 @@ config BACKPORTED_USB_NET_CH9200 - config BACKPORTED_USB_NET_AQC111 +@@ -1267,117 +1267,6 @@ config BACKPORTED_USB_NET_AQC111 + config BACKPORTED_USB_RTL8153_ECM tristate - default USB_NET_AQC111 + default USB_RTL8153_ECM -config BACKPORTED_SSB_POSSIBLE - tristate - default SSB_POSSIBLE diff --git a/package/kernel/mac80211/patches/build/070-headers-fix-lockdep_assert_not_held.patch b/package/kernel/mac80211/patches/build/070-headers-fix-lockdep_assert_not_held.patch new file mode 100644 index 000000000..d946efa17 --- /dev/null +++ b/package/kernel/mac80211/patches/build/070-headers-fix-lockdep_assert_not_held.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20=C5=A0tetiar?= +Date: Fri, 11 Mar 2022 18:21:04 +0100 +Subject: [PATCH] headers: fix lockdep_assert_not_held() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +LOCK_STATE_HELD define was omitted during backport of +lockdep_assert_not_held() which leads to build failures of kernels with +CONFIG_LOCKDEP=y: + + backports-5.15.8-1/backport-include/linux/lockdep.h:16:47: error: 'LOCK_STATE_HELD' undeclared (first use in this function) + +Fix it by adding missing LOCK_STATE_HELD define. + +References: https://github.com/openwrt/openwrt/pull/9373 +References: https://lore.kernel.org/backports/20220311194800.452-1-ynezz@true.cz/T/#u +Fixes: af58b27b1b1a ("headers: Add lockdep_assert_not_held()") +Reported-by: Oskari Rauta +Signed-off-by: Petr Štetiar +--- + backport-include/linux/lockdep.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/backport-include/linux/lockdep.h b/backport-include/linux/lockdep.h +index ed5ea67894e4..842e24b7ff8f 100644 +--- a/backport-include/linux/lockdep.h ++++ b/backport-include/linux/lockdep.h +@@ -11,6 +11,9 @@ struct lockdep_map { }; + + #ifndef lockdep_assert_not_held + #ifdef CONFIG_LOCKDEP ++#ifndef LOCK_STATE_HELD ++#define LOCK_STATE_HELD 1 ++#endif /* LOCK_STATE_HELD */ + #define lockdep_assert_not_held(l) do { \ + WARN_ON(debug_locks && \ + lockdep_is_held(l) == LOCK_STATE_HELD); \ diff --git a/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch index d358cfe36..140949f9a 100644 --- a/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch +++ b/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c -@@ -5695,6 +5695,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") +@@ -5699,6 +5699,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); static const struct pci_device_id mwl8k_pci_id_table[] = { diff --git a/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch index a35cf1875..96b1ce77e 100644 --- a/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c -@@ -6280,6 +6280,8 @@ static int mwl8k_probe(struct pci_dev *p +@@ -6285,6 +6285,8 @@ static int mwl8k_probe(struct pci_dev *p priv->running_bsses = 0; @@ -9,7 +9,7 @@ return rc; err_stop_firmware: -@@ -6313,8 +6315,6 @@ static void mwl8k_remove(struct pci_dev +@@ -6318,8 +6320,6 @@ static void mwl8k_remove(struct pci_dev return; priv = hw->priv; diff --git a/package/kernel/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch b/package/kernel/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch index a50a19528..96eeb37dc 100644 --- a/package/kernel/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch +++ b/package/kernel/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch @@ -40,7 +40,7 @@ Signed-off-by: Tomislav Požega --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -9416,6 +9416,8 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9435,6 +9435,8 @@ static int rt2800_init_eeprom(struct rt2 rf = RF3853; else if (rt2x00_rt(rt2x00dev, RT5350)) rf = RF5350; diff --git a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch index 1c52132da..5bc55cc90 100644 --- a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch @@ -1,6 +1,6 @@ --- a/local-symbols +++ b/local-symbols -@@ -333,6 +333,7 @@ RT2X00_LIB_FIRMWARE= +@@ -315,6 +315,7 @@ RT2X00_LIB_FIRMWARE= RT2X00_LIB_CRYPTO= RT2X00_LIB_LEDS= RT2X00_LIB_DEBUGFS= @@ -105,7 +105,7 @@ .drv_init_registers = rt2800mmio_init_registers, --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -694,6 +694,7 @@ enum rt2x00_capability_flags { +@@ -703,6 +703,7 @@ enum rt2x00_capability_flags { REQUIRE_HT_TX_DESC, REQUIRE_PS_AUTOWAKE, REQUIRE_DELAYED_RFKILL, @@ -113,7 +113,7 @@ /* * Capabilities -@@ -970,6 +971,11 @@ struct rt2x00_dev { +@@ -980,6 +981,11 @@ struct rt2x00_dev { const struct firmware *fw; /* @@ -127,7 +127,7 @@ DECLARE_KFIFO_PTR(txstatus_fifo, u32); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1406,6 +1406,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de +@@ -1401,6 +1401,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep); @@ -138,7 +138,7 @@ /* * Let the driver probe the device to detect the capabilities. */ -@@ -1549,6 +1553,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ +@@ -1541,6 +1545,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ * Free the driver data. */ kfree(rt2x00dev->drv_data); diff --git a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch index 6a8e594d5..ffee2189d 100644 --- a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch +++ b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -12,7 +12,7 @@ #endif /* _RT2X00_PLATFORM_H */ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1012,6 +1012,22 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1007,6 +1007,22 @@ static int rt2x00lib_probe_hw_modes(stru unsigned int num_rates; unsigned int i; @@ -37,7 +37,7 @@ num_rates += 4; --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -399,6 +399,7 @@ struct hw_mode_spec { +@@ -408,6 +408,7 @@ struct hw_mode_spec { unsigned int supported_bands; #define SUPPORT_BAND_2GHZ 0x00000001 #define SUPPORT_BAND_5GHZ 0x00000002 diff --git a/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch index b5b2c6103..37553bb80 100644 --- a/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch +++ b/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch @@ -1,19 +1,18 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -990,8 +990,13 @@ static void rt2x00lib_rate(struct ieee80 +@@ -989,6 +989,12 @@ static void rt2x00lib_rate(struct ieee80 void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) { + struct rt2x00_platform_data *pdata; - const char *mac_addr; - ++ + pdata = rt2x00dev->dev->platform_data; + if (pdata && pdata->mac_address) + ether_addr_copy(eeprom_mac_addr, pdata->mac_address); + - mac_addr = of_get_mac_address(rt2x00dev->dev->of_node); - if (!IS_ERR(mac_addr)) - ether_addr_copy(eeprom_mac_addr, mac_addr); + of_get_mac_address(rt2x00dev->dev->of_node, eeprom_mac_addr); + + if (!is_valid_ether_addr(eeprom_mac_addr)) { --- a/include/linux/rt2x00_platform.h +++ b/include/linux/rt2x00_platform.h @@ -14,6 +14,7 @@ diff --git a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch index ff8b2c947..6211809c0 100644 --- a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch +++ b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1016,6 +1016,16 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1012,6 +1012,16 @@ static int rt2x00lib_probe_hw_modes(stru struct ieee80211_rate *rates; unsigned int num_rates; unsigned int i; diff --git a/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch index 039c6f6af..d78b76d7f 100644 --- a/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch +++ b/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -9530,6 +9531,17 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9549,6 +9550,17 @@ static int rt2800_init_eeprom(struct rt2 rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); diff --git a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch index 88d6dd559..0da9356e0 100644 --- a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch +++ b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1344,7 +1344,7 @@ static inline void rt2x00lib_set_if_comb +@@ -1340,7 +1340,7 @@ static inline void rt2x00lib_set_if_comb */ if_limit = &rt2x00dev->if_limits_ap; if_limit->max = rt2x00dev->ops->max_ap_intf; diff --git a/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch index fca1fb2cd..6e6564f87 100644 --- a/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch +++ b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch @@ -11,7 +11,7 @@ Tested-by: Christoph Krapp --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1129,6 +1129,19 @@ static void rt2x00lib_remove_hw(struct r +@@ -1125,6 +1125,19 @@ static void rt2x00lib_remove_hw(struct r kfree(rt2x00dev->spec.channels_info); } @@ -31,7 +31,7 @@ Tested-by: Christoph Krapp static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; -@@ -1210,6 +1223,10 @@ static int rt2x00lib_probe_hw(struct rt2 +@@ -1206,6 +1219,10 @@ static int rt2x00lib_probe_hw(struct rt2 #undef RT2X00_TASKLET_INIT diff --git a/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch b/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch index 20452cd8a..8814c0253 100644 --- a/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch +++ b/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch @@ -30,7 +30,7 @@ Signed-off-by: Tomislav Po=C5=BEega * EEPROM LNA --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -4356,6 +4356,45 @@ static void rt2800_config_channel(struct +@@ -4369,6 +4369,45 @@ static void rt2800_config_channel(struct rt2800_iq_calibrate(rt2x00dev, rf->channel); } @@ -76,7 +76,7 @@ Signed-off-by: Tomislav Po=C5=BEega bbp = rt2800_bbp_read(rt2x00dev, 4); rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); rt2800_bbp_write(rt2x00dev, 4, bbp); -@@ -9559,7 +9598,8 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9578,7 +9617,8 @@ static int rt2800_init_eeprom(struct rt2 */ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1); @@ -86,7 +86,7 @@ Signed-off-by: Tomislav Po=C5=BEega if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352)) __set_bit(CAPABILITY_EXTERNAL_PA_TX0, -@@ -9570,6 +9610,18 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9589,6 +9629,18 @@ static int rt2800_init_eeprom(struct rt2 &rt2x00dev->cap_flags); } diff --git a/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch b/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch index 6be847478..b798dcc6d 100644 --- a/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8419,6 +8419,56 @@ static void rt2800_init_rfcsr_5592(struc +@@ -8438,6 +8438,56 @@ static void rt2800_init_rfcsr_5592(struc rt2800_led_open_drain_enable(rt2x00dev); } @@ -57,7 +57,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9026,6 +9076,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9045,6 +9095,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); diff --git a/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch b/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch index 3ed0ff7ef..cf21c39a6 100644 --- a/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8469,6 +8469,155 @@ static void rt2800_rf_self_txdc_cal(stru +@@ -8488,6 +8488,155 @@ static void rt2800_rf_self_txdc_cal(stru rt2x00_info(rt2x00dev, "RF Tx self calibration end\n"); } @@ -156,7 +156,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9076,6 +9225,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9095,6 +9244,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); diff --git a/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch b/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch index 77be986d1..1f8684b0b 100644 --- a/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8618,6 +8618,70 @@ static void rt2800_r_calibration(struct +@@ -8637,6 +8637,70 @@ static void rt2800_r_calibration(struct rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG); } @@ -71,7 +71,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9227,6 +9291,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9246,6 +9310,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_r_calibration(rt2x00dev); rt2800_rf_self_txdc_cal(rt2x00dev); diff --git a/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch b/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch index 7352ad036..98f2e245c 100644 --- a/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8682,6 +8682,384 @@ static void rt2800_rxdcoc_calibration(st +@@ -8701,6 +8701,384 @@ static void rt2800_rxdcoc_calibration(st rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2); } @@ -385,7 +385,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9294,6 +9672,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9313,6 +9691,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rxdcoc_calibration(rt2x00dev); rt2800_bw_filter_calibration(rt2x00dev, true); rt2800_bw_filter_calibration(rt2x00dev, false); diff --git a/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch b/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch index fe0961baa..6a685f80a 100644 --- a/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -9060,6 +9060,943 @@ restore_value: +@@ -9079,6 +9079,943 @@ restore_value: rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl); } @@ -944,7 +944,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9672,6 +10609,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9691,6 +10628,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rxdcoc_calibration(rt2x00dev); rt2800_bw_filter_calibration(rt2x00dev, true); rt2800_bw_filter_calibration(rt2x00dev, false); diff --git a/package/kernel/mac80211/patches/rt2x00/991-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch b/package/kernel/mac80211/patches/rt2x00/991-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch index 3de00b226..40b20ec59 100644 --- a/package/kernel/mac80211/patches/rt2x00/991-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch +++ b/package/kernel/mac80211/patches/rt2x00/991-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch @@ -14,7 +14,7 @@ */ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -3685,14 +3685,16 @@ static void rt2800_config_channel_rf7620 +@@ -3698,14 +3698,16 @@ static void rt2800_config_channel_rf7620 rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4); rt2800_rfcsr_write(rt2x00dev, 19, rfcsr); @@ -39,7 +39,7 @@ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1); rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620, -@@ -3726,18 +3728,23 @@ static void rt2800_config_channel_rf7620 +@@ -3739,18 +3741,23 @@ static void rt2800_config_channel_rf7620 rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20); } @@ -73,7 +73,7 @@ if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) { if (conf_is_ht40(conf)) { -@@ -3837,25 +3844,29 @@ static void rt2800_config_alc(struct rt2 +@@ -3850,25 +3857,29 @@ static void rt2800_config_alc(struct rt2 if (i == 10000) rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n"); @@ -121,7 +121,7 @@ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl); rt2800_vco_calibration(rt2x00dev); -@@ -5887,18 +5898,33 @@ static int rt2800_init_registers(struct +@@ -5906,18 +5917,33 @@ static int rt2800_init_registers(struct } else if (rt2x00_rt(rt2x00dev, RT5350)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); } else if (rt2x00_rt(rt2x00dev, RT6352)) { @@ -167,7 +167,7 @@ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1); rt2x00_set_field32(®, TX_ALC_CFG_1_ROS_BUSY_EN, 0); rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg); -@@ -7042,14 +7068,16 @@ static void rt2800_init_bbp_6352(struct +@@ -7061,14 +7087,16 @@ static void rt2800_init_bbp_6352(struct rt2800_bbp_write(rt2x00dev, 188, 0x00); rt2800_bbp_write(rt2x00dev, 189, 0x00); @@ -192,7 +192,7 @@ /* BBP for G band GLRT function (BBP_128 ~ BBP_221) */ rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00); -@@ -10388,31 +10416,36 @@ static void rt2800_init_rfcsr_6352(struc +@@ -10407,31 +10435,36 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write(rt2x00dev, 42, 0x5B); rt2800_rfcsr_write(rt2x00dev, 43, 0x00); @@ -254,7 +254,7 @@ /* Initialize RF channel register to default value */ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03); -@@ -10478,63 +10511,71 @@ static void rt2800_init_rfcsr_6352(struc +@@ -10497,63 +10530,71 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5); @@ -383,7 +383,7 @@ /* Initialize RF DC calibration register to default value */ rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47); -@@ -10597,12 +10638,17 @@ static void rt2800_init_rfcsr_6352(struc +@@ -10616,12 +10657,17 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00); rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00); diff --git a/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch deleted file mode 100644 index 31a7baeee..000000000 --- a/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch +++ /dev/null @@ -1,183 +0,0 @@ ---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -1238,6 +1238,8 @@ void rt2800_watchdog(struct rt2x00_dev * - if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) - return; - -+ rt2800_update_survey(rt2x00dev); -+ - queue_for_each(rt2x00dev, queue) { - switch (queue->qid) { - case QID_AC_VO: -@@ -1274,6 +1276,18 @@ void rt2800_watchdog(struct rt2x00_dev * - } - EXPORT_SYMBOL_GPL(rt2800_watchdog); - -+void rt2800_update_survey(struct rt2x00_dev *rt2x00dev) -+{ -+ struct ieee80211_channel *chan = rt2x00dev->hw->conf.chandef.chan; -+ struct rt2x00_chan_survey *chan_survey = -+ &rt2x00dev->chan_survey[chan->hw_value]; -+ -+ chan_survey->time_idle += rt2800_register_read(rt2x00dev, CH_IDLE_STA); -+ chan_survey->time_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA); -+ chan_survey->time_ext_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC); -+} -+EXPORT_SYMBOL_GPL(rt2800_update_survey); -+ - static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, - unsigned int index) - { -@@ -12199,26 +12213,30 @@ int rt2800_get_survey(struct ieee80211_h - { - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_conf *conf = &hw->conf; -- u32 idle, busy, busy_ext; -+ struct rt2x00_chan_survey *chan_survey = -+ &rt2x00dev->chan_survey[idx]; -+ enum nl80211_band band = NL80211_BAND_2GHZ; - -- if (idx != 0) -+ if (idx >= rt2x00dev->bands[band].n_channels) { -+ idx -= rt2x00dev->bands[band].n_channels; -+ band = NL80211_BAND_5GHZ; -+ } -+ -+ if (idx >= rt2x00dev->bands[band].n_channels) - return -ENOENT; - -- survey->channel = conf->chandef.chan; -+ if (idx == 0) -+ rt2800_update_survey(rt2x00dev); - -- idle = rt2800_register_read(rt2x00dev, CH_IDLE_STA); -- busy = rt2800_register_read(rt2x00dev, CH_BUSY_STA); -- busy_ext = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC); -- -- if (idle || busy) { -- survey->filled = SURVEY_INFO_TIME | -- SURVEY_INFO_TIME_BUSY | -- SURVEY_INFO_TIME_EXT_BUSY; -- -- survey->time = (idle + busy) / 1000; -- survey->time_busy = busy / 1000; -- survey->time_ext_busy = busy_ext / 1000; -- } -+ survey->channel = &rt2x00dev->bands[band].channels[idx]; -+ -+ survey->filled = SURVEY_INFO_TIME | -+ SURVEY_INFO_TIME_BUSY | -+ SURVEY_INFO_TIME_EXT_BUSY; -+ -+ survey->time = div_u64(chan_survey->time_idle + chan_survey->time_busy, 1000); -+ survey->time_busy = div_u64(chan_survey->time_busy, 1000); -+ survey->time_ext_busy = div_u64(chan_survey->time_ext_busy, 1000); - - if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) - survey->filled |= SURVEY_INFO_IN_USE; ---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -@@ -243,6 +243,7 @@ bool rt2800_txstatus_timeout(struct rt2x - bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev); - - void rt2800_watchdog(struct rt2x00_dev *rt2x00dev); -+void rt2800_update_survey(struct rt2x00_dev *rt2x00dev); - - void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); - void rt2800_clear_beacon(struct queue_entry *entry); ---- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c -@@ -360,6 +360,7 @@ static const struct rt2x00lib_ops rt2800 - .gain_calibration = rt2800_gain_calibration, - .vco_calibration = rt2800_vco_calibration, - .watchdog = rt2800_watchdog, -+ .update_survey = rt2800_update_survey, - .start_queue = rt2800mmio_start_queue, - .kick_queue = rt2800mmio_kick_queue, - .stop_queue = rt2800mmio_stop_queue, ---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c -@@ -214,6 +214,7 @@ static const struct rt2x00lib_ops rt2800 - .gain_calibration = rt2800_gain_calibration, - .vco_calibration = rt2800_vco_calibration, - .watchdog = rt2800_watchdog, -+ .update_survey = rt2800_update_survey, - .start_queue = rt2800mmio_start_queue, - .kick_queue = rt2800mmio_kick_queue, - .stop_queue = rt2800mmio_stop_queue, ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -183,6 +183,15 @@ struct rf_channel { - }; - - /* -+ * Information structure for channel survey. -+ */ -+struct rt2x00_chan_survey { -+ u64 time_idle; -+ u64 time_busy; -+ u64 time_ext_busy; -+}; -+ -+/* - * Channel information structure - */ - struct channel_info { -@@ -567,6 +576,7 @@ struct rt2x00lib_ops { - * Data queue handlers. - */ - void (*watchdog) (struct rt2x00_dev *rt2x00dev); -+ void (*update_survey) (struct rt2x00_dev *rt2x00dev); - void (*start_queue) (struct data_queue *queue); - void (*kick_queue) (struct data_queue *queue); - void (*stop_queue) (struct data_queue *queue); -@@ -755,6 +765,7 @@ struct rt2x00_dev { - */ - struct ieee80211_hw *hw; - struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; -+ struct rt2x00_chan_survey *chan_survey; - enum nl80211_band curr_band; - int curr_freq; - ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1057,6 +1057,12 @@ static int rt2x00lib_probe_hw_modes(stru - if (!rates) - goto exit_free_channels; - -+ rt2x00dev->chan_survey = -+ kcalloc(spec->num_channels, sizeof(struct rt2x00_chan_survey), -+ GFP_KERNEL); -+ if (!rt2x00dev->chan_survey) -+ goto exit_free_rates; -+ - /* - * Initialize Rate list. - */ -@@ -1108,6 +1114,8 @@ static int rt2x00lib_probe_hw_modes(stru - - return 0; - -+ exit_free_rates: -+ kfree(rates); - exit_free_channels: - kfree(channels); - rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n"); ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c -@@ -317,6 +317,15 @@ int rt2x00mac_config(struct ieee80211_hw - return 0; - - /* -+ * To provide correct survey data for survey-based ACS algorithm -+ * we have to save survey data for current channel before switching. -+ */ -+ if (rt2x00dev->ops->lib->update_survey && -+ (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { -+ rt2x00dev->ops->lib->update_survey(rt2x00dev); -+ } -+ -+ /* - * Some configuration parameters (e.g. channel and antenna values) can - * only be set when the radio is enabled, but do require the RX to - * be off. During this period we should keep link tuning enabled, diff --git a/package/kernel/mac80211/patches/rtl/002-v5.13-rtlwifi-implement-set_tim-by-update-beacon-content.patch b/package/kernel/mac80211/patches/rtl/002-v5.13-rtlwifi-implement-set_tim-by-update-beacon-content.patch deleted file mode 100644 index 3daf65e96..000000000 --- a/package/kernel/mac80211/patches/rtl/002-v5.13-rtlwifi-implement-set_tim-by-update-beacon-content.patch +++ /dev/null @@ -1,118 +0,0 @@ -Date: Mon, 19 Apr 2021 14:59:56 +0800 -From: Ping-Ke Shih -To: -CC: , , - -Subject: [PATCH] rtlwifi: implement set_tim by update beacon content - -Once beacon content is changed, we update the content to wifi card by -send_beacon_frame(). Then, STA with PS can wake up properly to receive its -packets. - -Since we update beacon content to PCI wifi devices every beacon interval, -the only one usb device, 8192CU, needs to update beacon content when -mac80211 calling set_tim. - -Reported-by: Maciej S. Szmigiero -Signed-off-by: Ping-Ke Shih -Tested-by: Maciej S. Szmigiero ---- - drivers/net/wireless/realtek/rtlwifi/core.c | 32 +++++++++++++++++++++ - drivers/net/wireless/realtek/rtlwifi/core.h | 1 + - drivers/net/wireless/realtek/rtlwifi/usb.c | 3 ++ - drivers/net/wireless/realtek/rtlwifi/wifi.h | 1 + - 4 files changed, 37 insertions(+) - ---- a/drivers/net/wireless/realtek/rtlwifi/core.c -+++ b/drivers/net/wireless/realtek/rtlwifi/core.c -@@ -1018,6 +1018,25 @@ static void send_beacon_frame(struct iee - } - } - -+void rtl_update_beacon_work_callback(struct work_struct *work) -+{ -+ struct rtl_works *rtlworks = -+ container_of(work, struct rtl_works, update_beacon_work); -+ struct ieee80211_hw *hw = rtlworks->hw; -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct ieee80211_vif *vif = rtlpriv->mac80211.vif; -+ -+ if (!vif) { -+ WARN_ONCE(true, "no vif to update beacon\n"); -+ return; -+ } -+ -+ mutex_lock(&rtlpriv->locks.conf_mutex); -+ send_beacon_frame(hw, vif); -+ mutex_unlock(&rtlpriv->locks.conf_mutex); -+} -+EXPORT_SYMBOL_GPL(rtl_update_beacon_work_callback); -+ - static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, -@@ -1747,6 +1766,18 @@ static void rtl_op_flush(struct ieee8021 - rtlpriv->intf_ops->flush(hw, queues, drop); - } - -+static int rtl_op_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, -+ bool set) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) -+ schedule_work(&rtlpriv->works.update_beacon_work); -+ -+ return 0; -+} -+ - /* Description: - * This routine deals with the Power Configuration CMD - * parsing for RTL8723/RTL8188E Series IC. -@@ -1903,6 +1934,7 @@ const struct ieee80211_ops rtl_ops = { - .sta_add = rtl_op_sta_add, - .sta_remove = rtl_op_sta_remove, - .flush = rtl_op_flush, -+ .set_tim = rtl_op_set_tim, - }; - EXPORT_SYMBOL_GPL(rtl_ops); - ---- a/drivers/net/wireless/realtek/rtlwifi/core.h -+++ b/drivers/net/wireless/realtek/rtlwifi/core.h -@@ -60,5 +60,6 @@ void rtl_bb_delay(struct ieee80211_hw *h - bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); - bool rtl_btc_status_false(void); - void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igval); -+void rtl_update_beacon_work_callback(struct work_struct *work); - - #endif ---- a/drivers/net/wireless/realtek/rtlwifi/usb.c -+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c -@@ -807,6 +807,7 @@ static void rtl_usb_stop(struct ieee8021 - - tasklet_kill(&rtlusb->rx_work_tasklet); - cancel_work_sync(&rtlpriv->works.lps_change_work); -+ cancel_work_sync(&rtlpriv->works.update_beacon_work); - - flush_workqueue(rtlpriv->works.rtl_wq); - -@@ -1033,6 +1034,8 @@ int rtl_usb_probe(struct usb_interface * - rtl_fill_h2c_cmd_work_callback); - INIT_WORK(&rtlpriv->works.lps_change_work, - rtl_lps_change_work_callback); -+ INIT_WORK(&rtlpriv->works.update_beacon_work, -+ rtl_update_beacon_work_callback); - - rtlpriv->usb_data_index = 0; - init_completion(&rtlpriv->firmware_loading_complete); ---- a/drivers/net/wireless/realtek/rtlwifi/wifi.h -+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h -@@ -2487,6 +2487,7 @@ struct rtl_works { - - struct work_struct lps_change_work; - struct work_struct fill_h2c_cmd; -+ struct work_struct update_beacon_work; - }; - - struct rtl_debug { diff --git a/package/kernel/mac80211/patches/subsys/010-sync-nl80211_h.patch b/package/kernel/mac80211/patches/subsys/010-sync-nl80211_h.patch deleted file mode 100644 index e1f66ac1c..000000000 --- a/package/kernel/mac80211/patches/subsys/010-sync-nl80211_h.patch +++ /dev/null @@ -1,297 +0,0 @@ ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -655,6 +655,9 @@ - * When a security association was established on an 802.1X network using - * fast transition, this event should be followed by an - * %NL80211_CMD_PORT_AUTHORIZED event. -+ * Following a %NL80211_CMD_ROAM event userspace can issue -+ * %NL80211_CMD_GET_SCAN in order to obtain the scan information for the -+ * new BSS the card/driver roamed to. - * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify - * userspace that a connection was dropped by the AP or due to other - * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and -@@ -757,7 +760,8 @@ - * of any other interfaces, and other interfaces will again take - * precedence when they are used. - * -- * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. -+ * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface -+ * (no longer supported). - * - * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform - * multicast to unicast conversion. When enabled, all multicast packets -@@ -1177,6 +1181,10 @@ - * includes the contents of the frame. %NL80211_ATTR_ACK flag is included - * if the recipient acknowledged the frame. - * -+ * @NL80211_CMD_SET_SAR_SPECS: SAR power limitation configuration is -+ * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to -+ * specify the wiphy index to be applied to. -+ * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -@@ -1407,6 +1415,8 @@ enum nl80211_commands { - - NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS, - -+ NL80211_CMD_SET_SAR_SPECS, -+ - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ -@@ -1750,8 +1760,9 @@ enum nl80211_commands { - * specify just a single bitrate, which is to be used for the beacon. - * The driver must also specify support for this with the extended - * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, -- * NL80211_EXT_FEATURE_BEACON_RATE_HT and -- * NL80211_EXT_FEATURE_BEACON_RATE_VHT. -+ * NL80211_EXT_FEATURE_BEACON_RATE_HT, -+ * NL80211_EXT_FEATURE_BEACON_RATE_VHT and -+ * NL80211_EXT_FEATURE_BEACON_RATE_HE. - * - * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain - * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. -@@ -1955,8 +1966,15 @@ enum nl80211_commands { - * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire - * probe-response frame. The DA field in the 802.11 header is zero-ed out, - * to be filled by the FW. -- * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable -- * this feature. Currently, only supported in mac80211 drivers. -+ * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable -+ * this feature during association. This is a flag attribute. -+ * Currently only supported in mac80211 drivers. -+ * @NL80211_ATTR_DISABLE_VHT: Force VHT capable interfaces to disable -+ * this feature during association. This is a flag attribute. -+ * Currently only supported in mac80211 drivers. -+ * @NL80211_ATTR_DISABLE_HE: Force HE capable interfaces to disable -+ * this feature during association. This is a flag attribute. -+ * Currently only supported in mac80211 drivers. - * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the - * ATTR_HT_CAPABILITY to which attention should be paid. - * Currently, only mac80211 NICs support this feature. -@@ -2077,7 +2095,8 @@ enum nl80211_commands { - * until the channel switch event. - * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission - * must be blocked on the current channel (before the channel switch -- * operation). -+ * operation). Also included in the channel switch started event if quiet -+ * was requested by the AP. - * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information - * for the time while performing a channel switch. - * @NL80211_ATTR_CNTDWN_OFFS_BEACON: An array of offsets (u16) to the channel -@@ -2527,6 +2546,20 @@ enum nl80211_commands { - * override mask. Used with NL80211_ATTR_S1G_CAPABILITY in - * NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT. - * -+ * @NL80211_ATTR_SAE_PWE: Indicates the mechanism(s) allowed for SAE PWE -+ * derivation in WPA3-Personal networks which are using SAE authentication. -+ * This is a u8 attribute that encapsulates one of the values from -+ * &enum nl80211_sae_pwe_mechanism. -+ * -+ * @NL80211_ATTR_SAR_SPEC: SAR power limitation specification when -+ * used with %NL80211_CMD_SET_SAR_SPECS. The message contains fields -+ * of %nl80211_sar_attrs which specifies the sar type and related -+ * sar specs. Sar specs contains array of %nl80211_sar_specs_attrs. -+ * -+ * @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and -+ * disassoc events to indicate that an immediate reconnect to the AP -+ * is desired. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3016,6 +3049,14 @@ enum nl80211_attrs { - NL80211_ATTR_S1G_CAPABILITY, - NL80211_ATTR_S1G_CAPABILITY_MASK, - -+ NL80211_ATTR_SAE_PWE, -+ -+ NL80211_ATTR_RECONNECT_REQUESTED, -+ -+ NL80211_ATTR_SAR_SPEC, -+ -+ NL80211_ATTR_DISABLE_HE, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -5896,6 +5937,19 @@ enum nl80211_feature_flags { - * @NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP: Driver/device supports - * unsolicited broadcast probe response transmission - * -+ * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate -+ * configuration (AP/mesh) with HE rates. -+ * -+ * @NL80211_EXT_FEATURE_SECURE_LTF: Device supports secure LTF measurement -+ * exchange protocol. -+ * -+ * @NL80211_EXT_FEATURE_SECURE_RTT: Device supports secure RTT measurement -+ * exchange protocol. -+ * -+ * @NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE: Device supports management -+ * frame protection for all management frames exchanged during the -+ * negotiation and range measurement procedure. -+ * - * @NUM_NL80211_EXT_FEATURES: number of extended features. - * @MAX_NL80211_EXT_FEATURES: highest extended feature index. - */ -@@ -5956,6 +6010,10 @@ enum nl80211_ext_feature_index { - NL80211_EXT_FEATURE_SAE_OFFLOAD_AP, - NL80211_EXT_FEATURE_FILS_DISCOVERY, - NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP, -+ NL80211_EXT_FEATURE_BEACON_RATE_HE, -+ NL80211_EXT_FEATURE_SECURE_LTF, -+ NL80211_EXT_FEATURE_SECURE_RTT, -+ NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, - - /* add new features before the definition below */ - NUM_NL80211_EXT_FEATURES, -@@ -6253,11 +6311,13 @@ struct nl80211_vendor_cmd_info { - * @NL80211_TDLS_PEER_HT: TDLS peer is HT capable. - * @NL80211_TDLS_PEER_VHT: TDLS peer is VHT capable. - * @NL80211_TDLS_PEER_WMM: TDLS peer is WMM capable. -+ * @NL80211_TDLS_PEER_HE: TDLS peer is HE capable. - */ - enum nl80211_tdls_peer_capability { - NL80211_TDLS_PEER_HT = 1<<0, - NL80211_TDLS_PEER_VHT = 1<<1, - NL80211_TDLS_PEER_WMM = 1<<2, -+ NL80211_TDLS_PEER_HE = 1<<3, - }; - - /** -@@ -6849,6 +6909,9 @@ enum nl80211_peer_measurement_ftm_capa { - * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor - * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based - * ranging will be used. -+ * @NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK: negotiate for LMR feedback. Only -+ * valid if either %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED or -+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. - * - * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal - * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number -@@ -6867,6 +6930,7 @@ enum nl80211_peer_measurement_ftm_req { - NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC, - NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED, - NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED, -+ NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK, - - /* keep last */ - NUM_NL80211_PMSR_FTM_REQ_ATTR, -@@ -7124,4 +7188,115 @@ enum nl80211_unsol_bcast_probe_resp_attr - NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX = - __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST - 1 - }; -+ -+/** -+ * enum nl80211_sae_pwe_mechanism - The mechanism(s) allowed for SAE PWE -+ * derivation. Applicable only when WPA3-Personal SAE authentication is -+ * used. -+ * -+ * @NL80211_SAE_PWE_UNSPECIFIED: not specified, used internally to indicate that -+ * attribute is not present from userspace. -+ * @NL80211_SAE_PWE_HUNT_AND_PECK: hunting-and-pecking loop only -+ * @NL80211_SAE_PWE_HASH_TO_ELEMENT: hash-to-element only -+ * @NL80211_SAE_PWE_BOTH: both hunting-and-pecking loop and hash-to-element -+ * can be used. -+ */ -+enum nl80211_sae_pwe_mechanism { -+ NL80211_SAE_PWE_UNSPECIFIED, -+ NL80211_SAE_PWE_HUNT_AND_PECK, -+ NL80211_SAE_PWE_HASH_TO_ELEMENT, -+ NL80211_SAE_PWE_BOTH, -+}; -+ -+/** -+ * enum nl80211_sar_type - type of SAR specs -+ * -+ * @NL80211_SAR_TYPE_POWER: power limitation specified in 0.25dBm unit -+ * -+ */ -+enum nl80211_sar_type { -+ NL80211_SAR_TYPE_POWER, -+ -+ /* add new type here */ -+ -+ /* Keep last */ -+ NUM_NL80211_SAR_TYPE, -+}; -+ -+/** -+ * enum nl80211_sar_attrs - Attributes for SAR spec -+ * -+ * @NL80211_SAR_ATTR_TYPE: the SAR type as defined in &enum nl80211_sar_type. -+ * -+ * @NL80211_SAR_ATTR_SPECS: Nested array of SAR power -+ * limit specifications. Each specification contains a set -+ * of %nl80211_sar_specs_attrs. -+ * -+ * For SET operation, it contains array of %NL80211_SAR_ATTR_SPECS_POWER -+ * and %NL80211_SAR_ATTR_SPECS_RANGE_INDEX. -+ * -+ * For sar_capa dump, it contains array of -+ * %NL80211_SAR_ATTR_SPECS_START_FREQ -+ * and %NL80211_SAR_ATTR_SPECS_END_FREQ. -+ * -+ * @__NL80211_SAR_ATTR_LAST: Internal -+ * @NL80211_SAR_ATTR_MAX: highest sar attribute -+ * -+ * These attributes are used with %NL80211_CMD_SET_SAR_SPEC -+ */ -+enum nl80211_sar_attrs { -+ __NL80211_SAR_ATTR_INVALID, -+ -+ NL80211_SAR_ATTR_TYPE, -+ NL80211_SAR_ATTR_SPECS, -+ -+ __NL80211_SAR_ATTR_LAST, -+ NL80211_SAR_ATTR_MAX = __NL80211_SAR_ATTR_LAST - 1, -+}; -+ -+/** -+ * enum nl80211_sar_specs_attrs - Attributes for SAR power limit specs -+ * -+ * @NL80211_SAR_ATTR_SPECS_POWER: Required (s32)value to specify the actual -+ * power limit value in units of 0.25 dBm if type is -+ * NL80211_SAR_TYPE_POWER. (i.e., a value of 44 represents 11 dBm). -+ * 0 means userspace doesn't have SAR limitation on this associated range. -+ * -+ * @NL80211_SAR_ATTR_SPECS_RANGE_INDEX: Required (u32) value to specify the -+ * index of exported freq range table and the associated power limitation -+ * is applied to this range. -+ * -+ * Userspace isn't required to set all the ranges advertised by WLAN driver, -+ * and userspace can skip some certain ranges. These skipped ranges don't -+ * have SAR limitations, and they are same as setting the -+ * %NL80211_SAR_ATTR_SPECS_POWER to any unreasonable high value because any -+ * value higher than regulatory allowed value just means SAR power -+ * limitation is removed, but it's required to set at least one range. -+ * It's not allowed to set duplicated range in one SET operation. -+ * -+ * Every SET operation overwrites previous SET operation. -+ * -+ * @NL80211_SAR_ATTR_SPECS_START_FREQ: Required (u32) value to specify the start -+ * frequency of this range edge when registering SAR capability to wiphy. -+ * It's not a channel center frequency. The unit is kHz. -+ * -+ * @NL80211_SAR_ATTR_SPECS_END_FREQ: Required (u32) value to specify the end -+ * frequency of this range edge when registering SAR capability to wiphy. -+ * It's not a channel center frequency. The unit is kHz. -+ * -+ * @__NL80211_SAR_ATTR_SPECS_LAST: Internal -+ * @NL80211_SAR_ATTR_SPECS_MAX: highest sar specs attribute -+ */ -+enum nl80211_sar_specs_attrs { -+ __NL80211_SAR_ATTR_SPECS_INVALID, -+ -+ NL80211_SAR_ATTR_SPECS_POWER, -+ NL80211_SAR_ATTR_SPECS_RANGE_INDEX, -+ NL80211_SAR_ATTR_SPECS_START_FREQ, -+ NL80211_SAR_ATTR_SPECS_END_FREQ, -+ -+ __NL80211_SAR_ATTR_SPECS_LAST, -+ NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, -+}; -+ - #endif /* __LINUX_NL80211_H */ diff --git a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch index 665231a04..638da1434 100644 --- a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch +++ b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch @@ -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 -@@ -1288,7 +1288,6 @@ static int ieee80211_stop_ap(struct wiph +@@ -1316,7 +1316,6 @@ static int ieee80211_stop_ap(struct wiph sdata->vif.bss_conf.ftmr_params = NULL; __sta_info_flush(sdata, true); diff --git a/package/kernel/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch b/package/kernel/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch index 172e5b04f..ffd8807cc 100644 --- a/package/kernel/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch +++ b/package/kernel/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch @@ -1,6 +1,6 @@ --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c -@@ -23,18 +23,35 @@ static inline struct cfg80211_registered +@@ -24,18 +24,35 @@ static inline struct cfg80211_registered return container_of(dev, struct cfg80211_registered_device, wiphy.dev); } diff --git a/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch index 8d086625e..e93efa442 100644 --- a/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch +++ b/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch @@ -1,6 +1,6 @@ --- a/net/mac80211/main.c +++ b/net/mac80211/main.c -@@ -321,7 +321,7 @@ void ieee80211_restart_hw(struct ieee802 +@@ -337,7 +337,7 @@ void ieee80211_restart_hw(struct ieee802 } EXPORT_SYMBOL(ieee80211_restart_hw); @@ -9,7 +9,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, unsigned long data, void *arg) { -@@ -380,7 +380,7 @@ static int ieee80211_ifa_changed(struct +@@ -396,7 +396,7 @@ static int ieee80211_ifa_changed(struct } #endif @@ -18,8 +18,8 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, unsigned long data, void *arg) { -@@ -1315,14 +1315,14 @@ int ieee80211_register_hw(struct ieee802 - +@@ -1324,14 +1324,14 @@ int ieee80211_register_hw(struct ieee802 + wiphy_unlock(hw->wiphy); rtnl_unlock(); -#ifdef CONFIG_INET @@ -35,7 +35,7 @@ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; result = register_inet6addr_notifier(&local->ifa6_notifier); if (result) -@@ -1331,13 +1331,13 @@ int ieee80211_register_hw(struct ieee802 +@@ -1340,13 +1340,13 @@ int ieee80211_register_hw(struct ieee802 return 0; @@ -52,7 +52,7 @@ fail_ifa: #endif wiphy_unregister(local->hw.wiphy); -@@ -1365,10 +1365,10 @@ void ieee80211_unregister_hw(struct ieee +@@ -1374,10 +1374,10 @@ void ieee80211_unregister_hw(struct ieee tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); diff --git a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch index ee4994245..0c06829ce 100644 --- a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch +++ b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch @@ -1,6 +1,6 @@ --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2444,7 +2444,7 @@ static int ieee80211_scan(struct wiphy * +@@ -2497,7 +2497,7 @@ static int ieee80211_scan(struct wiphy * * the frames sent while scanning on other channel will be * lost) */ diff --git a/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch b/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch deleted file mode 100644 index 8fe8723cf..000000000 --- a/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch +++ /dev/null @@ -1,279 +0,0 @@ -From: Johannes Berg -Date: Sun, 6 Dec 2020 14:54:42 +0200 -Subject: [PATCH] cfg80211: support immediate reconnect request hint - -There are cases where it's necessary to disconnect, but an -immediate reconnection is desired. Support a hint to userspace -that this is the case, by including a new attribute in the -deauth or disassoc event. - -Signed-off-by: Luca Coelho -Link: https://lore.kernel.org/r/iwlwifi.20201206145305.58d33941fb9d.I0e7168c205c7949529c8e3b86f3c9b12c01a7017@changeid -Signed-off-by: Johannes Berg ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -6410,13 +6410,15 @@ void cfg80211_abandon_assoc(struct net_d - * @dev: network device - * @buf: 802.11 frame (header + body) - * @len: length of the frame data -+ * @reconnect: immediate reconnect is desired (include the nl80211 attribute) - * - * This function is called whenever deauthentication has been processed in - * station mode. This includes both received deauthentication frames and - * locally generated ones. This function may sleep. The caller must hold the - * corresponding wdev's mutex. - */ --void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len); -+void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len, -+ bool reconnect); - - /** - * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -2734,7 +2734,7 @@ static void ieee80211_report_disconnect( - }; - - if (tx) -- cfg80211_tx_mlme_mgmt(sdata->dev, buf, len); -+ cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false); - else - cfg80211_rx_mlme_mgmt(sdata->dev, buf, len); - -@@ -4724,7 +4724,8 @@ void ieee80211_mgd_quiesce(struct ieee80 - if (ifmgd->auth_data) - ieee80211_destroy_auth_data(sdata, false); - cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, -- IEEE80211_DEAUTH_FRAME_LEN); -+ IEEE80211_DEAUTH_FRAME_LEN, -+ false); - } - - /* This is a bit of a hack - we should find a better and more generic ---- a/net/wireless/mlme.c -+++ b/net/wireless/mlme.c -@@ -4,7 +4,7 @@ - * - * Copyright (c) 2009, Jouni Malinen - * Copyright (c) 2015 Intel Deutschland GmbH -- * Copyright (C) 2019 Intel Corporation -+ * Copyright (C) 2019-2020 Intel Corporation - */ - - #include -@@ -81,7 +81,8 @@ static void cfg80211_process_auth(struct - } - - static void cfg80211_process_deauth(struct wireless_dev *wdev, -- const u8 *buf, size_t len) -+ const u8 *buf, size_t len, -+ bool reconnect) - { - struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; -@@ -89,7 +90,7 @@ static void cfg80211_process_deauth(stru - u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); - bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); - -- nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL); -+ nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL); - - if (!wdev->current_bss || - !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) -@@ -100,7 +101,8 @@ static void cfg80211_process_deauth(stru - } - - static void cfg80211_process_disassoc(struct wireless_dev *wdev, -- const u8 *buf, size_t len) -+ const u8 *buf, size_t len, -+ bool reconnect) - { - struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; -@@ -108,7 +110,8 @@ static void cfg80211_process_disassoc(st - u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); - bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); - -- nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL); -+ nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect, -+ GFP_KERNEL); - - if (WARN_ON(!wdev->current_bss || - !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) -@@ -133,9 +136,9 @@ void cfg80211_rx_mlme_mgmt(struct net_de - if (ieee80211_is_auth(mgmt->frame_control)) - cfg80211_process_auth(wdev, buf, len); - else if (ieee80211_is_deauth(mgmt->frame_control)) -- cfg80211_process_deauth(wdev, buf, len); -+ cfg80211_process_deauth(wdev, buf, len, false); - else if (ieee80211_is_disassoc(mgmt->frame_control)) -- cfg80211_process_disassoc(wdev, buf, len); -+ cfg80211_process_disassoc(wdev, buf, len, false); - } - EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt); - -@@ -180,22 +183,23 @@ void cfg80211_abandon_assoc(struct net_d - } - EXPORT_SYMBOL(cfg80211_abandon_assoc); - --void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) -+void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len, -+ bool reconnect) - { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct ieee80211_mgmt *mgmt = (void *)buf; - - ASSERT_WDEV_LOCK(wdev); - -- trace_cfg80211_tx_mlme_mgmt(dev, buf, len); -+ trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect); - - if (WARN_ON(len < 2)) - return; - - if (ieee80211_is_deauth(mgmt->frame_control)) -- cfg80211_process_deauth(wdev, buf, len); -+ cfg80211_process_deauth(wdev, buf, len, reconnect); - else -- cfg80211_process_disassoc(wdev, buf, len); -+ cfg80211_process_disassoc(wdev, buf, len, reconnect); - } - EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt); - ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -736,6 +736,7 @@ static const struct nla_policy nl80211_p - NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN), - [NL80211_ATTR_S1G_CAPABILITY_MASK] = - NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN), -+ [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, - }; - - /* policy for the key attributes */ -@@ -15903,7 +15904,7 @@ static void nl80211_send_mlme_event(stru - const u8 *buf, size_t len, - enum nl80211_commands cmd, gfp_t gfp, - int uapsd_queues, const u8 *req_ies, -- size_t req_ies_len) -+ size_t req_ies_len, bool reconnect) - { - struct sk_buff *msg; - void *hdr; -@@ -15925,6 +15926,9 @@ static void nl80211_send_mlme_event(stru - nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies))) - goto nla_put_failure; - -+ if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED)) -+ goto nla_put_failure; -+ - if (uapsd_queues >= 0) { - struct nlattr *nla_wmm = - nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME); -@@ -15953,7 +15957,8 @@ void nl80211_send_rx_auth(struct cfg8021 - size_t len, gfp_t gfp) - { - nl80211_send_mlme_event(rdev, netdev, buf, len, -- NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0); -+ NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0, -+ false); - } - - void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, -@@ -15963,23 +15968,25 @@ void nl80211_send_rx_assoc(struct cfg802 - { - nl80211_send_mlme_event(rdev, netdev, buf, len, - NL80211_CMD_ASSOCIATE, gfp, uapsd_queues, -- req_ies, req_ies_len); -+ req_ies, req_ies_len, false); - } - - void nl80211_send_deauth(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *buf, -- size_t len, gfp_t gfp) -+ size_t len, bool reconnect, gfp_t gfp) - { - nl80211_send_mlme_event(rdev, netdev, buf, len, -- NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0); -+ NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0, -+ reconnect); - } - - void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *buf, -- size_t len, gfp_t gfp) -+ size_t len, bool reconnect, gfp_t gfp) - { - nl80211_send_mlme_event(rdev, netdev, buf, len, -- NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0); -+ NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0, -+ reconnect); - } - - void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, -@@ -16010,7 +16017,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct - - trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); - nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1, -- NULL, 0); -+ NULL, 0, false); - } - EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); - ---- a/net/wireless/nl80211.h -+++ b/net/wireless/nl80211.h -@@ -1,7 +1,7 @@ - /* SPDX-License-Identifier: GPL-2.0 */ - /* - * Portions of this file -- * Copyright (C) 2018 Intel Corporation -+ * Copyright (C) 2018, 2020 Intel Corporation - */ - #ifndef __NET_WIRELESS_NL80211_H - #define __NET_WIRELESS_NL80211_H -@@ -69,10 +69,12 @@ void nl80211_send_rx_assoc(struct cfg802 - const u8 *req_ies, size_t req_ies_len); - void nl80211_send_deauth(struct cfg80211_registered_device *rdev, - struct net_device *netdev, -- const u8 *buf, size_t len, gfp_t gfp); -+ const u8 *buf, size_t len, -+ bool reconnect, gfp_t gfp); - void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *netdev, -- const u8 *buf, size_t len, gfp_t gfp); -+ const u8 *buf, size_t len, -+ bool reconnect, gfp_t gfp); - void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - const u8 *addr, gfp_t gfp); ---- a/net/wireless/trace.h -+++ b/net/wireless/trace.h -@@ -2684,19 +2684,23 @@ DEFINE_EVENT(netdev_frame_event, cfg8021 - ); - - TRACE_EVENT(cfg80211_tx_mlme_mgmt, -- TP_PROTO(struct net_device *netdev, const u8 *buf, int len), -- TP_ARGS(netdev, buf, len), -+ TP_PROTO(struct net_device *netdev, const u8 *buf, int len, -+ bool reconnect), -+ TP_ARGS(netdev, buf, len, reconnect), - TP_STRUCT__entry( - NETDEV_ENTRY - __dynamic_array(u8, frame, len) -+ __field(int, reconnect) - ), - TP_fast_assign( - NETDEV_ASSIGN; - memcpy(__get_dynamic_array(frame), buf, len); -+ __entry->reconnect = reconnect; - ), -- TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x", -+ TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x reconnect:%d", - NETDEV_PR_ARG, -- le16_to_cpup((__le16 *)__get_dynamic_array(frame))) -+ le16_to_cpup((__le16 *)__get_dynamic_array(frame)), -+ __entry->reconnect) - ); - - DECLARE_EVENT_CLASS(netdev_mac_evt, diff --git a/package/kernel/mac80211/patches/subsys/300-mac80211-fix-rate-control-for-retransmitted-frames.patch b/package/kernel/mac80211/patches/subsys/300-mac80211-fix-rate-control-for-retransmitted-frames.patch new file mode 100644 index 000000000..98dfe88cb --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/300-mac80211-fix-rate-control-for-retransmitted-frames.patch @@ -0,0 +1,35 @@ +From: Felix Fietkau +Date: Mon, 22 Nov 2021 21:39:38 +0100 +Subject: [PATCH] mac80211: fix rate control for retransmitted frames + +Since retransmission clears info->control, rate control needs to be called +again, otherwise the driver might crash due to invalid rates. + +Cc: stable@vger.kernel.org # 5.14+ +Reported-by: Aaro Koskinen +Reported-by: Robert W +Fixes: 03c3911d2d67 ("mac80211: call ieee80211_tx_h_rate_ctrl() when dequeue") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1821,15 +1821,15 @@ static int invoke_tx_handlers_late(struc + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + ieee80211_tx_result res = TX_CONTINUE; + ++ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) ++ CALL_TXH(ieee80211_tx_h_rate_ctrl); ++ + if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) { + __skb_queue_tail(&tx->skbs, tx->skb); + tx->skb = NULL; + goto txh_done; + } + +- if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) +- CALL_TXH(ieee80211_tx_h_rate_ctrl); +- + CALL_TXH(ieee80211_tx_h_michael_mic_add); + CALL_TXH(ieee80211_tx_h_sequence); + CALL_TXH(ieee80211_tx_h_fragment); diff --git a/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch rename to package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch deleted file mode 100644 index 31621ebf1..000000000 --- a/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch +++ /dev/null @@ -1,271 +0,0 @@ -From: Johannes Berg -Date: Sun, 6 Dec 2020 14:54:43 +0200 -Subject: [PATCH] mac80211: support driver-based disconnect with reconnect hint - -Support the driver indicating that a disconnection needs -to be performed, and pass through the reconnect hint in -this case. - -Signed-off-by: Johannes Berg -Signed-off-by: Luca Coelho -Link: https://lore.kernel.org/r/iwlwifi.20201206145305.5c8dab7a22a0.I58459fdf6968b16c90cab9c574f0f04ca22b0c79@changeid -Signed-off-by: Johannes Berg ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -5885,6 +5885,17 @@ void ieee80211_beacon_loss(struct ieee80 - void ieee80211_connection_loss(struct ieee80211_vif *vif); - - /** -+ * ieee80211_disconnect - request disconnection -+ * -+ * @vif: &struct ieee80211_vif pointer from the add_interface callback. -+ * @reconnect: immediate reconnect is desired -+ * -+ * Request disconnection from the current network and, if enabled, send a -+ * hint to the higher layers that immediate reconnect is desired. -+ */ -+void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect); -+ -+/** - * ieee80211_resume_disconnect - disconnect from AP after resume - * - * @vif: &struct ieee80211_vif pointer from the add_interface callback. ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -450,7 +450,9 @@ struct ieee80211_if_managed { - unsigned long probe_timeout; - int probe_send_count; - bool nullfunc_failed; -- bool connection_loss; -+ u8 connection_loss:1, -+ driver_disconnect:1, -+ reconnect:1; - - struct cfg80211_bss *associated; - struct ieee80211_mgd_auth_data *auth_data; ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -2725,7 +2725,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get) - - static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata, - const u8 *buf, size_t len, bool tx, -- u16 reason) -+ u16 reason, bool reconnect) - { - struct ieee80211_event event = { - .type = MLME_EVENT, -@@ -2734,7 +2734,7 @@ static void ieee80211_report_disconnect( - }; - - if (tx) -- cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false); -+ cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, reconnect); - else - cfg80211_rx_mlme_mgmt(sdata->dev, buf, len); - -@@ -2756,13 +2756,18 @@ static void __ieee80211_disconnect(struc - - tx = !sdata->csa_block_tx; - -- /* AP is probably out of range (or not reachable for another reason) so -- * remove the bss struct for that AP. -- */ -- cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated); -+ if (!ifmgd->driver_disconnect) { -+ /* -+ * AP is probably out of range (or not reachable for another -+ * reason) so remove the bss struct for that AP. -+ */ -+ cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated); -+ } - - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, -- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, -+ ifmgd->driver_disconnect ? -+ WLAN_REASON_DEAUTH_LEAVING : -+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - tx, frame_buf); - mutex_lock(&local->mtx); - sdata->vif.csa_active = false; -@@ -2775,7 +2780,9 @@ static void __ieee80211_disconnect(struc - mutex_unlock(&local->mtx); - - ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx, -- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); -+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, -+ ifmgd->reconnect); -+ ifmgd->reconnect = false; - - sdata_unlock(sdata); - } -@@ -2794,6 +2801,13 @@ static void ieee80211_beacon_connection_ - sdata_info(sdata, "Connection to AP %pM lost\n", - ifmgd->bssid); - __ieee80211_disconnect(sdata); -+ ifmgd->connection_loss = false; -+ } else if (ifmgd->driver_disconnect) { -+ sdata_info(sdata, -+ "Driver requested disconnection from AP %pM\n", -+ ifmgd->bssid); -+ __ieee80211_disconnect(sdata); -+ ifmgd->driver_disconnect = false; - } else { - ieee80211_mgd_probe_ap(sdata, true); - } -@@ -2832,6 +2846,21 @@ void ieee80211_connection_loss(struct ie - } - EXPORT_SYMBOL(ieee80211_connection_loss); - -+void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect) -+{ -+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); -+ struct ieee80211_hw *hw = &sdata->local->hw; -+ -+ trace_api_disconnect(sdata, reconnect); -+ -+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) -+ return; -+ -+ sdata->u.mgd.driver_disconnect = true; -+ sdata->u.mgd.reconnect = reconnect; -+ ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); -+} -+EXPORT_SYMBOL(ieee80211_disconnect); - - static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, - bool assoc) -@@ -3135,7 +3164,7 @@ static void ieee80211_rx_mgmt_deauth(str - ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - - ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, -- reason_code); -+ reason_code, false); - return; - } - -@@ -3184,7 +3213,8 @@ static void ieee80211_rx_mgmt_disassoc(s - - ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - -- ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code); -+ ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code, -+ false); - } - - static void ieee80211_get_rates(struct ieee80211_supported_band *sband, -@@ -4204,7 +4234,8 @@ static void ieee80211_rx_mgmt_beacon(str - true, deauth_buf); - ieee80211_report_disconnect(sdata, deauth_buf, - sizeof(deauth_buf), true, -- WLAN_REASON_DEAUTH_LEAVING); -+ WLAN_REASON_DEAUTH_LEAVING, -+ false); - return; - } - -@@ -4349,7 +4380,7 @@ static void ieee80211_sta_connection_los - tx, frame_buf); - - ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, -- reason); -+ reason, false); - } - - static int ieee80211_auth(struct ieee80211_sub_if_data *sdata) -@@ -5439,7 +5470,8 @@ int ieee80211_mgd_auth(struct ieee80211_ - - ieee80211_report_disconnect(sdata, frame_buf, - sizeof(frame_buf), true, -- WLAN_REASON_UNSPECIFIED); -+ WLAN_REASON_UNSPECIFIED, -+ false); - } - - sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); -@@ -5511,7 +5543,8 @@ int ieee80211_mgd_assoc(struct ieee80211 - - ieee80211_report_disconnect(sdata, frame_buf, - sizeof(frame_buf), true, -- WLAN_REASON_UNSPECIFIED); -+ WLAN_REASON_UNSPECIFIED, -+ false); - } - - if (ifmgd->auth_data && !ifmgd->auth_data->done) { -@@ -5810,7 +5843,7 @@ int ieee80211_mgd_deauth(struct ieee8021 - ieee80211_destroy_auth_data(sdata, false); - ieee80211_report_disconnect(sdata, frame_buf, - sizeof(frame_buf), true, -- req->reason_code); -+ req->reason_code, false); - - return 0; - } -@@ -5830,7 +5863,7 @@ int ieee80211_mgd_deauth(struct ieee8021 - ieee80211_destroy_assoc_data(sdata, false, true); - ieee80211_report_disconnect(sdata, frame_buf, - sizeof(frame_buf), true, -- req->reason_code); -+ req->reason_code, false); - return 0; - } - -@@ -5845,7 +5878,7 @@ int ieee80211_mgd_deauth(struct ieee8021 - req->reason_code, tx, frame_buf); - ieee80211_report_disconnect(sdata, frame_buf, - sizeof(frame_buf), true, -- req->reason_code); -+ req->reason_code, false); - return 0; - } - -@@ -5878,7 +5911,7 @@ int ieee80211_mgd_disassoc(struct ieee80 - frame_buf); - - ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, -- req->reason_code); -+ req->reason_code, false); - - return 0; - } ---- a/net/mac80211/trace.h -+++ b/net/mac80211/trace.h -@@ -2,7 +2,7 @@ - /* - * Portions of this file - * Copyright(c) 2016-2017 Intel Deutschland GmbH --* Copyright (C) 2018 - 2019 Intel Corporation -+* Copyright (C) 2018 - 2020 Intel Corporation - */ - - #if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ) -@@ -2086,6 +2086,27 @@ TRACE_EVENT(api_connection_loss, - ) - ); - -+TRACE_EVENT(api_disconnect, -+ TP_PROTO(struct ieee80211_sub_if_data *sdata, bool reconnect), -+ -+ TP_ARGS(sdata, reconnect), -+ -+ TP_STRUCT__entry( -+ VIF_ENTRY -+ __field(int, reconnect) -+ ), -+ -+ TP_fast_assign( -+ VIF_ASSIGN; -+ __entry->reconnect = reconnect; -+ ), -+ -+ TP_printk( -+ VIF_PR_FMT " reconnect:%d", -+ VIF_PR_ARG, __entry->reconnect -+ ) -+); -+ - TRACE_EVENT(api_cqm_rssi_notify, - TP_PROTO(struct ieee80211_sub_if_data *sdata, - enum nl80211_cqm_rssi_threshold_event rssi_event, diff --git a/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch b/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch deleted file mode 100644 index acfdae0f5..000000000 --- a/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch +++ /dev/null @@ -1,74 +0,0 @@ -From: Rohan Dutta -Date: Tue, 27 Oct 2020 12:09:10 +0200 -Subject: [PATCH] cfg80211: Add support to configure SAE PWE value to drivers - -Add support to configure SAE PWE preference from userspace to drivers in -both AP and STA modes. This is needed for cases where the driver takes -care of Authentication frame processing (SME in the driver) so that -correct enforcement of the acceptable PWE derivation mechanism can be -performed. - -The userspace applications can pass the sae_pwe value using the -NL80211_ATTR_SAE_PWE attribute in the NL80211_CMD_CONNECT and -NL80211_CMD_START_AP commands to the driver. This allows selection -between the hunting-and-pecking loop and hash-to-element options for PWE -derivation. For backwards compatibility, this new attribute is optional -and if not included, the driver is notified of the value being -unspecified. - -Signed-off-by: Rohan Dutta -Signed-off-by: Jouni Malinen -Link: https://lore.kernel.org/r/20201027100910.22283-1-jouni@codeaurora.org -Signed-off-by: Johannes Berg ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1009,6 +1009,14 @@ struct survey_info { - * @sae_pwd: password for SAE authentication (for devices supporting SAE - * offload) - * @sae_pwd_len: length of SAE password (for devices supporting SAE offload) -+ * @sae_pwe: The mechanisms allowed for SAE PWE derivation -+ * NL80211_SAE_PWE_UNSPECIFIED: Not-specified, used to indicate userspace -+ * did not specify any preference. The driver should follow its -+ * internal policy in such a scenario. -+ * NL80211_SAE_PWE_HUNT_AND_PECK: Allow hunting-and-pecking loop only -+ * NL80211_SAE_PWE_HASH_TO_ELEMENT: Allow hash-to-element only -+ * NL80211_SAE_PWE_BOTH: Allow either hunting-and-pecking loop -+ * or hash-to-element - */ - struct cfg80211_crypto_settings { - u32 wpa_versions; -@@ -1027,6 +1035,7 @@ struct cfg80211_crypto_settings { - const u8 *psk; - const u8 *sae_pwd; - u8 sae_pwd_len; -+ enum nl80211_sae_pwe_mechanism sae_pwe; - }; - - /** ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -736,6 +736,9 @@ static const struct nla_policy nl80211_p - NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN), - [NL80211_ATTR_S1G_CAPABILITY_MASK] = - NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN), -+ [NL80211_ATTR_SAE_PWE] = -+ NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK, -+ NL80211_SAE_PWE_BOTH), - [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, - }; - -@@ -9764,6 +9767,12 @@ static int nl80211_crypto_settings(struc - nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]); - } - -+ if (info->attrs[NL80211_ATTR_SAE_PWE]) -+ settings->sae_pwe = -+ nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]); -+ else -+ settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED; -+ - return 0; - } - diff --git a/package/kernel/mac80211/patches/subsys/302-mac80211-fix-regression-in-SSN-handling-of-addba-tx.patch b/package/kernel/mac80211/patches/subsys/302-mac80211-fix-regression-in-SSN-handling-of-addba-tx.patch new file mode 100644 index 000000000..dc8afb918 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/302-mac80211-fix-regression-in-SSN-handling-of-addba-tx.patch @@ -0,0 +1,44 @@ +From: Felix Fietkau +Date: Wed, 24 Nov 2021 10:30:41 +0100 +Subject: [PATCH] mac80211: fix regression in SSN handling of addba tx + +Some drivers that do their own sequence number allocation (e.g. ath9k) rely +on being able to modify params->ssn on starting tx ampdu sessions. +This was broken by a change that modified it to use sta->tid_seq[tid] instead. + +Cc: stable@vger.kernel.org +Fixes: 31d8bb4e07f8 ("mac80211: agg-tx: refactor sending addba") +Reported-by: Eneas U de Queiroz +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -480,8 +480,7 @@ static void ieee80211_send_addba_with_ti + + /* send AddBA request */ + ieee80211_send_addba_request(sdata, sta->sta.addr, tid, +- tid_tx->dialog_token, +- sta->tid_seq[tid] >> 4, ++ tid_tx->dialog_token, tid_tx->ssn, + buf_size, tid_tx->timeout); + + WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); +@@ -523,6 +522,7 @@ void ieee80211_tx_ba_session_handle_star + + params.ssn = sta->tid_seq[tid] >> 4; + ret = drv_ampdu_action(local, sdata, ¶ms); ++ tid_tx->ssn = params.ssn; + if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) { + return; + } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -199,6 +199,7 @@ struct tid_ampdu_tx { + u8 stop_initiator; + bool tx_stop; + u16 buf_size; ++ u16 ssn; + + u16 failed_bar_ssn; + bool bar_pending; diff --git a/package/kernel/mac80211/patches/subsys/303-mac80211-set-up-the-fwd_skb-dev-for-mesh-forwarding.patch b/package/kernel/mac80211/patches/subsys/303-mac80211-set-up-the-fwd_skb-dev-for-mesh-forwarding.patch new file mode 100644 index 000000000..1ceb2be25 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/303-mac80211-set-up-the-fwd_skb-dev-for-mesh-forwarding.patch @@ -0,0 +1,62 @@ +From: Xing Song +Date: Tue, 23 Nov 2021 11:31:23 +0800 +Subject: [PATCH] mac80211: set up the fwd_skb->dev for mesh forwarding + +Mesh forwarding requires that the fwd_skb->dev is set up for TX handling, +otherwise the following warning will be generated, so set it up for the +pending frames. + +[ 72.835674 ] WARNING: CPU: 0 PID: 1193 at __skb_flow_dissect+0x284/0x1298 +[ 72.842379 ] Modules linked in: ksmbd pppoe ppp_async l2tp_ppp ... +[ 72.962020 ] CPU: 0 PID: 1193 Comm: kworker/u5:1 Tainted: P S 5.4.137 #0 +[ 72.969938 ] Hardware name: MT7622_MT7531 RFB (DT) +[ 72.974659 ] Workqueue: napi_workq napi_workfn +[ 72.979025 ] pstate: 60000005 (nZCv daif -PAN -UAO) +[ 72.983822 ] pc : __skb_flow_dissect+0x284/0x1298 +[ 72.988444 ] lr : __skb_flow_dissect+0x54/0x1298 +[ 72.992977 ] sp : ffffffc010c738c0 +[ 72.996293 ] x29: ffffffc010c738c0 x28: 0000000000000000 +[ 73.001615 ] x27: 000000000000ffc2 x26: ffffff800c2eb818 +[ 73.006937 ] x25: ffffffc010a987c8 x24: 00000000000000ce +[ 73.012259 ] x23: ffffffc010c73a28 x22: ffffffc010a99c60 +[ 73.017581 ] x21: 000000000000ffc2 x20: ffffff80094da800 +[ 73.022903 ] x19: 0000000000000000 x18: 0000000000000014 +[ 73.028226 ] x17: 00000000084d16af x16: 00000000d1fc0bab +[ 73.033548 ] x15: 00000000715f6034 x14: 000000009dbdd301 +[ 73.038870 ] x13: 00000000ea4dcbc3 x12: 0000000000000040 +[ 73.044192 ] x11: 000000000eb00ff0 x10: 0000000000000000 +[ 73.049513 ] x9 : 000000000eb00073 x8 : 0000000000000088 +[ 73.054834 ] x7 : 0000000000000000 x6 : 0000000000000001 +[ 73.060155 ] x5 : 0000000000000000 x4 : 0000000000000000 +[ 73.065476 ] x3 : ffffffc010a98000 x2 : 0000000000000000 +[ 73.070797 ] x1 : 0000000000000000 x0 : 0000000000000000 +[ 73.076120 ] Call trace: +[ 73.078572 ] __skb_flow_dissect+0x284/0x1298 +[ 73.082846 ] __skb_get_hash+0x7c/0x228 +[ 73.086629 ] ieee80211_txq_may_transmit+0x7fc/0x17b8 [mac80211] +[ 73.092564 ] ieee80211_tx_prepare_skb+0x20c/0x268 [mac80211] +[ 73.098238 ] ieee80211_tx_pending+0x144/0x330 [mac80211] +[ 73.103560 ] tasklet_action_common.isra.16+0xb4/0x158 +[ 73.108618 ] tasklet_action+0x2c/0x38 +[ 73.112286 ] __do_softirq+0x168/0x3b0 +[ 73.115954 ] do_softirq.part.15+0x88/0x98 +[ 73.119969 ] __local_bh_enable_ip+0xb0/0xb8 +[ 73.124156 ] napi_workfn+0x58/0x90 +[ 73.127565 ] process_one_work+0x20c/0x478 +[ 73.131579 ] worker_thread+0x50/0x4f0 +[ 73.135249 ] kthread+0x124/0x128 +[ 73.138484 ] ret_from_fork+0x10/0x1c + +Signed-off-by: Xing Song +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2948,6 +2948,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 + if (!fwd_skb) + goto out; + ++ fwd_skb->dev = sdata->dev; + fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; + fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY); + info = IEEE80211_SKB_CB(fwd_skb); diff --git a/package/kernel/mac80211/patches/subsys/304-mac80211-send-ADDBA-requests-using-the-tid-queue-of-.patch b/package/kernel/mac80211/patches/subsys/304-mac80211-send-ADDBA-requests-using-the-tid-queue-of-.patch new file mode 100644 index 000000000..1c213289c --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/304-mac80211-send-ADDBA-requests-using-the-tid-queue-of-.patch @@ -0,0 +1,28 @@ +From: Felix Fietkau +Date: Thu, 2 Dec 2021 13:30:05 +0100 +Subject: [PATCH] mac80211: send ADDBA requests using the tid/queue of the + aggregation session + +Sending them out on a different queue can cause a race condition where a +number of packets in the queue may be discarded by the receiver, because +the ADDBA request is sent too early. +This affects any driver with software A-MPDU setup which does not allocate +packet seqno in hardware on tx, regardless of whether iTXQ is used or not. +The only driver I've seen that explicitly deals with this issue internally +is mwl8k. + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -106,7 +106,7 @@ static void ieee80211_send_addba_request + mgmt->u.action.u.addba_req.start_seq_num = + cpu_to_le16(start_seq_num << 4); + +- ieee80211_tx_skb(sdata, skb); ++ ieee80211_tx_skb_tid(sdata, skb, tid); + } + + void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) diff --git a/package/kernel/mac80211/patches/subsys/305-mac80211-agg-tx-don-t-schedule_and_wake_txq-under-st.patch b/package/kernel/mac80211/patches/subsys/305-mac80211-agg-tx-don-t-schedule_and_wake_txq-under-st.patch new file mode 100644 index 000000000..008ee49cf --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/305-mac80211-agg-tx-don-t-schedule_and_wake_txq-under-st.patch @@ -0,0 +1,79 @@ +From: Johannes Berg +Date: Mon, 29 Nov 2021 15:32:47 +0200 +Subject: [PATCH] mac80211: agg-tx: don't schedule_and_wake_txq() under + sta->lock + +When we call ieee80211_agg_start_txq(), that will in turn call +schedule_and_wake_txq(). Called from ieee80211_stop_tx_ba_cb() +this is done under sta->lock, which leads to certain circular +lock dependencies, as reported by Chris Murphy: +https://lore.kernel.org/r/CAJCQCtSXJ5qA4bqSPY=oLRMbv-irihVvP7A2uGutEbXQVkoNaw@mail.gmail.com + +In general, ieee80211_agg_start_txq() is usually not called +with sta->lock held, only in this one place. But it's always +called with sta->ampdu_mlme.mtx held, and that's therefore +clearly sufficient. + +Change ieee80211_stop_tx_ba_cb() to also call it without the +sta->lock held, by factoring it out of ieee80211_remove_tid_tx() +(which is only called in this one place). + +This breaks the locking chain and makes it less likely that +we'll have similar locking chain problems in the future. + +Reported-by: Chris Murphy +Signed-off-by: Johannes Berg +Signed-off-by: Luca Coelho +--- + +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -9,7 +9,7 @@ + * Copyright 2007, Michael Wu + * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2020 Intel Corporation ++ * Copyright (C) 2018 - 2021 Intel Corporation + */ + + #include +@@ -213,6 +213,8 @@ ieee80211_agg_start_txq(struct sta_info + struct ieee80211_txq *txq = sta->sta.txq[tid]; + struct txq_info *txqi; + ++ lockdep_assert_held(&sta->ampdu_mlme.mtx); ++ + if (!txq) + return; + +@@ -290,7 +292,6 @@ static void ieee80211_remove_tid_tx(stru + ieee80211_assign_tid_tx(sta, tid, NULL); + + ieee80211_agg_splice_finish(sta->sdata, tid); +- ieee80211_agg_start_txq(sta, tid, false); + + kfree_rcu(tid_tx, rcu_head); + } +@@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_ + { + struct ieee80211_sub_if_data *sdata = sta->sdata; + bool send_delba = false; ++ bool start_txq = false; + + ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", + sta->sta.addr, tid); +@@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_ + send_delba = true; + + ieee80211_remove_tid_tx(sta, tid); ++ start_txq = true; + + unlock_sta: + spin_unlock_bh(&sta->lock); + ++ if (start_txq) ++ ieee80211_agg_start_txq(sta, tid, false); ++ + if (send_delba) + ieee80211_send_delba(sdata, sta->sta.addr, tid, + WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); diff --git a/package/kernel/mac80211/patches/subsys/305-mac80211-fix-regression-in-SSN-handling-of-addba-tx.patch b/package/kernel/mac80211/patches/subsys/305-mac80211-fix-regression-in-SSN-handling-of-addba-tx.patch deleted file mode 100644 index dc502f6e3..000000000 --- a/package/kernel/mac80211/patches/subsys/305-mac80211-fix-regression-in-SSN-handling-of-addba-tx.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 8146ed72e9754f67c1090e92f29b9b0f542f12f9 Mon Sep 17 00:00:00 2001 -From: W_Y_CPP <383152993@qq.com> -Date: Tue, 15 Feb 2022 00:19:41 -0500 -Subject: [PATCH] mac80211-fix-regression-in-SSN-handling-of-addba-tx. - ---- - net/mac80211/agg-tx.c | 4 ++-- - net/mac80211/sta_info.h | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c -index b37c8a9..49f0102 100644 ---- a/net/mac80211/agg-tx.c -+++ b/net/mac80211/agg-tx.c -@@ -480,8 +480,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, - - /* send AddBA request */ - ieee80211_send_addba_request(sdata, sta->sta.addr, tid, -- tid_tx->dialog_token, -- sta->tid_seq[tid] >> 4, -+ tid_tx->dialog_token, tid_tx->ssn, - buf_size, tid_tx->timeout); - - WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); -@@ -523,6 +522,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) - - params.ssn = sta->tid_seq[tid] >> 4; - ret = drv_ampdu_action(local, sdata, ¶ms); -+ tid_tx->ssn = params.ssn; - if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) { - return; - } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { -diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h -index 8559801..05d7405 100644 ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -190,7 +190,7 @@ struct tid_ampdu_tx { - u8 stop_initiator; - bool tx_stop; - u16 buf_size; -- -+ u16 ssn; - u16 failed_bar_ssn; - bool bar_pending; - bool amsdu; --- -2.17.1 - diff --git a/package/kernel/mac80211/patches/subsys/306-mac80211-use-coarse-boottime-for-airtime-fairness-co.patch b/package/kernel/mac80211/patches/subsys/306-mac80211-use-coarse-boottime-for-airtime-fairness-co.patch new file mode 100644 index 000000000..c43cd3acb --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/306-mac80211-use-coarse-boottime-for-airtime-fairness-co.patch @@ -0,0 +1,60 @@ +From: Felix Fietkau +Date: Tue, 14 Dec 2021 17:53:12 +0100 +Subject: [PATCH] mac80211: use coarse boottime for airtime fairness code + +The time values used by the airtime fairness code only need to be accurate +enough to cover station activity detection. +Using ktime_get_coarse_boottime_ns instead of ktime_get_boottime_ns will +drop the accuracy down to jiffies intervals, but at the same time saves +a lot of CPU cycles in a hot path + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3820,7 +3820,7 @@ struct ieee80211_txq *ieee80211_next_txq + { + struct ieee80211_local *local = hw_to_local(hw); + struct airtime_sched_info *air_sched; +- u64 now = ktime_get_boottime_ns(); ++ u64 now = ktime_get_coarse_boottime_ns(); + struct ieee80211_txq *ret = NULL; + struct airtime_info *air_info; + struct txq_info *txqi = NULL; +@@ -3947,7 +3947,7 @@ void ieee80211_update_airtime_weight(str + u64 weight_sum = 0; + + if (unlikely(!now)) +- now = ktime_get_boottime_ns(); ++ now = ktime_get_coarse_boottime_ns(); + + lockdep_assert_held(&air_sched->lock); + +@@ -3973,7 +3973,7 @@ void ieee80211_schedule_txq(struct ieee8 + struct ieee80211_local *local = hw_to_local(hw); + struct txq_info *txqi = to_txq_info(txq); + struct airtime_sched_info *air_sched; +- u64 now = ktime_get_boottime_ns(); ++ u64 now = ktime_get_coarse_boottime_ns(); + struct airtime_info *air_info; + u8 ac = txq->ac; + bool was_active; +@@ -4031,7 +4031,7 @@ static void __ieee80211_unschedule_txq(s + + if (!purge) + airtime_set_active(air_sched, air_info, +- ktime_get_boottime_ns()); ++ ktime_get_coarse_boottime_ns()); + + rb_erase_cached(&txqi->schedule_order, + &air_sched->active_txqs); +@@ -4119,7 +4119,7 @@ bool ieee80211_txq_may_transmit(struct i + if (RB_EMPTY_NODE(&txqi->schedule_order)) + goto out; + +- now = ktime_get_boottime_ns(); ++ now = ktime_get_coarse_boottime_ns(); + + /* Like in ieee80211_next_txq(), make sure the first station in the + * scheduling order is eligible for transmission to avoid starvation. diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch b/package/kernel/mac80211/patches/subsys/307-mac80211_hwsim-make-6-GHz-channels-usable.patch similarity index 88% rename from package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch rename to package/kernel/mac80211/patches/subsys/307-mac80211_hwsim-make-6-GHz-channels-usable.patch index 4bac10eef..9c7417e5f 100644 --- a/package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch +++ b/package/kernel/mac80211/patches/subsys/307-mac80211_hwsim-make-6-GHz-channels-usable.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -2968,15 +2968,19 @@ static void mac80211_hwsim_he_capab(stru +@@ -2992,15 +2992,19 @@ static void mac80211_hwsim_he_capab(stru { u16 n_iftype_data; @@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau return; } -@@ -3265,6 +3269,12 @@ static int mac80211_hwsim_new_radio(stru +@@ -3290,6 +3294,12 @@ static int mac80211_hwsim_new_radio(stru sband->vht_cap.vht_mcs.tx_mcs_map = sband->vht_cap.vht_mcs.rx_mcs_map; break; @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau case NL80211_BAND_S1GHZ: memcpy(&sband->s1g_cap, &hwsim_s1g_cap, sizeof(sband->s1g_cap)); -@@ -3275,6 +3285,13 @@ static int mac80211_hwsim_new_radio(stru +@@ -3300,6 +3310,13 @@ static int mac80211_hwsim_new_radio(stru continue; } @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau sband->ht_cap.ht_supported = true; sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD | -@@ -3288,10 +3305,6 @@ static int mac80211_hwsim_new_radio(stru +@@ -3313,10 +3330,6 @@ static int mac80211_hwsim_new_radio(stru sband->ht_cap.mcs.rx_mask[0] = 0xff; sband->ht_cap.mcs.rx_mask[1] = 0xff; sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; diff --git a/package/kernel/mac80211/patches/subsys/308-mac80211-add-support-for-.ndo_fill_forward_path.patch b/package/kernel/mac80211/patches/subsys/308-mac80211-add-support-for-.ndo_fill_forward_path.patch new file mode 100644 index 000000000..2f3c1a266 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/308-mac80211-add-support-for-.ndo_fill_forward_path.patch @@ -0,0 +1,178 @@ +From: Felix Fietkau +Date: Fri, 12 Nov 2021 12:22:23 +0100 +Subject: [PATCH] mac80211: add support for .ndo_fill_forward_path + +This allows drivers to provide a destination device + info for flow offload +Only supported in combination with 802.3 encap offload + +Signed-off-by: Felix Fietkau +Tested-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20211112112223.1209-1-nbd@nbd.name +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3937,6 +3937,8 @@ struct ieee80211_prep_tx_info { + * twt structure. + * @twt_teardown_request: Update the hw with TWT teardown request received + * from the peer. ++ * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to ++ * resolve a path for hardware flow offloading + */ + struct ieee80211_ops { + void (*tx)(struct ieee80211_hw *hw, +@@ -4265,6 +4267,13 @@ struct ieee80211_ops { + struct ieee80211_twt_setup *twt); + void (*twt_teardown_request)(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 flowid); ++#if LINUX_VERSION_IS_GEQ(5,10,0) ++ int (*net_fill_forward_path)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ struct net_device_path_ctx *ctx, ++ struct net_device_path *path); ++#endif + }; + + /** +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1483,4 +1483,28 @@ static inline void drv_twt_teardown_requ + trace_drv_return_void(local); + } + ++#if LINUX_VERSION_IS_GEQ(5,10,0) ++static inline int drv_net_fill_forward_path(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ int ret = -EOPNOTSUPP; ++ ++ sdata = get_bss_sdata(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; ++ ++ trace_drv_net_fill_forward_path(local, sdata, sta); ++ if (local->ops->net_fill_forward_path) ++ ret = local->ops->net_fill_forward_path(&local->hw, ++ &sdata->vif, sta, ++ ctx, path); ++ trace_drv_return_int(local, ret); ++ ++ return ret; ++} ++#endif ++ + #endif /* __MAC80211_DRIVER_OPS */ +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1465,7 +1465,7 @@ struct ieee80211_local { + }; + + static inline struct ieee80211_sub_if_data * +-IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) ++IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev) + { + return netdev_priv(dev); + } +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -822,6 +822,66 @@ static const struct net_device_ops ieee8 + + }; + ++#if LINUX_VERSION_IS_GEQ(5,10,0) ++static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_local *local; ++ struct sta_info *sta; ++ int ret = -ENOENT; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev); ++ local = sdata->local; ++ ++ if (!local->ops->net_fill_forward_path) ++ return -EOPNOTSUPP; ++ ++ rcu_read_lock(); ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ sta = rcu_dereference(sdata->u.vlan.sta); ++ if (sta) ++ break; ++ if (sdata->wdev.use_4addr) ++ goto out; ++ if (is_multicast_ether_addr(ctx->daddr)) ++ goto out; ++ sta = sta_info_get_bss(sdata, ctx->daddr); ++ break; ++ case NL80211_IFTYPE_AP: ++ if (is_multicast_ether_addr(ctx->daddr)) ++ goto out; ++ sta = sta_info_get(sdata, ctx->daddr); ++ break; ++ case NL80211_IFTYPE_STATION: ++ if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { ++ sta = sta_info_get(sdata, ctx->daddr); ++ if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { ++ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) ++ goto out; ++ ++ break; ++ } ++ } ++ ++ sta = sta_info_get(sdata, sdata->u.mgd.bssid); ++ break; ++ default: ++ goto out; ++ } ++ ++ if (!sta) ++ goto out; ++ ++ ret = drv_net_fill_forward_path(local, sdata, &sta->sta, ctx, path); ++out: ++ rcu_read_unlock(); ++ ++ return ret; ++} ++#endif ++ + static const struct net_device_ops ieee80211_dataif_8023_ops = { + #if LINUX_VERSION_IS_LESS(4,10,0) + .ndo_change_mtu = __change_mtu, +@@ -839,7 +901,9 @@ static const struct net_device_ops ieee8 + #else + .ndo_get_stats64 = bp_ieee80211_get_stats64, + #endif +- ++#if LINUX_VERSION_IS_GEQ(5,10,0) ++ .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path, ++#endif + }; + + static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype) +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -2892,6 +2892,15 @@ TRACE_EVENT(drv_twt_teardown_request, + ) + ); + ++#if LINUX_VERSION_IS_GEQ(5,10,0) ++DEFINE_EVENT(sta_event, drv_net_fill_forward_path, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta), ++ TP_ARGS(local, sdata, sta) ++); ++#endif ++ + #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ + + #undef TRACE_INCLUDE_PATH diff --git a/package/kernel/mac80211/patches/subsys/353-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch b/package/kernel/mac80211/patches/subsys/309-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/353-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch rename to package/kernel/mac80211/patches/subsys/309-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch diff --git a/package/kernel/mac80211/patches/subsys/354-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch b/package/kernel/mac80211/patches/subsys/310-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/354-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch rename to package/kernel/mac80211/patches/subsys/310-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch diff --git a/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch b/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch deleted file mode 100644 index 05a888006..000000000 --- a/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch +++ /dev/null @@ -1,95 +0,0 @@ -From: Felix Fietkau -Date: Wed, 25 Nov 2020 18:03:46 +0100 -Subject: [PATCH] net/fq_impl: bulk-free packets from a flow on overmemory - -This is similar to what sch_fq_codel does. It also amortizes the worst -case cost of a follow-up patch that changes the selection of the biggest -flow for dropping packets - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/fq_impl.h -+++ b/include/net/fq_impl.h -@@ -11,17 +11,25 @@ - - /* functions that are embedded into includer */ - -+ -+static void -+__fq_adjust_removal(struct fq *fq, struct fq_flow *flow, unsigned int packets, -+ unsigned int bytes, unsigned int truesize) -+{ -+ struct fq_tin *tin = flow->tin; -+ -+ tin->backlog_bytes -= bytes; -+ tin->backlog_packets -= packets; -+ flow->backlog -= bytes; -+ fq->backlog -= packets; -+ fq->memory_usage -= truesize; -+} -+ - static void fq_adjust_removal(struct fq *fq, - struct fq_flow *flow, - struct sk_buff *skb) - { -- struct fq_tin *tin = flow->tin; -- -- tin->backlog_bytes -= skb->len; -- tin->backlog_packets--; -- flow->backlog -= skb->len; -- fq->backlog--; -- fq->memory_usage -= skb->truesize; -+ __fq_adjust_removal(fq, flow, 1, skb->len, skb->truesize); - } - - static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow) -@@ -59,6 +67,34 @@ static struct sk_buff *fq_flow_dequeue(s - return skb; - } - -+static int fq_flow_drop(struct fq *fq, struct fq_flow *flow, -+ fq_skb_free_t free_func) -+{ -+ unsigned int packets = 0, bytes = 0, truesize = 0; -+ struct fq_tin *tin = flow->tin; -+ struct sk_buff *skb; -+ int pending; -+ -+ lockdep_assert_held(&fq->lock); -+ -+ pending = min_t(int, 32, skb_queue_len(&flow->queue) / 2); -+ do { -+ skb = __skb_dequeue(&flow->queue); -+ if (!skb) -+ break; -+ -+ packets++; -+ bytes += skb->len; -+ truesize += skb->truesize; -+ free_func(fq, tin, flow, skb); -+ } while (packets < pending); -+ -+ __fq_adjust_removal(fq, flow, packets, bytes, truesize); -+ fq_rejigger_backlog(fq, flow); -+ -+ return packets; -+} -+ - static struct sk_buff *fq_tin_dequeue(struct fq *fq, - struct fq_tin *tin, - fq_tin_dequeue_t dequeue_func) -@@ -190,12 +226,9 @@ static void fq_tin_enqueue(struct fq *fq - if (!flow) - return; - -- skb = fq_flow_dequeue(fq, flow); -- if (!skb) -+ if (!fq_flow_drop(fq, flow, free_func)) - return; - -- free_func(fq, flow->tin, flow, skb); -- - flow->tin->overlimit++; - fq->overlimit++; - if (oom) { diff --git a/package/kernel/mac80211/patches/subsys/355-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch b/package/kernel/mac80211/patches/subsys/311-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch similarity index 93% rename from package/kernel/mac80211/patches/subsys/355-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch rename to package/kernel/mac80211/patches/subsys/311-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch index aec2e0778..a6817bd4a 100644 --- a/package/kernel/mac80211/patches/subsys/355-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch +++ b/package/kernel/mac80211/patches/subsys/311-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch @@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau static u16 __minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi, enum minstrel_sample_type type) -@@ -1111,8 +1080,6 @@ minstrel_ht_update_stats(struct minstrel +@@ -1107,8 +1076,6 @@ minstrel_ht_update_stats(struct minstrel mi->max_prob_rate = tmp_max_prob_rate; @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau minstrel_ht_refill_sample_rates(mi); #ifdef CPTCFG_MAC80211_DEBUGFS -@@ -1157,7 +1124,7 @@ minstrel_ht_txstat_valid(struct minstrel +@@ -1153,7 +1120,7 @@ minstrel_ht_txstat_valid(struct minstrel } static void @@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau { int group, orig_group; -@@ -1172,11 +1139,7 @@ minstrel_downgrade_rate(struct minstrel_ +@@ -1168,11 +1135,7 @@ minstrel_downgrade_rate(struct minstrel_ minstrel_mcs_groups[orig_group].streams) continue; @@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau } } -@@ -1210,7 +1173,7 @@ minstrel_ht_tx_status(void *priv, struct +@@ -1183,7 +1146,7 @@ minstrel_ht_tx_status(void *priv, struct struct ieee80211_tx_info *info = st->info; struct minstrel_ht_sta *mi = priv_sta; struct ieee80211_tx_rate *ar = info->status.rates; @@ -126,7 +126,7 @@ Signed-off-by: Felix Fietkau struct minstrel_priv *mp = priv; u32 update_interval = mp->update_interval; bool last, update = false; -@@ -1256,18 +1219,13 @@ minstrel_ht_tx_status(void *priv, struct +@@ -1233,18 +1196,13 @@ minstrel_ht_tx_status(void *priv, struct /* * check for sudden death of spatial multiplexing, * downgrade to a lower number of streams if necessary. diff --git a/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch b/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch deleted file mode 100644 index 33dbb5eb9..000000000 --- a/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch +++ /dev/null @@ -1,144 +0,0 @@ -From: Felix Fietkau -Date: Wed, 25 Nov 2020 18:09:10 +0100 -Subject: [PATCH] net/fq_impl: drop get_default_func, move default flow to - fq_tin - -Simplifies the code and prepares for a rework of scanning for flows on -overmemory drop. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/fq.h -+++ b/include/net/fq.h -@@ -47,6 +47,7 @@ struct fq_flow { - struct fq_tin { - struct list_head new_flows; - struct list_head old_flows; -+ struct fq_flow default_flow; - u32 backlog_bytes; - u32 backlog_packets; - u32 overlimit; ---- a/include/net/fq_impl.h -+++ b/include/net/fq_impl.h -@@ -151,8 +151,7 @@ static u32 fq_flow_idx(struct fq *fq, st - - static struct fq_flow *fq_flow_classify(struct fq *fq, - struct fq_tin *tin, u32 idx, -- struct sk_buff *skb, -- fq_flow_get_default_t get_default_func) -+ struct sk_buff *skb) - { - struct fq_flow *flow; - -@@ -160,7 +159,7 @@ static struct fq_flow *fq_flow_classify( - - flow = &fq->flows[idx]; - if (flow->tin && flow->tin != tin) { -- flow = get_default_func(fq, tin, idx, skb); -+ flow = &tin->default_flow; - tin->collisions++; - fq->collisions++; - } -@@ -192,15 +191,14 @@ static void fq_recalc_backlog(struct fq - static void fq_tin_enqueue(struct fq *fq, - struct fq_tin *tin, u32 idx, - struct sk_buff *skb, -- fq_skb_free_t free_func, -- fq_flow_get_default_t get_default_func) -+ fq_skb_free_t free_func) - { - struct fq_flow *flow; - bool oom; - - lockdep_assert_held(&fq->lock); - -- flow = fq_flow_classify(fq, tin, idx, skb, get_default_func); -+ flow = fq_flow_classify(fq, tin, idx, skb); - - flow->tin = tin; - flow->backlog += skb->len; -@@ -331,6 +329,7 @@ static void fq_tin_init(struct fq_tin *t - { - INIT_LIST_HEAD(&tin->new_flows); - INIT_LIST_HEAD(&tin->old_flows); -+ fq_flow_init(&tin->default_flow); - } - - static int fq_init(struct fq *fq, int flows_cnt) ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -846,7 +846,6 @@ enum txq_info_flags { - */ - struct txq_info { - struct fq_tin tin; -- struct fq_flow def_flow; - struct codel_vars def_cvars; - struct codel_stats cstats; - struct sk_buff_head frags; ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1322,7 +1322,7 @@ static struct sk_buff *codel_dequeue_fun - fq = &local->fq; - - if (cvars == &txqi->def_cvars) -- flow = &txqi->def_flow; -+ flow = &txqi->tin.default_flow; - else - flow = &fq->flows[cvars - local->cvars]; - -@@ -1365,7 +1365,7 @@ static struct sk_buff *fq_tin_dequeue_fu - cparams = &local->cparams; - } - -- if (flow == &txqi->def_flow) -+ if (flow == &tin->default_flow) - cvars = &txqi->def_cvars; - else - cvars = &local->cvars[flow - fq->flows]; -@@ -1392,17 +1392,6 @@ static void fq_skb_free_func(struct fq * - ieee80211_free_txskb(&local->hw, skb); - } - --static struct fq_flow *fq_flow_get_default_func(struct fq *fq, -- struct fq_tin *tin, -- int idx, -- struct sk_buff *skb) --{ -- struct txq_info *txqi; -- -- txqi = container_of(tin, struct txq_info, tin); -- return &txqi->def_flow; --} -- - static void ieee80211_txq_enqueue(struct ieee80211_local *local, - struct txq_info *txqi, - struct sk_buff *skb) -@@ -1415,8 +1404,7 @@ static void ieee80211_txq_enqueue(struct - - spin_lock_bh(&fq->lock); - fq_tin_enqueue(fq, tin, flow_idx, skb, -- fq_skb_free_func, -- fq_flow_get_default_func); -+ fq_skb_free_func); - spin_unlock_bh(&fq->lock); - } - -@@ -1459,7 +1447,6 @@ void ieee80211_txq_init(struct ieee80211 - struct txq_info *txqi, int tid) - { - fq_tin_init(&txqi->tin); -- fq_flow_init(&txqi->def_flow); - codel_vars_init(&txqi->def_cvars); - codel_stats_init(&txqi->cstats); - __skb_queue_head_init(&txqi->frags); -@@ -3310,8 +3297,7 @@ static bool ieee80211_amsdu_aggregate(st - */ - - tin = &txqi->tin; -- flow = fq_flow_classify(fq, tin, flow_idx, skb, -- fq_flow_get_default_func); -+ flow = fq_flow_classify(fq, tin, flow_idx, skb); - head = skb_peek_tail(&flow->queue); - if (!head || skb_is_gso(head)) - goto out; diff --git a/package/kernel/mac80211/patches/subsys/312-mac80211-split-beacon-retrieval-functions.patch b/package/kernel/mac80211/patches/subsys/312-mac80211-split-beacon-retrieval-functions.patch new file mode 100644 index 000000000..18b1951f6 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/312-mac80211-split-beacon-retrieval-functions.patch @@ -0,0 +1,262 @@ +From: Aloka Dixit +Date: Tue, 5 Oct 2021 21:09:36 -0700 +Subject: [PATCH] mac80211: split beacon retrieval functions + +Split __ieee80211_beacon_get() into a separate function for AP mode +ieee80211_beacon_get_ap(). +Also, move the code common to all modes (AP, adhoc and mesh) to +a separate function ieee80211_beacon_get_finish(). + +Signed-off-by: Aloka Dixit +Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4987,6 +4987,115 @@ static int ieee80211_beacon_protect(stru + return 0; + } + ++static void ++ieee80211_beacon_get_finish(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs, ++ struct beacon_data *beacon, ++ struct sk_buff *skb, ++ struct ieee80211_chanctx_conf *chanctx_conf, ++ u16 csa_off_base) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_tx_info *info; ++ enum nl80211_band band; ++ struct ieee80211_tx_rate_control txrc; ++ ++ /* CSA offsets */ ++ if (offs && beacon) { ++ u16 i; ++ ++ for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { ++ u16 csa_off = beacon->cntdwn_counter_offsets[i]; ++ ++ if (!csa_off) ++ continue; ++ ++ offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; ++ } ++ } ++ ++ band = chanctx_conf->def.chan->band; ++ info = IEEE80211_SKB_CB(skb); ++ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ++ info->flags |= IEEE80211_TX_CTL_NO_ACK; ++ info->band = band; ++ ++ memset(&txrc, 0, sizeof(txrc)); ++ txrc.hw = hw; ++ txrc.sband = local->hw.wiphy->bands[band]; ++ txrc.bss_conf = &sdata->vif.bss_conf; ++ txrc.skb = skb; ++ txrc.reported_rate.idx = -1; ++ if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) ++ txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; ++ else ++ txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; ++ txrc.bss = true; ++ rate_control_get_rate(sdata, NULL, &txrc); ++ ++ info->control.vif = vif; ++ info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | ++ IEEE80211_TX_CTL_ASSIGN_SEQ | ++ IEEE80211_TX_CTL_FIRST_FRAGMENT; ++} ++ ++static struct sk_buff * ++ieee80211_beacon_get_ap(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs, ++ bool is_template, ++ struct beacon_data *beacon, ++ struct ieee80211_chanctx_conf *chanctx_conf) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_if_ap *ap = &sdata->u.ap; ++ struct sk_buff *skb = NULL; ++ u16 csa_off_base = 0; ++ ++ if (beacon->cntdwn_counter_offsets[0]) { ++ if (!is_template) ++ ieee80211_beacon_update_cntdwn(vif); ++ ++ ieee80211_set_beacon_cntdwn(sdata, beacon); ++ } ++ ++ /* headroom, head length, ++ * tail length and maximum TIM length ++ */ ++ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + ++ beacon->tail_len + 256 + ++ local->hw.extra_beacon_tailroom); ++ if (!skb) ++ return NULL; ++ ++ skb_reserve(skb, local->tx_headroom); ++ skb_put_data(skb, beacon->head, beacon->head_len); ++ ++ ieee80211_beacon_add_tim(sdata, &ap->ps, skb, is_template); ++ ++ 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; ++ } ++ ++ if (beacon->tail) ++ skb_put_data(skb, beacon->tail, beacon->tail_len); ++ ++ if (ieee80211_beacon_protect(skb, local, sdata) < 0) ++ return NULL; ++ ++ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, chanctx_conf, ++ csa_off_base); ++ return skb; ++} ++ + static struct sk_buff * + __ieee80211_beacon_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -4996,12 +5105,8 @@ __ieee80211_beacon_get(struct ieee80211_ + struct ieee80211_local *local = hw_to_local(hw); + struct beacon_data *beacon = NULL; + struct sk_buff *skb = NULL; +- struct ieee80211_tx_info *info; + struct ieee80211_sub_if_data *sdata = NULL; +- enum nl80211_band band; +- struct ieee80211_tx_rate_control txrc; + struct ieee80211_chanctx_conf *chanctx_conf; +- int csa_off_base = 0; + + rcu_read_lock(); + +@@ -5018,48 +5123,11 @@ __ieee80211_beacon_get(struct ieee80211_ + struct ieee80211_if_ap *ap = &sdata->u.ap; + + beacon = rcu_dereference(ap->beacon); +- if (beacon) { +- if (beacon->cntdwn_counter_offsets[0]) { +- if (!is_template) +- ieee80211_beacon_update_cntdwn(vif); +- +- ieee80211_set_beacon_cntdwn(sdata, beacon); +- } +- +- /* +- * headroom, head length, +- * tail length and maximum TIM length +- */ +- skb = dev_alloc_skb(local->tx_headroom + +- beacon->head_len + +- beacon->tail_len + 256 + +- local->hw.extra_beacon_tailroom); +- if (!skb) +- goto out; +- +- skb_reserve(skb, local->tx_headroom); +- skb_put_data(skb, beacon->head, beacon->head_len); +- +- ieee80211_beacon_add_tim(sdata, &ap->ps, skb, +- is_template); +- +- 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; +- } +- +- if (beacon->tail) +- skb_put_data(skb, beacon->tail, +- beacon->tail_len); +- +- if (ieee80211_beacon_protect(skb, local, sdata) < 0) +- goto out; +- } else ++ if (!beacon) + goto out; ++ ++ skb = ieee80211_beacon_get_ap(hw, vif, offs, is_template, ++ beacon, chanctx_conf); + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + struct ieee80211_hdr *hdr; +@@ -5085,6 +5153,9 @@ __ieee80211_beacon_get(struct ieee80211_ + hdr = (struct ieee80211_hdr *) skb->data; + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_BEACON); ++ ++ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, ++ chanctx_conf, 0); + } else if (ieee80211_vif_is_mesh(&sdata->vif)) { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + +@@ -5124,51 +5195,13 @@ __ieee80211_beacon_get(struct ieee80211_ + } + + skb_put_data(skb, beacon->tail, beacon->tail_len); ++ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, ++ chanctx_conf, 0); + } else { + WARN_ON(1); + goto out; + } + +- /* CSA offsets */ +- if (offs && beacon) { +- int i; +- +- for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { +- u16 csa_off = beacon->cntdwn_counter_offsets[i]; +- +- if (!csa_off) +- continue; +- +- offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; +- } +- } +- +- band = chanctx_conf->def.chan->band; +- +- info = IEEE80211_SKB_CB(skb); +- +- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; +- info->flags |= IEEE80211_TX_CTL_NO_ACK; +- info->band = band; +- +- memset(&txrc, 0, sizeof(txrc)); +- txrc.hw = hw; +- txrc.sband = local->hw.wiphy->bands[band]; +- txrc.bss_conf = &sdata->vif.bss_conf; +- txrc.skb = skb; +- txrc.reported_rate.idx = -1; +- if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) +- txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; +- else +- txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; +- txrc.bss = true; +- rate_control_get_rate(sdata, NULL, &txrc); +- +- info->control.vif = vif; +- +- info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | +- IEEE80211_TX_CTL_ASSIGN_SEQ | +- IEEE80211_TX_CTL_FIRST_FRAGMENT; + out: + rcu_read_unlock(); + return skb; diff --git a/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch b/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch deleted file mode 100644 index 08e5cbb5b..000000000 --- a/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch +++ /dev/null @@ -1,317 +0,0 @@ -From: Felix Fietkau -Date: Wed, 25 Nov 2020 18:10:34 +0100 -Subject: [PATCH] net/fq_impl: do not maintain a backlog-sorted list of - flows - -A sorted flow list is only needed to drop packets in the biggest flow when -hitting the overmemory condition. -By scanning flows only when needed, we can avoid paying the cost of -maintaining the list under normal conditions -In order to avoid scanning lots of empty flows and touching too many cold -cache lines, a bitmap of flows with backlog is maintained - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/fq.h -+++ b/include/net/fq.h -@@ -19,8 +19,6 @@ struct fq_tin; - * @flowchain: can be linked to fq_tin's new_flows or old_flows. Used for DRR++ - * (deficit round robin) based round robin queuing similar to the one - * found in net/sched/sch_fq_codel.c -- * @backlogchain: can be linked to other fq_flow and fq. Used to keep track of -- * fat flows and efficient head-dropping if packet limit is reached - * @queue: sk_buff queue to hold packets - * @backlog: number of bytes pending in the queue. The number of packets can be - * found in @queue.qlen -@@ -29,7 +27,6 @@ struct fq_tin; - struct fq_flow { - struct fq_tin *tin; - struct list_head flowchain; -- struct list_head backlogchain; - struct sk_buff_head queue; - u32 backlog; - int deficit; -@@ -47,6 +44,7 @@ struct fq_flow { - struct fq_tin { - struct list_head new_flows; - struct list_head old_flows; -+ struct list_head tin_list; - struct fq_flow default_flow; - u32 backlog_bytes; - u32 backlog_packets; -@@ -60,14 +58,14 @@ struct fq_tin { - /** - * struct fq - main container for fair queuing purposes - * -- * @backlogs: linked to fq_flows. Used to maintain fat flows for efficient -- * head-dropping when @backlog reaches @limit - * @limit: max number of packets that can be queued across all flows - * @backlog: number of packets queued across all flows - */ - struct fq { - struct fq_flow *flows; -- struct list_head backlogs; -+ unsigned long *flows_bitmap; -+ -+ struct list_head tin_backlog; - spinlock_t lock; - u32 flows_cnt; - u32 limit; ---- a/include/net/fq_impl.h -+++ b/include/net/fq_impl.h -@@ -17,12 +17,24 @@ __fq_adjust_removal(struct fq *fq, struc - unsigned int bytes, unsigned int truesize) - { - struct fq_tin *tin = flow->tin; -+ int idx; - - tin->backlog_bytes -= bytes; - tin->backlog_packets -= packets; - flow->backlog -= bytes; - fq->backlog -= packets; - fq->memory_usage -= truesize; -+ -+ if (flow->backlog) -+ return; -+ -+ if (flow == &tin->default_flow) { -+ list_del_init(&tin->tin_list); -+ return; -+ } -+ -+ idx = flow - fq->flows; -+ __clear_bit(idx, fq->flows_bitmap); - } - - static void fq_adjust_removal(struct fq *fq, -@@ -32,24 +44,6 @@ static void fq_adjust_removal(struct fq - __fq_adjust_removal(fq, flow, 1, skb->len, skb->truesize); - } - --static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow) --{ -- struct fq_flow *i; -- -- if (flow->backlog == 0) { -- list_del_init(&flow->backlogchain); -- } else { -- i = flow; -- -- list_for_each_entry_continue(i, &fq->backlogs, backlogchain) -- if (i->backlog < flow->backlog) -- break; -- -- list_move_tail(&flow->backlogchain, -- &i->backlogchain); -- } --} -- - static struct sk_buff *fq_flow_dequeue(struct fq *fq, - struct fq_flow *flow) - { -@@ -62,7 +56,6 @@ static struct sk_buff *fq_flow_dequeue(s - return NULL; - - fq_adjust_removal(fq, flow, skb); -- fq_rejigger_backlog(fq, flow); - - return skb; - } -@@ -90,7 +83,6 @@ static int fq_flow_drop(struct fq *fq, s - } while (packets < pending); - - __fq_adjust_removal(fq, flow, packets, bytes, truesize); -- fq_rejigger_backlog(fq, flow); - - return packets; - } -@@ -170,22 +162,36 @@ static struct fq_flow *fq_flow_classify( - return flow; - } - --static void fq_recalc_backlog(struct fq *fq, -- struct fq_tin *tin, -- struct fq_flow *flow) --{ -- struct fq_flow *i; -- -- if (list_empty(&flow->backlogchain)) -- list_add_tail(&flow->backlogchain, &fq->backlogs); -- -- i = flow; -- list_for_each_entry_continue_reverse(i, &fq->backlogs, -- backlogchain) -- if (i->backlog > flow->backlog) -- break; -+static struct fq_flow *fq_find_fattest_flow(struct fq *fq) -+{ -+ struct fq_tin *tin; -+ struct fq_flow *flow = NULL; -+ u32 len = 0; -+ int i; -+ -+ for_each_set_bit(i, fq->flows_bitmap, fq->flows_cnt) { -+ struct fq_flow *cur = &fq->flows[i]; -+ unsigned int cur_len; -+ -+ cur_len = cur->backlog; -+ if (cur_len <= len) -+ continue; -+ -+ flow = cur; -+ len = cur_len; -+ } - -- list_move(&flow->backlogchain, &i->backlogchain); -+ list_for_each_entry(tin, &fq->tin_backlog, tin_list) { -+ unsigned int cur_len = tin->default_flow.backlog; -+ -+ if (cur_len <= len) -+ continue; -+ -+ flow = &tin->default_flow; -+ len = cur_len; -+ } -+ -+ return flow; - } - - static void fq_tin_enqueue(struct fq *fq, -@@ -200,6 +206,13 @@ static void fq_tin_enqueue(struct fq *fq - - flow = fq_flow_classify(fq, tin, idx, skb); - -+ if (!flow->backlog) { -+ if (flow != &tin->default_flow) -+ __set_bit(idx, fq->flows_bitmap); -+ else if (list_empty(&tin->tin_list)) -+ list_add(&tin->tin_list, &fq->tin_backlog); -+ } -+ - flow->tin = tin; - flow->backlog += skb->len; - tin->backlog_bytes += skb->len; -@@ -207,8 +220,6 @@ static void fq_tin_enqueue(struct fq *fq - fq->memory_usage += skb->truesize; - fq->backlog++; - -- fq_recalc_backlog(fq, tin, flow); -- - if (list_empty(&flow->flowchain)) { - flow->deficit = fq->quantum; - list_add_tail(&flow->flowchain, -@@ -218,9 +229,7 @@ static void fq_tin_enqueue(struct fq *fq - __skb_queue_tail(&flow->queue, skb); - oom = (fq->memory_usage > fq->memory_limit); - while (fq->backlog > fq->limit || oom) { -- flow = list_first_entry_or_null(&fq->backlogs, -- struct fq_flow, -- backlogchain); -+ flow = fq_find_fattest_flow(fq); - if (!flow) - return; - -@@ -255,8 +264,6 @@ static void fq_flow_filter(struct fq *fq - fq_adjust_removal(fq, flow, skb); - free_func(fq, tin, flow, skb); - } -- -- fq_rejigger_backlog(fq, flow); - } - - static void fq_tin_filter(struct fq *fq, -@@ -279,16 +286,18 @@ static void fq_flow_reset(struct fq *fq, - struct fq_flow *flow, - fq_skb_free_t free_func) - { -+ struct fq_tin *tin = flow->tin; - struct sk_buff *skb; - - while ((skb = fq_flow_dequeue(fq, flow))) -- free_func(fq, flow->tin, flow, skb); -+ free_func(fq, tin, flow, skb); - -- if (!list_empty(&flow->flowchain)) -+ if (!list_empty(&flow->flowchain)) { - list_del_init(&flow->flowchain); -- -- if (!list_empty(&flow->backlogchain)) -- list_del_init(&flow->backlogchain); -+ if (list_empty(&tin->new_flows) && -+ list_empty(&tin->old_flows)) -+ list_del_init(&tin->tin_list); -+ } - - flow->tin = NULL; - -@@ -314,6 +323,7 @@ static void fq_tin_reset(struct fq *fq, - fq_flow_reset(fq, flow, free_func); - } - -+ WARN_ON_ONCE(!list_empty(&tin->tin_list)); - WARN_ON_ONCE(tin->backlog_bytes); - WARN_ON_ONCE(tin->backlog_packets); - } -@@ -321,7 +331,6 @@ static void fq_tin_reset(struct fq *fq, - static void fq_flow_init(struct fq_flow *flow) - { - INIT_LIST_HEAD(&flow->flowchain); -- INIT_LIST_HEAD(&flow->backlogchain); - __skb_queue_head_init(&flow->queue); - } - -@@ -329,6 +338,7 @@ static void fq_tin_init(struct fq_tin *t - { - INIT_LIST_HEAD(&tin->new_flows); - INIT_LIST_HEAD(&tin->old_flows); -+ INIT_LIST_HEAD(&tin->tin_list); - fq_flow_init(&tin->default_flow); - } - -@@ -337,8 +347,8 @@ static int fq_init(struct fq *fq, int fl - int i; - - memset(fq, 0, sizeof(fq[0])); -- INIT_LIST_HEAD(&fq->backlogs); - spin_lock_init(&fq->lock); -+ INIT_LIST_HEAD(&fq->tin_backlog); - fq->flows_cnt = max_t(u32, flows_cnt, 1); - fq->quantum = 300; - fq->limit = 8192; -@@ -348,6 +358,14 @@ static int fq_init(struct fq *fq, int fl - if (!fq->flows) - return -ENOMEM; - -+ fq->flows_bitmap = kcalloc(BITS_TO_LONGS(fq->flows_cnt), sizeof(long), -+ GFP_KERNEL); -+ if (!fq->flows_bitmap) { -+ kvfree(fq->flows); -+ fq->flows = NULL; -+ return -ENOMEM; -+ } -+ - for (i = 0; i < fq->flows_cnt; i++) - fq_flow_init(&fq->flows[i]); - -@@ -364,6 +382,9 @@ static void fq_reset(struct fq *fq, - - kvfree(fq->flows); - fq->flows = NULL; -+ -+ kfree(fq->flows_bitmap); -+ fq->flows_bitmap = NULL; - } - - #endif ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3364,8 +3364,6 @@ out_recalc: - if (head->len != orig_len) { - flow->backlog += head->len - orig_len; - tin->backlog_bytes += head->len - orig_len; -- -- fq_recalc_backlog(fq, tin, flow); - } - out: - spin_unlock_bh(&fq->lock); diff --git a/package/kernel/mac80211/patches/subsys/313-nl80211-MBSSID-and-EMA-support-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/313-nl80211-MBSSID-and-EMA-support-in-AP-mode.patch new file mode 100644 index 000000000..8e6b30188 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/313-nl80211-MBSSID-and-EMA-support-in-AP-mode.patch @@ -0,0 +1,493 @@ +From: John Crispin +Date: Wed, 15 Sep 2021 19:54:34 -0700 +Subject: [PATCH] nl80211: MBSSID and EMA support in AP mode + +Add new attributes to configure support for multiple BSSID +and advanced multi-BSSID advertisements (EMA) in AP mode. + +- NL80211_ATTR_MBSSID_CONFIG used for per interface configuration. +- NL80211_ATTR_MBSSID_ELEMS used to MBSSID elements for beacons. + +Memory for the elements is allocated dynamically. This change frees +the memory in existing functions which call nl80211_parse_beacon(), +a comment is added to indicate the new references to do the same. + +Signed-off-by: John Crispin +Co-developed-by: Aloka Dixit +Signed-off-by: Aloka Dixit +Link: https://lore.kernel.org/r/20210916025437.29138-2-alokad@codeaurora.org +[don't leave ERR_PTR hanging around] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1046,6 +1046,36 @@ struct cfg80211_crypto_settings { + }; + + /** ++ * struct cfg80211_mbssid_config - AP settings for multi bssid ++ * ++ * @tx_wdev: pointer to the transmitted interface in the MBSSID set ++ * @index: index of this AP in the multi bssid group. ++ * @ema: set to true if the beacons should be sent out in EMA mode. ++ */ ++struct cfg80211_mbssid_config { ++ struct wireless_dev *tx_wdev; ++ u8 index; ++ bool ema; ++}; ++ ++/** ++ * struct cfg80211_mbssid_elems - Multiple BSSID elements ++ * ++ * @cnt: Number of elements in array %elems. ++ * ++ * @elem: Array of multiple BSSID element(s) to be added into Beacon frames. ++ * @elem.data: Data for multiple BSSID elements. ++ * @elem.len: Length of data. ++ */ ++struct cfg80211_mbssid_elems { ++ u8 cnt; ++ struct { ++ const u8 *data; ++ size_t len; ++ } elem[]; ++}; ++ ++/** + * struct cfg80211_beacon_data - beacon data + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed +@@ -1063,6 +1093,7 @@ struct cfg80211_crypto_settings { + * @assocresp_ies_len: length of assocresp_ies in octets + * @probe_resp_len: length of probe response template (@probe_resp) + * @probe_resp: probe response template (AP mode only) ++ * @mbssid_ies: multiple BSSID elements + * @ftm_responder: enable FTM responder functionality; -1 for no change + * (which also implies no change in LCI/civic location data) + * @lci: Measurement Report element content, starting with Measurement Token +@@ -1080,6 +1111,7 @@ struct cfg80211_beacon_data { + const u8 *probe_resp; + const u8 *lci; + const u8 *civicloc; ++ struct cfg80211_mbssid_elems *mbssid_ies; + s8 ftm_responder; + + size_t head_len, tail_len; +@@ -1194,6 +1226,7 @@ enum cfg80211_ap_settings_flags { + * @he_oper: HE operation IE (or %NULL if HE isn't enabled) + * @fils_discovery: FILS discovery transmission parameters + * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters ++ * @mbssid_config: AP settings for multiple bssid + */ + struct cfg80211_ap_settings { + struct cfg80211_chan_def chandef; +@@ -1226,6 +1259,7 @@ struct cfg80211_ap_settings { + struct cfg80211_he_bss_color he_bss_color; + struct cfg80211_fils_discovery fils_discovery; + struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; ++ struct cfg80211_mbssid_config mbssid_config; + }; + + /** +@@ -4986,6 +5020,13 @@ struct wiphy_iftype_akm_suites { + * %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes + * @sar_capa: SAR control capabilities + * @rfkill: a pointer to the rfkill structure ++ * ++ * @mbssid_max_interfaces: maximum number of interfaces supported by the driver ++ * in a multiple BSSID set. This field must be set to a non-zero value ++ * by the driver to advertise MBSSID support. ++ * @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by ++ * the driver. Setting this field to a non-zero value indicates that the ++ * driver supports enhanced multi-BSSID advertisements (EMA AP). + */ + struct wiphy { + struct mutex mtx; +@@ -5133,6 +5174,9 @@ struct wiphy { + + struct rfkill *rfkill; + ++ u8 mbssid_max_interfaces; ++ u8 ema_max_profile_periodicity; ++ + char priv[] __aligned(NETDEV_ALIGN); + }; + +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -337,7 +337,10 @@ + * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from + * userspace to request deletion of a virtual interface, then requires +- * attribute %NL80211_ATTR_IFINDEX. ++ * attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are ++ * enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS, ++ * and if this command is used for the transmitting interface, then all ++ * the non-transmitting interfaces are deleted as well. + * + * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified + * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. +@@ -2593,6 +2596,18 @@ enum nl80211_commands { + * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE + * information for the time while performing a color switch. + * ++ * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID ++ * advertisements (MBSSID) parameters in AP mode. ++ * Kernel uses this attribute to indicate the driver's support for MBSSID ++ * and enhanced multi-BSSID advertisements (EMA AP) to the userspace. ++ * Userspace should use this attribute to configure per interface MBSSID ++ * parameters. ++ * See &enum nl80211_mbssid_config_attributes for details. ++ * ++ * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements. ++ * Mandatory parameter for the transmitting interface to enable MBSSID. ++ * Optional for the non-transmitting interfaces. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3096,6 +3111,9 @@ enum nl80211_attrs { + NL80211_ATTR_COLOR_CHANGE_COLOR, + NL80211_ATTR_COLOR_CHANGE_ELEMS, + ++ NL80211_ATTR_MBSSID_CONFIG, ++ NL80211_ATTR_MBSSID_ELEMS, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -7349,4 +7367,60 @@ enum nl80211_sar_specs_attrs { + NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, + }; + ++/** ++ * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced ++ * multi-BSSID advertisements (EMA) in AP mode. ++ * Kernel uses some of these attributes to advertise driver's support for ++ * MBSSID and EMA. ++ * Remaining attributes should be used by the userspace to configure the ++ * features. ++ * ++ * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid ++ * ++ * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise ++ * the maximum number of MBSSID interfaces supported by the driver. ++ * Driver should indicate MBSSID support by setting ++ * wiphy->mbssid_max_interfaces to a value more than or equal to 2. ++ * ++ * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel ++ * to advertise the maximum profile periodicity supported by the driver ++ * if EMA is enabled. Driver should indicate EMA support to the userspace ++ * by setting wiphy->mbssid_max_ema_profile_periodicity to ++ * a non-zero value. ++ * ++ * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of ++ * this BSS (u8) in the multiple BSSID set. ++ * Value must be set to 0 for the transmitting interface and non-zero for ++ * all non-transmitting interfaces. The userspace will be responsible ++ * for using unique indices for the interfaces. ++ * Range: 0 to wiphy->mbssid_max_interfaces-1. ++ * ++ * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for ++ * a non-transmitted profile which provides the interface index (u32) of ++ * the transmitted profile. The value must match one of the interface ++ * indices advertised by the kernel. Optional if the interface being set up ++ * is the transmitting one, however, if provided then the value must match ++ * the interface index of the same. ++ * ++ * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. ++ * Setting this flag is permitted only if the driver advertises EMA support ++ * by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero. ++ * ++ * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal ++ * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute ++ */ ++enum nl80211_mbssid_config_attributes { ++ __NL80211_MBSSID_CONFIG_ATTR_INVALID, ++ ++ NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, ++ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, ++ NL80211_MBSSID_CONFIG_ATTR_INDEX, ++ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, ++ NL80211_MBSSID_CONFIG_ATTR_EMA, ++ ++ /* keep last */ ++ __NL80211_MBSSID_CONFIG_ATTR_LAST, ++ NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1, ++}; ++ + #endif /* __LINUX_NL80211_H */ +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -439,6 +439,16 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = { + [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy), + }; + ++static const struct nla_policy ++nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = { ++ [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2), ++ [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] = ++ NLA_POLICY_MIN(NLA_U8, 1), ++ [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 }, ++ [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 }, ++ [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG }, ++}; ++ + static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { + [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, +@@ -780,6 +790,9 @@ static const struct nla_policy nl80211_p + [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), ++ [NL80211_ATTR_MBSSID_CONFIG] = ++ NLA_POLICY_NESTED(nl80211_mbssid_config_policy), ++ [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, + }; + + /* policy for the key attributes */ +@@ -2228,6 +2241,35 @@ fail: + return -ENOBUFS; + } + ++static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg) ++{ ++ struct nlattr *config; ++ ++ if (!wiphy->mbssid_max_interfaces) ++ return 0; ++ ++ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG); ++ if (!config) ++ return -ENOBUFS; ++ ++ if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, ++ wiphy->mbssid_max_interfaces)) ++ goto fail; ++ ++ if (wiphy->ema_max_profile_periodicity && ++ nla_put_u8(msg, ++ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, ++ wiphy->ema_max_profile_periodicity)) ++ goto fail; ++ ++ nla_nest_end(msg, config); ++ return 0; ++ ++fail: ++ nla_nest_cancel(msg, config); ++ return -ENOBUFS; ++} ++ + struct nl80211_dump_wiphy_state { + s64 filter_wiphy; + long start; +@@ -2813,6 +2855,9 @@ static int nl80211_send_wiphy(struct cfg + if (nl80211_put_sar_specs(rdev, msg)) + goto nla_put_failure; + ++ if (nl80211_put_mbssid_support(&rdev->wiphy, msg)) ++ goto nla_put_failure; ++ + /* done */ + state->split_start = 0; + break; +@@ -5002,6 +5047,96 @@ static int validate_beacon_tx_rate(struc + return 0; + } + ++static int nl80211_parse_mbssid_config(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct nlattr *attrs, ++ struct cfg80211_mbssid_config *config, ++ u8 num_elems) ++{ ++ struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1]; ++ ++ if (!wiphy->mbssid_max_interfaces) ++ return -EOPNOTSUPP; ++ ++ if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL, ++ NULL) || ++ !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]) ++ return -EINVAL; ++ ++ config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]); ++ if (config->ema) { ++ if (!wiphy->ema_max_profile_periodicity) ++ return -EOPNOTSUPP; ++ ++ if (num_elems > wiphy->ema_max_profile_periodicity) ++ return -EINVAL; ++ } ++ ++ config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]); ++ if (config->index >= wiphy->mbssid_max_interfaces || ++ (!config->index && !num_elems)) ++ return -EINVAL; ++ ++ if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) { ++ u32 tx_ifindex = ++ nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]); ++ ++ if ((!config->index && tx_ifindex != dev->ifindex) || ++ (config->index && tx_ifindex == dev->ifindex)) ++ return -EINVAL; ++ ++ if (tx_ifindex != dev->ifindex) { ++ struct net_device *tx_netdev = ++ dev_get_by_index(wiphy_net(wiphy), tx_ifindex); ++ ++ if (!tx_netdev || !tx_netdev->ieee80211_ptr || ++ tx_netdev->ieee80211_ptr->wiphy != wiphy || ++ tx_netdev->ieee80211_ptr->iftype != ++ NL80211_IFTYPE_AP) { ++ dev_put(tx_netdev); ++ return -EINVAL; ++ } ++ ++ config->tx_wdev = tx_netdev->ieee80211_ptr; ++ } else { ++ config->tx_wdev = dev->ieee80211_ptr; ++ } ++ } else if (!config->index) { ++ config->tx_wdev = dev->ieee80211_ptr; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static struct cfg80211_mbssid_elems * ++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) ++{ ++ struct nlattr *nl_elems; ++ struct cfg80211_mbssid_elems *elems; ++ int rem_elems; ++ u8 i = 0, num_elems = 0; ++ ++ if (!wiphy->mbssid_max_interfaces) ++ return ERR_PTR(-EINVAL); ++ ++ nla_for_each_nested(nl_elems, attrs, rem_elems) ++ num_elems++; ++ ++ elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL); ++ if (!elems) ++ return ERR_PTR(-ENOMEM); ++ ++ nla_for_each_nested(nl_elems, attrs, rem_elems) { ++ elems->elem[i].data = nla_data(nl_elems); ++ elems->elem[i].len = nla_len(nl_elems); ++ i++; ++ } ++ elems->cnt = num_elems; ++ return elems; ++} ++ + static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + struct nlattr *attrs[], + struct cfg80211_beacon_data *bcn) +@@ -5082,6 +5217,17 @@ static int nl80211_parse_beacon(struct c + bcn->ftm_responder = -1; + } + ++ if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { ++ struct cfg80211_mbssid_elems *mbssid = ++ nl80211_parse_mbssid_elems(&rdev->wiphy, ++ attrs[NL80211_ATTR_MBSSID_ELEMS]); ++ ++ if (IS_ERR(mbssid)) ++ return PTR_ERR(mbssid); ++ ++ bcn->mbssid_ies = mbssid; ++ } ++ + return 0; + } + +@@ -5538,6 +5684,17 @@ static int nl80211_start_ap(struct sk_bu + goto out; + } + ++ if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) { ++ err = nl80211_parse_mbssid_config(&rdev->wiphy, dev, ++ info->attrs[NL80211_ATTR_MBSSID_CONFIG], ++ ¶ms.mbssid_config, ++ params.beacon.mbssid_ies ? ++ params.beacon.mbssid_ies->cnt : ++ 0); ++ if (err) ++ goto out; ++ } ++ + nl80211_calculate_ap_params(¶ms); + + if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT]) +@@ -5559,6 +5716,11 @@ static int nl80211_start_ap(struct sk_bu + + out: + kfree(params.acl); ++ kfree(params.beacon.mbssid_ies); ++ if (params.mbssid_config.tx_wdev && ++ params.mbssid_config.tx_wdev->netdev && ++ params.mbssid_config.tx_wdev->netdev != dev) ++ dev_put(params.mbssid_config.tx_wdev->netdev); + + return err; + } +@@ -5583,12 +5745,14 @@ static int nl80211_set_beacon(struct sk_ + + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); + if (err) +- return err; ++ goto out; + + wdev_lock(wdev); + err = rdev_change_beacon(rdev, dev, ¶ms); + wdev_unlock(wdev); + ++out: ++ kfree(params.mbssid_ies); + return err; + } + +@@ -9265,12 +9429,14 @@ static int nl80211_channel_switch(struct + + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_after); + if (err) +- return err; ++ goto free; + + csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs), + GFP_KERNEL); +- if (!csa_attrs) +- return -ENOMEM; ++ if (!csa_attrs) { ++ err = -ENOMEM; ++ goto free; ++ } + + err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX, + info->attrs[NL80211_ATTR_CSA_IES], +@@ -9389,6 +9555,8 @@ skip_beacons: + wdev_unlock(wdev); + + free: ++ kfree(params.beacon_after.mbssid_ies); ++ kfree(params.beacon_csa.mbssid_ies); + kfree(csa_attrs); + return err; + } +@@ -14924,6 +15092,8 @@ static int nl80211_color_change(struct s + wdev_unlock(wdev); + + out: ++ kfree(params.beacon_next.mbssid_ies); ++ kfree(params.beacon_color_change.mbssid_ies); + kfree(tb); + return err; + } diff --git a/package/kernel/mac80211/patches/subsys/314-cfg80211-implement-APIs-for-dedicated-radar-detectio.patch b/package/kernel/mac80211/patches/subsys/314-cfg80211-implement-APIs-for-dedicated-radar-detectio.patch new file mode 100644 index 000000000..032bcf7a0 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/314-cfg80211-implement-APIs-for-dedicated-radar-detectio.patch @@ -0,0 +1,378 @@ +From: Lorenzo Bianconi +Date: Sat, 23 Oct 2021 11:10:50 +0200 +Subject: [PATCH] cfg80211: implement APIs for dedicated radar detection HW + +If a dedicated (off-channel) radar detection hardware (chain) +is available in the hardware/driver, allow this to be used by +calling the NL80211_CMD_RADAR_DETECT command with a new flag +attribute requesting off-channel radar detection is used. + +Offchannel CAC (channel availability check) avoids the CAC +downtime when switching to a radar channel or when turning on +the AP. + +Drivers advertise support for this using the new feature flag +NL80211_EXT_FEATURE_RADAR_OFFCHAN. + +Tested-by: Evelyn Tsai +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/7468e291ef5d05d692c1738d25b8f778d8ea5c3f.1634979655.git.lorenzo@kernel.org +Link: https://lore.kernel.org/r/1e60e60fef00e14401adae81c3d49f3e5f307537.1634979655.git.lorenzo@kernel.org +Link: https://lore.kernel.org/r/85fa50f57fc3adb2934c8d9ca0be30394de6b7e8.1634979655.git.lorenzo@kernel.org +Link: https://lore.kernel.org/r/4b6c08671ad59aae0ac46fc94c02f31b1610eb72.1634979655.git.lorenzo@kernel.org +Link: https://lore.kernel.org/r/241849ccaf2c228873c6f8495bf87b19159ba458.1634979655.git.lorenzo@kernel.org +[remove offchan_mutex, fix cfg80211_stop_offchan_radar_detection(), + remove gfp_t argument, fix documentation, fix tracing] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4057,6 +4057,15 @@ struct mgmt_frame_regs { + * @set_sar_specs: Update the SAR (TX power) settings. + * + * @color_change: Initiate a color change. ++ * ++ * @set_radar_offchan: Configure dedicated offchannel chain available for ++ * radar/CAC detection on some hw. This chain can't be used to transmit ++ * or receive frames and it is bounded to a running wdev. ++ * Offchannel radar/CAC detection allows to avoid the CAC downtime ++ * switching to a different channel during CAC detection on the selected ++ * radar channel. ++ * The caller is expected to set chandef pointer to NULL in order to ++ * disable offchannel CAC/radar detection. + */ + struct cfg80211_ops { + int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); +@@ -4387,6 +4396,8 @@ struct cfg80211_ops { + int (*color_change)(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_color_change_settings *params); ++ int (*set_radar_offchan)(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); + }; + + /* +@@ -7608,6 +7619,20 @@ void cfg80211_cac_event(struct net_devic + const struct cfg80211_chan_def *chandef, + enum nl80211_radar_event event, gfp_t gfp); + ++/** ++ * cfg80211_offchan_cac_event - Channel Availability Check (CAC) offchan event ++ * @wiphy: the wiphy ++ * @chandef: chandef for the current channel ++ * @event: type of event ++ * ++ * This function is called when a Channel Availability Check (CAC) is finished, ++ * started or aborted by a offchannel dedicated chain. ++ * ++ * Note that this acquires the wiphy lock. ++ */ ++void cfg80211_offchan_cac_event(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef, ++ enum nl80211_radar_event event); + + /** + * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2608,6 +2608,13 @@ enum nl80211_commands { + * Mandatory parameter for the transmitting interface to enable MBSSID. + * Optional for the non-transmitting interfaces. + * ++ * @NL80211_ATTR_RADAR_OFFCHAN: Configure dedicated offchannel chain available for ++ * radar/CAC detection on some hw. This chain can't be used to transmit ++ * or receive frames and it is bounded to a running wdev. ++ * Offchannel radar/CAC detection allows to avoid the CAC downtime ++ * switching on a different channel during CAC detection on the selected ++ * radar channel. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3114,6 +3121,8 @@ enum nl80211_attrs { + NL80211_ATTR_MBSSID_CONFIG, + NL80211_ATTR_MBSSID_ELEMS, + ++ NL80211_ATTR_RADAR_OFFCHAN, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -6013,6 +6022,9 @@ enum nl80211_feature_flags { + * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision + * detection and change announcemnts. + * ++ * @NL80211_EXT_FEATURE_RADAR_OFFCHAN: Device supports offchannel radar/CAC ++ * detection. ++ * + * @NUM_NL80211_EXT_FEATURES: number of extended features. + * @MAX_NL80211_EXT_FEATURES: highest extended feature index. + */ +@@ -6078,6 +6090,7 @@ enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_SECURE_RTT, + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, + NL80211_EXT_FEATURE_BSS_COLOR, ++ NL80211_EXT_FEATURE_RADAR_OFFCHAN, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -552,6 +552,7 @@ use_default_name: + INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work); + INIT_WORK(&rdev->conn_work, cfg80211_conn_work); + INIT_WORK(&rdev->event_work, cfg80211_event_work); ++ INIT_DELAYED_WORK(&rdev->offchan_cac_work, cfg80211_offchan_cac_work); + + init_waitqueue_head(&rdev->dev_wait); + +@@ -1214,6 +1215,8 @@ void __cfg80211_leave(struct cfg80211_re + + cfg80211_pmsr_wdev_down(wdev); + ++ cfg80211_stop_offchan_radar_detection(wdev); ++ + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + __cfg80211_leave_ibss(rdev, dev, true); +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -84,6 +84,10 @@ struct cfg80211_registered_device { + + struct delayed_work dfs_update_channels_wk; + ++ struct wireless_dev *offchan_radar_wdev; ++ struct cfg80211_chan_def offchan_radar_chandef; ++ struct delayed_work offchan_cac_work; ++ + /* netlink port which started critical protocol (0 means not started) */ + u32 crit_proto_nlportid; + +@@ -491,6 +495,15 @@ cfg80211_chandef_dfs_cac_time(struct wip + + void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); + ++int ++cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev, ++ struct cfg80211_chan_def *chandef); ++ ++void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev); ++ ++void cfg80211_offchan_cac_work(struct work_struct *work); ++ + bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan); + +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -970,3 +970,116 @@ void cfg80211_cac_event(struct net_devic + nl80211_radar_notify(rdev, chandef, event, netdev, gfp); + } + EXPORT_SYMBOL(cfg80211_cac_event); ++ ++void cfg80211_offchan_cac_work(struct work_struct *work) ++{ ++ struct delayed_work *delayed_work = to_delayed_work(work); ++ struct cfg80211_registered_device *rdev; ++ ++ rdev = container_of(delayed_work, struct cfg80211_registered_device, ++ offchan_cac_work); ++ cfg80211_offchan_cac_event(&rdev->wiphy, &rdev->offchan_radar_chandef, ++ NL80211_RADAR_CAC_FINISHED); ++} ++ ++static void ++__cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev, ++ const struct cfg80211_chan_def *chandef, ++ enum nl80211_radar_event event) ++{ ++ struct wiphy *wiphy = &rdev->wiphy; ++ struct net_device *netdev; ++ ++ lockdep_assert_wiphy(&rdev->wiphy); ++ ++ if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev) ++ return; ++ ++ switch (event) { ++ case NL80211_RADAR_CAC_FINISHED: ++ cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); ++ memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef)); ++ queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); ++ cfg80211_sched_dfs_chan_update(rdev); ++ wdev = rdev->offchan_radar_wdev; ++ rdev->offchan_radar_wdev = NULL; ++ break; ++ case NL80211_RADAR_CAC_ABORTED: ++ cancel_delayed_work(&rdev->offchan_cac_work); ++ wdev = rdev->offchan_radar_wdev; ++ rdev->offchan_radar_wdev = NULL; ++ break; ++ case NL80211_RADAR_CAC_STARTED: ++ WARN_ON(!wdev); ++ rdev->offchan_radar_wdev = wdev; ++ break; ++ default: ++ return; ++ } ++ ++ netdev = wdev ? wdev->netdev : NULL; ++ nl80211_radar_notify(rdev, chandef, event, netdev, GFP_KERNEL); ++} ++ ++void cfg80211_offchan_cac_event(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef, ++ enum nl80211_radar_event event) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ ++ wiphy_lock(wiphy); ++ __cfg80211_offchan_cac_event(rdev, NULL, chandef, event); ++ wiphy_unlock(wiphy); ++} ++EXPORT_SYMBOL(cfg80211_offchan_cac_event); ++ ++int ++cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev, ++ struct cfg80211_chan_def *chandef) ++{ ++ unsigned int cac_time_ms; ++ int err; ++ ++ lockdep_assert_wiphy(&rdev->wiphy); ++ ++ if (!wiphy_ext_feature_isset(&rdev->wiphy, ++ NL80211_EXT_FEATURE_RADAR_OFFCHAN)) ++ return -EOPNOTSUPP; ++ ++ if (rdev->offchan_radar_wdev) ++ return -EBUSY; ++ ++ err = rdev_set_radar_offchan(rdev, chandef); ++ if (err) ++ return err; ++ ++ cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, chandef); ++ if (!cac_time_ms) ++ cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; ++ ++ rdev->offchan_radar_chandef = *chandef; ++ __cfg80211_offchan_cac_event(rdev, wdev, chandef, ++ NL80211_RADAR_CAC_STARTED); ++ queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_work, ++ msecs_to_jiffies(cac_time_ms)); ++ ++ return 0; ++} ++ ++void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev) ++{ ++ struct wiphy *wiphy = wdev->wiphy; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ ++ lockdep_assert_wiphy(wiphy); ++ ++ if (wdev != rdev->offchan_radar_wdev) ++ return; ++ ++ rdev_set_radar_offchan(rdev, NULL); ++ ++ __cfg80211_offchan_cac_event(rdev, NULL, NULL, ++ NL80211_RADAR_CAC_ABORTED); ++} +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -793,6 +793,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MBSSID_CONFIG] = + NLA_POLICY_NESTED(nl80211_mbssid_config_policy), + [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, ++ [NL80211_ATTR_RADAR_OFFCHAN] = { .type = NLA_FLAG }, + }; + + /* policy for the key attributes */ +@@ -9269,12 +9270,6 @@ static int nl80211_start_radar_detection + if (err) + return err; + +- if (netif_carrier_ok(dev)) +- return -EBUSY; +- +- if (wdev->cac_started) +- return -EBUSY; +- + err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype); + if (err < 0) + return err; +@@ -9285,6 +9280,16 @@ static int nl80211_start_radar_detection + if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) + return -EINVAL; + ++ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN])) ++ return cfg80211_start_offchan_radar_detection(rdev, wdev, ++ &chandef); ++ ++ if (netif_carrier_ok(dev)) ++ return -EBUSY; ++ ++ if (wdev->cac_started) ++ return -EBUSY; ++ + /* CAC start is offloaded to HW and can't be started manually */ + if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) + return -EOPNOTSUPP; +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1381,4 +1381,21 @@ static inline int rdev_color_change(stru + return ret; + } + ++static inline int ++rdev_set_radar_offchan(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct wiphy *wiphy = &rdev->wiphy; ++ int ret; ++ ++ if (!rdev->ops->set_radar_offchan) ++ return -EOPNOTSUPP; ++ ++ trace_rdev_set_radar_offchan(wiphy, chandef); ++ ret = rdev->ops->set_radar_offchan(wiphy, chandef); ++ trace_rdev_return_int(wiphy, ret); ++ ++ return ret; ++} ++ + #endif /* __CFG80211_RDEV_OPS */ +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -3643,6 +3643,25 @@ TRACE_EVENT(cfg80211_bss_color_notify, + __entry->color_bitmap) + ); + ++TRACE_EVENT(rdev_set_radar_offchan, ++ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), ++ ++ TP_ARGS(wiphy, chandef), ++ ++ TP_STRUCT__entry( ++ WIPHY_ENTRY ++ CHAN_DEF_ENTRY ++ ), ++ ++ TP_fast_assign( ++ WIPHY_ASSIGN; ++ CHAN_DEF_ASSIGN(chandef) ++ ), ++ ++ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, ++ WIPHY_PR_ARG, CHAN_DEF_PR_ARG) ++); ++ + #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ + + #undef TRACE_INCLUDE_PATH diff --git a/package/kernel/mac80211/patches/subsys/315-cfg80211-move-offchan_cac_event-to-a-dedicated-work.patch b/package/kernel/mac80211/patches/subsys/315-cfg80211-move-offchan_cac_event-to-a-dedicated-work.patch new file mode 100644 index 000000000..e58c3b99b --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/315-cfg80211-move-offchan_cac_event-to-a-dedicated-work.patch @@ -0,0 +1,183 @@ +From: Lorenzo Bianconi +Date: Wed, 27 Oct 2021 11:03:42 +0200 +Subject: [PATCH] cfg80211: move offchan_cac_event to a dedicated work + +In order to make cfg80211_offchan_cac_abort() (renamed from +cfg80211_offchan_cac_event) callable in other contexts and +without so much locking restrictions, make it trigger a new +work instead of operating directly. + +Do some other renames while at it to clarify. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/6145c3d0f30400a568023f67981981d24c7c6133.1635325205.git.lorenzo@kernel.org +[rewrite commit log] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -7620,19 +7620,13 @@ void cfg80211_cac_event(struct net_devic + enum nl80211_radar_event event, gfp_t gfp); + + /** +- * cfg80211_offchan_cac_event - Channel Availability Check (CAC) offchan event ++ * cfg80211_offchan_cac_abort - Channel Availability Check offchan abort event + * @wiphy: the wiphy +- * @chandef: chandef for the current channel +- * @event: type of event + * +- * This function is called when a Channel Availability Check (CAC) is finished, +- * started or aborted by a offchannel dedicated chain. +- * +- * Note that this acquires the wiphy lock. ++ * This function is called by the driver when a Channel Availability Check ++ * (CAC) is aborted by a offchannel dedicated chain. + */ +-void cfg80211_offchan_cac_event(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef, +- enum nl80211_radar_event event); ++void cfg80211_offchan_cac_abort(struct wiphy *wiphy); + + /** + * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -552,7 +552,9 @@ use_default_name: + INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work); + INIT_WORK(&rdev->conn_work, cfg80211_conn_work); + INIT_WORK(&rdev->event_work, cfg80211_event_work); +- INIT_DELAYED_WORK(&rdev->offchan_cac_work, cfg80211_offchan_cac_work); ++ INIT_WORK(&rdev->offchan_cac_abort_wk, cfg80211_offchan_cac_abort_wk); ++ INIT_DELAYED_WORK(&rdev->offchan_cac_done_wk, ++ cfg80211_offchan_cac_done_wk); + + init_waitqueue_head(&rdev->dev_wait); + +@@ -1062,11 +1064,13 @@ void wiphy_unregister(struct wiphy *wiph + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); + cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); ++ cancel_delayed_work_sync(&rdev->offchan_cac_done_wk); + flush_work(&rdev->destroy_work); + flush_work(&rdev->sched_scan_stop_wk); + flush_work(&rdev->propagate_radar_detect_wk); + flush_work(&rdev->propagate_cac_done_wk); + flush_work(&rdev->mgmt_registrations_update_wk); ++ flush_work(&rdev->offchan_cac_abort_wk); + + #ifdef CONFIG_PM + if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -86,7 +86,8 @@ struct cfg80211_registered_device { + + struct wireless_dev *offchan_radar_wdev; + struct cfg80211_chan_def offchan_radar_chandef; +- struct delayed_work offchan_cac_work; ++ struct delayed_work offchan_cac_done_wk; ++ struct work_struct offchan_cac_abort_wk; + + /* netlink port which started critical protocol (0 means not started) */ + u32 crit_proto_nlportid; +@@ -502,7 +503,9 @@ cfg80211_start_offchan_radar_detection(s + + void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev); + +-void cfg80211_offchan_cac_work(struct work_struct *work); ++void cfg80211_offchan_cac_done_wk(struct work_struct *work); ++ ++void cfg80211_offchan_cac_abort_wk(struct work_struct *work); + + bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan); +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -971,17 +971,6 @@ void cfg80211_cac_event(struct net_devic + } + EXPORT_SYMBOL(cfg80211_cac_event); + +-void cfg80211_offchan_cac_work(struct work_struct *work) +-{ +- struct delayed_work *delayed_work = to_delayed_work(work); +- struct cfg80211_registered_device *rdev; +- +- rdev = container_of(delayed_work, struct cfg80211_registered_device, +- offchan_cac_work); +- cfg80211_offchan_cac_event(&rdev->wiphy, &rdev->offchan_radar_chandef, +- NL80211_RADAR_CAC_FINISHED); +-} +- + static void + __cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, +@@ -1006,7 +995,7 @@ __cfg80211_offchan_cac_event(struct cfg8 + rdev->offchan_radar_wdev = NULL; + break; + case NL80211_RADAR_CAC_ABORTED: +- cancel_delayed_work(&rdev->offchan_cac_work); ++ cancel_delayed_work(&rdev->offchan_cac_done_wk); + wdev = rdev->offchan_radar_wdev; + rdev->offchan_radar_wdev = NULL; + break; +@@ -1022,17 +1011,44 @@ __cfg80211_offchan_cac_event(struct cfg8 + nl80211_radar_notify(rdev, chandef, event, netdev, GFP_KERNEL); + } + +-void cfg80211_offchan_cac_event(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef, +- enum nl80211_radar_event event) ++static void ++cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev, ++ const struct cfg80211_chan_def *chandef, ++ enum nl80211_radar_event event) ++{ ++ wiphy_lock(&rdev->wiphy); ++ __cfg80211_offchan_cac_event(rdev, NULL, chandef, event); ++ wiphy_unlock(&rdev->wiphy); ++} ++ ++void cfg80211_offchan_cac_done_wk(struct work_struct *work) ++{ ++ struct delayed_work *delayed_work = to_delayed_work(work); ++ struct cfg80211_registered_device *rdev; ++ ++ rdev = container_of(delayed_work, struct cfg80211_registered_device, ++ offchan_cac_done_wk); ++ cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef, ++ NL80211_RADAR_CAC_FINISHED); ++} ++ ++void cfg80211_offchan_cac_abort_wk(struct work_struct *work) ++{ ++ struct cfg80211_registered_device *rdev; ++ ++ rdev = container_of(work, struct cfg80211_registered_device, ++ offchan_cac_abort_wk); ++ cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef, ++ NL80211_RADAR_CAC_ABORTED); ++} ++ ++void cfg80211_offchan_cac_abort(struct wiphy *wiphy) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + +- wiphy_lock(wiphy); +- __cfg80211_offchan_cac_event(rdev, NULL, chandef, event); +- wiphy_unlock(wiphy); ++ queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk); + } +-EXPORT_SYMBOL(cfg80211_offchan_cac_event); ++EXPORT_SYMBOL(cfg80211_offchan_cac_abort); + + int + cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, +@@ -1062,7 +1078,7 @@ cfg80211_start_offchan_radar_detection(s + rdev->offchan_radar_chandef = *chandef; + __cfg80211_offchan_cac_event(rdev, wdev, chandef, + NL80211_RADAR_CAC_STARTED); +- queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_work, ++ queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_done_wk, + msecs_to_jiffies(cac_time_ms)); + + return 0; diff --git a/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch b/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch deleted file mode 100644 index b8bb2930f..000000000 --- a/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch +++ /dev/null @@ -1,570 +0,0 @@ -From: Felix Fietkau -Date: Wed, 16 Dec 2020 21:34:03 +0100 -Subject: [PATCH] mac80211: add rx decapsulation offload support - -This allows drivers to pass 802.3 frames to mac80211, with some restrictions: - -- the skb must be passed with a valid sta -- fast-rx needs to be active for the sta -- monitor mode needs to be disabled - -mac80211 will tell the driver when it is safe to enable rx decap offload for -a particular station. - -In order to implement support, a driver must: - -- call ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD) -- implement ops->sta_set_decap_offload -- mark 802.3 frames with RX_FLAG_8023 - -If it doesn't want to enable offload for some vif types, it can mask out -IEEE80211_OFFLOAD_DECAP_ENABLED in vif->offload_flags from within the -.add_interface or .update_vif_offload driver ops - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1297,6 +1297,8 @@ ieee80211_tx_info_clear_status(struct ie - * the "0-length PSDU" field included there. The value for it is - * in &struct ieee80211_rx_status. Note that if this value isn't - * known the frame shouldn't be reported. -+ * @RX_FLAG_8023: the frame has an 802.3 header (decap offload performed by -+ * hardware or driver) - */ - enum mac80211_rx_flags { - RX_FLAG_MMIC_ERROR = BIT(0), -@@ -1329,6 +1331,7 @@ enum mac80211_rx_flags { - RX_FLAG_RADIOTAP_HE_MU = BIT(27), - RX_FLAG_RADIOTAP_LSIG = BIT(28), - RX_FLAG_NO_PSDU = BIT(29), -+ RX_FLAG_8023 = BIT(30), - }; - - /** -@@ -1650,11 +1653,15 @@ enum ieee80211_vif_flags { - * The driver supports sending frames passed as 802.3 frames by mac80211. - * It must also support sending 802.11 packets for the same interface. - * @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload -+ * @IEEE80211_OFFLOAD_DECAP_ENABLED: rx encapsulation offload is enabled -+ * The driver supports passing received 802.11 frames as 802.3 frames to -+ * mac80211. - */ - - enum ieee80211_offload_flags { - IEEE80211_OFFLOAD_ENCAP_ENABLED = BIT(0), - IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1), -+ IEEE80211_OFFLOAD_DECAP_ENABLED = BIT(2), - }; - - /** -@@ -2390,6 +2397,9 @@ struct ieee80211_txq { - * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation - * offload - * -+ * @IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD: Hardware supports rx decapsulation -+ * offload -+ * - * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays - */ - enum ieee80211_hw_flags { -@@ -2443,6 +2453,7 @@ enum ieee80211_hw_flags { - IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, - IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT, - IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, -+ IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD, - - /* keep last, obviously */ - NUM_IEEE80211_HW_FLAGS -@@ -4196,6 +4207,9 @@ struct ieee80211_ops { - struct ieee80211_vif *vif); - void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enabled); -+ void (*sta_set_decap_offload)(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta, bool enabled); - }; - - /** ---- a/net/mac80211/debugfs.c -+++ b/net/mac80211/debugfs.c -@@ -405,6 +405,7 @@ static const char *hw_flag_names[] = { - FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID), - FLAG(AMPDU_KEYBORDER_SUPPORT), - FLAG(SUPPORTS_TX_ENCAP_OFFLOAD), -+ FLAG(SUPPORTS_RX_DECAP_OFFLOAD), - #undef FLAG - }; - ---- a/net/mac80211/debugfs_sta.c -+++ b/net/mac80211/debugfs_sta.c -@@ -79,6 +79,7 @@ static const char * const sta_flag_names - FLAG(MPSP_RECIPIENT), - FLAG(PS_DELIVER), - FLAG(USES_ENCRYPTION), -+ FLAG(DECAP_OFFLOAD), - #undef FLAG - }; - ---- a/net/mac80211/driver-ops.h -+++ b/net/mac80211/driver-ops.h -@@ -1413,4 +1413,20 @@ static inline void drv_sta_set_4addr(str - trace_drv_return_void(local); - } - -+static inline void drv_sta_set_decap_offload(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_sta *sta, -+ bool enabled) -+{ -+ sdata = get_bss_sdata(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; -+ -+ trace_drv_sta_set_decap_offload(local, sdata, sta, enabled); -+ if (local->ops->sta_set_decap_offload) -+ local->ops->sta_set_decap_offload(&local->hw, &sdata->vif, sta, -+ enabled); -+ trace_drv_return_void(local); -+} -+ - #endif /* __MAC80211_DRIVER_OPS */ ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -835,7 +835,7 @@ static const struct net_device_ops ieee8 - - }; - --static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) -+static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype) - { - switch (iftype) { - /* P2P GO and client are mapped to AP/STATION types */ -@@ -855,7 +855,7 @@ static bool ieee80211_set_sdata_offload_ - flags = sdata->vif.offload_flags; - - if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && -- ieee80211_iftype_supports_encap_offload(sdata->vif.type)) { -+ ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) { - flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED; - - if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && -@@ -868,10 +868,21 @@ static bool ieee80211_set_sdata_offload_ - flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; - } - -+ if (ieee80211_hw_check(&local->hw, SUPPORTS_RX_DECAP_OFFLOAD) && -+ ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) { -+ flags |= IEEE80211_OFFLOAD_DECAP_ENABLED; -+ -+ if (local->monitors) -+ flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; -+ } else { -+ flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; -+ } -+ - if (sdata->vif.offload_flags == flags) - return false; - - sdata->vif.offload_flags = flags; -+ ieee80211_check_fast_rx_iface(sdata); - return true; - } - -@@ -889,7 +900,7 @@ static void ieee80211_set_vif_encap_ops( - } - - if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || -- !ieee80211_iftype_supports_encap_offload(bss->vif.type)) -+ !ieee80211_iftype_supports_hdr_offload(bss->vif.type)) - return; - - enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -4198,7 +4198,9 @@ void ieee80211_check_fast_rx(struct sta_ - .vif_type = sdata->vif.type, - .control_port_protocol = sdata->control_port_protocol, - }, *old, *new = NULL; -+ bool set_offload = false; - bool assign = false; -+ bool offload; - - /* use sparse to check that we don't return without updating */ - __acquire(check_fast_rx); -@@ -4311,6 +4313,17 @@ void ieee80211_check_fast_rx(struct sta_ - if (assign) - new = kmemdup(&fastrx, sizeof(fastrx), GFP_KERNEL); - -+ offload = assign && -+ (sdata->vif.offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED); -+ -+ if (offload) -+ set_offload = !test_and_set_sta_flag(sta, WLAN_STA_DECAP_OFFLOAD); -+ else -+ set_offload = test_and_clear_sta_flag(sta, WLAN_STA_DECAP_OFFLOAD); -+ -+ if (set_offload) -+ drv_sta_set_decap_offload(local, sdata, &sta->sta, assign); -+ - spin_lock_bh(&sta->lock); - old = rcu_dereference_protected(sta->fast_rx, true); - rcu_assign_pointer(sta->fast_rx, new); -@@ -4357,6 +4370,108 @@ void ieee80211_check_fast_rx_iface(struc - mutex_unlock(&local->sta_mtx); - } - -+static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, -+ struct ieee80211_fast_rx *fast_rx, -+ int orig_len) -+{ -+ struct ieee80211_sta_rx_stats *stats; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ struct sta_info *sta = rx->sta; -+ struct sk_buff *skb = rx->skb; -+ void *sa = skb->data + ETH_ALEN; -+ void *da = skb->data; -+ -+ stats = &sta->rx_stats; -+ if (fast_rx->uses_rss) -+ stats = this_cpu_ptr(sta->pcpu_rx_stats); -+ -+ /* statistics part of ieee80211_rx_h_sta_process() */ -+ if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { -+ stats->last_signal = status->signal; -+ if (!fast_rx->uses_rss) -+ ewma_signal_add(&sta->rx_stats_avg.signal, -+ -status->signal); -+ } -+ -+ if (status->chains) { -+ int i; -+ -+ stats->chains = status->chains; -+ for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { -+ int signal = status->chain_signal[i]; -+ -+ if (!(status->chains & BIT(i))) -+ continue; -+ -+ stats->chain_signal_last[i] = signal; -+ if (!fast_rx->uses_rss) -+ ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], -+ -signal); -+ } -+ } -+ /* end of statistics */ -+ -+ stats->last_rx = jiffies; -+ stats->last_rate = sta_stats_encode_rate(status); -+ -+ stats->fragments++; -+ stats->packets++; -+ -+ skb->dev = fast_rx->dev; -+ -+ ieee80211_rx_stats(fast_rx->dev, skb->len); -+ -+ /* The seqno index has the same property as needed -+ * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS -+ * for non-QoS-data frames. Here we know it's a data -+ * frame, so count MSDUs. -+ */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->msdu[rx->seqno_idx]++; -+ stats->bytes += orig_len; -+ u64_stats_update_end(&stats->syncp); -+ -+ if (fast_rx->internal_forward) { -+ struct sk_buff *xmit_skb = NULL; -+ if (is_multicast_ether_addr(da)) { -+ xmit_skb = skb_copy(skb, GFP_ATOMIC); -+ } else if (!ether_addr_equal(da, sa) && -+ sta_info_get(rx->sdata, da)) { -+ xmit_skb = skb; -+ skb = NULL; -+ } -+ -+ if (xmit_skb) { -+ /* -+ * Send to wireless media and increase priority by 256 -+ * to keep the received priority instead of -+ * reclassifying the frame (see cfg80211_classify8021d). -+ */ -+ xmit_skb->priority += 256; -+ xmit_skb->protocol = htons(ETH_P_802_3); -+ skb_reset_network_header(xmit_skb); -+ skb_reset_mac_header(xmit_skb); -+ dev_queue_xmit(xmit_skb); -+ } -+ -+ if (!skb) -+ return; -+ } -+ -+ /* deliver to local stack */ -+ skb->protocol = eth_type_trans(skb, fast_rx->dev); -+ memset(skb->cb, 0, sizeof(skb->cb)); -+ if (rx->list) -+#if LINUX_VERSION_IS_GEQ(4,19,0) -+ list_add_tail(&skb->list, rx->list); -+#else -+ __skb_queue_tail(rx->list, skb); -+#endif -+ else -+ netif_receive_skb(skb); -+ -+} -+ - static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, - struct ieee80211_fast_rx *fast_rx) - { -@@ -4377,9 +4492,6 @@ static bool ieee80211_invoke_fast_rx(str - } addrs __aligned(2); - struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; - -- if (fast_rx->uses_rss) -- stats = this_cpu_ptr(sta->pcpu_rx_stats); -- - /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write - * to a common data structure; drivers can implement that per queue - * but we don't have that information in mac80211 -@@ -4453,32 +4565,6 @@ static bool ieee80211_invoke_fast_rx(str - pskb_trim(skb, skb->len - fast_rx->icv_len)) - goto drop; - -- /* statistics part of ieee80211_rx_h_sta_process() */ -- if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { -- stats->last_signal = status->signal; -- if (!fast_rx->uses_rss) -- ewma_signal_add(&sta->rx_stats_avg.signal, -- -status->signal); -- } -- -- if (status->chains) { -- int i; -- -- stats->chains = status->chains; -- for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { -- int signal = status->chain_signal[i]; -- -- if (!(status->chains & BIT(i))) -- continue; -- -- stats->chain_signal_last[i] = signal; -- if (!fast_rx->uses_rss) -- ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], -- -signal); -- } -- } -- /* end of statistics */ -- - if (rx->key && !ieee80211_has_protected(hdr->frame_control)) - goto drop; - -@@ -4490,12 +4576,6 @@ static bool ieee80211_invoke_fast_rx(str - return true; - } - -- stats->last_rx = jiffies; -- stats->last_rate = sta_stats_encode_rate(status); -- -- stats->fragments++; -- stats->packets++; -- - /* do the header conversion - first grab the addresses */ - ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs); - ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); -@@ -4504,62 +4584,14 @@ static bool ieee80211_invoke_fast_rx(str - /* push the addresses in front */ - memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); - -- skb->dev = fast_rx->dev; -- -- ieee80211_rx_stats(fast_rx->dev, skb->len); -- -- /* The seqno index has the same property as needed -- * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS -- * for non-QoS-data frames. Here we know it's a data -- * frame, so count MSDUs. -- */ -- u64_stats_update_begin(&stats->syncp); -- stats->msdu[rx->seqno_idx]++; -- stats->bytes += orig_len; -- u64_stats_update_end(&stats->syncp); -- -- if (fast_rx->internal_forward) { -- struct sk_buff *xmit_skb = NULL; -- if (is_multicast_ether_addr(addrs.da)) { -- xmit_skb = skb_copy(skb, GFP_ATOMIC); -- } else if (!ether_addr_equal(addrs.da, addrs.sa) && -- sta_info_get(rx->sdata, addrs.da)) { -- xmit_skb = skb; -- skb = NULL; -- } -- -- if (xmit_skb) { -- /* -- * Send to wireless media and increase priority by 256 -- * to keep the received priority instead of -- * reclassifying the frame (see cfg80211_classify8021d). -- */ -- xmit_skb->priority += 256; -- xmit_skb->protocol = htons(ETH_P_802_3); -- skb_reset_network_header(xmit_skb); -- skb_reset_mac_header(xmit_skb); -- dev_queue_xmit(xmit_skb); -- } -- -- if (!skb) -- return true; -- } -- -- /* deliver to local stack */ -- skb->protocol = eth_type_trans(skb, fast_rx->dev); -- memset(skb->cb, 0, sizeof(skb->cb)); -- if (rx->list) --#if LINUX_VERSION_IS_GEQ(4,19,0) -- list_add_tail(&skb->list, rx->list); --#else -- __skb_queue_tail(rx->list, skb); --#endif -- else -- netif_receive_skb(skb); -+ ieee80211_rx_8023(rx, fast_rx, orig_len); - - return true; - drop: - dev_kfree_skb(skb); -+ if (fast_rx->uses_rss) -+ stats = this_cpu_ptr(sta->pcpu_rx_stats); -+ - stats->dropped++; - return true; - } -@@ -4613,6 +4645,47 @@ static bool ieee80211_prepare_and_rx_han - return true; - } - -+static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw, -+ struct ieee80211_sta *pubsta, -+ struct sk_buff *skb, -+#if LINUX_VERSION_IS_GEQ(4,19,0) -+ struct list_head *list) -+#else -+ struct sk_buff_head *list) -+#endif -+{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ struct ieee80211_fast_rx *fast_rx; -+ struct ieee80211_rx_data rx; -+ -+ memset(&rx, 0, sizeof(rx)); -+ rx.skb = skb; -+ rx.local = local; -+ rx.list = list; -+ -+ I802_DEBUG_INC(local->dot11ReceivedFragmentCount); -+ -+ /* drop frame if too short for header */ -+ if (skb->len < sizeof(struct ethhdr)) -+ goto drop; -+ -+ if (!pubsta) -+ goto drop; -+ -+ rx.sta = container_of(pubsta, struct sta_info, sta); -+ rx.sdata = rx.sta->sdata; -+ -+ fast_rx = rcu_dereference(rx.sta->fast_rx); -+ if (!fast_rx) -+ goto drop; -+ -+ ieee80211_rx_8023(&rx, fast_rx, skb->len); -+ return; -+ -+drop: -+ dev_kfree_skb(skb); -+} -+ - /* - * This is the actual Rx frames handler. as it belongs to Rx path it must - * be called with rcu_read_lock protection. -@@ -4850,15 +4923,20 @@ void ieee80211_rx_list(struct ieee80211_ - * if it was previously present. - * Also, frames with less than 16 bytes are dropped. - */ -- skb = ieee80211_rx_monitor(local, skb, rate); -- if (!skb) -- return; -+ if (!(status->flag & RX_FLAG_8023)) { -+ skb = ieee80211_rx_monitor(local, skb, rate); -+ if (!skb) -+ return; -+ } - - ieee80211_tpt_led_trig_rx(local, - ((struct ieee80211_hdr *)skb->data)->frame_control, - skb->len); - -- __ieee80211_rx_handle_packet(hw, pubsta, skb, list); -+ if (status->flag & RX_FLAG_8023) -+ __ieee80211_rx_handle_8023(hw, pubsta, skb, list); -+ else -+ __ieee80211_rx_handle_packet(hw, pubsta, skb, list); - - return; - drop: ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -71,6 +71,7 @@ - * until pending frames are delivered - * @WLAN_STA_USES_ENCRYPTION: This station was configured for encryption, - * so drop all packets without a key later. -+ * @WLAN_STA_DECAP_OFFLOAD: This station uses rx decap offload - * - * @NUM_WLAN_STA_FLAGS: number of defined flags - */ -@@ -102,6 +103,7 @@ enum ieee80211_sta_info_flags { - WLAN_STA_MPSP_RECIPIENT, - WLAN_STA_PS_DELIVER, - WLAN_STA_USES_ENCRYPTION, -+ WLAN_STA_DECAP_OFFLOAD, - - NUM_WLAN_STA_FLAGS, - }; ---- a/net/mac80211/trace.h -+++ b/net/mac80211/trace.h -@@ -2761,7 +2761,7 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u - TP_ARGS(local, sdata) - ); - --TRACE_EVENT(drv_sta_set_4addr, -+DECLARE_EVENT_CLASS(sta_flag_evt, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, bool enabled), -@@ -2788,6 +2788,22 @@ TRACE_EVENT(drv_sta_set_4addr, - ) - ); - -+DEFINE_EVENT(sta_flag_evt, drv_sta_set_4addr, -+ TP_PROTO(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_sta *sta, bool enabled), -+ -+ TP_ARGS(local, sdata, sta, enabled) -+); -+ -+DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload, -+ TP_PROTO(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_sta *sta, bool enabled), -+ -+ TP_ARGS(local, sdata, sta, enabled) -+); -+ - #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ - - #undef TRACE_INCLUDE_PATH diff --git a/package/kernel/mac80211/patches/subsys/316-cfg80211-fix-possible-NULL-pointer-dereference-in-cf.patch b/package/kernel/mac80211/patches/subsys/316-cfg80211-fix-possible-NULL-pointer-dereference-in-cf.patch new file mode 100644 index 000000000..362bb885d --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/316-cfg80211-fix-possible-NULL-pointer-dereference-in-cf.patch @@ -0,0 +1,99 @@ +From: Lorenzo Bianconi +Date: Wed, 3 Nov 2021 18:02:35 +0100 +Subject: [PATCH] cfg80211: fix possible NULL pointer dereference in + cfg80211_stop_offchan_radar_detection + +Fix the following NULL pointer dereference in +cfg80211_stop_offchan_radar_detection routine that occurs when hostapd +is stopped during the CAC on offchannel chain: + +Sat Jan 1 0[ 779.567851] ESR = 0x96000005 +0:12:50 2000 dae[ 779.572346] EC = 0x25: DABT (current EL), IL = 32 bits +mon.debug hostap[ 779.578984] SET = 0, FnV = 0 +d: hostapd_inter[ 779.583445] EA = 0, S1PTW = 0 +face_deinit_free[ 779.587936] Data abort info: +: num_bss=1 conf[ 779.592224] ISV = 0, ISS = 0x00000005 +->num_bss=1 +Sat[ 779.597403] CM = 0, WnR = 0 + Jan 1 00:12:50[ 779.601749] user pgtable: 4k pages, 39-bit VAs, pgdp=00000000418b2000 + 2000 daemon.deb[ 779.609601] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 +ug hostapd: host[ 779.619657] Internal error: Oops: 96000005 [#1] SMP +[ 779.770810] CPU: 0 PID: 2202 Comm: hostapd Not tainted 5.10.75 #0 +[ 779.776892] Hardware name: MediaTek MT7622 RFB1 board (DT) +[ 779.782370] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO BTYPE=--) +[ 779.788384] pc : cfg80211_chandef_valid+0x10/0x490 [cfg80211] +[ 779.794128] lr : cfg80211_check_station_change+0x3190/0x3950 [cfg80211] +[ 779.800731] sp : ffffffc01204b7e0 +[ 779.804036] x29: ffffffc01204b7e0 x28: ffffff80039bdc00 +[ 779.809340] x27: 0000000000000000 x26: ffffffc008cb3050 +[ 779.814644] x25: 0000000000000000 x24: 0000000000000002 +[ 779.819948] x23: ffffff8002630000 x22: ffffff8003e748d0 +[ 779.825252] x21: 0000000000000cc0 x20: ffffff8003da4a00 +[ 779.830556] x19: 0000000000000000 x18: ffffff8001bf7ce0 +[ 779.835860] x17: 00000000ffffffff x16: 0000000000000000 +[ 779.841164] x15: 0000000040d59200 x14: 00000000000019c0 +[ 779.846467] x13: 00000000000001c8 x12: 000636b9e9dab1c6 +[ 779.851771] x11: 0000000000000141 x10: 0000000000000820 +[ 779.857076] x9 : 0000000000000000 x8 : ffffff8003d7d038 +[ 779.862380] x7 : 0000000000000000 x6 : ffffff8003d7d038 +[ 779.867683] x5 : 0000000000000e90 x4 : 0000000000000038 +[ 779.872987] x3 : 0000000000000002 x2 : 0000000000000004 +[ 779.878291] x1 : 0000000000000000 x0 : 0000000000000000 +[ 779.883594] Call trace: +[ 779.886039] cfg80211_chandef_valid+0x10/0x490 [cfg80211] +[ 779.891434] cfg80211_check_station_change+0x3190/0x3950 [cfg80211] +[ 779.897697] nl80211_radar_notify+0x138/0x19c [cfg80211] +[ 779.903005] cfg80211_stop_offchan_radar_detection+0x7c/0x8c [cfg80211] +[ 779.909616] __cfg80211_leave+0x2c/0x190 [cfg80211] +[ 779.914490] cfg80211_register_netdevice+0x1c0/0x6d0 [cfg80211] +[ 779.920404] raw_notifier_call_chain+0x50/0x70 +[ 779.924841] call_netdevice_notifiers_info+0x54/0xa0 +[ 779.929796] __dev_close_many+0x40/0x100 +[ 779.933712] __dev_change_flags+0x98/0x190 +[ 779.937800] dev_change_flags+0x20/0x60 +[ 779.941628] devinet_ioctl+0x534/0x6d0 +[ 779.945370] inet_ioctl+0x1bc/0x230 +[ 779.948849] sock_do_ioctl+0x44/0x200 +[ 779.952502] sock_ioctl+0x268/0x4c0 +[ 779.955985] __arm64_sys_ioctl+0xac/0xd0 +[ 779.959900] el0_svc_common.constprop.0+0x60/0x110 +[ 779.964682] do_el0_svc+0x1c/0x24 +[ 779.967990] el0_svc+0x10/0x1c +[ 779.971036] el0_sync_handler+0x9c/0x120 +[ 779.974950] el0_sync+0x148/0x180 +[ 779.978259] Code: a9bc7bfd 910003fd a90153f3 aa0003f3 (f9400000) +[ 779.984344] ---[ end trace 0e67b4f5d6cdeec7 ]--- +[ 779.996400] Kernel panic - not syncing: Oops: Fatal exception +[ 780.002139] SMP: stopping secondary CPUs +[ 780.006057] Kernel Offset: disabled +[ 780.009537] CPU features: 0x0000002,04002004 +[ 780.013796] Memory Limit: none + +Fixes: b8f5facf286b ("cfg80211: implement APIs for dedicated radar detection HW") +Reported-by: Evelyn Tsai +Tested-by: Evelyn Tsai +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/c2e34c065bf8839c5ffa45498ae154021a72a520.1635958796.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -982,6 +982,9 @@ __cfg80211_offchan_cac_event(struct cfg8 + + lockdep_assert_wiphy(&rdev->wiphy); + ++ if (!cfg80211_chandef_valid(chandef)) ++ return; ++ + if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev) + return; + +@@ -1096,6 +1099,6 @@ void cfg80211_stop_offchan_radar_detecti + + rdev_set_radar_offchan(rdev, NULL); + +- __cfg80211_offchan_cac_event(rdev, NULL, NULL, ++ __cfg80211_offchan_cac_event(rdev, wdev, &rdev->offchan_radar_chandef, + NL80211_RADAR_CAC_ABORTED); + } diff --git a/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch b/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch deleted file mode 100644 index 4be011ffe..000000000 --- a/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch +++ /dev/null @@ -1,116 +0,0 @@ -From: Markus Theil -Date: Sat, 6 Feb 2021 12:51:12 +0100 -Subject: [PATCH] mac80211: enable QoS support for nl80211 ctrl port - -This patch unifies sending control port frames -over nl80211 and AF_PACKET sockets a little more. - -Before this patch, EAPOL frames got QoS prioritization -only when using AF_PACKET sockets. - -__ieee80211_select_queue only selects a QoS-enabled queue -for control port frames, when the control port protocol -is set correctly on the skb. For the AF_PACKET path this -works, but the nl80211 path used ETH_P_802_3. - -Another check for injected frames in wme.c then prevented -the QoS TID to be copied in the frame. - -In order to fix this, get rid of the frame injection marking -for nl80211 ctrl port and set the correct ethernet protocol. - -Please note: -An erlier version of this path tried to prevent -frame aggregation for control port frames in order to speed up -the initial connection setup a little. This seemed to cause -issues on my older Intel dvm-based hardware, and was therefore -removed again. Future commits which try to reintroduce this -have to check carefully how hw behaves with aggregated and -non-aggregated traffic for the same TID. -My NIC: Intel(R) Centrino(R) Ultimate-N 6300 AGN, REV=0x74 - -Reported-by: kernel test robot -Signed-off-by: Markus Theil -Link: https://lore.kernel.org/r/20210206115112.567881-1-markus.theil@tu-ilmenau.de -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -628,16 +628,12 @@ static void ieee80211_report_ack_skb(str - u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_hdr *hdr = (void *)skb->data; -- __be16 ethertype = 0; -- -- if (skb->len >= ETH_HLEN && skb->protocol == cpu_to_be16(ETH_P_802_3)) -- skb_copy_bits(skb, 2 * ETH_ALEN, ðertype, ETH_TLEN); - - rcu_read_lock(); - sdata = ieee80211_sdata_from_skb(local, skb); - if (sdata) { -- if (ethertype == sdata->control_port_protocol || -- ethertype == cpu_to_be16(ETH_P_PREAUTH)) -+ if (skb->protocol == sdata->control_port_protocol || -+ skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) - cfg80211_control_port_tx_status(&sdata->wdev, - cookie, - skb->data, ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1195,9 +1195,7 @@ ieee80211_tx_prepare(struct ieee80211_su - tx->sta = rcu_dereference(sdata->u.vlan.sta); - if (!tx->sta && sdata->wdev.use_4addr) - return TX_DROP; -- } else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX | -- IEEE80211_TX_CTL_INJECTED) || -- tx->sdata->control_port_protocol == tx->skb->protocol) { -+ } else if (tx->sdata->control_port_protocol == tx->skb->protocol) { - tx->sta = sta_info_get_bss(sdata, hdr->addr1); - } - if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) -@@ -5421,6 +5419,7 @@ int ieee80211_tx_control_port(struct wip - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; -+ struct sta_info *sta; - struct sk_buff *skb; - struct ethhdr *ehdr; - u32 ctrl_flags = 0; -@@ -5443,8 +5442,7 @@ int ieee80211_tx_control_port(struct wip - if (cookie) - ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - -- flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX | -- IEEE80211_TX_CTL_INJECTED; -+ flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(struct ethhdr) + len); -@@ -5461,10 +5459,25 @@ int ieee80211_tx_control_port(struct wip - ehdr->h_proto = proto; - - skb->dev = dev; -- skb->protocol = htons(ETH_P_802_3); -+ skb->protocol = proto; - skb_reset_network_header(skb); - skb_reset_mac_header(skb); - -+ /* update QoS header to prioritize control port frames if possible, -+ * priorization also happens for control port frames send over -+ * AF_PACKET -+ */ -+ rcu_read_lock(); -+ -+ if (ieee80211_lookup_ra_sta(sdata, skb, &sta) == 0 && !IS_ERR(sta)) { -+ u16 queue = __ieee80211_select_queue(sdata, sta, skb); -+ -+ skb_set_queue_mapping(skb, queue); -+ skb_get_hash(skb); -+ } -+ -+ rcu_read_unlock(); -+ - /* mutex lock is only needed for incrementing the cookie counter */ - mutex_lock(&local->mtx); - diff --git a/package/kernel/mac80211/patches/subsys/317-cfg80211-schedule-offchan_cac_abort_wk-in-cfg80211_r.patch b/package/kernel/mac80211/patches/subsys/317-cfg80211-schedule-offchan_cac_abort_wk-in-cfg80211_r.patch new file mode 100644 index 000000000..df7afefb3 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/317-cfg80211-schedule-offchan_cac_abort_wk-in-cfg80211_r.patch @@ -0,0 +1,136 @@ +From: Lorenzo Bianconi +Date: Tue, 16 Nov 2021 12:41:52 +0100 +Subject: [PATCH] cfg80211: schedule offchan_cac_abort_wk in + cfg80211_radar_event + +If necessary schedule offchan_cac_abort_wk work in cfg80211_radar_event +routine adding offchan parameter to cfg80211_radar_event signature. +Rename cfg80211_radar_event in __cfg80211_radar_event and introduce +the two following inline helpers: +- cfg80211_radar_event +- cfg80211_offchan_radar_event +Doing so the drv will not need to run cfg80211_offchan_cac_abort() after +radar detection on the offchannel chain. + +Tested-by: Owen Peng +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/3ff583e021e3343a3ced54a7b09b5e184d1880dc.1637062727.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -7580,15 +7580,33 @@ void cfg80211_cqm_txe_notify(struct net_ + void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp); + + /** +- * cfg80211_radar_event - radar detection event ++ * __cfg80211_radar_event - radar detection event + * @wiphy: the wiphy + * @chandef: chandef for the current channel ++ * @offchan: the radar has been detected on the offchannel chain + * @gfp: context flags + * + * This function is called when a radar is detected on the current chanenl. + */ +-void cfg80211_radar_event(struct wiphy *wiphy, +- struct cfg80211_chan_def *chandef, gfp_t gfp); ++void __cfg80211_radar_event(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef, ++ bool offchan, gfp_t gfp); ++ ++static inline void ++cfg80211_radar_event(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp) ++{ ++ __cfg80211_radar_event(wiphy, chandef, false, gfp); ++} ++ ++static inline void ++cfg80211_offchan_radar_event(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp) ++{ ++ __cfg80211_radar_event(wiphy, chandef, true, gfp); ++} + + /** + * cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -905,13 +905,13 @@ void cfg80211_dfs_channels_update_work(s + } + + +-void cfg80211_radar_event(struct wiphy *wiphy, +- struct cfg80211_chan_def *chandef, +- gfp_t gfp) ++void __cfg80211_radar_event(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef, ++ bool offchan, gfp_t gfp) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + +- trace_cfg80211_radar_event(wiphy, chandef); ++ trace_cfg80211_radar_event(wiphy, chandef, offchan); + + /* only set the chandef supplied channel to unavailable, in + * case the radar is detected on only one of multiple channels +@@ -919,6 +919,9 @@ void cfg80211_radar_event(struct wiphy * + */ + cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE); + ++ if (offchan) ++ queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk); ++ + cfg80211_sched_dfs_chan_update(rdev); + + nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp); +@@ -926,7 +929,7 @@ void cfg80211_radar_event(struct wiphy * + memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def)); + queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk); + } +-EXPORT_SYMBOL(cfg80211_radar_event); ++EXPORT_SYMBOL(__cfg80211_radar_event); + + void cfg80211_cac_event(struct net_device *netdev, + const struct cfg80211_chan_def *chandef, +@@ -998,7 +1001,8 @@ __cfg80211_offchan_cac_event(struct cfg8 + rdev->offchan_radar_wdev = NULL; + break; + case NL80211_RADAR_CAC_ABORTED: +- cancel_delayed_work(&rdev->offchan_cac_done_wk); ++ if (!cancel_delayed_work(&rdev->offchan_cac_done_wk)) ++ return; + wdev = rdev->offchan_radar_wdev; + rdev->offchan_radar_wdev = NULL; + break; +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -3022,18 +3022,21 @@ TRACE_EVENT(cfg80211_ch_switch_started_n + ); + + TRACE_EVENT(cfg80211_radar_event, +- TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), +- TP_ARGS(wiphy, chandef), ++ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, ++ bool offchan), ++ TP_ARGS(wiphy, chandef, offchan), + TP_STRUCT__entry( + WIPHY_ENTRY + CHAN_DEF_ENTRY ++ __field(bool, offchan) + ), + TP_fast_assign( + WIPHY_ASSIGN; + CHAN_DEF_ASSIGN(chandef); ++ __entry->offchan = offchan; + ), +- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, +- WIPHY_PR_ARG, CHAN_DEF_PR_ARG) ++ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", offchan %d", ++ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->offchan) + ); + + TRACE_EVENT(cfg80211_cac_event, diff --git a/package/kernel/mac80211/patches/subsys/318-cfg80211-allow-continuous-radar-monitoring-on-offcha.patch b/package/kernel/mac80211/patches/subsys/318-cfg80211-allow-continuous-radar-monitoring-on-offcha.patch new file mode 100644 index 000000000..ae97947fa --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/318-cfg80211-allow-continuous-radar-monitoring-on-offcha.patch @@ -0,0 +1,220 @@ +From: Lorenzo Bianconi +Date: Tue, 16 Nov 2021 15:03:36 +0100 +Subject: [PATCH] cfg80211: allow continuous radar monitoring on offchannel + chain + +Allow continuous radar detection on the offchannel chain in order +to switch to the monitored channel whenever the underlying driver +reports a radar pattern on the main channel. + +Tested-by: Owen Peng +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/d46217310a49b14ff0e9c002f0a6e0547d70fd2c.1637071350.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -712,6 +712,19 @@ static bool cfg80211_is_wiphy_oper_chan( + return false; + } + ++static bool ++cfg80211_offchan_chain_is_active(struct cfg80211_registered_device *rdev, ++ struct ieee80211_channel *channel) ++{ ++ if (!rdev->offchan_radar_wdev) ++ return false; ++ ++ if (!cfg80211_chandef_valid(&rdev->offchan_radar_chandef)) ++ return false; ++ ++ return cfg80211_is_sub_chan(&rdev->offchan_radar_chandef, channel); ++} ++ + bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) + { +@@ -728,6 +741,9 @@ bool cfg80211_any_wiphy_oper_chan(struct + + if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan)) + return true; ++ ++ if (cfg80211_offchan_chain_is_active(rdev, chan)) ++ return true; + } + + return false; +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -988,7 +988,7 @@ __cfg80211_offchan_cac_event(struct cfg8 + if (!cfg80211_chandef_valid(chandef)) + return; + +- if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev) ++ if (!rdev->offchan_radar_wdev) + return; + + switch (event) { +@@ -998,17 +998,13 @@ __cfg80211_offchan_cac_event(struct cfg8 + queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); + cfg80211_sched_dfs_chan_update(rdev); + wdev = rdev->offchan_radar_wdev; +- rdev->offchan_radar_wdev = NULL; + break; + case NL80211_RADAR_CAC_ABORTED: + if (!cancel_delayed_work(&rdev->offchan_cac_done_wk)) + return; + wdev = rdev->offchan_radar_wdev; +- rdev->offchan_radar_wdev = NULL; + break; + case NL80211_RADAR_CAC_STARTED: +- WARN_ON(!wdev); +- rdev->offchan_radar_wdev = wdev; + break; + default: + return; +@@ -1024,7 +1020,8 @@ cfg80211_offchan_cac_event(struct cfg802 + enum nl80211_radar_event event) + { + wiphy_lock(&rdev->wiphy); +- __cfg80211_offchan_cac_event(rdev, NULL, chandef, event); ++ __cfg80211_offchan_cac_event(rdev, rdev->offchan_radar_wdev, ++ chandef, event); + wiphy_unlock(&rdev->wiphy); + } + +@@ -1071,7 +1068,13 @@ cfg80211_start_offchan_radar_detection(s + NL80211_EXT_FEATURE_RADAR_OFFCHAN)) + return -EOPNOTSUPP; + +- if (rdev->offchan_radar_wdev) ++ /* Offchannel chain already locked by another wdev */ ++ if (rdev->offchan_radar_wdev && rdev->offchan_radar_wdev != wdev) ++ return -EBUSY; ++ ++ /* CAC already in progress on the offchannel chain */ ++ if (rdev->offchan_radar_wdev == wdev && ++ delayed_work_pending(&rdev->offchan_cac_done_wk)) + return -EBUSY; + + err = rdev_set_radar_offchan(rdev, chandef); +@@ -1083,6 +1086,8 @@ cfg80211_start_offchan_radar_detection(s + cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; + + rdev->offchan_radar_chandef = *chandef; ++ rdev->offchan_radar_wdev = wdev; /* Get offchain ownership */ ++ + __cfg80211_offchan_cac_event(rdev, wdev, chandef, + NL80211_RADAR_CAC_STARTED); + queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_done_wk, +@@ -1102,6 +1107,7 @@ void cfg80211_stop_offchan_radar_detecti + return; + + rdev_set_radar_offchan(rdev, NULL); ++ rdev->offchan_radar_wdev = NULL; /* Release offchain ownership */ + + __cfg80211_offchan_cac_event(rdev, wdev, &rdev->offchan_radar_chandef, + NL80211_RADAR_CAC_ABORTED); +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9260,42 +9260,60 @@ static int nl80211_start_radar_detection + struct cfg80211_chan_def chandef; + enum nl80211_dfs_regions dfs_region; + unsigned int cac_time_ms; +- int err; ++ int err = -EINVAL; ++ ++ flush_delayed_work(&rdev->dfs_update_channels_wk); ++ ++ wiphy_lock(wiphy); + + dfs_region = reg_get_dfs_region(wiphy); + if (dfs_region == NL80211_DFS_UNSET) +- return -EINVAL; ++ goto unlock; + + err = nl80211_parse_chandef(rdev, info, &chandef); + if (err) +- return err; ++ goto unlock; + + err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype); + if (err < 0) +- return err; ++ goto unlock; + +- if (err == 0) +- return -EINVAL; ++ if (err == 0) { ++ err = -EINVAL; ++ goto unlock; ++ } + +- if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) +- return -EINVAL; ++ if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) { ++ err = -EINVAL; ++ goto unlock; ++ } + +- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN])) +- return cfg80211_start_offchan_radar_detection(rdev, wdev, +- &chandef); ++ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN])) { ++ err = cfg80211_start_offchan_radar_detection(rdev, wdev, ++ &chandef); ++ goto unlock; ++ } + +- if (netif_carrier_ok(dev)) +- return -EBUSY; ++ if (netif_carrier_ok(dev)) { ++ err = -EBUSY; ++ goto unlock; ++ } + +- if (wdev->cac_started) +- return -EBUSY; ++ if (wdev->cac_started) { ++ err = -EBUSY; ++ goto unlock; ++ } + + /* CAC start is offloaded to HW and can't be started manually */ +- if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) +- return -EOPNOTSUPP; ++ if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) { ++ err = -EOPNOTSUPP; ++ goto unlock; ++ } + +- if (!rdev->ops->start_radar_detection) +- return -EOPNOTSUPP; ++ if (!rdev->ops->start_radar_detection) { ++ err = -EOPNOTSUPP; ++ goto unlock; ++ } + + cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef); + if (WARN_ON(!cac_time_ms)) +@@ -9308,6 +9326,9 @@ static int nl80211_start_radar_detection + wdev->cac_start_time = jiffies; + wdev->cac_time_ms = cac_time_ms; + } ++unlock: ++ wiphy_unlock(wiphy); ++ + return err; + } + +@@ -15926,7 +15947,8 @@ static const struct genl_small_ops nl802 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = nl80211_start_radar_detection, + .flags = GENL_UNS_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NO_WIPHY_MTX, + }, + { + .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, diff --git a/package/kernel/mac80211/patches/subsys/319-mac80211-introduce-set_radar_offchan-callback.patch b/package/kernel/mac80211/patches/subsys/319-mac80211-introduce-set_radar_offchan-callback.patch new file mode 100644 index 000000000..eb80afbcc --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/319-mac80211-introduce-set_radar_offchan-callback.patch @@ -0,0 +1,67 @@ +From: Lorenzo Bianconi +Date: Sat, 23 Oct 2021 11:10:51 +0200 +Subject: [PATCH] mac80211: introduce set_radar_offchan callback + +Similar to cfg80211, introduce set_radar_offchan callback in mac80211_ops +in order to configure a dedicated offchannel chain available on some hw +(e.g. mt7915) to perform offchannel CAC detection and avoid tx/rx downtime. + +Tested-by: Evelyn Tsai +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/201110606d4f3a7dfdf31440e351f2e2c375d4f0.1634979655.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3937,6 +3937,14 @@ struct ieee80211_prep_tx_info { + * twt structure. + * @twt_teardown_request: Update the hw with TWT teardown request received + * from the peer. ++ * @set_radar_offchan: Configure dedicated offchannel chain available for ++ * radar/CAC detection on some hw. This chain can't be used to transmit ++ * or receive frames and it is bounded to a running wdev. ++ * Offchannel radar/CAC detection allows to avoid the CAC downtime ++ * switching to a different channel during CAC detection on the selected ++ * radar channel. ++ * The caller is expected to set chandef pointer to NULL in order to ++ * disable offchannel CAC/radar detection. + * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to + * resolve a path for hardware flow offloading + */ +@@ -4267,6 +4275,8 @@ struct ieee80211_ops { + struct ieee80211_twt_setup *twt); + void (*twt_teardown_request)(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 flowid); ++ int (*set_radar_offchan)(struct ieee80211_hw *hw, ++ struct cfg80211_chan_def *chandef); + #if LINUX_VERSION_IS_GEQ(5,10,0) + int (*net_fill_forward_path)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4344,6 +4344,18 @@ out: + return err; + } + ++static int ++ieee80211_set_radar_offchan(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct ieee80211_local *local = wiphy_priv(wiphy); ++ ++ if (!local->ops->set_radar_offchan) ++ return -EOPNOTSUPP; ++ ++ return local->ops->set_radar_offchan(&local->hw, chandef); ++} ++ + const struct cfg80211_ops mac80211_config_ops = { + .add_virtual_intf = ieee80211_add_iface, + .del_virtual_intf = ieee80211_del_iface, +@@ -4448,4 +4460,5 @@ const struct cfg80211_ops mac80211_confi + .reset_tid_config = ieee80211_reset_tid_config, + .set_sar_specs = ieee80211_set_sar_specs, + .color_change = ieee80211_color_change, ++ .set_radar_offchan = ieee80211_set_radar_offchan, + }; diff --git a/package/kernel/mac80211/patches/subsys/320-cfg80211-rename-offchannel_chain-structs-to-backgrou.patch b/package/kernel/mac80211/patches/subsys/320-cfg80211-rename-offchannel_chain-structs-to-backgrou.patch new file mode 100644 index 000000000..a73e81bec --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/320-cfg80211-rename-offchannel_chain-structs-to-backgrou.patch @@ -0,0 +1,532 @@ +From: Lorenzo Bianconi +Date: Mon, 29 Nov 2021 14:11:24 +0100 +Subject: [PATCH] cfg80211: rename offchannel_chain structs to background_chain + to avoid confusion with ETSI standard + +ETSI standard defines "Offchannel CAC" as: +"Off-Channel CAC is performed by a number of non-continuous checks +spread over a period in time. This period, which is required to +determine the presence of radar signals, is defined as the Off-Channel +CAC Time.. +Minimum Off-Channel CAC Time 6 minutes and Maximum Off-Channel CAC Time +4 hours..". +mac80211 implementation refers to a dedicated hw chain used for continuous +radar monitoring. Rename offchannel_* references to background_* in +order to avoid confusion with ETSI standard. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/4204cc1d648d76b44557981713231e030a3bd991.1638190762.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4058,14 +4058,14 @@ struct mgmt_frame_regs { + * + * @color_change: Initiate a color change. + * +- * @set_radar_offchan: Configure dedicated offchannel chain available for ++ * @set_radar_background: Configure dedicated offchannel chain available for + * radar/CAC detection on some hw. This chain can't be used to transmit + * or receive frames and it is bounded to a running wdev. +- * Offchannel radar/CAC detection allows to avoid the CAC downtime ++ * Background radar/CAC detection allows to avoid the CAC downtime + * switching to a different channel during CAC detection on the selected + * radar channel. + * The caller is expected to set chandef pointer to NULL in order to +- * disable offchannel CAC/radar detection. ++ * disable background CAC/radar detection. + */ + struct cfg80211_ops { + int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); +@@ -4396,8 +4396,8 @@ struct cfg80211_ops { + int (*color_change)(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_color_change_settings *params); +- int (*set_radar_offchan)(struct wiphy *wiphy, +- struct cfg80211_chan_def *chandef); ++ int (*set_radar_background)(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); + }; + + /* +@@ -7601,9 +7601,9 @@ cfg80211_radar_event(struct wiphy *wiphy + } + + static inline void +-cfg80211_offchan_radar_event(struct wiphy *wiphy, +- struct cfg80211_chan_def *chandef, +- gfp_t gfp) ++cfg80211_background_radar_event(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp) + { + __cfg80211_radar_event(wiphy, chandef, true, gfp); + } +@@ -7638,13 +7638,13 @@ void cfg80211_cac_event(struct net_devic + enum nl80211_radar_event event, gfp_t gfp); + + /** +- * cfg80211_offchan_cac_abort - Channel Availability Check offchan abort event ++ * cfg80211_background_cac_abort - Channel Availability Check offchan abort event + * @wiphy: the wiphy + * + * This function is called by the driver when a Channel Availability Check + * (CAC) is aborted by a offchannel dedicated chain. + */ +-void cfg80211_offchan_cac_abort(struct wiphy *wiphy); ++void cfg80211_background_cac_abort(struct wiphy *wiphy); + + /** + * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3937,14 +3937,14 @@ struct ieee80211_prep_tx_info { + * twt structure. + * @twt_teardown_request: Update the hw with TWT teardown request received + * from the peer. +- * @set_radar_offchan: Configure dedicated offchannel chain available for ++ * @set_radar_background: Configure dedicated offchannel chain available for + * radar/CAC detection on some hw. This chain can't be used to transmit + * or receive frames and it is bounded to a running wdev. +- * Offchannel radar/CAC detection allows to avoid the CAC downtime ++ * Background radar/CAC detection allows to avoid the CAC downtime + * switching to a different channel during CAC detection on the selected + * radar channel. + * The caller is expected to set chandef pointer to NULL in order to +- * disable offchannel CAC/radar detection. ++ * disable background CAC/radar detection. + * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to + * resolve a path for hardware flow offloading + */ +@@ -4275,8 +4275,8 @@ struct ieee80211_ops { + struct ieee80211_twt_setup *twt); + void (*twt_teardown_request)(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 flowid); +- int (*set_radar_offchan)(struct ieee80211_hw *hw, +- struct cfg80211_chan_def *chandef); ++ int (*set_radar_background)(struct ieee80211_hw *hw, ++ struct cfg80211_chan_def *chandef); + #if LINUX_VERSION_IS_GEQ(5,10,0) + int (*net_fill_forward_path)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2608,10 +2608,10 @@ enum nl80211_commands { + * Mandatory parameter for the transmitting interface to enable MBSSID. + * Optional for the non-transmitting interfaces. + * +- * @NL80211_ATTR_RADAR_OFFCHAN: Configure dedicated offchannel chain available for +- * radar/CAC detection on some hw. This chain can't be used to transmit +- * or receive frames and it is bounded to a running wdev. +- * Offchannel radar/CAC detection allows to avoid the CAC downtime ++ * @NL80211_ATTR_RADAR_BACKGROUND: Configure dedicated offchannel chain ++ * available for radar/CAC detection on some hw. This chain can't be used ++ * to transmit or receive frames and it is bounded to a running wdev. ++ * Background radar/CAC detection allows to avoid the CAC downtime + * switching on a different channel during CAC detection on the selected + * radar channel. + * +@@ -3121,7 +3121,7 @@ enum nl80211_attrs { + NL80211_ATTR_MBSSID_CONFIG, + NL80211_ATTR_MBSSID_ELEMS, + +- NL80211_ATTR_RADAR_OFFCHAN, ++ NL80211_ATTR_RADAR_BACKGROUND, + + /* add attributes here, update the policy in nl80211.c */ + +@@ -6022,7 +6022,7 @@ enum nl80211_feature_flags { + * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision + * detection and change announcemnts. + * +- * @NL80211_EXT_FEATURE_RADAR_OFFCHAN: Device supports offchannel radar/CAC ++ * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC + * detection. + * + * @NUM_NL80211_EXT_FEATURES: number of extended features. +@@ -6090,7 +6090,7 @@ enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_SECURE_RTT, + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, + NL80211_EXT_FEATURE_BSS_COLOR, +- NL80211_EXT_FEATURE_RADAR_OFFCHAN, ++ NL80211_EXT_FEATURE_RADAR_BACKGROUND, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4345,15 +4345,15 @@ out: + } + + static int +-ieee80211_set_radar_offchan(struct wiphy *wiphy, +- struct cfg80211_chan_def *chandef) ++ieee80211_set_radar_background(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef) + { + struct ieee80211_local *local = wiphy_priv(wiphy); + +- if (!local->ops->set_radar_offchan) ++ if (!local->ops->set_radar_background) + return -EOPNOTSUPP; + +- return local->ops->set_radar_offchan(&local->hw, chandef); ++ return local->ops->set_radar_background(&local->hw, chandef); + } + + const struct cfg80211_ops mac80211_config_ops = { +@@ -4460,5 +4460,5 @@ const struct cfg80211_ops mac80211_confi + .reset_tid_config = ieee80211_reset_tid_config, + .set_sar_specs = ieee80211_set_sar_specs, + .color_change = ieee80211_color_change, +- .set_radar_offchan = ieee80211_set_radar_offchan, ++ .set_radar_background = ieee80211_set_radar_background, + }; +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -716,13 +716,13 @@ static bool + cfg80211_offchan_chain_is_active(struct cfg80211_registered_device *rdev, + struct ieee80211_channel *channel) + { +- if (!rdev->offchan_radar_wdev) ++ if (!rdev->background_radar_wdev) + return false; + +- if (!cfg80211_chandef_valid(&rdev->offchan_radar_chandef)) ++ if (!cfg80211_chandef_valid(&rdev->background_radar_chandef)) + return false; + +- return cfg80211_is_sub_chan(&rdev->offchan_radar_chandef, channel); ++ return cfg80211_is_sub_chan(&rdev->background_radar_chandef, channel); + } + + bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -552,9 +552,10 @@ use_default_name: + INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work); + INIT_WORK(&rdev->conn_work, cfg80211_conn_work); + INIT_WORK(&rdev->event_work, cfg80211_event_work); +- INIT_WORK(&rdev->offchan_cac_abort_wk, cfg80211_offchan_cac_abort_wk); +- INIT_DELAYED_WORK(&rdev->offchan_cac_done_wk, +- cfg80211_offchan_cac_done_wk); ++ INIT_WORK(&rdev->background_cac_abort_wk, ++ cfg80211_background_cac_abort_wk); ++ INIT_DELAYED_WORK(&rdev->background_cac_done_wk, ++ cfg80211_background_cac_done_wk); + + init_waitqueue_head(&rdev->dev_wait); + +@@ -1064,13 +1065,13 @@ void wiphy_unregister(struct wiphy *wiph + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); + cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); +- cancel_delayed_work_sync(&rdev->offchan_cac_done_wk); ++ cancel_delayed_work_sync(&rdev->background_cac_done_wk); + flush_work(&rdev->destroy_work); + flush_work(&rdev->sched_scan_stop_wk); + flush_work(&rdev->propagate_radar_detect_wk); + flush_work(&rdev->propagate_cac_done_wk); + flush_work(&rdev->mgmt_registrations_update_wk); +- flush_work(&rdev->offchan_cac_abort_wk); ++ flush_work(&rdev->background_cac_abort_wk); + + #ifdef CONFIG_PM + if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) +@@ -1219,7 +1220,7 @@ void __cfg80211_leave(struct cfg80211_re + + cfg80211_pmsr_wdev_down(wdev); + +- cfg80211_stop_offchan_radar_detection(wdev); ++ cfg80211_stop_background_radar_detection(wdev); + + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -84,10 +84,10 @@ struct cfg80211_registered_device { + + struct delayed_work dfs_update_channels_wk; + +- struct wireless_dev *offchan_radar_wdev; +- struct cfg80211_chan_def offchan_radar_chandef; +- struct delayed_work offchan_cac_done_wk; +- struct work_struct offchan_cac_abort_wk; ++ struct wireless_dev *background_radar_wdev; ++ struct cfg80211_chan_def background_radar_chandef; ++ struct delayed_work background_cac_done_wk; ++ struct work_struct background_cac_abort_wk; + + /* netlink port which started critical protocol (0 means not started) */ + u32 crit_proto_nlportid; +@@ -497,15 +497,15 @@ cfg80211_chandef_dfs_cac_time(struct wip + void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); + + int +-cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev, +- struct cfg80211_chan_def *chandef); ++cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev, ++ struct cfg80211_chan_def *chandef); + +-void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev); ++void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev); + +-void cfg80211_offchan_cac_done_wk(struct work_struct *work); ++void cfg80211_background_cac_done_wk(struct work_struct *work); + +-void cfg80211_offchan_cac_abort_wk(struct work_struct *work); ++void cfg80211_background_cac_abort_wk(struct work_struct *work); + + bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan); +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -920,7 +920,7 @@ void __cfg80211_radar_event(struct wiphy + cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE); + + if (offchan) +- queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk); ++ queue_work(cfg80211_wq, &rdev->background_cac_abort_wk); + + cfg80211_sched_dfs_chan_update(rdev); + +@@ -975,10 +975,10 @@ void cfg80211_cac_event(struct net_devic + EXPORT_SYMBOL(cfg80211_cac_event); + + static void +-__cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev, +- const struct cfg80211_chan_def *chandef, +- enum nl80211_radar_event event) ++__cfg80211_background_cac_event(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev, ++ const struct cfg80211_chan_def *chandef, ++ enum nl80211_radar_event event) + { + struct wiphy *wiphy = &rdev->wiphy; + struct net_device *netdev; +@@ -988,7 +988,7 @@ __cfg80211_offchan_cac_event(struct cfg8 + if (!cfg80211_chandef_valid(chandef)) + return; + +- if (!rdev->offchan_radar_wdev) ++ if (!rdev->background_radar_wdev) + return; + + switch (event) { +@@ -997,12 +997,12 @@ __cfg80211_offchan_cac_event(struct cfg8 + memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef)); + queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); + cfg80211_sched_dfs_chan_update(rdev); +- wdev = rdev->offchan_radar_wdev; ++ wdev = rdev->background_radar_wdev; + break; + case NL80211_RADAR_CAC_ABORTED: +- if (!cancel_delayed_work(&rdev->offchan_cac_done_wk)) ++ if (!cancel_delayed_work(&rdev->background_cac_done_wk)) + return; +- wdev = rdev->offchan_radar_wdev; ++ wdev = rdev->background_radar_wdev; + break; + case NL80211_RADAR_CAC_STARTED: + break; +@@ -1015,49 +1015,49 @@ __cfg80211_offchan_cac_event(struct cfg8 + } + + static void +-cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev, +- const struct cfg80211_chan_def *chandef, +- enum nl80211_radar_event event) ++cfg80211_background_cac_event(struct cfg80211_registered_device *rdev, ++ const struct cfg80211_chan_def *chandef, ++ enum nl80211_radar_event event) + { + wiphy_lock(&rdev->wiphy); +- __cfg80211_offchan_cac_event(rdev, rdev->offchan_radar_wdev, +- chandef, event); ++ __cfg80211_background_cac_event(rdev, rdev->background_radar_wdev, ++ chandef, event); + wiphy_unlock(&rdev->wiphy); + } + +-void cfg80211_offchan_cac_done_wk(struct work_struct *work) ++void cfg80211_background_cac_done_wk(struct work_struct *work) + { + struct delayed_work *delayed_work = to_delayed_work(work); + struct cfg80211_registered_device *rdev; + + rdev = container_of(delayed_work, struct cfg80211_registered_device, +- offchan_cac_done_wk); +- cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef, +- NL80211_RADAR_CAC_FINISHED); ++ background_cac_done_wk); ++ cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef, ++ NL80211_RADAR_CAC_FINISHED); + } + +-void cfg80211_offchan_cac_abort_wk(struct work_struct *work) ++void cfg80211_background_cac_abort_wk(struct work_struct *work) + { + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, +- offchan_cac_abort_wk); +- cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef, +- NL80211_RADAR_CAC_ABORTED); ++ background_cac_abort_wk); ++ cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef, ++ NL80211_RADAR_CAC_ABORTED); + } + +-void cfg80211_offchan_cac_abort(struct wiphy *wiphy) ++void cfg80211_background_cac_abort(struct wiphy *wiphy) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + +- queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk); ++ queue_work(cfg80211_wq, &rdev->background_cac_abort_wk); + } +-EXPORT_SYMBOL(cfg80211_offchan_cac_abort); ++EXPORT_SYMBOL(cfg80211_background_cac_abort); + + int +-cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev, +- struct cfg80211_chan_def *chandef) ++cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev, ++ struct cfg80211_chan_def *chandef) + { + unsigned int cac_time_ms; + int err; +@@ -1065,19 +1065,19 @@ cfg80211_start_offchan_radar_detection(s + lockdep_assert_wiphy(&rdev->wiphy); + + if (!wiphy_ext_feature_isset(&rdev->wiphy, +- NL80211_EXT_FEATURE_RADAR_OFFCHAN)) ++ NL80211_EXT_FEATURE_RADAR_BACKGROUND)) + return -EOPNOTSUPP; + + /* Offchannel chain already locked by another wdev */ +- if (rdev->offchan_radar_wdev && rdev->offchan_radar_wdev != wdev) ++ if (rdev->background_radar_wdev && rdev->background_radar_wdev != wdev) + return -EBUSY; + + /* CAC already in progress on the offchannel chain */ +- if (rdev->offchan_radar_wdev == wdev && +- delayed_work_pending(&rdev->offchan_cac_done_wk)) ++ if (rdev->background_radar_wdev == wdev && ++ delayed_work_pending(&rdev->background_cac_done_wk)) + return -EBUSY; + +- err = rdev_set_radar_offchan(rdev, chandef); ++ err = rdev_set_radar_background(rdev, chandef); + if (err) + return err; + +@@ -1085,30 +1085,31 @@ cfg80211_start_offchan_radar_detection(s + if (!cac_time_ms) + cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; + +- rdev->offchan_radar_chandef = *chandef; +- rdev->offchan_radar_wdev = wdev; /* Get offchain ownership */ ++ rdev->background_radar_chandef = *chandef; ++ rdev->background_radar_wdev = wdev; /* Get offchain ownership */ + +- __cfg80211_offchan_cac_event(rdev, wdev, chandef, +- NL80211_RADAR_CAC_STARTED); +- queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_done_wk, ++ __cfg80211_background_cac_event(rdev, wdev, chandef, ++ NL80211_RADAR_CAC_STARTED); ++ queue_delayed_work(cfg80211_wq, &rdev->background_cac_done_wk, + msecs_to_jiffies(cac_time_ms)); + + return 0; + } + +-void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev) ++void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev) + { + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + + lockdep_assert_wiphy(wiphy); + +- if (wdev != rdev->offchan_radar_wdev) ++ if (wdev != rdev->background_radar_wdev) + return; + +- rdev_set_radar_offchan(rdev, NULL); +- rdev->offchan_radar_wdev = NULL; /* Release offchain ownership */ ++ rdev_set_radar_background(rdev, NULL); ++ rdev->background_radar_wdev = NULL; /* Release offchain ownership */ + +- __cfg80211_offchan_cac_event(rdev, wdev, &rdev->offchan_radar_chandef, +- NL80211_RADAR_CAC_ABORTED); ++ __cfg80211_background_cac_event(rdev, wdev, ++ &rdev->background_radar_chandef, ++ NL80211_RADAR_CAC_ABORTED); + } +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -793,7 +793,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MBSSID_CONFIG] = + NLA_POLICY_NESTED(nl80211_mbssid_config_policy), + [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, +- [NL80211_ATTR_RADAR_OFFCHAN] = { .type = NLA_FLAG }, ++ [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, + }; + + /* policy for the key attributes */ +@@ -9288,9 +9288,9 @@ static int nl80211_start_radar_detection + goto unlock; + } + +- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN])) { +- err = cfg80211_start_offchan_radar_detection(rdev, wdev, +- &chandef); ++ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) { ++ err = cfg80211_start_background_radar_detection(rdev, wdev, ++ &chandef); + goto unlock; + } + +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1382,17 +1382,17 @@ static inline int rdev_color_change(stru + } + + static inline int +-rdev_set_radar_offchan(struct cfg80211_registered_device *rdev, +- struct cfg80211_chan_def *chandef) ++rdev_set_radar_background(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef) + { + struct wiphy *wiphy = &rdev->wiphy; + int ret; + +- if (!rdev->ops->set_radar_offchan) ++ if (!rdev->ops->set_radar_background) + return -EOPNOTSUPP; + +- trace_rdev_set_radar_offchan(wiphy, chandef); +- ret = rdev->ops->set_radar_offchan(wiphy, chandef); ++ trace_rdev_set_radar_background(wiphy, chandef); ++ ret = rdev->ops->set_radar_background(wiphy, chandef); + trace_rdev_return_int(wiphy, ret); + + return ret; +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -3646,7 +3646,7 @@ TRACE_EVENT(cfg80211_bss_color_notify, + __entry->color_bitmap) + ); + +-TRACE_EVENT(rdev_set_radar_offchan, ++TRACE_EVENT(rdev_set_radar_background, + TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), + + TP_ARGS(wiphy, chandef), diff --git a/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch b/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch deleted file mode 100644 index a7c09f00b..000000000 --- a/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch +++ /dev/null @@ -1,123 +0,0 @@ -From: Ramon Fontes -Date: Sun, 27 Dec 2020 00:11:55 -0300 -Subject: [PATCH] mac80211_hwsim: add 6GHz channels - -Advertise 6GHz channels to mac80211. - -Signed-off-by: Ramon Fontes -Link: https://lore.kernel.org/r/20201227031155.81161-1-ramonreisfontes@gmail.com -[reword commit message] -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -311,6 +311,12 @@ static struct net_device *hwsim_mon; /* - .hw_value = (_freq), \ - } - -+#define CHAN6G(_freq) { \ -+ .band = NL80211_BAND_6GHZ, \ -+ .center_freq = (_freq), \ -+ .hw_value = (_freq), \ -+} -+ - static const struct ieee80211_channel hwsim_channels_2ghz[] = { - CHAN2G(2412), /* Channel 1 */ - CHAN2G(2417), /* Channel 2 */ -@@ -377,6 +383,68 @@ static const struct ieee80211_channel hw - CHAN5G(5925), /* Channel 185 */ - }; - -+static const struct ieee80211_channel hwsim_channels_6ghz[] = { -+ CHAN6G(5955), /* Channel 1 */ -+ CHAN6G(5975), /* Channel 5 */ -+ CHAN6G(5995), /* Channel 9 */ -+ CHAN6G(6015), /* Channel 13 */ -+ CHAN6G(6035), /* Channel 17 */ -+ CHAN6G(6055), /* Channel 21 */ -+ CHAN6G(6075), /* Channel 25 */ -+ CHAN6G(6095), /* Channel 29 */ -+ CHAN6G(6115), /* Channel 33 */ -+ CHAN6G(6135), /* Channel 37 */ -+ CHAN6G(6155), /* Channel 41 */ -+ CHAN6G(6175), /* Channel 45 */ -+ CHAN6G(6195), /* Channel 49 */ -+ CHAN6G(6215), /* Channel 53 */ -+ CHAN6G(6235), /* Channel 57 */ -+ CHAN6G(6255), /* Channel 61 */ -+ CHAN6G(6275), /* Channel 65 */ -+ CHAN6G(6295), /* Channel 69 */ -+ CHAN6G(6315), /* Channel 73 */ -+ CHAN6G(6335), /* Channel 77 */ -+ CHAN6G(6355), /* Channel 81 */ -+ CHAN6G(6375), /* Channel 85 */ -+ CHAN6G(6395), /* Channel 89 */ -+ CHAN6G(6415), /* Channel 93 */ -+ CHAN6G(6435), /* Channel 97 */ -+ CHAN6G(6455), /* Channel 181 */ -+ CHAN6G(6475), /* Channel 105 */ -+ CHAN6G(6495), /* Channel 109 */ -+ CHAN6G(6515), /* Channel 113 */ -+ CHAN6G(6535), /* Channel 117 */ -+ CHAN6G(6555), /* Channel 121 */ -+ CHAN6G(6575), /* Channel 125 */ -+ CHAN6G(6595), /* Channel 129 */ -+ CHAN6G(6615), /* Channel 133 */ -+ CHAN6G(6635), /* Channel 137 */ -+ CHAN6G(6655), /* Channel 141 */ -+ CHAN6G(6675), /* Channel 145 */ -+ CHAN6G(6695), /* Channel 149 */ -+ CHAN6G(6715), /* Channel 153 */ -+ CHAN6G(6735), /* Channel 157 */ -+ CHAN6G(6755), /* Channel 161 */ -+ CHAN6G(6775), /* Channel 165 */ -+ CHAN6G(6795), /* Channel 169 */ -+ CHAN6G(6815), /* Channel 173 */ -+ CHAN6G(6835), /* Channel 177 */ -+ CHAN6G(6855), /* Channel 181 */ -+ CHAN6G(6875), /* Channel 185 */ -+ CHAN6G(6895), /* Channel 189 */ -+ CHAN6G(6915), /* Channel 193 */ -+ CHAN6G(6935), /* Channel 197 */ -+ CHAN6G(6955), /* Channel 201 */ -+ CHAN6G(6975), /* Channel 205 */ -+ CHAN6G(6995), /* Channel 209 */ -+ CHAN6G(7015), /* Channel 213 */ -+ CHAN6G(7035), /* Channel 217 */ -+ CHAN6G(7055), /* Channel 221 */ -+ CHAN6G(7075), /* Channel 225 */ -+ CHAN6G(7095), /* Channel 229 */ -+ CHAN6G(7115), /* Channel 233 */ -+}; -+ - #define NUM_S1G_CHANS_US 51 - static struct ieee80211_channel hwsim_channels_s1g[NUM_S1G_CHANS_US]; - -@@ -548,6 +616,7 @@ struct mac80211_hwsim_data { - struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; - struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; - struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; -+ struct ieee80211_channel channels_6ghz[ARRAY_SIZE(hwsim_channels_6ghz)]; - struct ieee80211_channel channels_s1g[ARRAY_SIZE(hwsim_channels_s1g)]; - struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; - struct ieee80211_iface_combination if_combination; -@@ -578,7 +647,8 @@ struct mac80211_hwsim_data { - struct ieee80211_channel *channel; - unsigned long next_start, start, end; - } survey_data[ARRAY_SIZE(hwsim_channels_2ghz) + -- ARRAY_SIZE(hwsim_channels_5ghz)]; -+ ARRAY_SIZE(hwsim_channels_5ghz) + -+ ARRAY_SIZE(hwsim_channels_6ghz)]; - - struct ieee80211_channel *channel; - u64 beacon_int /* beacon interval in us */; -@@ -3149,6 +3219,8 @@ static int mac80211_hwsim_new_radio(stru - sizeof(hwsim_channels_2ghz)); - memcpy(data->channels_5ghz, hwsim_channels_5ghz, - sizeof(hwsim_channels_5ghz)); -+ memcpy(data->channels_6ghz, hwsim_channels_6ghz, -+ sizeof(hwsim_channels_6ghz)); - memcpy(data->channels_s1g, hwsim_channels_s1g, - sizeof(hwsim_channels_s1g)); - memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211-fix-EAPoL-rekey-fail-in-802.3-rx-path.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-fix-EAPoL-rekey-fail-in-802.3-rx-path.patch new file mode 100644 index 000000000..932403d65 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/321-mac80211-fix-EAPoL-rekey-fail-in-802.3-rx-path.patch @@ -0,0 +1,43 @@ +From: Deren Wu +Date: Sun, 13 Feb 2022 00:20:15 +0800 +Subject: [PATCH] mac80211: fix EAPoL rekey fail in 802.3 rx path + +mac80211 set capability NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211 +to upper layer by default. That means we should pass EAPoL packets through +nl80211 path only, and should not send the EAPoL skb to netdevice diretly. +At the meanwhile, wpa_supplicant would not regist sock to listen EAPoL skb +on the netdevice. + +However, there is no contorl_port_protocol handler in mac80211 for 802.3 RX +packets, mac80211 driver would pass up the EAPoL rekey frame to netdevice +and wpa_supplicant would be never interactive with this kind of packets, +if SUPPORTS_RX_DECAP_OFFLOAD is enabled. This causes STA always rekey fail +if EAPoL frame go through 802.3 path. + +To avoid this problem, align the same process as 802.11 type to handle +this frame before put it into network stack. + +Fixes: 80a915ec4427 ("mac80211: add rx decapsulation offload support") +Signed-off-by: Deren Wu +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4523,16 +4523,7 @@ static void ieee80211_rx_8023(struct iee + + /* deliver to local stack */ + skb->protocol = eth_type_trans(skb, fast_rx->dev); +- memset(skb->cb, 0, sizeof(skb->cb)); +- if (rx->list) +-#if LINUX_VERSION_IS_GEQ(4,19,0) +- list_add_tail(&skb->list, rx->list); +-#else +- __skb_queue_tail(rx->list, skb); +-#endif +- else +- netif_receive_skb(skb); +- ++ ieee80211_deliver_skb_to_local_stack(skb, rx); + } + + static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, diff --git a/package/kernel/mac80211/patches/subsys/322-mac80211-fix-forwarded-mesh-frames-AC-queue-selectio.patch b/package/kernel/mac80211/patches/subsys/322-mac80211-fix-forwarded-mesh-frames-AC-queue-selectio.patch new file mode 100644 index 000000000..50693f723 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/322-mac80211-fix-forwarded-mesh-frames-AC-queue-selectio.patch @@ -0,0 +1,50 @@ +From: Nicolas Escande +Date: Mon, 14 Feb 2022 18:32:14 +0100 +Subject: [PATCH] mac80211: fix forwarded mesh frames AC & queue selection + +There are two problems with the current code that have been highlighted +with the AQL feature that is now enbaled by default. + +First problem is in ieee80211_rx_h_mesh_fwding(), +ieee80211_select_queue_80211() is used on received packets to choose +the sending AC queue of the forwarding packet although this function +should only be called on TX packet (it uses ieee80211_tx_info). +This ends with forwarded mesh packets been sent on unrelated random AC +queue. To fix that, AC queue can directly be infered from skb->priority +which has been extracted from QOS info (see ieee80211_parse_qos()). + +Second problem is the value of queue_mapping set on forwarded mesh +frames via skb_set_queue_mapping() is not the AC of the packet but a +hardware queue index. This may or may not work depending on AC to HW +queue mapping which is driver specific. + +Both of these issues lead to improper AC selection while forwarding +mesh packets but more importantly due to improper airtime accounting +(which is done on a per STA, per AC basis) caused traffic stall with +the introduction of AQL. + +Fixes: cf44012810cc ("mac80211: fix unnecessary frame drops in mesh fwding") +Fixes: d3c1597b8d1b ("mac80211: fix forwarded mesh frame queue mapping") +Co-developed-by: Remi Pommarel +Signed-off-by: Remi Pommarel +Signed-off-by: Nicolas Escande +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2921,13 +2921,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 + ether_addr_equal(sdata->vif.addr, hdr->addr3)) + return RX_CONTINUE; + +- ac = ieee80211_select_queue_80211(sdata, skb, hdr); ++ ac = ieee802_1d_to_ac[skb->priority]; + q = sdata->vif.hw_queue[ac]; + if (ieee80211_queue_stopped(&local->hw, q)) { + IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); + return RX_DROP_MONITOR; + } +- skb_set_queue_mapping(skb, q); ++ skb_set_queue_mapping(skb, ac); + + if (!--mesh_hdr->ttl) { + if (!is_multicast_ether_addr(hdr->addr1)) diff --git a/package/kernel/mac80211/patches/subsys/323-mac80211-MBSSID-support-in-interface-handling.patch b/package/kernel/mac80211/patches/subsys/323-mac80211-MBSSID-support-in-interface-handling.patch new file mode 100644 index 000000000..a135e3d1b --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/323-mac80211-MBSSID-support-in-interface-handling.patch @@ -0,0 +1,144 @@ +From: John Crispin +Date: Wed, 15 Sep 2021 19:54:35 -0700 +Subject: [PATCH] mac80211: MBSSID support in interface handling + +Configure multiple BSSID and enhanced multi-BSSID advertisement (EMA) +parameters in mac80211 for AP mode. + +For each interface, 'mbssid_tx_vif' points to the transmitting interface of +the MBSSID set. The pointer is set to NULL if MBSSID is disabled. + +Function ieee80211_stop() is modified to always bring down all the +non-transmitting interfaces first and the transmitting interface last. + +Signed-off-by: John Crispin +Co-developed-by: Aloka Dixit +Signed-off-by: Aloka Dixit +Link: https://lore.kernel.org/r/20210916025437.29138-3-alokad@codeaurora.org +[slightly change logic to be more obvious] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1719,6 +1719,7 @@ enum ieee80211_offload_flags { + * 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. ++ * @mbssid_tx_vif: Pointer to the transmitting interface if MBSSID is enabled. + */ + struct ieee80211_vif { + enum nl80211_iftype type; +@@ -1750,6 +1751,8 @@ struct ieee80211_vif { + bool color_change_active; + u8 color_change_color; + ++ struct ieee80211_vif *mbssid_tx_vif; ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -112,6 +112,36 @@ static int ieee80211_set_mon_options(str + return 0; + } + ++static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, ++ struct cfg80211_mbssid_config params) ++{ ++ struct ieee80211_sub_if_data *tx_sdata; ++ ++ sdata->vif.mbssid_tx_vif = NULL; ++ sdata->vif.bss_conf.bssid_index = 0; ++ sdata->vif.bss_conf.nontransmitted = false; ++ sdata->vif.bss_conf.ema_ap = false; ++ ++ if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev) ++ return -EINVAL; ++ ++ tx_sdata = IEEE80211_WDEV_TO_SUB_IF(params.tx_wdev); ++ if (!tx_sdata) ++ return -EINVAL; ++ ++ if (tx_sdata == sdata) { ++ sdata->vif.mbssid_tx_vif = &sdata->vif; ++ } else { ++ sdata->vif.mbssid_tx_vif = &tx_sdata->vif; ++ sdata->vif.bss_conf.nontransmitted = true; ++ sdata->vif.bss_conf.bssid_index = params.index; ++ } ++ if (params.ema) ++ sdata->vif.bss_conf.ema_ap = true; ++ ++ return 0; ++} ++ + static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, +@@ -1107,6 +1137,14 @@ static int ieee80211_start_ap(struct wip + changed |= BSS_CHANGED_HE_BSS_COLOR; + } + ++ if (sdata->vif.type == NL80211_IFTYPE_AP && ++ params->mbssid_config.tx_wdev) { ++ err = ieee80211_set_ap_mbssid_options(sdata, ++ params->mbssid_config); ++ if (err) ++ return err; ++ } ++ + mutex_lock(&local->mtx); + err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, + IEEE80211_CHANCTX_SHARED); +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -632,17 +632,46 @@ static void ieee80211_do_stop(struct iee + ieee80211_add_virtual_monitor(local); + } + ++static void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_sub_if_data *tx_sdata, *non_tx_sdata, *tmp_sdata; ++ struct ieee80211_vif *tx_vif = sdata->vif.mbssid_tx_vif; ++ ++ if (!tx_vif) ++ return; ++ ++ tx_sdata = vif_to_sdata(tx_vif); ++ sdata->vif.mbssid_tx_vif = NULL; ++ ++ list_for_each_entry_safe(non_tx_sdata, tmp_sdata, ++ &tx_sdata->local->interfaces, list) { ++ if (non_tx_sdata != sdata && non_tx_sdata != tx_sdata && ++ non_tx_sdata->vif.mbssid_tx_vif == tx_vif && ++ ieee80211_sdata_running(non_tx_sdata)) { ++ non_tx_sdata->vif.mbssid_tx_vif = NULL; ++ dev_close(non_tx_sdata->wdev.netdev); ++ } ++ } ++ ++ if (sdata != tx_sdata && ieee80211_sdata_running(tx_sdata)) { ++ tx_sdata->vif.mbssid_tx_vif = NULL; ++ dev_close(tx_sdata->wdev.netdev); ++ } ++} ++ + static int ieee80211_stop(struct net_device *dev) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + +- /* close all dependent VLAN interfaces before locking wiphy */ ++ /* close dependent VLAN and MBSSID interfaces before locking wiphy */ + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan, *tmpsdata; + + list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, + u.vlan.list) + dev_close(vlan->dev); ++ ++ ieee80211_stop_mbssid(sdata); + } + + wiphy_lock(sdata->local->hw.wiphy); diff --git a/package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch new file mode 100644 index 000000000..c76f4ae46 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch @@ -0,0 +1,326 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Feb 2022 12:54:58 +0100 +Subject: [PATCH] mac80211: MBSSID beacon handling in AP mode + +Add new fields in struct beacon_data to store all MBSSID elements. +Generate a beacon template which includes all MBSSID elements. +Move CSA offset to reflect the MBSSID element length. + +Co-developed-by: Aloka Dixit +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Signed-off-by: Lorenzo Bianconi +Tested-by: Money Wang +Link: https://lore.kernel.org/r/5322db3c303f431adaf191ab31c45e151dde5465.1645702516.git.lorenzo@kernel.org +[small cleanups] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4938,12 +4938,14 @@ void ieee80211_report_low_ack(struct iee + * @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets + * to countdown counters. This array can contain zero values which + * should be ignored. ++ * @mbssid_off: position of the multiple bssid element + */ + struct ieee80211_mutable_offsets { + u16 tim_offset; + u16 tim_length; + + u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; ++ u16 mbssid_off; + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -989,11 +989,29 @@ static int ieee80211_set_ftm_responder_p + return 0; + } + ++static int ++ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst, ++ struct cfg80211_mbssid_elems *src) ++{ ++ int i, offset = 0; ++ ++ for (i = 0; i < src->cnt; i++) { ++ memcpy(pos + offset, src->elem[i].data, src->elem[i].len); ++ dst->elem[i].len = src->elem[i].len; ++ dst->elem[i].data = pos + offset; ++ offset += dst->elem[i].len; ++ } ++ dst->cnt = src->cnt; ++ ++ return offset; ++} ++ + 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_color_change_settings *cca) + { ++ struct cfg80211_mbssid_elems *mbssid = NULL; + struct beacon_data *new, *old; + int new_head_len, new_tail_len; + int size, err; +@@ -1021,6 +1039,17 @@ static int ieee80211_assign_beacon(struc + + size = sizeof(*new) + new_head_len + new_tail_len; + ++ /* new or old multiple BSSID elements? */ ++ if (params->mbssid_ies) { ++ mbssid = params->mbssid_ies; ++ size += struct_size(new->mbssid_ies, elem, mbssid->cnt); ++ size += ieee80211_get_mbssid_beacon_len(mbssid); ++ } else if (old && old->mbssid_ies) { ++ mbssid = old->mbssid_ies; ++ size += struct_size(new->mbssid_ies, elem, mbssid->cnt); ++ size += ieee80211_get_mbssid_beacon_len(mbssid); ++ } ++ + new = kzalloc(size, GFP_KERNEL); + if (!new) + return -ENOMEM; +@@ -1029,12 +1058,20 @@ static int ieee80211_assign_beacon(struc + + /* + * pointers go into the block we allocated, +- * memory is | beacon_data | head | tail | ++ * memory is | beacon_data | head | tail | mbssid_ies + */ + new->head = ((u8 *) new) + sizeof(*new); + new->tail = new->head + new_head_len; + new->head_len = new_head_len; + new->tail_len = new_tail_len; ++ /* copy in optional mbssid_ies */ ++ if (mbssid) { ++ u8 *pos = new->tail + new->tail_len; ++ ++ new->mbssid_ies = (void *)pos; ++ pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); ++ ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); ++ } + + if (csa) { + new->cntdwn_current_counter = csa->count; +@@ -1329,8 +1366,11 @@ static int ieee80211_stop_ap(struct wiph + + mutex_unlock(&local->mtx); + +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + /* turn off carrier for this interface and dependent VLANs */ + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) +@@ -3126,12 +3166,24 @@ cfg80211_beacon_dup(struct cfg80211_beac + + len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + + beacon->proberesp_ies_len + beacon->assocresp_ies_len + +- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; ++ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + ++ ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); + + new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); + if (!new_beacon) + return NULL; + ++ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) { ++ new_beacon->mbssid_ies = ++ kzalloc(struct_size(new_beacon->mbssid_ies, ++ elem, beacon->mbssid_ies->cnt), ++ GFP_KERNEL); ++ if (!new_beacon->mbssid_ies) { ++ kfree(new_beacon); ++ return NULL; ++ } ++ } ++ + pos = (u8 *)(new_beacon + 1); + if (beacon->head_len) { + new_beacon->head_len = beacon->head_len; +@@ -3169,6 +3221,10 @@ cfg80211_beacon_dup(struct cfg80211_beac + memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); + pos += beacon->probe_resp_len; + } ++ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) ++ pos += ieee80211_copy_mbssid_beacon(pos, ++ new_beacon->mbssid_ies, ++ beacon->mbssid_ies); + + /* might copy -1, meaning no changes requested */ + new_beacon->ftm_responder = beacon->ftm_responder; +@@ -3206,8 +3262,11 @@ static int ieee80211_set_after_csa_beaco + case NL80211_IFTYPE_AP: + err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, + NULL, NULL); +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + if (err < 0) + return err; +@@ -3362,8 +3421,12 @@ static int ieee80211_set_csa_beacon(stru + if ((params->n_counter_offsets_beacon > + IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || + (params->n_counter_offsets_presp > +- IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) ++ IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; + return -EINVAL; ++ } + + csa.counter_offsets_beacon = params->counter_offsets_beacon; + csa.counter_offsets_presp = params->counter_offsets_presp; +@@ -3373,7 +3436,9 @@ static int ieee80211_set_csa_beacon(stru + + err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL); + if (err < 0) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); + kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; + return err; + } + *changed |= err; +@@ -3463,8 +3528,11 @@ static int ieee80211_set_csa_beacon(stru + 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; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + cfg80211_color_change_aborted_notify(sdata->dev); + } +@@ -4202,8 +4270,11 @@ ieee80211_set_after_color_change_beacon( + + 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 (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + if (ret < 0) + return ret; +@@ -4246,7 +4317,11 @@ ieee80211_set_color_change_beacon(struct + err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change, + NULL, &color_change); + if (err < 0) { +- kfree(sdata->u.ap.next_beacon); ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + return err; + } + *changed |= err; +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -261,6 +261,7 @@ struct beacon_data { + struct ieee80211_meshconf_ie *meshconf; + u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; + u8 cntdwn_current_counter; ++ struct cfg80211_mbssid_elems *mbssid_ies; + struct rcu_head rcu_head; + }; + +@@ -1063,6 +1064,20 @@ ieee80211_vif_get_shift(struct ieee80211 + return shift; + } + ++static inline int ++ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems) ++{ ++ int i, len = 0; ++ ++ if (!elems) ++ return 0; ++ ++ for (i = 0; i < elems->cnt; i++) ++ len += elems->elem[i].len; ++ ++ return len; ++} ++ + enum { + IEEE80211_RX_MSG = 1, + IEEE80211_TX_STATUS_MSG = 2, +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5041,6 +5041,19 @@ ieee80211_beacon_get_finish(struct ieee8 + IEEE80211_TX_CTL_FIRST_FRAGMENT; + } + ++static void ++ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon) ++{ ++ int i; ++ ++ if (!beacon->mbssid_ies) ++ return; ++ ++ for (i = 0; i < beacon->mbssid_ies->cnt; i++) ++ skb_put_data(skb, beacon->mbssid_ies->elem[i].data, ++ beacon->mbssid_ies->elem[i].len); ++} ++ + static struct sk_buff * + ieee80211_beacon_get_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -5054,6 +5067,7 @@ ieee80211_beacon_get_ap(struct ieee80211 + struct ieee80211_if_ap *ap = &sdata->u.ap; + struct sk_buff *skb = NULL; + u16 csa_off_base = 0; ++ int mbssid_len; + + if (beacon->cntdwn_counter_offsets[0]) { + if (!is_template) +@@ -5063,11 +5077,12 @@ ieee80211_beacon_get_ap(struct ieee80211 + } + + /* headroom, head length, +- * tail length and maximum TIM length ++ * tail length, maximum TIM length and multiple BSSID length + */ ++ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); + skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + + beacon->tail_len + 256 + +- local->hw.extra_beacon_tailroom); ++ local->hw.extra_beacon_tailroom + mbssid_len); + if (!skb) + return NULL; + +@@ -5081,6 +5096,11 @@ ieee80211_beacon_get_ap(struct ieee80211 + offs->tim_length = skb->len - beacon->head_len; + offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; + ++ if (mbssid_len) { ++ ieee80211_beacon_add_mbssid(skb, beacon); ++ offs->mbssid_off = skb->len - mbssid_len; ++ } ++ + /* for AP the csa offsets are from tail */ + csa_off_base = skb->len; + } diff --git a/package/kernel/mac80211/patches/subsys/325-mac80211-MBSSID-channel-switch.patch b/package/kernel/mac80211/patches/subsys/325-mac80211-MBSSID-channel-switch.patch new file mode 100644 index 000000000..38b0de180 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/325-mac80211-MBSSID-channel-switch.patch @@ -0,0 +1,52 @@ +From: John Crispin +Date: Thu, 24 Feb 2022 12:54:59 +0100 +Subject: [PATCH] mac80211: MBSSID channel switch + +Trigger ieee80211_csa_finish() on the non-transmitting interfaces +when channel switch concludes on the transmitting interface. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Co-developed-by: Aloka Dixit +Signed-off-by: Aloka Dixit +Signed-off-by: John Crispin +Link: https://lore.kernel.org/r/6fde4d7f9fa387494f46a7aa4a584478dcda06f1.1645702516.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3247,9 +3247,31 @@ cfg80211_beacon_dup(struct cfg80211_beac + void ieee80211_csa_finish(struct ieee80211_vif *vif) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_local *local = sdata->local; + +- ieee80211_queue_work(&sdata->local->hw, +- &sdata->csa_finalize_work); ++ rcu_read_lock(); ++ ++ if (vif->mbssid_tx_vif == vif) { ++ /* Trigger ieee80211_csa_finish() on the non-transmitting ++ * interfaces when channel switch is received on ++ * transmitting interface ++ */ ++ struct ieee80211_sub_if_data *iter; ++ ++ list_for_each_entry_rcu(iter, &local->interfaces, list) { ++ if (!ieee80211_sdata_running(iter)) ++ continue; ++ ++ if (iter == sdata || iter->vif.mbssid_tx_vif != vif) ++ continue; ++ ++ ieee80211_queue_work(&iter->local->hw, ++ &iter->csa_finalize_work); ++ } ++ } ++ ieee80211_queue_work(&local->hw, &sdata->csa_finalize_work); ++ ++ rcu_read_unlock(); + } + EXPORT_SYMBOL(ieee80211_csa_finish); + diff --git a/package/kernel/mac80211/patches/subsys/326-mac80211-update-bssid_indicator-in-ieee80211_assign_.patch b/package/kernel/mac80211/patches/subsys/326-mac80211-update-bssid_indicator-in-ieee80211_assign_.patch new file mode 100644 index 000000000..195556860 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/326-mac80211-update-bssid_indicator-in-ieee80211_assign_.patch @@ -0,0 +1,25 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Feb 2022 12:55:00 +0100 +Subject: [PATCH] mac80211: update bssid_indicator in + ieee80211_assign_beacon + +Update bssid_indicator in ieee80211_bss_conf according to the +number of bssid in the set. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/f92317e002fca9933f05a445fcefb4f53291d601.1645702516.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1071,6 +1071,9 @@ static int ieee80211_assign_beacon(struc + new->mbssid_ies = (void *)pos; + pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); + ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); ++ /* update bssid_indicator */ ++ sdata->vif.bss_conf.bssid_indicator = ++ ilog2(__roundup_pow_of_two(mbssid->cnt + 1)); + } + + if (csa) { diff --git a/package/kernel/mac80211/patches/subsys/327-mac80211-allow-non-standard-VHT-MCS-10-11.patch b/package/kernel/mac80211/patches/subsys/327-mac80211-allow-non-standard-VHT-MCS-10-11.patch new file mode 100644 index 000000000..7c68e7557 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/327-mac80211-allow-non-standard-VHT-MCS-10-11.patch @@ -0,0 +1,36 @@ +From: Ping-Ke Shih +Date: Mon, 3 Jan 2022 09:36:21 +0800 +Subject: [PATCH] mac80211: allow non-standard VHT MCS-10/11 + +Some AP can possibly try non-standard VHT rate and mac80211 warns and drops +packets, and leads low TCP throughput. + + Rate marked as a VHT rate but data is invalid: MCS: 10, NSS: 2 + WARNING: CPU: 1 PID: 7817 at net/mac80211/rx.c:4856 ieee80211_rx_list+0x223/0x2f0 [mac8021 + +Since commit c27aa56a72b8 ("cfg80211: add VHT rate entries for MCS-10 and MCS-11") +has added, mac80211 adds this support as well. + +After this patch, throughput is good and iw can get the bitrate: + rx bitrate: 975.1 MBit/s VHT-MCS 10 80MHz short GI VHT-NSS 2 +or + rx bitrate: 1083.3 MBit/s VHT-MCS 11 80MHz short GI VHT-NSS 2 + +Buglink: https://bugzilla.suse.com/show_bug.cgi?id=1192891 +Reported-by: Goldwyn Rodrigues +Signed-off-by: Ping-Ke Shih +Link: https://lore.kernel.org/r/20220103013623.17052-1-pkshih@realtek.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4945,7 +4945,7 @@ void ieee80211_rx_list(struct ieee80211_ + goto drop; + break; + case RX_ENC_VHT: +- if (WARN_ONCE(status->rate_idx > 9 || ++ if (WARN_ONCE(status->rate_idx > 11 || + !status->nss || + status->nss > 8, + "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n", diff --git a/package/kernel/mac80211/patches/subsys/337-mac80211-minstrel_ht-clean-up-CCK-code.patch b/package/kernel/mac80211/patches/subsys/337-mac80211-minstrel_ht-clean-up-CCK-code.patch deleted file mode 100644 index f667d2c94..000000000 --- a/package/kernel/mac80211/patches/subsys/337-mac80211-minstrel_ht-clean-up-CCK-code.patch +++ /dev/null @@ -1,166 +0,0 @@ -From: Felix Fietkau -Date: Fri, 25 Dec 2020 16:22:52 +0100 -Subject: [PATCH] mac80211: minstrel_ht: clean up CCK code - -- move ack overhead out of rate duration table -- remove cck_supported, cck_supported_short - -Preparation for adding OFDM legacy rates support - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -136,20 +136,16 @@ - __VHT_GROUP(_streams, _sgi, _bw, \ - VHT_GROUP_SHIFT(_streams, _sgi, _bw)) - --#define CCK_DURATION(_bitrate, _short, _len) \ -+#define CCK_DURATION(_bitrate, _short) \ - (1000 * (10 /* SIFS */ + \ - (_short ? 72 + 24 : 144 + 48) + \ -- (8 * (_len + 4) * 10) / (_bitrate))) -- --#define CCK_ACK_DURATION(_bitrate, _short) \ -- (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ -- CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE)) -+ (8 * (AVG_PKT_SIZE + 4) * 10) / (_bitrate))) - - #define CCK_DURATION_LIST(_short, _s) \ -- CCK_ACK_DURATION(10, _short) >> _s, \ -- CCK_ACK_DURATION(20, _short) >> _s, \ -- CCK_ACK_DURATION(55, _short) >> _s, \ -- CCK_ACK_DURATION(110, _short) >> _s -+ CCK_DURATION(10, _short) >> _s, \ -+ CCK_DURATION(20, _short) >> _s, \ -+ CCK_DURATION(55, _short) >> _s, \ -+ CCK_DURATION(110, _short) >> _s - - #define __CCK_GROUP(_s) \ - [MINSTREL_CCK_GROUP] = { \ -@@ -163,7 +159,7 @@ - } - - #define CCK_GROUP_SHIFT \ -- GROUP_SHIFT(CCK_ACK_DURATION(10, false)) -+ GROUP_SHIFT(CCK_DURATION(10, false)) - - #define CCK_GROUP __CCK_GROUP(CCK_GROUP_SHIFT) - -@@ -349,15 +345,19 @@ int - minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, - int prob_avg) - { -- unsigned int nsecs = 0; -+ unsigned int nsecs = 0, overhead = mi->overhead; -+ unsigned int ampdu_len = 1; - - /* do not account throughput if sucess prob is below 10% */ - if (prob_avg < MINSTREL_FRAC(10, 100)) - return 0; - -- if (group != MINSTREL_CCK_GROUP) -- nsecs = 1000 * mi->overhead / minstrel_ht_avg_ampdu_len(mi); -+ if (group == MINSTREL_CCK_GROUP) -+ overhead = mi->overhead_legacy; -+ else -+ ampdu_len = minstrel_ht_avg_ampdu_len(mi); - -+ nsecs = 1000 * overhead / ampdu_len; - nsecs += minstrel_mcs_groups[group].duration[rate] << - minstrel_mcs_groups[group].shift; - -@@ -1031,7 +1031,10 @@ minstrel_calc_retransmit(struct minstrel - ctime += (t_slot * cw) >> 1; - cw = min((cw << 1) | 1, mp->cw_max); - -- if (index / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) { -+ if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) { -+ overhead = mi->overhead_legacy; -+ overhead_rtscts = mi->overhead_legacy_rtscts; -+ } else { - overhead = mi->overhead; - overhead_rtscts = mi->overhead_rtscts; - } -@@ -1369,18 +1372,14 @@ minstrel_ht_update_cck(struct minstrel_p - if (!ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) - return; - -- mi->cck_supported = 0; -- mi->cck_supported_short = 0; - for (i = 0; i < 4; i++) { - if (!rate_supported(sta, sband->band, mp->cck_rates[i])) - continue; - -- mi->cck_supported |= BIT(i); -+ mi->supported[MINSTREL_CCK_GROUP] |= BIT(i); - if (sband->bitrates[i].flags & IEEE80211_RATE_SHORT_PREAMBLE) -- mi->cck_supported_short |= BIT(i); -+ mi->supported[MINSTREL_CCK_GROUP] |= BIT(i + 4); - } -- -- mi->supported[MINSTREL_CCK_GROUP] = mi->cck_supported; - } - - static void -@@ -1394,12 +1393,13 @@ minstrel_ht_update_caps(void *priv, stru - struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; - u16 ht_cap = sta->ht_cap.cap; - struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; -+ const struct ieee80211_rate *ctl_rate; -+ bool ldpc, erp; - int use_vht; - int n_supported = 0; - int ack_dur; - int stbc; - int i; -- bool ldpc; - - /* fall back to the old minstrel for legacy stations */ - if (!sta->ht_cap.ht_supported) -@@ -1423,6 +1423,14 @@ minstrel_ht_update_caps(void *priv, stru - mi->overhead += ack_dur; - mi->overhead_rtscts = mi->overhead + 2 * ack_dur; - -+ ctl_rate = &sband->bitrates[rate_lowest_index(sband, sta)]; -+ erp = ctl_rate->flags & IEEE80211_RATE_ERP_G; -+ ack_dur = ieee80211_frame_duration(sband->band, 10, -+ ctl_rate->bitrate, erp, 1, -+ ieee80211_chandef_get_shift(chandef)); -+ mi->overhead_legacy = ack_dur; -+ mi->overhead_legacy_rtscts = mi->overhead_legacy + 2 * ack_dur; -+ - mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); - - /* When using MRR, sample more on the first attempt, without delay */ -@@ -1523,8 +1531,6 @@ minstrel_ht_update_caps(void *priv, stru - if (!n_supported) - goto use_legacy; - -- mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4; -- - /* create an initial rate table with the lowest supported rates */ - minstrel_ht_update_stats(mp, mi, true); - minstrel_ht_update_rates(mp, mi); ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -77,6 +77,8 @@ struct minstrel_ht_sta { - /* overhead time in usec for each frame */ - unsigned int overhead; - unsigned int overhead_rtscts; -+ unsigned int overhead_legacy; -+ unsigned int overhead_legacy_rtscts; - - unsigned int total_packets_last; - unsigned int total_packets_cur; -@@ -97,9 +99,6 @@ struct minstrel_ht_sta { - /* current MCS group to be sampled */ - u8 sample_group; - -- u8 cck_supported; -- u8 cck_supported_short; -- - /* Bitfield of supported MCS rates of all groups */ - u16 supported[MINSTREL_GROUPS_NB]; - diff --git a/package/kernel/mac80211/patches/subsys/338-mac80211-minstrel_ht-add-support-for-OFDM-rates-on-n.patch b/package/kernel/mac80211/patches/subsys/338-mac80211-minstrel_ht-add-support-for-OFDM-rates-on-n.patch deleted file mode 100644 index abefde710..000000000 --- a/package/kernel/mac80211/patches/subsys/338-mac80211-minstrel_ht-add-support-for-OFDM-rates-on-n.patch +++ /dev/null @@ -1,762 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 13:56:42 +0100 -Subject: [PATCH] mac80211: minstrel_ht: add support for OFDM rates on - non-HT clients - -The legacy minstrel code is essentially unmaintained and receives only very -little testing. In order to bring the significant algorithm improvements from -minstrel_ht to legacy clients, this patch adds support for OFDM rates to -minstrel_ht and removes the fallback to the legacy codepath. -This also makes it work much better on hardware with rate selection constraints, -e.g. mt76. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel.h -+++ b/net/mac80211/rc80211_minstrel.h -@@ -152,6 +152,7 @@ struct minstrel_priv { - unsigned int lookaround_rate_mrr; - - u8 cck_rates[4]; -+ u8 ofdm_rates[NUM_NL80211_BANDS][8]; - - #ifdef CPTCFG_MAC80211_DEBUGFS - /* ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -163,6 +163,38 @@ - - #define CCK_GROUP __CCK_GROUP(CCK_GROUP_SHIFT) - -+#define OFDM_DURATION(_bitrate) \ -+ (1000 * (16 /* SIFS + signal ext */ + \ -+ 16 /* T_PREAMBLE */ + \ -+ 4 /* T_SIGNAL */ + \ -+ 4 * (((16 + 80 * (AVG_PKT_SIZE + 4) + 6) / \ -+ ((_bitrate) * 4))))) -+ -+#define OFDM_DURATION_LIST(_s) \ -+ OFDM_DURATION(60) >> _s, \ -+ OFDM_DURATION(90) >> _s, \ -+ OFDM_DURATION(120) >> _s, \ -+ OFDM_DURATION(180) >> _s, \ -+ OFDM_DURATION(240) >> _s, \ -+ OFDM_DURATION(360) >> _s, \ -+ OFDM_DURATION(480) >> _s, \ -+ OFDM_DURATION(540) >> _s -+ -+#define __OFDM_GROUP(_s) \ -+ [MINSTREL_OFDM_GROUP] = { \ -+ .streams = 1, \ -+ .flags = 0, \ -+ .shift = _s, \ -+ .duration = { \ -+ OFDM_DURATION_LIST(_s), \ -+ } \ -+ } -+ -+#define OFDM_GROUP_SHIFT \ -+ GROUP_SHIFT(OFDM_DURATION(60)) -+ -+#define OFDM_GROUP __OFDM_GROUP(OFDM_GROUP_SHIFT) -+ - - static bool minstrel_vht_only = true; - module_param(minstrel_vht_only, bool, 0644); -@@ -199,6 +231,7 @@ const struct mcs_group minstrel_mcs_grou - MCS_GROUP(4, 1, BW_40), - - CCK_GROUP, -+ OFDM_GROUP, - - VHT_GROUP(1, 0, BW_20), - VHT_GROUP(2, 0, BW_20), -@@ -231,6 +264,8 @@ const struct mcs_group minstrel_mcs_grou - VHT_GROUP(4, 1, BW_80), - }; - -+const s16 minstrel_cck_bitrates[4] = { 10, 20, 55, 110 }; -+const s16 minstrel_ofdm_bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 }; - static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; - - static void -@@ -275,6 +310,13 @@ minstrel_get_valid_vht_rates(int bw, int - return 0x3ff & ~mask; - } - -+static bool -+minstrel_ht_is_legacy_group(int group) -+{ -+ return group == MINSTREL_CCK_GROUP || -+ group == MINSTREL_OFDM_GROUP; -+} -+ - /* - * Look up an MCS group index based on mac80211 rate information - */ -@@ -304,21 +346,34 @@ minstrel_ht_get_stats(struct minstrel_pr - if (rate->flags & IEEE80211_TX_RC_MCS) { - group = minstrel_ht_get_group_idx(rate); - idx = rate->idx % 8; -- } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { -+ goto out; -+ } -+ -+ if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { - group = minstrel_vht_get_group_idx(rate); - idx = ieee80211_rate_get_vht_mcs(rate); -- } else { -- group = MINSTREL_CCK_GROUP; -+ goto out; -+ } - -- for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) -- if (rate->idx == mp->cck_rates[idx]) -- break; -+ group = MINSTREL_CCK_GROUP; -+ for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) { -+ if (rate->idx != mp->cck_rates[idx]) -+ continue; - - /* short preamble */ - if ((mi->supported[group] & BIT(idx + 4)) && - (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) -- idx += 4; -+ idx += 4; -+ goto out; - } -+ -+ group = MINSTREL_OFDM_GROUP; -+ for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++) -+ if (rate->idx == mp->ofdm_rates[mi->band][idx]) -+ goto out; -+ -+ idx = 0; -+out: - return &mi->groups[group].rates[idx]; - } - -@@ -352,7 +407,7 @@ minstrel_ht_get_tp_avg(struct minstrel_h - if (prob_avg < MINSTREL_FRAC(10, 100)) - return 0; - -- if (group == MINSTREL_CCK_GROUP) -+ if (minstrel_ht_is_legacy_group(group)) - overhead = mi->overhead_legacy; - else - ampdu_len = minstrel_ht_avg_ampdu_len(mi); -@@ -439,8 +494,8 @@ minstrel_ht_set_best_prob_rate(struct mi - /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from - * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ - max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES; -- if((index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) && -- (max_tp_group != MINSTREL_CCK_GROUP)) -+ if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) && -+ !minstrel_ht_is_legacy_group(max_tp_group)) - return; - - max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; -@@ -476,13 +531,13 @@ minstrel_ht_set_best_prob_rate(struct mi - static void - minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi, - u16 tmp_mcs_tp_rate[MAX_THR_RATES], -- u16 tmp_cck_tp_rate[MAX_THR_RATES]) -+ u16 tmp_legacy_tp_rate[MAX_THR_RATES]) - { - unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob; - int i; - -- tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; -- tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; -+ tmp_group = tmp_legacy_tp_rate[0] / MCS_GROUP_RATES; -+ tmp_idx = tmp_legacy_tp_rate[0] % MCS_GROUP_RATES; - tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; - tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); - -@@ -493,7 +548,7 @@ minstrel_ht_assign_best_tp_rates(struct - - if (tmp_cck_tp > tmp_mcs_tp) { - for(i = 0; i < MAX_THR_RATES; i++) { -- minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i], -+ minstrel_ht_sort_best_tp_rates(mi, tmp_legacy_tp_rate[i], - tmp_mcs_tp_rate); - } - } -@@ -511,6 +566,9 @@ minstrel_ht_prob_rate_reduce_streams(str - int tmp_max_streams, group, tmp_idx, tmp_prob; - int tmp_tp = 0; - -+ if (!mi->sta->ht_cap.ht_supported) -+ return; -+ - tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / - MCS_GROUP_RATES].streams; - for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { -@@ -675,7 +733,8 @@ minstrel_ht_update_stats(struct minstrel - struct minstrel_rate_stats *mrs; - int group, i, j, cur_prob; - u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; -- u16 tmp_cck_tp_rate[MAX_THR_RATES], index; -+ u16 tmp_legacy_tp_rate[MAX_THR_RATES], index; -+ bool ht_supported = mi->sta->ht_cap.ht_supported; - - mi->sample_mode = MINSTREL_SAMPLE_IDLE; - -@@ -704,21 +763,29 @@ minstrel_ht_update_stats(struct minstrel - mi->sample_count = 0; - - memset(tmp_mcs_tp_rate, 0, sizeof(tmp_mcs_tp_rate)); -- memset(tmp_cck_tp_rate, 0, sizeof(tmp_cck_tp_rate)); -+ memset(tmp_legacy_tp_rate, 0, sizeof(tmp_legacy_tp_rate)); - if (mi->supported[MINSTREL_CCK_GROUP]) -- for (j = 0; j < ARRAY_SIZE(tmp_cck_tp_rate); j++) -- tmp_cck_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; -+ for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) -+ tmp_legacy_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; -+ else if (mi->supported[MINSTREL_OFDM_GROUP]) -+ for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) -+ tmp_legacy_tp_rate[j] = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; - - if (mi->supported[MINSTREL_VHT_GROUP_0]) - index = MINSTREL_VHT_GROUP_0 * MCS_GROUP_RATES; -- else -+ else if (ht_supported) - index = MINSTREL_HT_GROUP_0 * MCS_GROUP_RATES; -+ else if (mi->supported[MINSTREL_CCK_GROUP]) -+ index = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; -+ else -+ index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; - - for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) - tmp_mcs_tp_rate[j] = index; - - /* Find best rate sets within all MCS groups*/ - for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { -+ u16 *tp_rate = tmp_mcs_tp_rate; - - mg = &mi->groups[group]; - if (!mi->supported[group]) -@@ -730,6 +797,9 @@ minstrel_ht_update_stats(struct minstrel - for(j = 0; j < MAX_THR_RATES; j++) - tmp_group_tp_rate[j] = MCS_GROUP_RATES * group; - -+ if (group == MINSTREL_CCK_GROUP && ht_supported) -+ tp_rate = tmp_legacy_tp_rate; -+ - for (i = 0; i < MCS_GROUP_RATES; i++) { - if (!(mi->supported[group] & BIT(i))) - continue; -@@ -745,13 +815,7 @@ minstrel_ht_update_stats(struct minstrel - continue; - - /* Find max throughput rate set */ -- if (group != MINSTREL_CCK_GROUP) { -- minstrel_ht_sort_best_tp_rates(mi, index, -- tmp_mcs_tp_rate); -- } else if (group == MINSTREL_CCK_GROUP) { -- minstrel_ht_sort_best_tp_rates(mi, index, -- tmp_cck_tp_rate); -- } -+ minstrel_ht_sort_best_tp_rates(mi, index, tp_rate); - - /* Find max throughput rate set within a group */ - minstrel_ht_sort_best_tp_rates(mi, index, -@@ -766,7 +830,8 @@ minstrel_ht_update_stats(struct minstrel - } - - /* Assign new rate set per sta */ -- minstrel_ht_assign_best_tp_rates(mi, tmp_mcs_tp_rate, tmp_cck_tp_rate); -+ minstrel_ht_assign_best_tp_rates(mi, tmp_mcs_tp_rate, -+ tmp_legacy_tp_rate); - memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate)); - - /* Try to increase robustness of max_prob_rate*/ -@@ -795,8 +860,11 @@ minstrel_ht_update_stats(struct minstrel - } - - static bool --minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct ieee80211_tx_rate *rate) -+minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, -+ struct ieee80211_tx_rate *rate) - { -+ int i; -+ - if (rate->idx < 0) - return false; - -@@ -807,10 +875,15 @@ minstrel_ht_txstat_valid(struct minstrel - rate->flags & IEEE80211_TX_RC_VHT_MCS) - return true; - -- return rate->idx == mp->cck_rates[0] || -- rate->idx == mp->cck_rates[1] || -- rate->idx == mp->cck_rates[2] || -- rate->idx == mp->cck_rates[3]; -+ for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) -+ if (rate->idx == mp->cck_rates[i]) -+ return true; -+ -+ for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates[0]); i++) -+ if (rate->idx == mp->ofdm_rates[mi->band][i]) -+ return true; -+ -+ return false; - } - - static void -@@ -897,11 +970,6 @@ minstrel_ht_tx_status(void *priv, struct - bool sample_status = false; - int i; - -- if (!msp->is_ht) -- return mac80211_minstrel.tx_status_ext(priv, sband, -- &msp->legacy, st); -- -- - /* This packet was aggregated but doesn't carry status info */ - if ((info->flags & IEEE80211_TX_CTL_AMPDU) && - !(info->flags & IEEE80211_TX_STAT_AMPDU)) -@@ -930,10 +998,10 @@ minstrel_ht_tx_status(void *priv, struct - if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) - rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); - -- last = !minstrel_ht_txstat_valid(mp, &ar[0]); -+ last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]); - for (i = 0; !last; i++) { - last = (i == IEEE80211_TX_MAX_RATES - 1) || -- !minstrel_ht_txstat_valid(mp, &ar[i + 1]); -+ !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]); - - rate = minstrel_ht_get_stats(mp, mi, &ar[i]); - if (rate == rate_sample) -@@ -1031,7 +1099,7 @@ minstrel_calc_retransmit(struct minstrel - ctime += (t_slot * cw) >> 1; - cw = min((cw << 1) | 1, mp->cw_max); - -- if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) { -+ if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES)) { - overhead = mi->overhead_legacy; - overhead_rtscts = mi->overhead_legacy_rtscts; - } else { -@@ -1064,7 +1132,8 @@ static void - minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, - struct ieee80211_sta_rates *ratetbl, int offset, int index) - { -- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; -+ int group_idx = index / MCS_GROUP_RATES; -+ const struct mcs_group *group = &minstrel_mcs_groups[group_idx]; - struct minstrel_rate_stats *mrs; - u8 idx; - u16 flags = group->flags; -@@ -1083,13 +1152,17 @@ minstrel_ht_set_rate(struct minstrel_pri - ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts; - } - -- if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) -+ index %= MCS_GROUP_RATES; -+ if (group_idx == MINSTREL_CCK_GROUP) - idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; -+ else if (group_idx == MINSTREL_OFDM_GROUP) -+ idx = mp->ofdm_rates[mi->band][index % -+ ARRAY_SIZE(mp->ofdm_rates[0])]; - else if (flags & IEEE80211_TX_RC_VHT_MCS) - idx = ((group->streams - 1) << 4) | -- ((index % MCS_GROUP_RATES) & 0xF); -+ (index & 0xF); - else -- idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8; -+ idx = index + (group->streams - 1) * 8; - - /* enable RTS/CTS if needed: - * - if station is in dynamic SMPS (and streams > 1) -@@ -1304,11 +1377,8 @@ minstrel_ht_get_rate(void *priv, struct - struct minstrel_priv *mp = priv; - int sample_idx; - -- if (!msp->is_ht) -- return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc); -- - if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && -- mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) -+ !minstrel_ht_is_legacy_group(mi->max_prob_rate / MCS_GROUP_RATES)) - minstrel_aggr_check(sta, txrc->skb); - - info->flags |= mi->tx_flags; -@@ -1349,6 +1419,9 @@ minstrel_ht_get_rate(void *priv, struct - if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) { - int idx = sample_idx % ARRAY_SIZE(mp->cck_rates); - rate->idx = mp->cck_rates[idx]; -+ } else if (sample_group == &minstrel_mcs_groups[MINSTREL_OFDM_GROUP]) { -+ int idx = sample_idx % ARRAY_SIZE(mp->ofdm_rates[0]); -+ rate->idx = mp->ofdm_rates[mi->band][idx]; - } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { - ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES, - sample_group->streams); -@@ -1369,11 +1442,13 @@ minstrel_ht_update_cck(struct minstrel_p - if (sband->band != NL80211_BAND_2GHZ) - return; - -- if (!ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) -+ if (sta->ht_cap.ht_supported && -+ !ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) - return; - - for (i = 0; i < 4; i++) { -- if (!rate_supported(sta, sband->band, mp->cck_rates[i])) -+ if (mp->cck_rates[i] == 0xff || -+ !rate_supported(sta, sband->band, mp->cck_rates[i])) - continue; - - mi->supported[MINSTREL_CCK_GROUP] |= BIT(i); -@@ -1383,9 +1458,30 @@ minstrel_ht_update_cck(struct minstrel_p - } - - static void -+minstrel_ht_update_ofdm(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, -+ struct ieee80211_supported_band *sband, -+ struct ieee80211_sta *sta) -+{ -+ const u8 *rates; -+ int i; -+ -+ if (sta->ht_cap.ht_supported) -+ return; -+ -+ rates = mp->ofdm_rates[sband->band]; -+ for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates[0]); i++) { -+ if (rates[i] == 0xff || -+ !rate_supported(sta, sband->band, rates[i])) -+ continue; -+ -+ mi->supported[MINSTREL_OFDM_GROUP] |= BIT(i); -+ } -+} -+ -+static void - minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, - struct cfg80211_chan_def *chandef, -- struct ieee80211_sta *sta, void *priv_sta) -+ struct ieee80211_sta *sta, void *priv_sta) - { - struct minstrel_priv *mp = priv; - struct minstrel_ht_sta_priv *msp = priv_sta; -@@ -1401,10 +1497,6 @@ minstrel_ht_update_caps(void *priv, stru - int stbc; - int i; - -- /* fall back to the old minstrel for legacy stations */ -- if (!sta->ht_cap.ht_supported) -- goto use_legacy; -- - BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB); - - if (vht_cap->vht_supported) -@@ -1412,10 +1504,10 @@ minstrel_ht_update_caps(void *priv, stru - else - use_vht = 0; - -- msp->is_ht = true; - memset(mi, 0, sizeof(*mi)); - - mi->sta = sta; -+ mi->band = sband->band; - mi->last_stats_update = jiffies; - - ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0); -@@ -1464,10 +1556,8 @@ minstrel_ht_update_caps(void *priv, stru - int bw, nss; - - mi->supported[i] = 0; -- if (i == MINSTREL_CCK_GROUP) { -- minstrel_ht_update_cck(mp, mi, sband, sta); -+ if (minstrel_ht_is_legacy_group(i)) - continue; -- } - - if (gflags & IEEE80211_TX_RC_SHORT_GI) { - if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) { -@@ -1528,22 +1618,12 @@ minstrel_ht_update_caps(void *priv, stru - n_supported++; - } - -- if (!n_supported) -- goto use_legacy; -+ minstrel_ht_update_cck(mp, mi, sband, sta); -+ minstrel_ht_update_ofdm(mp, mi, sband, sta); - - /* create an initial rate table with the lowest supported rates */ - minstrel_ht_update_stats(mp, mi, true); - minstrel_ht_update_rates(mp, mi); -- -- return; -- --use_legacy: -- msp->is_ht = false; -- memset(&msp->legacy, 0, sizeof(msp->legacy)); -- msp->legacy.r = msp->ratelist; -- msp->legacy.sample_table = msp->sample_table; -- return mac80211_minstrel.rate_init(priv, sband, chandef, sta, -- &msp->legacy); - } - - static void -@@ -1611,40 +1691,70 @@ minstrel_ht_free_sta(void *priv, struct - } - - static void --minstrel_ht_init_cck_rates(struct minstrel_priv *mp) -+minstrel_ht_fill_rate_array(u8 *dest, struct ieee80211_supported_band *sband, -+ const s16 *bitrates, int n_rates, u32 rate_flags) - { -- static const int bitrates[4] = { 10, 20, 55, 110 }; -- struct ieee80211_supported_band *sband; -- u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); - int i, j; - -- sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; -- if (!sband) -- return; -- - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - -- if (rate->flags & IEEE80211_RATE_ERP_G) -- continue; -- - if ((rate_flags & sband->bitrates[i].flags) != rate_flags) - continue; - -- for (j = 0; j < ARRAY_SIZE(bitrates); j++) { -+ for (j = 0; j < n_rates; j++) { - if (rate->bitrate != bitrates[j]) - continue; - -- mp->cck_rates[j] = i; -+ dest[j] = i; - break; - } - } - } - -+static void -+minstrel_ht_init_cck_rates(struct minstrel_priv *mp) -+{ -+ static const s16 bitrates[4] = { 10, 20, 55, 110 }; -+ struct ieee80211_supported_band *sband; -+ u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); -+ -+ memset(mp->cck_rates, 0xff, sizeof(mp->cck_rates)); -+ sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; -+ if (!sband) -+ return; -+ -+ BUILD_BUG_ON(ARRAY_SIZE(mp->cck_rates) != ARRAY_SIZE(bitrates)); -+ minstrel_ht_fill_rate_array(mp->cck_rates, sband, -+ minstrel_cck_bitrates, -+ ARRAY_SIZE(minstrel_cck_bitrates), -+ rate_flags); -+} -+ -+static void -+minstrel_ht_init_ofdm_rates(struct minstrel_priv *mp, enum nl80211_band band) -+{ -+ static const s16 bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 }; -+ struct ieee80211_supported_band *sband; -+ u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); -+ -+ memset(mp->ofdm_rates[band], 0xff, sizeof(mp->ofdm_rates[band])); -+ sband = mp->hw->wiphy->bands[band]; -+ if (!sband) -+ return; -+ -+ BUILD_BUG_ON(ARRAY_SIZE(mp->ofdm_rates[band]) != ARRAY_SIZE(bitrates)); -+ minstrel_ht_fill_rate_array(mp->ofdm_rates[band], sband, -+ minstrel_ofdm_bitrates, -+ ARRAY_SIZE(minstrel_ofdm_bitrates), -+ rate_flags); -+} -+ - static void * - minstrel_ht_alloc(struct ieee80211_hw *hw) - { - struct minstrel_priv *mp; -+ int i; - - mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); - if (!mp) -@@ -1681,6 +1791,8 @@ minstrel_ht_alloc(struct ieee80211_hw *h - mp->new_avg = true; - - minstrel_ht_init_cck_rates(mp); -+ for (i = 0; i < ARRAY_SIZE(mp->hw->wiphy->bands); i++) -+ minstrel_ht_init_ofdm_rates(mp, i); - - return mp; - } -@@ -1713,9 +1825,6 @@ static u32 minstrel_ht_get_expected_thro - struct minstrel_ht_sta *mi = &msp->ht; - int i, j, prob, tp_avg; - -- if (!msp->is_ht) -- return mac80211_minstrel.get_expected_throughput(priv_sta); -- - i = mi->max_tp_rate[0] / MCS_GROUP_RATES; - j = mi->max_tp_rate[0] % MCS_GROUP_RATES; - prob = mi->groups[i].rates[j].prob_avg; ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -18,14 +18,15 @@ - MINSTREL_HT_STREAM_GROUPS) - #define MINSTREL_VHT_GROUPS_NB (MINSTREL_MAX_STREAMS * \ - MINSTREL_VHT_STREAM_GROUPS) --#define MINSTREL_CCK_GROUPS_NB 1 -+#define MINSTREL_LEGACY_GROUPS_NB 2 - #define MINSTREL_GROUPS_NB (MINSTREL_HT_GROUPS_NB + \ - MINSTREL_VHT_GROUPS_NB + \ -- MINSTREL_CCK_GROUPS_NB) -+ MINSTREL_LEGACY_GROUPS_NB) - - #define MINSTREL_HT_GROUP_0 0 - #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB) --#define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1) -+#define MINSTREL_OFDM_GROUP (MINSTREL_CCK_GROUP + 1) -+#define MINSTREL_VHT_GROUP_0 (MINSTREL_OFDM_GROUP + 1) - - #define MCS_GROUP_RATES 10 - -@@ -37,6 +38,8 @@ struct mcs_group { - u16 duration[MCS_GROUP_RATES]; - }; - -+extern const s16 minstrel_cck_bitrates[4]; -+extern const s16 minstrel_ofdm_bitrates[8]; - extern const struct mcs_group minstrel_mcs_groups[]; - - struct minstrel_mcs_group_data { -@@ -99,6 +102,8 @@ struct minstrel_ht_sta { - /* current MCS group to be sampled */ - u8 sample_group; - -+ u8 band; -+ - /* Bitfield of supported MCS rates of all groups */ - u16 supported[MINSTREL_GROUPS_NB]; - -@@ -107,13 +112,9 @@ struct minstrel_ht_sta { - }; - - struct minstrel_ht_sta_priv { -- union { -- struct minstrel_ht_sta ht; -- struct minstrel_sta_info legacy; -- }; -+ struct minstrel_ht_sta ht; - void *ratelist; - void *sample_table; -- bool is_ht; - }; - - void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); ---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c -+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c -@@ -52,7 +52,6 @@ minstrel_ht_stats_dump(struct minstrel_h - - for (j = 0; j < MCS_GROUP_RATES; j++) { - struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; -- static const int bitrates[4] = { 10, 20, 55, 110 }; - int idx = i * MCS_GROUP_RATES + j; - unsigned int duration; - -@@ -67,6 +66,9 @@ minstrel_ht_stats_dump(struct minstrel_h - p += sprintf(p, "VHT%c0 ", htmode); - p += sprintf(p, "%cGI ", gimode); - p += sprintf(p, "%d ", mg->streams); -+ } else if (i == MINSTREL_OFDM_GROUP) { -+ p += sprintf(p, "OFDM "); -+ p += sprintf(p, "1 "); - } else { - p += sprintf(p, "CCK "); - p += sprintf(p, "%cP ", j < 4 ? 'L' : 'S'); -@@ -84,7 +86,12 @@ minstrel_ht_stats_dump(struct minstrel_h - } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { - p += sprintf(p, " MCS%-1u/%1u", j, mg->streams); - } else { -- int r = bitrates[j % 4]; -+ int r; -+ -+ if (i == MINSTREL_OFDM_GROUP) -+ r = minstrel_ofdm_bitrates[j % 8]; -+ else -+ r = minstrel_cck_bitrates[j % 4]; - - p += sprintf(p, " %2u.%1uM", r / 10, r % 10); - } -@@ -124,16 +131,8 @@ minstrel_ht_stats_open(struct inode *ino - struct minstrel_ht_sta *mi = &msp->ht; - struct minstrel_debugfs_info *ms; - unsigned int i; -- int ret; - char *p; - -- if (!msp->is_ht) { -- inode->i_private = &msp->legacy; -- ret = minstrel_stats_open(inode, file); -- inode->i_private = msp; -- return ret; -- } -- - ms = kmalloc(32768, GFP_KERNEL); - if (!ms) - return -ENOMEM; -@@ -199,7 +198,6 @@ minstrel_ht_stats_csv_dump(struct minstr - - for (j = 0; j < MCS_GROUP_RATES; j++) { - struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; -- static const int bitrates[4] = { 10, 20, 55, 110 }; - int idx = i * MCS_GROUP_RATES + j; - unsigned int duration; - -@@ -214,6 +212,8 @@ minstrel_ht_stats_csv_dump(struct minstr - p += sprintf(p, "VHT%c0,", htmode); - p += sprintf(p, "%cGI,", gimode); - p += sprintf(p, "%d,", mg->streams); -+ } else if (i == MINSTREL_OFDM_GROUP) { -+ p += sprintf(p, "OFDM,,1,"); - } else { - p += sprintf(p, "CCK,"); - p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S'); -@@ -231,7 +231,13 @@ minstrel_ht_stats_csv_dump(struct minstr - } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { - p += sprintf(p, ",MCS%-1u/%1u,", j, mg->streams); - } else { -- int r = bitrates[j % 4]; -+ int r; -+ -+ if (i == MINSTREL_OFDM_GROUP) -+ r = minstrel_ofdm_bitrates[j % 8]; -+ else -+ r = minstrel_cck_bitrates[j % 4]; -+ - p += sprintf(p, ",%2u.%1uM,", r / 10, r % 10); - } - -@@ -274,18 +280,9 @@ minstrel_ht_stats_csv_open(struct inode - struct minstrel_ht_sta *mi = &msp->ht; - struct minstrel_debugfs_info *ms; - unsigned int i; -- int ret; - char *p; - -- if (!msp->is_ht) { -- inode->i_private = &msp->legacy; -- ret = minstrel_stats_csv_open(inode, file); -- inode->i_private = msp; -- return ret; -- } -- - ms = kmalloc(32768, GFP_KERNEL); -- - if (!ms) - return -ENOMEM; - diff --git a/package/kernel/mac80211/patches/subsys/339-mac80211-remove-legacy-minstrel-rate-control.patch b/package/kernel/mac80211/patches/subsys/339-mac80211-remove-legacy-minstrel-rate-control.patch deleted file mode 100644 index 1cab2eb19..000000000 --- a/package/kernel/mac80211/patches/subsys/339-mac80211-remove-legacy-minstrel-rate-control.patch +++ /dev/null @@ -1,1328 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 14:23:47 +0100 -Subject: [PATCH] mac80211: remove legacy minstrel rate control - -Now that minstrel_ht supports legacy rates, it is no longer needed - -Signed-off-by: Felix Fietkau ---- - delete mode 100644 net/mac80211/rc80211_minstrel.c - delete mode 100644 net/mac80211/rc80211_minstrel.h - delete mode 100644 net/mac80211/rc80211_minstrel_debugfs.c - ---- a/net/mac80211/Makefile -+++ b/net/mac80211/Makefile -@@ -56,11 +56,9 @@ mac80211-$(CONFIG_PM) += pm.o - CFLAGS_trace.o := -I$(src) - - rc80211_minstrel-y := \ -- rc80211_minstrel.o \ - rc80211_minstrel_ht.o - - rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += \ -- rc80211_minstrel_debugfs.o \ - rc80211_minstrel_ht_debugfs.o - - mac80211-$(CPTCFG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) ---- a/net/mac80211/rc80211_minstrel.c -+++ /dev/null -@@ -1,574 +0,0 @@ --/* -- * Copyright (C) 2008 Felix Fietkau -- * -- * 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. -- * -- * Based on minstrel.c: -- * Copyright (C) 2005-2007 Derek Smithies -- * Sponsored by Indranet Technologies Ltd -- * -- * Based on sample.c: -- * Copyright (c) 2005 John Bicket -- * All rights reserved. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions -- * are met: -- * 1. Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer, -- * without modification. -- * 2. Redistributions in binary form must reproduce at minimum a disclaimer -- * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any -- * redistribution must be conditioned upon including a substantially -- * similar Disclaimer requirement for further binary redistribution. -- * 3. Neither the names of the above-listed copyright holders nor the names -- * of any contributors may be used to endorse or promote products derived -- * from this software without specific prior written permission. -- * -- * Alternatively, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") version 2 as published by the Free -- * Software Foundation. -- * -- * NO WARRANTY -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY -- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, -- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -- * THE POSSIBILITY OF SUCH DAMAGES. -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include "rate.h" --#include "rc80211_minstrel.h" -- --#define SAMPLE_TBL(_mi, _idx, _col) \ -- _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] -- --/* convert mac80211 rate index to local array index */ --static inline int --rix_to_ndx(struct minstrel_sta_info *mi, int rix) --{ -- int i = rix; -- for (i = rix; i >= 0; i--) -- if (mi->r[i].rix == rix) -- break; -- return i; --} -- --/* return current EMWA throughput */ --int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg) --{ -- int usecs; -- -- usecs = mr->perfect_tx_time; -- if (!usecs) -- usecs = 1000000; -- -- /* reset thr. below 10% success */ -- if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100)) -- return 0; -- -- if (prob_avg > MINSTREL_FRAC(90, 100)) -- return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs)); -- else -- return MINSTREL_TRUNC(100000 * (prob_avg / usecs)); --} -- --/* find & sort topmost throughput rates */ --static inline void --minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) --{ -- int j; -- struct minstrel_rate_stats *tmp_mrs; -- struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats; -- -- for (j = MAX_THR_RATES; j > 0; --j) { -- tmp_mrs = &mi->r[tp_list[j - 1]].stats; -- if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <= -- minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg)) -- break; -- } -- -- if (j < MAX_THR_RATES - 1) -- memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); -- if (j < MAX_THR_RATES) -- tp_list[j] = i; --} -- --static void --minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *ratetbl, -- int offset, int idx) --{ -- struct minstrel_rate *r = &mi->r[idx]; -- -- ratetbl->rate[offset].idx = r->rix; -- ratetbl->rate[offset].count = r->adjusted_retry_count; -- ratetbl->rate[offset].count_cts = r->retry_count_cts; -- ratetbl->rate[offset].count_rts = r->stats.retry_count_rtscts; --} -- --static void --minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi) --{ -- struct ieee80211_sta_rates *ratetbl; -- int i = 0; -- -- ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC); -- if (!ratetbl) -- return; -- -- /* Start with max_tp_rate */ -- minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]); -- -- if (mp->hw->max_rates >= 3) { -- /* At least 3 tx rates supported, use max_tp_rate2 next */ -- minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[1]); -- } -- -- if (mp->hw->max_rates >= 2) { -- /* At least 2 tx rates supported, use max_prob_rate next */ -- minstrel_set_rate(mi, ratetbl, i++, mi->max_prob_rate); -- } -- -- /* Use lowest rate last */ -- ratetbl->rate[i].idx = mi->lowest_rix; -- ratetbl->rate[i].count = mp->max_retry; -- ratetbl->rate[i].count_cts = mp->max_retry; -- ratetbl->rate[i].count_rts = mp->max_retry; -- -- rate_control_set_rates(mp->hw, mi->sta, ratetbl); --} -- --/* --* Recalculate statistics and counters of a given rate --*/ --void --minstrel_calc_rate_stats(struct minstrel_priv *mp, -- struct minstrel_rate_stats *mrs) --{ -- unsigned int cur_prob; -- -- if (unlikely(mrs->attempts > 0)) { -- mrs->sample_skipped = 0; -- cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); -- if (mp->new_avg) { -- minstrel_filter_avg_add(&mrs->prob_avg, -- &mrs->prob_avg_1, cur_prob); -- } else if (unlikely(!mrs->att_hist)) { -- mrs->prob_avg = cur_prob; -- } else { -- /*update exponential weighted moving avarage */ -- mrs->prob_avg = minstrel_ewma(mrs->prob_avg, -- cur_prob, -- EWMA_LEVEL); -- } -- mrs->att_hist += mrs->attempts; -- mrs->succ_hist += mrs->success; -- } else { -- mrs->sample_skipped++; -- } -- -- mrs->last_success = mrs->success; -- mrs->last_attempts = mrs->attempts; -- mrs->success = 0; -- mrs->attempts = 0; --} -- --static void --minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) --{ -- u8 tmp_tp_rate[MAX_THR_RATES]; -- u8 tmp_prob_rate = 0; -- int i, tmp_cur_tp, tmp_prob_tp; -- -- for (i = 0; i < MAX_THR_RATES; i++) -- tmp_tp_rate[i] = 0; -- -- for (i = 0; i < mi->n_rates; i++) { -- struct minstrel_rate *mr = &mi->r[i]; -- struct minstrel_rate_stats *mrs = &mi->r[i].stats; -- struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; -- -- /* Update statistics of success probability per rate */ -- minstrel_calc_rate_stats(mp, mrs); -- -- /* Sample less often below the 10% chance of success. -- * Sample less often above the 95% chance of success. */ -- if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || -- mrs->prob_avg < MINSTREL_FRAC(10, 100)) { -- mr->adjusted_retry_count = mrs->retry_count >> 1; -- if (mr->adjusted_retry_count > 2) -- mr->adjusted_retry_count = 2; -- mr->sample_limit = 4; -- } else { -- mr->sample_limit = -1; -- mr->adjusted_retry_count = mrs->retry_count; -- } -- if (!mr->adjusted_retry_count) -- mr->adjusted_retry_count = 2; -- -- minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); -- -- /* To determine the most robust rate (max_prob_rate) used at -- * 3rd mmr stage we distinct between two cases: -- * (1) if any success probabilitiy >= 95%, out of those rates -- * choose the maximum throughput rate as max_prob_rate -- * (2) if all success probabilities < 95%, the rate with -- * highest success probability is chosen as max_prob_rate */ -- if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) { -- tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg); -- tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate], -- tmp_mrs->prob_avg); -- if (tmp_cur_tp >= tmp_prob_tp) -- tmp_prob_rate = i; -- } else { -- if (mrs->prob_avg >= tmp_mrs->prob_avg) -- tmp_prob_rate = i; -- } -- } -- -- /* Assign the new rate set */ -- memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); -- mi->max_prob_rate = tmp_prob_rate; -- --#ifdef CPTCFG_MAC80211_DEBUGFS -- /* use fixed index if set */ -- if (mp->fixed_rate_idx != -1) { -- mi->max_tp_rate[0] = mp->fixed_rate_idx; -- mi->max_tp_rate[1] = mp->fixed_rate_idx; -- mi->max_prob_rate = mp->fixed_rate_idx; -- } --#endif -- -- /* Reset update timer */ -- mi->last_stats_update = jiffies; -- -- minstrel_update_rates(mp, mi); --} -- --static void --minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, -- void *priv_sta, struct ieee80211_tx_status *st) --{ -- struct ieee80211_tx_info *info = st->info; -- struct minstrel_priv *mp = priv; -- struct minstrel_sta_info *mi = priv_sta; -- struct ieee80211_tx_rate *ar = info->status.rates; -- int i, ndx; -- int success; -- -- success = !!(info->flags & IEEE80211_TX_STAT_ACK); -- -- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -- if (ar[i].idx < 0 || !ar[i].count) -- break; -- -- ndx = rix_to_ndx(mi, ar[i].idx); -- if (ndx < 0) -- continue; -- -- mi->r[ndx].stats.attempts += ar[i].count; -- -- if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) -- mi->r[ndx].stats.success += success; -- } -- -- if (time_after(jiffies, mi->last_stats_update + -- mp->update_interval / (mp->new_avg ? 2 : 1))) -- minstrel_update_stats(mp, mi); --} -- -- --static inline unsigned int --minstrel_get_retry_count(struct minstrel_rate *mr, -- struct ieee80211_tx_info *info) --{ -- u8 retry = mr->adjusted_retry_count; -- -- if (info->control.use_rts) -- retry = max_t(u8, 2, min(mr->stats.retry_count_rtscts, retry)); -- else if (info->control.use_cts_prot) -- retry = max_t(u8, 2, min(mr->retry_count_cts, retry)); -- return retry; --} -- -- --static int --minstrel_get_next_sample(struct minstrel_sta_info *mi) --{ -- unsigned int sample_ndx; -- sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column); -- mi->sample_row++; -- if ((int) mi->sample_row >= mi->n_rates) { -- mi->sample_row = 0; -- mi->sample_column++; -- if (mi->sample_column >= SAMPLE_COLUMNS) -- mi->sample_column = 0; -- } -- return sample_ndx; --} -- --static void --minstrel_get_rate(void *priv, struct ieee80211_sta *sta, -- void *priv_sta, struct ieee80211_tx_rate_control *txrc) --{ -- struct sk_buff *skb = txrc->skb; -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- struct minstrel_sta_info *mi = priv_sta; -- struct minstrel_priv *mp = priv; -- struct ieee80211_tx_rate *rate = &info->control.rates[0]; -- struct minstrel_rate *msr, *mr; -- unsigned int ndx; -- bool mrr_capable; -- bool prev_sample; -- int delta; -- int sampling_ratio; -- -- /* check multi-rate-retry capabilities & adjust lookaround_rate */ -- mrr_capable = mp->has_mrr && -- !txrc->rts && -- !txrc->bss_conf->use_cts_prot; -- if (mrr_capable) -- sampling_ratio = mp->lookaround_rate_mrr; -- else -- sampling_ratio = mp->lookaround_rate; -- -- /* increase sum packet counter */ -- mi->total_packets++; -- --#ifdef CPTCFG_MAC80211_DEBUGFS -- if (mp->fixed_rate_idx != -1) -- return; --#endif -- -- /* Don't use EAPOL frames for sampling on non-mrr hw */ -- if (mp->hw->max_rates == 1 && -- (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) -- return; -- -- delta = (mi->total_packets * sampling_ratio / 100) - -- mi->sample_packets; -- -- /* delta < 0: no sampling required */ -- prev_sample = mi->prev_sample; -- mi->prev_sample = false; -- if (delta < 0 || (!mrr_capable && prev_sample)) -- return; -- -- if (mi->total_packets >= 10000) { -- mi->sample_packets = 0; -- mi->total_packets = 0; -- } else if (delta > mi->n_rates * 2) { -- /* With multi-rate retry, not every planned sample -- * attempt actually gets used, due to the way the retry -- * chain is set up - [max_tp,sample,prob,lowest] for -- * sample_rate < max_tp. -- * -- * If there's too much sampling backlog and the link -- * starts getting worse, minstrel would start bursting -- * out lots of sampling frames, which would result -- * in a large throughput loss. */ -- mi->sample_packets += (delta - mi->n_rates * 2); -- } -- -- /* get next random rate sample */ -- ndx = minstrel_get_next_sample(mi); -- msr = &mi->r[ndx]; -- mr = &mi->r[mi->max_tp_rate[0]]; -- -- /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage) -- * rate sampling method should be used. -- * Respect such rates that are not sampled for 20 interations. -- */ -- if (msr->perfect_tx_time < mr->perfect_tx_time || -- msr->stats.sample_skipped >= 20) { -- if (!msr->sample_limit) -- return; -- -- mi->sample_packets++; -- if (msr->sample_limit > 0) -- msr->sample_limit--; -- } -- -- /* If we're not using MRR and the sampling rate already -- * has a probability of >95%, we shouldn't be attempting -- * to use it, as this only wastes precious airtime */ -- if (!mrr_capable && -- (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100))) -- return; -- -- mi->prev_sample = true; -- -- rate->idx = mi->r[ndx].rix; -- rate->count = minstrel_get_retry_count(&mi->r[ndx], info); -- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; --} -- -- --static void --calc_rate_durations(enum nl80211_band band, -- struct minstrel_rate *d, -- struct ieee80211_rate *rate, -- struct cfg80211_chan_def *chandef) --{ -- int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); -- int shift = ieee80211_chandef_get_shift(chandef); -- -- d->perfect_tx_time = ieee80211_frame_duration(band, 1200, -- DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1, -- shift); -- d->ack_time = ieee80211_frame_duration(band, 10, -- DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1, -- shift); --} -- --static void --init_sample_table(struct minstrel_sta_info *mi) --{ -- unsigned int i, col, new_idx; -- u8 rnd[8]; -- -- mi->sample_column = 0; -- mi->sample_row = 0; -- memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); -- -- for (col = 0; col < SAMPLE_COLUMNS; col++) { -- prandom_bytes(rnd, sizeof(rnd)); -- for (i = 0; i < mi->n_rates; i++) { -- new_idx = (i + rnd[i & 7]) % mi->n_rates; -- while (SAMPLE_TBL(mi, new_idx, col) != 0xff) -- new_idx = (new_idx + 1) % mi->n_rates; -- -- SAMPLE_TBL(mi, new_idx, col) = i; -- } -- } --} -- --static void --minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, -- struct cfg80211_chan_def *chandef, -- struct ieee80211_sta *sta, void *priv_sta) --{ -- struct minstrel_sta_info *mi = priv_sta; -- struct minstrel_priv *mp = priv; -- struct ieee80211_rate *ctl_rate; -- unsigned int i, n = 0; -- unsigned int t_slot = 9; /* FIXME: get real slot time */ -- u32 rate_flags; -- -- mi->sta = sta; -- mi->lowest_rix = rate_lowest_index(sband, sta); -- ctl_rate = &sband->bitrates[mi->lowest_rix]; -- mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10, -- ctl_rate->bitrate, -- !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1, -- ieee80211_chandef_get_shift(chandef)); -- -- rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); -- memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate)); -- mi->max_prob_rate = 0; -- -- for (i = 0; i < sband->n_bitrates; i++) { -- struct minstrel_rate *mr = &mi->r[n]; -- struct minstrel_rate_stats *mrs = &mi->r[n].stats; -- unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; -- unsigned int tx_time_single; -- unsigned int cw = mp->cw_min; -- int shift; -- -- if (!rate_supported(sta, sband->band, i)) -- continue; -- if ((rate_flags & sband->bitrates[i].flags) != rate_flags) -- continue; -- -- n++; -- memset(mr, 0, sizeof(*mr)); -- memset(mrs, 0, sizeof(*mrs)); -- -- mr->rix = i; -- shift = ieee80211_chandef_get_shift(chandef); -- mr->bitrate = DIV_ROUND_UP(sband->bitrates[i].bitrate, -- (1 << shift) * 5); -- calc_rate_durations(sband->band, mr, &sband->bitrates[i], -- chandef); -- -- /* calculate maximum number of retransmissions before -- * fallback (based on maximum segment size) */ -- mr->sample_limit = -1; -- mrs->retry_count = 1; -- mr->retry_count_cts = 1; -- mrs->retry_count_rtscts = 1; -- tx_time = mr->perfect_tx_time + mi->sp_ack_dur; -- do { -- /* add one retransmission */ -- tx_time_single = mr->ack_time + mr->perfect_tx_time; -- -- /* contention window */ -- tx_time_single += (t_slot * cw) >> 1; -- cw = min((cw << 1) | 1, mp->cw_max); -- -- tx_time += tx_time_single; -- tx_time_cts += tx_time_single + mi->sp_ack_dur; -- tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; -- if ((tx_time_cts < mp->segment_size) && -- (mr->retry_count_cts < mp->max_retry)) -- mr->retry_count_cts++; -- if ((tx_time_rtscts < mp->segment_size) && -- (mrs->retry_count_rtscts < mp->max_retry)) -- mrs->retry_count_rtscts++; -- } while ((tx_time < mp->segment_size) && -- (++mr->stats.retry_count < mp->max_retry)); -- mr->adjusted_retry_count = mrs->retry_count; -- if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G)) -- mr->retry_count_cts = mrs->retry_count; -- } -- -- for (i = n; i < sband->n_bitrates; i++) { -- struct minstrel_rate *mr = &mi->r[i]; -- mr->rix = -1; -- } -- -- mi->n_rates = n; -- mi->last_stats_update = jiffies; -- -- init_sample_table(mi); -- minstrel_update_rates(mp, mi); --} -- --static u32 minstrel_get_expected_throughput(void *priv_sta) --{ -- struct minstrel_sta_info *mi = priv_sta; -- struct minstrel_rate_stats *tmp_mrs; -- int idx = mi->max_tp_rate[0]; -- int tmp_cur_tp; -- -- /* convert pkt per sec in kbps (1200 is the average pkt size used for -- * computing cur_tp -- */ -- tmp_mrs = &mi->r[idx].stats; -- tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10; -- tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; -- -- return tmp_cur_tp; --} -- --const struct rate_control_ops mac80211_minstrel = { -- .tx_status_ext = minstrel_tx_status, -- .get_rate = minstrel_get_rate, -- .rate_init = minstrel_rate_init, -- .get_expected_throughput = minstrel_get_expected_throughput, --}; ---- a/net/mac80211/rc80211_minstrel.h -+++ /dev/null -@@ -1,185 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0-only */ --/* -- * Copyright (C) 2008 Felix Fietkau -- */ -- --#ifndef __RC_MINSTREL_H --#define __RC_MINSTREL_H -- --#define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */ --#define EWMA_DIV 128 --#define SAMPLE_COLUMNS 10 /* number of columns in sample table */ -- --/* scaled fraction values */ --#define MINSTREL_SCALE 12 --#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) --#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) -- --/* number of highest throughput rates to consider*/ --#define MAX_THR_RATES 4 -- --/* -- * Coefficients for moving average with noise filter (period=16), -- * scaled by 10 bits -- * -- * a1 = exp(-pi * sqrt(2) / period) -- * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period) -- * coeff3 = -sqr(a1) -- * coeff1 = 1 - coeff2 - coeff3 -- */ --#define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \ -- MINSTREL_AVG_COEFF2 - \ -- MINSTREL_AVG_COEFF3) --#define MINSTREL_AVG_COEFF2 0x00001499 --#define MINSTREL_AVG_COEFF3 -0x0000092e -- --/* -- * Perform EWMA (Exponentially Weighted Moving Average) calculation -- */ --static inline int --minstrel_ewma(int old, int new, int weight) --{ -- int diff, incr; -- -- diff = new - old; -- incr = (EWMA_DIV - weight) * diff / EWMA_DIV; -- -- return old + incr; --} -- --static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) --{ -- s32 out_1 = *prev_1; -- s32 out_2 = *prev_2; -- s32 val; -- -- if (!in) -- in += 1; -- -- if (!out_1) { -- val = out_1 = in; -- goto out; -- } -- -- val = MINSTREL_AVG_COEFF1 * in; -- val += MINSTREL_AVG_COEFF2 * out_1; -- val += MINSTREL_AVG_COEFF3 * out_2; -- val >>= MINSTREL_SCALE; -- -- if (val > 1 << MINSTREL_SCALE) -- val = 1 << MINSTREL_SCALE; -- if (val < 0) -- val = 1; -- --out: -- *prev_2 = out_1; -- *prev_1 = val; -- -- return val; --} -- --struct minstrel_rate_stats { -- /* current / last sampling period attempts/success counters */ -- u16 attempts, last_attempts; -- u16 success, last_success; -- -- /* total attempts/success counters */ -- u32 att_hist, succ_hist; -- -- /* prob_avg - moving average of prob */ -- u16 prob_avg; -- u16 prob_avg_1; -- -- /* maximum retry counts */ -- u8 retry_count; -- u8 retry_count_rtscts; -- -- u8 sample_skipped; -- bool retry_updated; --}; -- --struct minstrel_rate { -- int bitrate; -- -- s8 rix; -- u8 retry_count_cts; -- u8 adjusted_retry_count; -- -- unsigned int perfect_tx_time; -- unsigned int ack_time; -- -- int sample_limit; -- -- struct minstrel_rate_stats stats; --}; -- --struct minstrel_sta_info { -- struct ieee80211_sta *sta; -- -- unsigned long last_stats_update; -- unsigned int sp_ack_dur; -- unsigned int rate_avg; -- -- unsigned int lowest_rix; -- -- u8 max_tp_rate[MAX_THR_RATES]; -- u8 max_prob_rate; -- unsigned int total_packets; -- unsigned int sample_packets; -- -- unsigned int sample_row; -- unsigned int sample_column; -- -- int n_rates; -- struct minstrel_rate *r; -- bool prev_sample; -- -- /* sampling table */ -- u8 *sample_table; --}; -- --struct minstrel_priv { -- struct ieee80211_hw *hw; -- bool has_mrr; -- bool new_avg; -- u32 sample_switch; -- unsigned int cw_min; -- unsigned int cw_max; -- unsigned int max_retry; -- unsigned int segment_size; -- unsigned int update_interval; -- unsigned int lookaround_rate; -- unsigned int lookaround_rate_mrr; -- -- u8 cck_rates[4]; -- u8 ofdm_rates[NUM_NL80211_BANDS][8]; -- --#ifdef CPTCFG_MAC80211_DEBUGFS -- /* -- * enable fixed rate processing per RC -- * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx -- * - write -1 to enable RC processing again -- * - setting will be applied on next update -- */ -- u32 fixed_rate_idx; --#endif --}; -- --struct minstrel_debugfs_info { -- size_t len; -- char buf[]; --}; -- --extern const struct rate_control_ops mac80211_minstrel; --void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); -- --/* Recalculate success probabilities and counters for a given rate using EWMA */ --void minstrel_calc_rate_stats(struct minstrel_priv *mp, -- struct minstrel_rate_stats *mrs); --int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg); -- --/* debugfs */ --int minstrel_stats_open(struct inode *inode, struct file *file); --int minstrel_stats_csv_open(struct inode *inode, struct file *file); -- --#endif ---- a/net/mac80211/rc80211_minstrel_debugfs.c -+++ /dev/null -@@ -1,172 +0,0 @@ --/* -- * Copyright (C) 2008 Felix Fietkau -- * -- * 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. -- * -- * Based on minstrel.c: -- * Copyright (C) 2005-2007 Derek Smithies -- * Sponsored by Indranet Technologies Ltd -- * -- * Based on sample.c: -- * Copyright (c) 2005 John Bicket -- * All rights reserved. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions -- * are met: -- * 1. Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer, -- * without modification. -- * 2. Redistributions in binary form must reproduce at minimum a disclaimer -- * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any -- * redistribution must be conditioned upon including a substantially -- * similar Disclaimer requirement for further binary redistribution. -- * 3. Neither the names of the above-listed copyright holders nor the names -- * of any contributors may be used to endorse or promote products derived -- * from this software without specific prior written permission. -- * -- * Alternatively, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") version 2 as published by the Free -- * Software Foundation. -- * -- * NO WARRANTY -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY -- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, -- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -- * THE POSSIBILITY OF SUCH DAMAGES. -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include "rc80211_minstrel.h" -- --int --minstrel_stats_open(struct inode *inode, struct file *file) --{ -- struct minstrel_sta_info *mi = inode->i_private; -- struct minstrel_debugfs_info *ms; -- unsigned int i, tp_max, tp_avg, eprob; -- char *p; -- -- ms = kmalloc(2048, GFP_KERNEL); -- if (!ms) -- return -ENOMEM; -- -- file->private_data = ms; -- p = ms->buf; -- p += sprintf(p, "\n"); -- p += sprintf(p, -- "best __________rate_________ ____statistics___ ____last_____ ______sum-of________\n"); -- p += sprintf(p, -- "rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n"); -- -- for (i = 0; i < mi->n_rates; i++) { -- struct minstrel_rate *mr = &mi->r[i]; -- struct minstrel_rate_stats *mrs = &mi->r[i].stats; -- -- *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; -- *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; -- *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; -- *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; -- *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; -- -- p += sprintf(p, " %3u%s ", mr->bitrate / 2, -- (mr->bitrate & 1 ? ".5" : " ")); -- p += sprintf(p, "%3u ", i); -- p += sprintf(p, "%6u ", mr->perfect_tx_time); -- -- tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); -- tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); -- eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); -- -- p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u" -- " %3u %3u %-3u " -- "%9llu %-9llu\n", -- tp_max / 10, tp_max % 10, -- tp_avg / 10, tp_avg % 10, -- eprob / 10, eprob % 10, -- mrs->retry_count, -- mrs->last_success, -- mrs->last_attempts, -- (unsigned long long)mrs->succ_hist, -- (unsigned long long)mrs->att_hist); -- } -- p += sprintf(p, "\nTotal packet count:: ideal %d " -- "lookaround %d\n\n", -- mi->total_packets - mi->sample_packets, -- mi->sample_packets); -- ms->len = p - ms->buf; -- -- WARN_ON(ms->len + sizeof(*ms) > 2048); -- -- return 0; --} -- --int --minstrel_stats_csv_open(struct inode *inode, struct file *file) --{ -- struct minstrel_sta_info *mi = inode->i_private; -- struct minstrel_debugfs_info *ms; -- unsigned int i, tp_max, tp_avg, eprob; -- char *p; -- -- ms = kmalloc(2048, GFP_KERNEL); -- if (!ms) -- return -ENOMEM; -- -- file->private_data = ms; -- p = ms->buf; -- -- for (i = 0; i < mi->n_rates; i++) { -- struct minstrel_rate *mr = &mi->r[i]; -- struct minstrel_rate_stats *mrs = &mi->r[i].stats; -- -- p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); -- p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : "")); -- p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C" : "")); -- p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D" : "")); -- p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P" : "")); -- -- p += sprintf(p, ",%u%s", mr->bitrate / 2, -- (mr->bitrate & 1 ? ".5," : ",")); -- p += sprintf(p, "%u,", i); -- p += sprintf(p, "%u,",mr->perfect_tx_time); -- -- tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); -- tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); -- eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); -- -- p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," -- "%llu,%llu,%d,%d\n", -- tp_max / 10, tp_max % 10, -- tp_avg / 10, tp_avg % 10, -- eprob / 10, eprob % 10, -- mrs->retry_count, -- mrs->last_success, -- mrs->last_attempts, -- (unsigned long long)mrs->succ_hist, -- (unsigned long long)mrs->att_hist, -- mi->total_packets - mi->sample_packets, -- mi->sample_packets); -- -- } -- ms->len = p - ms->buf; -- -- WARN_ON(ms->len + sizeof(*ms) > 2048); -- -- return 0; --} ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -13,7 +13,6 @@ - #include - #include "rate.h" - #include "sta_info.h" --#include "rc80211_minstrel.h" - #include "rc80211_minstrel_ht.h" - - #define AVG_AMPDU_SIZE 16 -@@ -716,6 +715,83 @@ out: - mi->sample_mode = MINSTREL_SAMPLE_ACTIVE; - } - -+static inline int -+minstrel_ewma(int old, int new, int weight) -+{ -+ int diff, incr; -+ -+ diff = new - old; -+ incr = (EWMA_DIV - weight) * diff / EWMA_DIV; -+ -+ return old + incr; -+} -+ -+static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) -+{ -+ s32 out_1 = *prev_1; -+ s32 out_2 = *prev_2; -+ s32 val; -+ -+ if (!in) -+ in += 1; -+ -+ if (!out_1) { -+ val = out_1 = in; -+ goto out; -+ } -+ -+ val = MINSTREL_AVG_COEFF1 * in; -+ val += MINSTREL_AVG_COEFF2 * out_1; -+ val += MINSTREL_AVG_COEFF3 * out_2; -+ val >>= MINSTREL_SCALE; -+ -+ if (val > 1 << MINSTREL_SCALE) -+ val = 1 << MINSTREL_SCALE; -+ if (val < 0) -+ val = 1; -+ -+out: -+ *prev_2 = out_1; -+ *prev_1 = val; -+ -+ return val; -+} -+ -+/* -+* Recalculate statistics and counters of a given rate -+*/ -+static void -+minstrel_ht_calc_rate_stats(struct minstrel_priv *mp, -+ struct minstrel_rate_stats *mrs) -+{ -+ unsigned int cur_prob; -+ -+ if (unlikely(mrs->attempts > 0)) { -+ mrs->sample_skipped = 0; -+ cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); -+ if (mp->new_avg) { -+ minstrel_filter_avg_add(&mrs->prob_avg, -+ &mrs->prob_avg_1, cur_prob); -+ } else if (unlikely(!mrs->att_hist)) { -+ mrs->prob_avg = cur_prob; -+ } else { -+ /*update exponential weighted moving avarage */ -+ mrs->prob_avg = minstrel_ewma(mrs->prob_avg, -+ cur_prob, -+ EWMA_LEVEL); -+ } -+ mrs->att_hist += mrs->attempts; -+ mrs->succ_hist += mrs->success; -+ } else { -+ mrs->sample_skipped++; -+ } -+ -+ mrs->last_success = mrs->success; -+ mrs->last_attempts = mrs->attempts; -+ mrs->success = 0; -+ mrs->attempts = 0; -+} -+ - /* - * Update rate statistics and select new primary rates - * -@@ -808,7 +884,7 @@ minstrel_ht_update_stats(struct minstrel - - mrs = &mg->rates[i]; - mrs->retry_updated = false; -- minstrel_calc_rate_stats(mp, mrs); -+ minstrel_ht_calc_rate_stats(mp, mrs); - cur_prob = mrs->prob_avg; - - if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) -@@ -960,8 +1036,7 @@ minstrel_ht_tx_status(void *priv, struct - void *priv_sta, struct ieee80211_tx_status *st) - { - struct ieee80211_tx_info *info = st->info; -- struct minstrel_ht_sta_priv *msp = priv_sta; -- struct minstrel_ht_sta *mi = &msp->ht; -+ struct minstrel_ht_sta *mi = priv_sta; - struct ieee80211_tx_rate *ar = info->status.rates; - struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL; - struct minstrel_priv *mp = priv; -@@ -1372,8 +1447,7 @@ minstrel_ht_get_rate(void *priv, struct - const struct mcs_group *sample_group; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); - struct ieee80211_tx_rate *rate = &info->status.rates[0]; -- struct minstrel_ht_sta_priv *msp = priv_sta; -- struct minstrel_ht_sta *mi = &msp->ht; -+ struct minstrel_ht_sta *mi = priv_sta; - struct minstrel_priv *mp = priv; - int sample_idx; - -@@ -1484,8 +1558,7 @@ minstrel_ht_update_caps(void *priv, stru - struct ieee80211_sta *sta, void *priv_sta) - { - struct minstrel_priv *mp = priv; -- struct minstrel_ht_sta_priv *msp = priv_sta; -- struct minstrel_ht_sta *mi = &msp->ht; -+ struct minstrel_ht_sta *mi = priv_sta; - struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; - u16 ht_cap = sta->ht_cap.cap; - struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; -@@ -1647,7 +1720,7 @@ static void * - minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) - { - struct ieee80211_supported_band *sband; -- struct minstrel_ht_sta_priv *msp; -+ struct minstrel_ht_sta *mi; - struct minstrel_priv *mp = priv; - struct ieee80211_hw *hw = mp->hw; - int max_rates = 0; -@@ -1659,35 +1732,13 @@ minstrel_ht_alloc_sta(void *priv, struct - max_rates = sband->n_bitrates; - } - -- msp = kzalloc(sizeof(*msp), gfp); -- if (!msp) -- return NULL; -- -- msp->ratelist = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp); -- if (!msp->ratelist) -- goto error; -- -- msp->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp); -- if (!msp->sample_table) -- goto error1; -- -- return msp; -- --error1: -- kfree(msp->ratelist); --error: -- kfree(msp); -- return NULL; -+ return kzalloc(sizeof(*mi), gfp); - } - - static void - minstrel_ht_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) - { -- struct minstrel_ht_sta_priv *msp = priv_sta; -- -- kfree(msp->sample_table); -- kfree(msp->ratelist); -- kfree(msp); -+ kfree(priv_sta); - } - - static void -@@ -1768,12 +1819,6 @@ minstrel_ht_alloc(struct ieee80211_hw *h - mp->cw_min = 15; - mp->cw_max = 1023; - -- /* number of packets (in %) to use for sampling other rates -- * sample less often for non-mrr packets, because the overhead -- * is much higher than with mrr */ -- mp->lookaround_rate = 5; -- mp->lookaround_rate_mrr = 10; -- - /* maximum time that the hw is allowed to stay in one MRR segment */ - mp->segment_size = 6000; - -@@ -1821,8 +1866,7 @@ minstrel_ht_free(void *priv) - - static u32 minstrel_ht_get_expected_throughput(void *priv_sta) - { -- struct minstrel_ht_sta_priv *msp = priv_sta; -- struct minstrel_ht_sta *mi = &msp->ht; -+ struct minstrel_ht_sta *mi = priv_sta; - int i, j, prob, tp_avg; - - i = mi->max_tp_rate[0] / MCS_GROUP_RATES; ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -6,6 +6,33 @@ - #ifndef __RC_MINSTREL_HT_H - #define __RC_MINSTREL_HT_H - -+/* number of highest throughput rates to consider*/ -+#define MAX_THR_RATES 4 -+#define SAMPLE_COLUMNS 10 /* number of columns in sample table */ -+ -+/* scaled fraction values */ -+#define MINSTREL_SCALE 12 -+#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) -+#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) -+ -+#define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */ -+#define EWMA_DIV 128 -+ -+/* -+ * Coefficients for moving average with noise filter (period=16), -+ * scaled by 10 bits -+ * -+ * a1 = exp(-pi * sqrt(2) / period) -+ * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period) -+ * coeff3 = -sqr(a1) -+ * coeff1 = 1 - coeff2 - coeff3 -+ */ -+#define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \ -+ MINSTREL_AVG_COEFF2 - \ -+ MINSTREL_AVG_COEFF3) -+#define MINSTREL_AVG_COEFF2 0x00001499 -+#define MINSTREL_AVG_COEFF3 -0x0000092e -+ - /* - * The number of streams can be changed to 2 to reduce code - * size and memory footprint. -@@ -30,6 +57,32 @@ - - #define MCS_GROUP_RATES 10 - -+struct minstrel_priv { -+ struct ieee80211_hw *hw; -+ bool has_mrr; -+ bool new_avg; -+ u32 sample_switch; -+ unsigned int cw_min; -+ unsigned int cw_max; -+ unsigned int max_retry; -+ unsigned int segment_size; -+ unsigned int update_interval; -+ -+ u8 cck_rates[4]; -+ u8 ofdm_rates[NUM_NL80211_BANDS][8]; -+ -+#ifdef CPTCFG_MAC80211_DEBUGFS -+ /* -+ * enable fixed rate processing per RC -+ * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx -+ * - write -1 to enable RC processing again -+ * - setting will be applied on next update -+ */ -+ u32 fixed_rate_idx; -+#endif -+}; -+ -+ - struct mcs_group { - u16 flags; - u8 streams; -@@ -42,6 +95,26 @@ extern const s16 minstrel_cck_bitrates[4 - extern const s16 minstrel_ofdm_bitrates[8]; - extern const struct mcs_group minstrel_mcs_groups[]; - -+struct minstrel_rate_stats { -+ /* current / last sampling period attempts/success counters */ -+ u16 attempts, last_attempts; -+ u16 success, last_success; -+ -+ /* total attempts/success counters */ -+ u32 att_hist, succ_hist; -+ -+ /* prob_avg - moving average of prob */ -+ u16 prob_avg; -+ u16 prob_avg_1; -+ -+ /* maximum retry counts */ -+ u8 retry_count; -+ u8 retry_count_rtscts; -+ -+ u8 sample_skipped; -+ bool retry_updated; -+}; -+ - struct minstrel_mcs_group_data { - u8 index; - u8 column; -@@ -111,12 +184,6 @@ struct minstrel_ht_sta { - struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB]; - }; - --struct minstrel_ht_sta_priv { -- struct minstrel_ht_sta ht; -- void *ratelist; -- void *sample_table; --}; -- - void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); - int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, - int prob_avg); ---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c -+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c -@@ -9,9 +9,13 @@ - #include - #include - #include --#include "rc80211_minstrel.h" - #include "rc80211_minstrel_ht.h" - -+struct minstrel_debugfs_info { -+ size_t len; -+ char buf[]; -+}; -+ - static ssize_t - minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) - { -@@ -127,8 +131,7 @@ minstrel_ht_stats_dump(struct minstrel_h - static int - minstrel_ht_stats_open(struct inode *inode, struct file *file) - { -- struct minstrel_ht_sta_priv *msp = inode->i_private; -- struct minstrel_ht_sta *mi = &msp->ht; -+ struct minstrel_ht_sta *mi = inode->i_private; - struct minstrel_debugfs_info *ms; - unsigned int i; - char *p; -@@ -276,8 +279,7 @@ minstrel_ht_stats_csv_dump(struct minstr - static int - minstrel_ht_stats_csv_open(struct inode *inode, struct file *file) - { -- struct minstrel_ht_sta_priv *msp = inode->i_private; -- struct minstrel_ht_sta *mi = &msp->ht; -+ struct minstrel_ht_sta *mi = inode->i_private; - struct minstrel_debugfs_info *ms; - unsigned int i; - char *p; -@@ -313,10 +315,8 @@ static const struct file_operations mins - void - minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) - { -- struct minstrel_ht_sta_priv *msp = priv_sta; -- -- debugfs_create_file("rc_stats", 0444, dir, msp, -+ debugfs_create_file("rc_stats", 0444, dir, priv_sta, - &minstrel_ht_stat_fops); -- debugfs_create_file("rc_stats_csv", 0444, dir, msp, -+ debugfs_create_file("rc_stats_csv", 0444, dir, priv_sta, - &minstrel_ht_stat_csv_fops); - } diff --git a/package/kernel/mac80211/patches/subsys/340-mac80211-minstrel_ht-remove-old-ewma-based-rate-aver.patch b/package/kernel/mac80211/patches/subsys/340-mac80211-minstrel_ht-remove-old-ewma-based-rate-aver.patch deleted file mode 100644 index 9b6a614aa..000000000 --- a/package/kernel/mac80211/patches/subsys/340-mac80211-minstrel_ht-remove-old-ewma-based-rate-aver.patch +++ /dev/null @@ -1,96 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 14:34:30 +0100 -Subject: [PATCH] mac80211: minstrel_ht: remove old ewma based rate average - code - -The new noise filter has been the default for a while now with no reported -downside and significant improvement compared to the old code. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -769,17 +769,8 @@ minstrel_ht_calc_rate_stats(struct minst - if (unlikely(mrs->attempts > 0)) { - mrs->sample_skipped = 0; - cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); -- if (mp->new_avg) { -- minstrel_filter_avg_add(&mrs->prob_avg, -- &mrs->prob_avg_1, cur_prob); -- } else if (unlikely(!mrs->att_hist)) { -- mrs->prob_avg = cur_prob; -- } else { -- /*update exponential weighted moving avarage */ -- mrs->prob_avg = minstrel_ewma(mrs->prob_avg, -- cur_prob, -- EWMA_LEVEL); -- } -+ minstrel_filter_avg_add(&mrs->prob_avg, -+ &mrs->prob_avg_1, cur_prob); - mrs->att_hist += mrs->attempts; - mrs->succ_hist += mrs->success; - } else { -@@ -913,10 +904,8 @@ minstrel_ht_update_stats(struct minstrel - /* Try to increase robustness of max_prob_rate*/ - minstrel_ht_prob_rate_reduce_streams(mi); - -- /* try to sample all available rates during each interval */ -- mi->sample_count *= 8; -- if (mp->new_avg) -- mi->sample_count /= 2; -+ /* try to sample half of all available rates during each interval */ -+ mi->sample_count *= 4; - - if (sample) - minstrel_ht_rate_sample_switch(mp, mi); -@@ -1040,7 +1029,7 @@ minstrel_ht_tx_status(void *priv, struct - struct ieee80211_tx_rate *ar = info->status.rates; - struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL; - struct minstrel_priv *mp = priv; -- u32 update_interval = mp->update_interval / 2; -+ u32 update_interval = mp->update_interval; - bool last, update = false; - bool sample_status = false; - int i; -@@ -1090,9 +1079,8 @@ minstrel_ht_tx_status(void *priv, struct - - switch (mi->sample_mode) { - case MINSTREL_SAMPLE_IDLE: -- if (mp->new_avg && -- (mp->hw->max_rates > 1 || -- mi->total_packets_cur < SAMPLE_SWITCH_THR)) -+ if (mp->hw->max_rates > 1 || -+ mi->total_packets_cur < SAMPLE_SWITCH_THR) - update_interval /= 2; - break; - -@@ -1832,8 +1820,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h - mp->has_mrr = true; - - mp->hw = hw; -- mp->update_interval = HZ / 10; -- mp->new_avg = true; -+ mp->update_interval = HZ / 20; - - minstrel_ht_init_cck_rates(mp); - for (i = 0; i < ARRAY_SIZE(mp->hw->wiphy->bands); i++) -@@ -1853,8 +1840,6 @@ static void minstrel_ht_add_debugfs(stru - &mp->fixed_rate_idx); - debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir, - &mp->sample_switch); -- debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir, -- &mp->new_avg); - } - #endif - ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -60,7 +60,6 @@ - struct minstrel_priv { - struct ieee80211_hw *hw; - bool has_mrr; -- bool new_avg; - u32 sample_switch; - unsigned int cw_min; - unsigned int cw_max; diff --git a/package/kernel/mac80211/patches/subsys/341-mac80211-minstrel_ht-improve-ampdu-length-estimation.patch b/package/kernel/mac80211/patches/subsys/341-mac80211-minstrel_ht-improve-ampdu-length-estimation.patch deleted file mode 100644 index a8e6e8995..000000000 --- a/package/kernel/mac80211/patches/subsys/341-mac80211-minstrel_ht-improve-ampdu-length-estimation.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 19:08:19 +0100 -Subject: [PATCH] mac80211: minstrel_ht: improve ampdu length estimation - -If the driver does not report A-MPDU length, estimate it based on the rate. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -382,13 +382,37 @@ minstrel_get_ratestats(struct minstrel_h - return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; - } - -+static inline int -+minstrel_get_duration(int index) -+{ -+ const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; -+ unsigned int duration = group->duration[index % MCS_GROUP_RATES]; -+ return duration << group->shift; -+} -+ - static unsigned int - minstrel_ht_avg_ampdu_len(struct minstrel_ht_sta *mi) - { -- if (!mi->avg_ampdu_len) -- return AVG_AMPDU_SIZE; -+ int duration; -+ -+ if (mi->avg_ampdu_len) -+ return MINSTREL_TRUNC(mi->avg_ampdu_len); -+ -+ if (minstrel_ht_is_legacy_group(mi->max_tp_rate[0] / MCS_GROUP_RATES)) -+ return 1; -+ -+ duration = minstrel_get_duration(mi->max_tp_rate[0]); - -- return MINSTREL_TRUNC(mi->avg_ampdu_len); -+ if (duration > 400 * 1000) -+ return 2; -+ -+ if (duration > 250 * 1000) -+ return 4; -+ -+ if (duration > 150 * 1000) -+ return 8; -+ -+ return 16; - } - - /* -@@ -588,14 +612,6 @@ minstrel_ht_prob_rate_reduce_streams(str - } - } - --static inline int --minstrel_get_duration(int index) --{ -- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; -- unsigned int duration = group->duration[index % MCS_GROUP_RATES]; -- return duration << group->shift; --} -- - static bool - minstrel_ht_probe_group(struct minstrel_ht_sta *mi, const struct mcs_group *tp_group, - int tp_idx, const struct mcs_group *group) diff --git a/package/kernel/mac80211/patches/subsys/342-mac80211-minstrel_ht-improve-sample-rate-selection.patch b/package/kernel/mac80211/patches/subsys/342-mac80211-minstrel_ht-improve-sample-rate-selection.patch deleted file mode 100644 index e08452523..000000000 --- a/package/kernel/mac80211/patches/subsys/342-mac80211-minstrel_ht-improve-sample-rate-selection.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 19:12:22 +0100 -Subject: [PATCH] mac80211: minstrel_ht: improve sample rate selection - -Always allow sampling of rates faster than the primary max throughput rate. -When the second max_tp_rate is higher than the first one, sample attempts were -previously skipped, potentially causing rate control to get stuck at a slightly -lower rate - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1379,13 +1379,13 @@ minstrel_get_sample_rate(struct minstrel - mrs = &mg->rates[sample_idx]; - sample_idx += sample_group * MCS_GROUP_RATES; - -- /* Set tp_rate1, tp_rate2 to the highest / second highest max_tp_rate */ -+ tp_rate1 = mi->max_tp_rate[0]; -+ -+ /* Set tp_rate2 to the second highest max_tp_rate */ - if (minstrel_get_duration(mi->max_tp_rate[0]) > - minstrel_get_duration(mi->max_tp_rate[1])) { -- tp_rate1 = mi->max_tp_rate[1]; - tp_rate2 = mi->max_tp_rate[0]; - } else { -- tp_rate1 = mi->max_tp_rate[0]; - tp_rate2 = mi->max_tp_rate[1]; - } - diff --git a/package/kernel/mac80211/patches/subsys/343-mac80211-minstrel_ht-fix-max-probability-rate-select.patch b/package/kernel/mac80211/patches/subsys/343-mac80211-minstrel_ht-fix-max-probability-rate-select.patch deleted file mode 100644 index 0dbfa9d4f..000000000 --- a/package/kernel/mac80211/patches/subsys/343-mac80211-minstrel_ht-fix-max-probability-rate-select.patch +++ /dev/null @@ -1,124 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 19:09:08 +0100 -Subject: [PATCH] mac80211: minstrel_ht: fix max probability rate selection - -- do not select rates faster than the max throughput rate if probability is lower -- reset previous rate before sorting again - -This ensures that the max prob rate gets set to a more reliable rate - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -495,12 +495,13 @@ minstrel_ht_sort_best_tp_rates(struct mi - * Find and set the topmost probability rate per sta and per group - */ - static void --minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index) -+minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 *dest, u16 index) - { - struct minstrel_mcs_group_data *mg; - struct minstrel_rate_stats *mrs; - int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob; -- int max_tp_group, cur_tp_avg, cur_group, cur_idx; -+ int max_tp_group, max_tp_idx, max_tp_prob; -+ int cur_tp_avg, cur_group, cur_idx; - int max_gpr_group, max_gpr_idx; - int max_gpr_tp_avg, max_gpr_prob; - -@@ -509,18 +510,26 @@ minstrel_ht_set_best_prob_rate(struct mi - mg = &mi->groups[index / MCS_GROUP_RATES]; - mrs = &mg->rates[index % MCS_GROUP_RATES]; - -- tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; -- tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; -+ tmp_group = *dest / MCS_GROUP_RATES; -+ tmp_idx = *dest % MCS_GROUP_RATES; - tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; - tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); - - /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from - * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ - max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES; -+ max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; -+ max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg; -+ - if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) && - !minstrel_ht_is_legacy_group(max_tp_group)) - return; - -+ /* skip rates faster than max tp rate with lower prob */ -+ if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) && -+ mrs->prob_avg < max_tp_prob) -+ return; -+ - max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; - max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; - max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; -@@ -538,7 +547,7 @@ minstrel_ht_set_best_prob_rate(struct mi - mg->max_group_prob_rate = index; - } else { - if (mrs->prob_avg > tmp_prob) -- mi->max_prob_rate = index; -+ *dest = index; - if (mrs->prob_avg > max_gpr_prob) - mg->max_group_prob_rate = index; - } -@@ -816,7 +825,8 @@ minstrel_ht_update_stats(struct minstrel - struct minstrel_rate_stats *mrs; - int group, i, j, cur_prob; - u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; -- u16 tmp_legacy_tp_rate[MAX_THR_RATES], index; -+ u16 tmp_legacy_tp_rate[MAX_THR_RATES], tmp_max_prob_rate; -+ u16 index; - bool ht_supported = mi->sta->ht_cap.ht_supported; - - mi->sample_mode = MINSTREL_SAMPLE_IDLE; -@@ -863,6 +873,7 @@ minstrel_ht_update_stats(struct minstrel - else - index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; - -+ tmp_max_prob_rate = index; - for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) - tmp_mcs_tp_rate[j] = index; - -@@ -903,9 +914,6 @@ minstrel_ht_update_stats(struct minstrel - /* Find max throughput rate set within a group */ - minstrel_ht_sort_best_tp_rates(mi, index, - tmp_group_tp_rate); -- -- /* Find max probability rate per group and global */ -- minstrel_ht_set_best_prob_rate(mi, index); - } - - memcpy(mg->max_group_tp_rate, tmp_group_tp_rate, -@@ -917,6 +925,27 @@ minstrel_ht_update_stats(struct minstrel - tmp_legacy_tp_rate); - memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate)); - -+ for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { -+ if (!mi->supported[group]) -+ continue; -+ -+ mg = &mi->groups[group]; -+ mg->max_group_prob_rate = MCS_GROUP_RATES * group; -+ -+ for (i = 0; i < MCS_GROUP_RATES; i++) { -+ if (!(mi->supported[group] & BIT(i))) -+ continue; -+ -+ index = MCS_GROUP_RATES * group + i; -+ -+ /* Find max probability rate per group and global */ -+ minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate, -+ index); -+ } -+ } -+ -+ mi->max_prob_rate = tmp_max_prob_rate; -+ - /* Try to increase robustness of max_prob_rate*/ - minstrel_ht_prob_rate_reduce_streams(mi); - diff --git a/package/kernel/mac80211/patches/subsys/344-mac80211-minstrel_ht-increase-stats-update-interval.patch b/package/kernel/mac80211/patches/subsys/344-mac80211-minstrel_ht-increase-stats-update-interval.patch deleted file mode 100644 index 9972a9414..000000000 --- a/package/kernel/mac80211/patches/subsys/344-mac80211-minstrel_ht-increase-stats-update-interval.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Felix Fietkau -Date: Sat, 26 Dec 2020 19:14:58 +0100 -Subject: [PATCH] mac80211: minstrel_ht: increase stats update interval - -The shorter interval was leading to too many frames being used for probing - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1865,7 +1865,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h - mp->has_mrr = true; - - mp->hw = hw; -- mp->update_interval = HZ / 20; -+ mp->update_interval = HZ / 10; - - minstrel_ht_init_cck_rates(mp); - for (i = 0; i < ARRAY_SIZE(mp->hw->wiphy->bands); i++) diff --git a/package/kernel/mac80211/patches/subsys/345-mac80211-minstrel_ht-fix-rounding-error-in-throughpu.patch b/package/kernel/mac80211/patches/subsys/345-mac80211-minstrel_ht-fix-rounding-error-in-throughpu.patch deleted file mode 100644 index 1df5dec03..000000000 --- a/package/kernel/mac80211/patches/subsys/345-mac80211-minstrel_ht-fix-rounding-error-in-throughpu.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Felix Fietkau -Date: Fri, 15 Jan 2021 12:15:06 +0100 -Subject: [PATCH] mac80211: minstrel_ht: fix rounding error in throughput - calculation - -On lower data rates, the throughput calculation has a significant rounding -error, causing rates like 48M and 54M OFDM to share the same throughput -value with >= 90% success probablity. - -This is because the result of the division (prob_avg * 1000) / nsecs -is really small (8 in this example). - -Improve accuracy by moving over some zeroes, making better use of the full -range of u32 before the division. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -445,10 +445,9 @@ minstrel_ht_get_tp_avg(struct minstrel_h - * (prob is scaled - see MINSTREL_FRAC above) - */ - if (prob_avg > MINSTREL_FRAC(90, 100)) -- return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000) -- / nsecs)); -- else -- return MINSTREL_TRUNC(100000 * ((prob_avg * 1000) / nsecs)); -+ prob_avg = MINSTREL_FRAC(90, 100); -+ -+ return MINSTREL_TRUNC(100 * ((prob_avg * 1000000) / nsecs)); - } - - /* diff --git a/package/kernel/mac80211/patches/subsys/346-mac80211-minstrel_ht-use-bitfields-to-encode-rate-in.patch b/package/kernel/mac80211/patches/subsys/346-mac80211-minstrel_ht-use-bitfields-to-encode-rate-in.patch deleted file mode 100644 index 6aa6f0ed9..000000000 --- a/package/kernel/mac80211/patches/subsys/346-mac80211-minstrel_ht-use-bitfields-to-encode-rate-in.patch +++ /dev/null @@ -1,412 +0,0 @@ -From: Felix Fietkau -Date: Thu, 21 Jan 2021 18:29:30 +0100 -Subject: [PATCH] mac80211: minstrel_ht: use bitfields to encode rate - indexes - -Get rid of a lot of divisions and modulo operations -Reduces code size and improves performance - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -379,14 +379,14 @@ out: - static inline struct minstrel_rate_stats * - minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index) - { -- return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; -+ return &mi->groups[MI_RATE_GROUP(index)].rates[MI_RATE_IDX(index)]; - } - --static inline int --minstrel_get_duration(int index) -+static inline int minstrel_get_duration(int index) - { -- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; -- unsigned int duration = group->duration[index % MCS_GROUP_RATES]; -+ const struct mcs_group *group = &minstrel_mcs_groups[MI_RATE_GROUP(index)]; -+ unsigned int duration = group->duration[MI_RATE_IDX(index)]; -+ - return duration << group->shift; - } - -@@ -398,7 +398,7 @@ minstrel_ht_avg_ampdu_len(struct minstre - if (mi->avg_ampdu_len) - return MINSTREL_TRUNC(mi->avg_ampdu_len); - -- if (minstrel_ht_is_legacy_group(mi->max_tp_rate[0] / MCS_GROUP_RATES)) -+ if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_tp_rate[0]))) - return 1; - - duration = minstrel_get_duration(mi->max_tp_rate[0]); -@@ -465,14 +465,14 @@ minstrel_ht_sort_best_tp_rates(struct mi - int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob; - int j = MAX_THR_RATES; - -- cur_group = index / MCS_GROUP_RATES; -- cur_idx = index % MCS_GROUP_RATES; -+ cur_group = MI_RATE_GROUP(index); -+ cur_idx = MI_RATE_IDX(index); - cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg; - cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob); - - do { -- tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; -- tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; -+ tmp_group = MI_RATE_GROUP(tp_list[j - 1]); -+ tmp_idx = MI_RATE_IDX(tp_list[j - 1]); - tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; - tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, - tmp_prob); -@@ -504,23 +504,23 @@ minstrel_ht_set_best_prob_rate(struct mi - int max_gpr_group, max_gpr_idx; - int max_gpr_tp_avg, max_gpr_prob; - -- cur_group = index / MCS_GROUP_RATES; -- cur_idx = index % MCS_GROUP_RATES; -- mg = &mi->groups[index / MCS_GROUP_RATES]; -- mrs = &mg->rates[index % MCS_GROUP_RATES]; -+ cur_group = MI_RATE_GROUP(index); -+ cur_idx = MI_RATE_IDX(index); -+ mg = &mi->groups[cur_group]; -+ mrs = &mg->rates[cur_idx]; - -- tmp_group = *dest / MCS_GROUP_RATES; -- tmp_idx = *dest % MCS_GROUP_RATES; -+ tmp_group = MI_RATE_GROUP(*dest); -+ tmp_idx = MI_RATE_IDX(*dest); - tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; - tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); - - /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from - * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ -- max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES; -- max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; -+ max_tp_group = MI_RATE_GROUP(mi->max_tp_rate[0]); -+ max_tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); - max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg; - -- if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) && -+ if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(index)) && - !minstrel_ht_is_legacy_group(max_tp_group)) - return; - -@@ -529,8 +529,8 @@ minstrel_ht_set_best_prob_rate(struct mi - mrs->prob_avg < max_tp_prob) - return; - -- max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; -- max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; -+ max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate); -+ max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate); - max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; - - if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) { -@@ -567,13 +567,13 @@ minstrel_ht_assign_best_tp_rates(struct - unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob; - int i; - -- tmp_group = tmp_legacy_tp_rate[0] / MCS_GROUP_RATES; -- tmp_idx = tmp_legacy_tp_rate[0] % MCS_GROUP_RATES; -+ tmp_group = MI_RATE_GROUP(tmp_legacy_tp_rate[0]); -+ tmp_idx = MI_RATE_IDX(tmp_legacy_tp_rate[0]); - tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; - tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); - -- tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES; -- tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES; -+ tmp_group = MI_RATE_GROUP(tmp_mcs_tp_rate[0]); -+ tmp_idx = MI_RATE_IDX(tmp_mcs_tp_rate[0]); - tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; - tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); - -@@ -600,14 +600,14 @@ minstrel_ht_prob_rate_reduce_streams(str - if (!mi->sta->ht_cap.ht_supported) - return; - -- tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / -- MCS_GROUP_RATES].streams; -+ group = MI_RATE_GROUP(mi->max_tp_rate[0]); -+ tmp_max_streams = minstrel_mcs_groups[group].streams; - for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { - mg = &mi->groups[group]; - if (!mi->supported[group] || group == MINSTREL_CCK_GROUP) - continue; - -- tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; -+ tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate); - tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg; - - if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) && -@@ -644,8 +644,8 @@ minstrel_ht_find_probe_rates(struct mins - int i, g, max_dur; - int tp_idx; - -- tp_group = &minstrel_mcs_groups[mi->max_tp_rate[0] / MCS_GROUP_RATES]; -- tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; -+ tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])]; -+ tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); - - max_dur = minstrel_get_duration(mi->max_tp_rate[0]); - if (faster_rate) -@@ -670,7 +670,7 @@ minstrel_ht_find_probe_rates(struct mins - if ((group->duration[i] << group->shift) > max_dur) - continue; - -- idx = g * MCS_GROUP_RATES + i; -+ idx = MI_RATE(g, i); - if (idx == mi->max_tp_rate[0]) - continue; - -@@ -712,10 +712,10 @@ minstrel_ht_rate_sample_switch(struct mi - - /* If no suitable rate was found, try to pick the next one in the group */ - if (!n_rates) { -- int g_idx = mi->max_tp_rate[0] / MCS_GROUP_RATES; -+ int g_idx = MI_RATE_GROUP(mi->max_tp_rate[0]); - u16 supported = mi->supported[g_idx]; - -- supported >>= mi->max_tp_rate[0] % MCS_GROUP_RATES; -+ supported >>= MI_RATE_IDX(mi->max_tp_rate[0]); - for (i = 0; supported; supported >>= 1, i++) { - if (!(supported & 1)) - continue; -@@ -854,24 +854,27 @@ minstrel_ht_update_stats(struct minstrel - mi->sample_slow = 0; - mi->sample_count = 0; - -- memset(tmp_mcs_tp_rate, 0, sizeof(tmp_mcs_tp_rate)); -- memset(tmp_legacy_tp_rate, 0, sizeof(tmp_legacy_tp_rate)); - if (mi->supported[MINSTREL_CCK_GROUP]) -- for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) -- tmp_legacy_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; -+ group = MINSTREL_CCK_GROUP; - else if (mi->supported[MINSTREL_OFDM_GROUP]) -- for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) -- tmp_legacy_tp_rate[j] = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; -+ group = MINSTREL_OFDM_GROUP; -+ else -+ group = 0; -+ -+ index = MI_RATE(group, 0); -+ for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) -+ tmp_legacy_tp_rate[j] = index; - - if (mi->supported[MINSTREL_VHT_GROUP_0]) -- index = MINSTREL_VHT_GROUP_0 * MCS_GROUP_RATES; -+ group = MINSTREL_VHT_GROUP_0; - else if (ht_supported) -- index = MINSTREL_HT_GROUP_0 * MCS_GROUP_RATES; -+ group = MINSTREL_HT_GROUP_0; - else if (mi->supported[MINSTREL_CCK_GROUP]) -- index = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; -+ group = MINSTREL_CCK_GROUP; - else -- index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; -+ group = MINSTREL_OFDM_GROUP; - -+ index = MI_RATE(group, 0); - tmp_max_prob_rate = index; - for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) - tmp_mcs_tp_rate[j] = index; -@@ -888,7 +891,7 @@ minstrel_ht_update_stats(struct minstrel - - /* (re)Initialize group rate indexes */ - for(j = 0; j < MAX_THR_RATES; j++) -- tmp_group_tp_rate[j] = MCS_GROUP_RATES * group; -+ tmp_group_tp_rate[j] = MI_RATE(group, 0); - - if (group == MINSTREL_CCK_GROUP && ht_supported) - tp_rate = tmp_legacy_tp_rate; -@@ -897,7 +900,7 @@ minstrel_ht_update_stats(struct minstrel - if (!(mi->supported[group] & BIT(i))) - continue; - -- index = MCS_GROUP_RATES * group + i; -+ index = MI_RATE(group, i); - - mrs = &mg->rates[i]; - mrs->retry_updated = false; -@@ -929,13 +932,13 @@ minstrel_ht_update_stats(struct minstrel - continue; - - mg = &mi->groups[group]; -- mg->max_group_prob_rate = MCS_GROUP_RATES * group; -+ mg->max_group_prob_rate = MI_RATE(group, 0); - - for (i = 0; i < MCS_GROUP_RATES; i++) { - if (!(mi->supported[group] & BIT(i))) - continue; - -- index = MCS_GROUP_RATES * group + i; -+ index = MI_RATE(group, i); - - /* Find max probability rate per group and global */ - minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate, -@@ -1022,7 +1025,7 @@ minstrel_downgrade_rate(struct minstrel_ - { - int group, orig_group; - -- orig_group = group = *idx / MCS_GROUP_RATES; -+ orig_group = group = MI_RATE_GROUP(*idx); - while (group > 0) { - group--; - -@@ -1206,7 +1209,7 @@ minstrel_calc_retransmit(struct minstrel - ctime += (t_slot * cw) >> 1; - cw = min((cw << 1) | 1, mp->cw_max); - -- if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES)) { -+ if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(index))) { - overhead = mi->overhead_legacy; - overhead_rtscts = mi->overhead_legacy_rtscts; - } else { -@@ -1239,7 +1242,7 @@ static void - minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, - struct ieee80211_sta_rates *ratetbl, int offset, int index) - { -- int group_idx = index / MCS_GROUP_RATES; -+ int group_idx = MI_RATE_GROUP(index); - const struct mcs_group *group = &minstrel_mcs_groups[group_idx]; - struct minstrel_rate_stats *mrs; - u8 idx; -@@ -1259,7 +1262,7 @@ minstrel_ht_set_rate(struct minstrel_pri - ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts; - } - -- index %= MCS_GROUP_RATES; -+ index = MI_RATE_IDX(index); - if (group_idx == MINSTREL_CCK_GROUP) - idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; - else if (group_idx == MINSTREL_OFDM_GROUP) -@@ -1289,17 +1292,17 @@ minstrel_ht_set_rate(struct minstrel_pri - static inline int - minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate) - { -- int group = rate / MCS_GROUP_RATES; -- rate %= MCS_GROUP_RATES; -+ int group = MI_RATE_GROUP(rate); -+ rate = MI_RATE_IDX(rate); - return mi->groups[group].rates[rate].prob_avg; - } - - static int - minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) - { -- int group = mi->max_prob_rate / MCS_GROUP_RATES; -+ int group = MI_RATE_GROUP(mi->max_prob_rate); - const struct mcs_group *g = &minstrel_mcs_groups[group]; -- int rate = mi->max_prob_rate % MCS_GROUP_RATES; -+ int rate = MI_RATE_IDX(mi->max_prob_rate); - unsigned int duration; - - /* Disable A-MSDU if max_prob_rate is bad */ -@@ -1405,7 +1408,7 @@ minstrel_get_sample_rate(struct minstrel - return -1; - - mrs = &mg->rates[sample_idx]; -- sample_idx += sample_group * MCS_GROUP_RATES; -+ sample_idx += MI_RATE(sample_group, 0); - - tp_rate1 = mi->max_tp_rate[0]; - -@@ -1455,8 +1458,7 @@ minstrel_get_sample_rate(struct minstrel - * if the link is working perfectly. - */ - -- cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 / -- MCS_GROUP_RATES].streams; -+ cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams; - if (sample_dur >= minstrel_get_duration(tp_rate2) && - (cur_max_tp_streams - 1 < - minstrel_mcs_groups[sample_group].streams || -@@ -1484,7 +1486,7 @@ minstrel_ht_get_rate(void *priv, struct - int sample_idx; - - if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && -- !minstrel_ht_is_legacy_group(mi->max_prob_rate / MCS_GROUP_RATES)) -+ !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate))) - minstrel_aggr_check(sta, txrc->skb); - - info->flags |= mi->tx_flags; -@@ -1512,8 +1514,8 @@ minstrel_ht_get_rate(void *priv, struct - if (sample_idx < 0) - return; - -- sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES]; -- sample_idx %= MCS_GROUP_RATES; -+ sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)]; -+ sample_idx = MI_RATE_IDX(sample_idx); - - if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] && - (sample_idx >= 4) != txrc->short_preamble) -@@ -1529,7 +1531,7 @@ minstrel_ht_get_rate(void *priv, struct - int idx = sample_idx % ARRAY_SIZE(mp->ofdm_rates[0]); - rate->idx = mp->ofdm_rates[mi->band][idx]; - } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { -- ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES, -+ ieee80211_rate_set_vht(rate, MI_RATE_IDX(sample_idx), - sample_group->streams); - } else { - rate->idx = sample_idx + (sample_group->streams - 1) * 8; -@@ -1898,8 +1900,8 @@ static u32 minstrel_ht_get_expected_thro - struct minstrel_ht_sta *mi = priv_sta; - int i, j, prob, tp_avg; - -- i = mi->max_tp_rate[0] / MCS_GROUP_RATES; -- j = mi->max_tp_rate[0] % MCS_GROUP_RATES; -+ i = MI_RATE_GROUP(mi->max_tp_rate[0]); -+ j = MI_RATE_IDX(mi->max_tp_rate[0]); - prob = mi->groups[i].rates[j].prob_avg; - - /* convert tp_avg from pkt per second in kbps */ ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -6,6 +6,8 @@ - #ifndef __RC_MINSTREL_HT_H - #define __RC_MINSTREL_HT_H - -+#include -+ - /* number of highest throughput rates to consider*/ - #define MAX_THR_RATES 4 - #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ -@@ -57,6 +59,17 @@ - - #define MCS_GROUP_RATES 10 - -+#define MI_RATE_IDX_MASK GENMASK(3, 0) -+#define MI_RATE_GROUP_MASK GENMASK(15, 4) -+ -+#define MI_RATE(_group, _idx) \ -+ (FIELD_PREP(MI_RATE_GROUP_MASK, _group) | \ -+ FIELD_PREP(MI_RATE_IDX_MASK, _idx)) -+ -+#define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate) -+#define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate) -+ -+ - struct minstrel_priv { - struct ieee80211_hw *hw; - bool has_mrr; ---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c -+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c -@@ -56,7 +56,7 @@ minstrel_ht_stats_dump(struct minstrel_h - - for (j = 0; j < MCS_GROUP_RATES; j++) { - struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; -- int idx = i * MCS_GROUP_RATES + j; -+ int idx = MI_RATE(i, j); - unsigned int duration; - - if (!(mi->supported[i] & BIT(j))) -@@ -201,7 +201,7 @@ minstrel_ht_stats_csv_dump(struct minstr - - for (j = 0; j < MCS_GROUP_RATES; j++) { - struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; -- int idx = i * MCS_GROUP_RATES + j; -+ int idx = MI_RATE(i, j); - unsigned int duration; - - if (!(mi->supported[i] & BIT(j))) diff --git a/package/kernel/mac80211/patches/subsys/347-mac80211-minstrel_ht-update-total-packets-counter-in.patch b/package/kernel/mac80211/patches/subsys/347-mac80211-minstrel_ht-update-total-packets-counter-in.patch deleted file mode 100644 index dce810493..000000000 --- a/package/kernel/mac80211/patches/subsys/347-mac80211-minstrel_ht-update-total-packets-counter-in.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Felix Fietkau -Date: Fri, 22 Jan 2021 18:21:13 +0100 -Subject: [PATCH] mac80211: minstrel_ht: update total packets counter in tx - status path - -Keep the update in one place and prepare for further rework - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1092,6 +1092,16 @@ minstrel_ht_tx_status(void *priv, struct - info->status.ampdu_len = 1; - } - -+ /* wraparound */ -+ if (mi->total_packets >= ~0 - info->status.ampdu_len) { -+ mi->total_packets = 0; -+ mi->sample_packets = 0; -+ } -+ -+ mi->total_packets += info->status.ampdu_len; -+ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) -+ mi->sample_packets += info->status.ampdu_len; -+ - mi->ampdu_packets++; - mi->ampdu_len += info->status.ampdu_len; - -@@ -1103,9 +1113,6 @@ minstrel_ht_tx_status(void *priv, struct - mi->sample_count--; - } - -- if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) -- mi->sample_packets += info->status.ampdu_len; -- - if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) - rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); - -@@ -1503,14 +1510,6 @@ minstrel_ht_get_rate(void *priv, struct - else - sample_idx = minstrel_get_sample_rate(mp, mi); - -- mi->total_packets++; -- -- /* wraparound */ -- if (mi->total_packets == ~0) { -- mi->total_packets = 0; -- mi->sample_packets = 0; -- } -- - if (sample_idx < 0) - return; - diff --git a/package/kernel/mac80211/patches/subsys/348-mac80211-minstrel_ht-reduce-the-need-to-sample-slowe.patch b/package/kernel/mac80211/patches/subsys/348-mac80211-minstrel_ht-reduce-the-need-to-sample-slowe.patch deleted file mode 100644 index dc6f11e4b..000000000 --- a/package/kernel/mac80211/patches/subsys/348-mac80211-minstrel_ht-reduce-the-need-to-sample-slowe.patch +++ /dev/null @@ -1,102 +0,0 @@ -From: Felix Fietkau -Date: Fri, 22 Jan 2021 19:24:59 +0100 -Subject: [PATCH] mac80211: minstrel_ht: reduce the need to sample slower - rates - -In order to more gracefully be able to fall back to lower rates without too -much throughput fluctuations, initialize all untested rates below tested ones -to the maximum probabilty of higher rates. -Usually this leads to untested lower rates getting initialized with a -probability value of 100%, making them better candidates for fallback without -having to rely on random probing - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -791,14 +791,11 @@ minstrel_ht_calc_rate_stats(struct minst - unsigned int cur_prob; - - if (unlikely(mrs->attempts > 0)) { -- mrs->sample_skipped = 0; - cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); - minstrel_filter_avg_add(&mrs->prob_avg, - &mrs->prob_avg_1, cur_prob); - mrs->att_hist += mrs->attempts; - mrs->succ_hist += mrs->success; -- } else { -- mrs->sample_skipped++; - } - - mrs->last_success = mrs->success; -@@ -851,7 +848,6 @@ minstrel_ht_update_stats(struct minstrel - mi->ampdu_packets = 0; - } - -- mi->sample_slow = 0; - mi->sample_count = 0; - - if (mi->supported[MINSTREL_CCK_GROUP]) -@@ -882,6 +878,7 @@ minstrel_ht_update_stats(struct minstrel - /* Find best rate sets within all MCS groups*/ - for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { - u16 *tp_rate = tmp_mcs_tp_rate; -+ u16 last_prob = 0; - - mg = &mi->groups[group]; - if (!mi->supported[group]) -@@ -896,7 +893,7 @@ minstrel_ht_update_stats(struct minstrel - if (group == MINSTREL_CCK_GROUP && ht_supported) - tp_rate = tmp_legacy_tp_rate; - -- for (i = 0; i < MCS_GROUP_RATES; i++) { -+ for (i = MCS_GROUP_RATES - 1; i >= 0; i--) { - if (!(mi->supported[group] & BIT(i))) - continue; - -@@ -905,6 +902,11 @@ minstrel_ht_update_stats(struct minstrel - mrs = &mg->rates[i]; - mrs->retry_updated = false; - minstrel_ht_calc_rate_stats(mp, mrs); -+ -+ if (mrs->att_hist) -+ last_prob = max(last_prob, mrs->prob_avg); -+ else -+ mrs->prob_avg = max(last_prob, mrs->prob_avg); - cur_prob = mrs->prob_avg; - - if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) -@@ -1469,13 +1471,9 @@ minstrel_get_sample_rate(struct minstrel - if (sample_dur >= minstrel_get_duration(tp_rate2) && - (cur_max_tp_streams - 1 < - minstrel_mcs_groups[sample_group].streams || -- sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { -- if (mrs->sample_skipped < 20) -+ sample_dur >= minstrel_get_duration(mi->max_prob_rate))) - return -1; - -- if (mi->sample_slow++ > 2) -- return -1; -- } - mi->sample_tries--; - - return sample_idx; ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -123,7 +123,6 @@ struct minstrel_rate_stats { - u8 retry_count; - u8 retry_count_rtscts; - -- u8 sample_skipped; - bool retry_updated; - }; - -@@ -179,7 +178,6 @@ struct minstrel_ht_sta { - u8 sample_wait; - u8 sample_tries; - u8 sample_count; -- u8 sample_slow; - - enum minstrel_sample_mode sample_mode; - u16 sample_rate; diff --git a/package/kernel/mac80211/patches/subsys/349-mac80211-minstrel_ht-significantly-redesign-the-rate.patch b/package/kernel/mac80211/patches/subsys/349-mac80211-minstrel_ht-significantly-redesign-the-rate.patch deleted file mode 100644 index 09f6fd221..000000000 --- a/package/kernel/mac80211/patches/subsys/349-mac80211-minstrel_ht-significantly-redesign-the-rate.patch +++ /dev/null @@ -1,767 +0,0 @@ -From: Felix Fietkau -Date: Fri, 22 Jan 2021 23:57:50 +0100 -Subject: [PATCH] mac80211: minstrel_ht: significantly redesign the rate - probing strategy - -The biggest flaw in current minstrel_ht is the fact that it needs way too -many probing packets to be able to quickly find the best rate. -Depending on the wifi hardware and operating mode, this can significantly -reduce throughput when not operating at the highest available data rate. - -In order to be able to significantly reduce the amount of rate sampling, -we need a much smarter selection of probing rates. - -The new approach introduced by this patch maintains a limited set of -available rates to be tested during a statistics window. - -They are split into distinct categories: -- MINSTREL_SAMPLE_TYPE_INC - incremental rate upgrade: - Pick the next rate group and find the first rate that is faster than - the current max. throughput rate -- MINSTREL_SAMPLE_TYPE_JUMP - random testing of higher rates: - Pick a random rate from the next group that is faster than the current - max throughput rate. This allows faster adaptation when the link changes - significantly -- MINSTREL_SAMPLE_TYPE_SLOW - test a rate between max_prob, max_tp2 and - max_tp in order to reduce the gap between them - -In order to prioritize sampling, every 6 attempts are split into 3x INC, -2x JUMP, 1x SLOW. - -Available rates are checked and refilled on every stats window update. - -With this approach, we finally get a very small delta in throughput when -comparing setting the optimal data rate as a fixed rate vs normal rate -control operation. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -266,6 +266,14 @@ const struct mcs_group minstrel_mcs_grou - const s16 minstrel_cck_bitrates[4] = { 10, 20, 55, 110 }; - const s16 minstrel_ofdm_bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 }; - static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; -+static const u8 minstrel_sample_seq[] = { -+ MINSTREL_SAMPLE_TYPE_INC, -+ MINSTREL_SAMPLE_TYPE_JUMP, -+ MINSTREL_SAMPLE_TYPE_INC, -+ MINSTREL_SAMPLE_TYPE_JUMP, -+ MINSTREL_SAMPLE_TYPE_INC, -+ MINSTREL_SAMPLE_TYPE_SLOW, -+}; - - static void - minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); -@@ -620,77 +628,31 @@ minstrel_ht_prob_rate_reduce_streams(str - } - } - --static bool --minstrel_ht_probe_group(struct minstrel_ht_sta *mi, const struct mcs_group *tp_group, -- int tp_idx, const struct mcs_group *group) --{ -- if (group->bw < tp_group->bw) -- return false; -- -- if (group->streams == tp_group->streams) -- return true; -- -- if (tp_idx < 4 && group->streams == tp_group->streams - 1) -- return true; -- -- return group->streams == tp_group->streams + 1; --} -- --static void --minstrel_ht_find_probe_rates(struct minstrel_ht_sta *mi, u16 *rates, int *n_rates, -- bool faster_rate) -+static u16 -+__minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi, -+ enum minstrel_sample_type type) - { -- const struct mcs_group *group, *tp_group; -- int i, g, max_dur; -- int tp_idx; -- -- tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])]; -- tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); -- -- max_dur = minstrel_get_duration(mi->max_tp_rate[0]); -- if (faster_rate) -- max_dur -= max_dur / 16; -- -- for (g = 0; g < MINSTREL_GROUPS_NB; g++) { -- u16 supported = mi->supported[g]; -- -- if (!supported) -- continue; -+ u16 *rates = mi->sample[type].sample_rates; -+ u16 cur; -+ int i; - -- group = &minstrel_mcs_groups[g]; -- if (!minstrel_ht_probe_group(mi, tp_group, tp_idx, group)) -+ for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) { -+ if (!rates[i]) - continue; - -- for (i = 0; supported; supported >>= 1, i++) { -- int idx; -- -- if (!(supported & 1)) -- continue; -- -- if ((group->duration[i] << group->shift) > max_dur) -- continue; -- -- idx = MI_RATE(g, i); -- if (idx == mi->max_tp_rate[0]) -- continue; -- -- rates[(*n_rates)++] = idx; -- break; -- } -+ cur = rates[i]; -+ rates[i] = 0; -+ return cur; - } -+ -+ return 0; - } - - static void - minstrel_ht_rate_sample_switch(struct minstrel_priv *mp, - struct minstrel_ht_sta *mi) - { -- struct minstrel_rate_stats *mrs; -- u16 rates[MINSTREL_GROUPS_NB]; -- int n_rates = 0; -- int probe_rate = 0; -- bool faster_rate; -- int i; -- u8 random; -+ u16 rate; - - /* - * Use rate switching instead of probing packets for devices with -@@ -699,43 +661,11 @@ minstrel_ht_rate_sample_switch(struct mi - if (mp->hw->max_rates > 1) - return; - -- /* -- * If the current EWMA prob is >75%, look for a rate that's 6.25% -- * faster than the max tp rate. -- * If that fails, look again for a rate that is at least as fast -- */ -- mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); -- faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100); -- minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate); -- if (!n_rates && faster_rate) -- minstrel_ht_find_probe_rates(mi, rates, &n_rates, false); -- -- /* If no suitable rate was found, try to pick the next one in the group */ -- if (!n_rates) { -- int g_idx = MI_RATE_GROUP(mi->max_tp_rate[0]); -- u16 supported = mi->supported[g_idx]; -- -- supported >>= MI_RATE_IDX(mi->max_tp_rate[0]); -- for (i = 0; supported; supported >>= 1, i++) { -- if (!(supported & 1)) -- continue; -- -- probe_rate = mi->max_tp_rate[0] + i; -- goto out; -- } -- -+ rate = __minstrel_ht_get_sample_rate(mi, MINSTREL_SAMPLE_TYPE_INC); -+ if (!rate) - return; -- } -- -- i = 0; -- if (n_rates > 1) { -- random = prandom_u32(); -- i = random % n_rates; -- } -- probe_rate = rates[i]; - --out: -- mi->sample_rate = probe_rate; -+ mi->sample_rate = rate; - mi->sample_mode = MINSTREL_SAMPLE_ACTIVE; - } - -@@ -804,6 +734,274 @@ minstrel_ht_calc_rate_stats(struct minst - mrs->attempts = 0; - } - -+static bool -+minstrel_ht_find_sample_rate(struct minstrel_ht_sta *mi, int type, int idx) -+{ -+ int i; -+ -+ for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) { -+ u16 cur = mi->sample[type].sample_rates[i]; -+ -+ if (cur == idx) -+ return true; -+ -+ if (!cur) -+ break; -+ } -+ -+ return false; -+} -+ -+static int -+minstrel_ht_move_sample_rates(struct minstrel_ht_sta *mi, int type, -+ u32 fast_rate_dur, u32 slow_rate_dur) -+{ -+ u16 *rates = mi->sample[type].sample_rates; -+ int i, j; -+ -+ for (i = 0, j = 0; i < MINSTREL_SAMPLE_RATES; i++) { -+ u32 duration; -+ bool valid = false; -+ u16 cur; -+ -+ cur = rates[i]; -+ if (!cur) -+ continue; -+ -+ duration = minstrel_get_duration(cur); -+ switch (type) { -+ case MINSTREL_SAMPLE_TYPE_SLOW: -+ valid = duration > fast_rate_dur && -+ duration < slow_rate_dur; -+ break; -+ case MINSTREL_SAMPLE_TYPE_INC: -+ case MINSTREL_SAMPLE_TYPE_JUMP: -+ valid = duration < fast_rate_dur; -+ break; -+ default: -+ valid = false; -+ break; -+ } -+ -+ if (!valid) { -+ rates[i] = 0; -+ continue; -+ } -+ -+ if (i == j) -+ continue; -+ -+ rates[j++] = cur; -+ rates[i] = 0; -+ } -+ -+ return j; -+} -+ -+static int -+minstrel_ht_group_min_rate_offset(struct minstrel_ht_sta *mi, int group, -+ u32 max_duration) -+{ -+ u16 supported = mi->supported[group]; -+ int i; -+ -+ for (i = 0; i < MCS_GROUP_RATES && supported; i++, supported >>= 1) { -+ if (!(supported & BIT(0))) -+ continue; -+ -+ if (minstrel_get_duration(MI_RATE(group, i)) >= max_duration) -+ continue; -+ -+ return i; -+ } -+ -+ return -1; -+} -+ -+/* -+ * Incremental update rates: -+ * Flip through groups and pick the first group rate that is faster than the -+ * highest currently selected rate -+ */ -+static u16 -+minstrel_ht_next_inc_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur) -+{ -+ struct minstrel_mcs_group_data *mg; -+ u8 type = MINSTREL_SAMPLE_TYPE_INC; -+ int i, index = 0; -+ u8 group; -+ -+ group = mi->sample[type].sample_group; -+ for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) { -+ group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups); -+ mg = &mi->groups[group]; -+ -+ index = minstrel_ht_group_min_rate_offset(mi, group, -+ fast_rate_dur); -+ if (index < 0) -+ continue; -+ -+ index = MI_RATE(group, index & 0xf); -+ if (!minstrel_ht_find_sample_rate(mi, type, index)) -+ goto out; -+ } -+ index = 0; -+ -+out: -+ mi->sample[type].sample_group = group; -+ -+ return index; -+} -+ -+static int -+minstrel_ht_next_group_sample_rate(struct minstrel_ht_sta *mi, int group, -+ u16 supported, int offset) -+{ -+ struct minstrel_mcs_group_data *mg = &mi->groups[group]; -+ u16 idx; -+ int i; -+ -+ for (i = 0; i < MCS_GROUP_RATES; i++) { -+ idx = sample_table[mg->column][mg->index]; -+ if (++mg->index >= MCS_GROUP_RATES) { -+ mg->index = 0; -+ if (++mg->column >= ARRAY_SIZE(sample_table)) -+ mg->column = 0; -+ } -+ -+ if (idx < offset) -+ continue; -+ -+ if (!(supported & BIT(idx))) -+ continue; -+ -+ return MI_RATE(group, idx); -+ } -+ -+ return -1; -+} -+ -+/* -+ * Jump rates: -+ * Sample random rates, use those that are faster than the highest -+ * currently selected rate. Rates between the fastest and the slowest -+ * get sorted into the slow sample bucket, but only if it has room -+ */ -+static u16 -+minstrel_ht_next_jump_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur, -+ u32 slow_rate_dur, int *slow_rate_ofs) -+{ -+ struct minstrel_mcs_group_data *mg; -+ struct minstrel_rate_stats *mrs; -+ u32 max_duration = slow_rate_dur; -+ int i, index, offset; -+ u16 *slow_rates; -+ u16 supported; -+ u32 duration; -+ u8 group; -+ -+ if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES) -+ max_duration = fast_rate_dur; -+ -+ slow_rates = mi->sample[MINSTREL_SAMPLE_TYPE_SLOW].sample_rates; -+ group = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group; -+ for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) { -+ u8 type; -+ -+ group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups); -+ mg = &mi->groups[group]; -+ -+ supported = mi->supported[group]; -+ if (!supported) -+ continue; -+ -+ offset = minstrel_ht_group_min_rate_offset(mi, group, -+ max_duration); -+ if (offset < 0) -+ continue; -+ -+ index = minstrel_ht_next_group_sample_rate(mi, group, supported, -+ offset); -+ if (index < 0) -+ continue; -+ -+ duration = minstrel_get_duration(index); -+ if (duration < fast_rate_dur) -+ type = MINSTREL_SAMPLE_TYPE_JUMP; -+ else -+ type = MINSTREL_SAMPLE_TYPE_SLOW; -+ -+ if (minstrel_ht_find_sample_rate(mi, type, index)) -+ continue; -+ -+ if (type == MINSTREL_SAMPLE_TYPE_JUMP) -+ goto found; -+ -+ if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES) -+ continue; -+ -+ if (duration >= slow_rate_dur) -+ continue; -+ -+ /* skip slow rates with high success probability */ -+ mrs = minstrel_get_ratestats(mi, index); -+ if (mrs->prob_avg > MINSTREL_FRAC(95, 100)) -+ continue; -+ -+ slow_rates[(*slow_rate_ofs)++] = index; -+ if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES) -+ max_duration = fast_rate_dur; -+ } -+ index = 0; -+ -+found: -+ mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group = group; -+ -+ return index; -+} -+ -+static void -+minstrel_ht_refill_sample_rates(struct minstrel_ht_sta *mi) -+{ -+ u32 prob_dur = minstrel_get_duration(mi->max_prob_rate); -+ u32 tp_dur = minstrel_get_duration(mi->max_tp_rate[0]); -+ u32 tp2_dur = minstrel_get_duration(mi->max_tp_rate[1]); -+ u32 fast_rate_dur = min(min(tp_dur, tp2_dur), prob_dur); -+ u32 slow_rate_dur = max(max(tp_dur, tp2_dur), prob_dur); -+ u16 *rates; -+ int i, j; -+ -+ rates = mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates; -+ i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_INC, -+ fast_rate_dur, slow_rate_dur); -+ while (i < MINSTREL_SAMPLE_RATES) { -+ rates[i] = minstrel_ht_next_inc_rate(mi, tp_dur); -+ if (!rates[i]) -+ break; -+ -+ i++; -+ } -+ -+ rates = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_rates; -+ i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_JUMP, -+ fast_rate_dur, slow_rate_dur); -+ j = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_SLOW, -+ fast_rate_dur, slow_rate_dur); -+ while (i < MINSTREL_SAMPLE_RATES) { -+ rates[i] = minstrel_ht_next_jump_rate(mi, fast_rate_dur, -+ slow_rate_dur, &j); -+ if (!rates[i]) -+ break; -+ -+ i++; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(mi->sample); i++) -+ memcpy(mi->sample[i].cur_sample_rates, mi->sample[i].sample_rates, -+ sizeof(mi->sample[i].cur_sample_rates)); -+} -+ -+ - /* - * Update rate statistics and select new primary rates - * -@@ -848,8 +1046,6 @@ minstrel_ht_update_stats(struct minstrel - mi->ampdu_packets = 0; - } - -- mi->sample_count = 0; -- - if (mi->supported[MINSTREL_CCK_GROUP]) - group = MINSTREL_CCK_GROUP; - else if (mi->supported[MINSTREL_OFDM_GROUP]) -@@ -884,8 +1080,6 @@ minstrel_ht_update_stats(struct minstrel - if (!mi->supported[group]) - continue; - -- mi->sample_count++; -- - /* (re)Initialize group rate indexes */ - for(j = 0; j < MAX_THR_RATES; j++) - tmp_group_tp_rate[j] = MI_RATE(group, 0); -@@ -952,9 +1146,7 @@ minstrel_ht_update_stats(struct minstrel - - /* Try to increase robustness of max_prob_rate*/ - minstrel_ht_prob_rate_reduce_streams(mi); -- -- /* try to sample half of all available rates during each interval */ -- mi->sample_count *= 4; -+ minstrel_ht_refill_sample_rates(mi); - - if (sample) - minstrel_ht_rate_sample_switch(mp, mi); -@@ -971,6 +1163,7 @@ minstrel_ht_update_stats(struct minstrel - - /* Reset update timer */ - mi->last_stats_update = jiffies; -+ mi->sample_time = jiffies; - } - - static bool -@@ -1001,28 +1194,6 @@ minstrel_ht_txstat_valid(struct minstrel - } - - static void --minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi) --{ -- struct minstrel_mcs_group_data *mg; -- -- for (;;) { -- mi->sample_group++; -- mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups); -- mg = &mi->groups[mi->sample_group]; -- -- if (!mi->supported[mi->sample_group]) -- continue; -- -- if (++mg->index >= MCS_GROUP_RATES) { -- mg->index = 0; -- if (++mg->column >= ARRAY_SIZE(sample_table)) -- mg->column = 0; -- } -- break; -- } --} -- --static void - minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary) - { - int group, orig_group; -@@ -1107,14 +1278,6 @@ minstrel_ht_tx_status(void *priv, struct - mi->ampdu_packets++; - mi->ampdu_len += info->status.ampdu_len; - -- if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { -- int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi); -- -- mi->sample_wait = 16 + 2 * avg_ampdu_len; -- mi->sample_tries = 1; -- mi->sample_count--; -- } -- - if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) - rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); - -@@ -1386,97 +1549,20 @@ minstrel_ht_update_rates(struct minstrel - rate_control_set_rates(mp->hw, mi->sta, rates); - } - --static int --minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) -+static u16 -+minstrel_ht_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) - { -- struct minstrel_rate_stats *mrs; -- struct minstrel_mcs_group_data *mg; -- unsigned int sample_dur, sample_group, cur_max_tp_streams; -- int tp_rate1, tp_rate2; -- int sample_idx = 0; -- -- if (mp->hw->max_rates == 1 && mp->sample_switch && -- (mi->total_packets_cur >= SAMPLE_SWITCH_THR || -- mp->sample_switch == 1)) -- return -1; -- -- if (mi->sample_wait > 0) { -- mi->sample_wait--; -- return -1; -- } -- -- if (!mi->sample_tries) -- return -1; -- -- sample_group = mi->sample_group; -- mg = &mi->groups[sample_group]; -- sample_idx = sample_table[mg->column][mg->index]; -- minstrel_set_next_sample_idx(mi); -- -- if (!(mi->supported[sample_group] & BIT(sample_idx))) -- return -1; -+ u8 seq; - -- mrs = &mg->rates[sample_idx]; -- sample_idx += MI_RATE(sample_group, 0); -- -- tp_rate1 = mi->max_tp_rate[0]; -- -- /* Set tp_rate2 to the second highest max_tp_rate */ -- if (minstrel_get_duration(mi->max_tp_rate[0]) > -- minstrel_get_duration(mi->max_tp_rate[1])) { -- tp_rate2 = mi->max_tp_rate[0]; -+ if (mp->hw->max_rates > 1) { -+ seq = mi->sample_seq; -+ mi->sample_seq = (seq + 1) % ARRAY_SIZE(minstrel_sample_seq); -+ seq = minstrel_sample_seq[seq]; - } else { -- tp_rate2 = mi->max_tp_rate[1]; -+ seq = MINSTREL_SAMPLE_TYPE_INC; - } - -- /* -- * Sampling might add some overhead (RTS, no aggregation) -- * to the frame. Hence, don't use sampling for the highest currently -- * used highest throughput or probability rate. -- */ -- if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate) -- return -1; -- -- /* -- * Do not sample if the probability is already higher than 95%, -- * or if the rate is 3 times slower than the current max probability -- * rate, to avoid wasting airtime. -- */ -- sample_dur = minstrel_get_duration(sample_idx); -- if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || -- minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur) -- return -1; -- -- -- /* -- * For devices with no configurable multi-rate retry, skip sampling -- * below the per-group max throughput rate, and only use one sampling -- * attempt per rate -- */ -- if (mp->hw->max_rates == 1 && -- (minstrel_get_duration(mg->max_group_tp_rate[0]) < sample_dur || -- mrs->attempts)) -- return -1; -- -- /* Skip already sampled slow rates */ -- if (sample_dur >= minstrel_get_duration(tp_rate1) && mrs->attempts) -- return -1; -- -- /* -- * Make sure that lower rates get sampled only occasionally, -- * if the link is working perfectly. -- */ -- -- cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams; -- if (sample_dur >= minstrel_get_duration(tp_rate2) && -- (cur_max_tp_streams - 1 < -- minstrel_mcs_groups[sample_group].streams || -- sample_dur >= minstrel_get_duration(mi->max_prob_rate))) -- return -1; -- -- mi->sample_tries--; -- -- return sample_idx; -+ return __minstrel_ht_get_sample_rate(mi, seq); - } - - static void -@@ -1488,7 +1574,7 @@ minstrel_ht_get_rate(void *priv, struct - struct ieee80211_tx_rate *rate = &info->status.rates[0]; - struct minstrel_ht_sta *mi = priv_sta; - struct minstrel_priv *mp = priv; -- int sample_idx; -+ u16 sample_idx; - - if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && - !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate))) -@@ -1504,11 +1590,19 @@ minstrel_ht_get_rate(void *priv, struct - /* Don't use EAPOL frames for sampling on non-mrr hw */ - if (mp->hw->max_rates == 1 && - (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) -- sample_idx = -1; -- else -- sample_idx = minstrel_get_sample_rate(mp, mi); -+ return; -+ -+ if (mp->hw->max_rates == 1 && mp->sample_switch && -+ (mi->total_packets_cur >= SAMPLE_SWITCH_THR || -+ mp->sample_switch == 1)) -+ return; -+ -+ if (time_is_before_jiffies(mi->sample_time)) -+ return; - -- if (sample_idx < 0) -+ mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL; -+ sample_idx = minstrel_ht_get_sample_rate(mp, mi); -+ if (!sample_idx) - return; - - sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)]; -@@ -1629,16 +1723,6 @@ minstrel_ht_update_caps(void *priv, stru - - mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); - -- /* When using MRR, sample more on the first attempt, without delay */ -- if (mp->has_mrr) { -- mi->sample_count = 16; -- mi->sample_wait = 0; -- } else { -- mi->sample_count = 8; -- mi->sample_wait = 8; -- } -- mi->sample_tries = 4; -- - if (!use_vht) { - stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >> - IEEE80211_HT_CAP_RX_STBC_SHIFT; ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -69,6 +69,8 @@ - #define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate) - #define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate) - -+#define MINSTREL_SAMPLE_RATES 5 /* rates per sample type */ -+#define MINSTREL_SAMPLE_INTERVAL (HZ / 50) - - struct minstrel_priv { - struct ieee80211_hw *hw; -@@ -126,6 +128,13 @@ struct minstrel_rate_stats { - bool retry_updated; - }; - -+enum minstrel_sample_type { -+ MINSTREL_SAMPLE_TYPE_INC, -+ MINSTREL_SAMPLE_TYPE_JUMP, -+ MINSTREL_SAMPLE_TYPE_SLOW, -+ __MINSTREL_SAMPLE_TYPE_MAX -+}; -+ - struct minstrel_mcs_group_data { - u8 index; - u8 column; -@@ -144,6 +153,12 @@ enum minstrel_sample_mode { - MINSTREL_SAMPLE_PENDING, - }; - -+struct minstrel_sample_category { -+ u8 sample_group; -+ u16 sample_rates[MINSTREL_SAMPLE_RATES]; -+ u16 cur_sample_rates[MINSTREL_SAMPLE_RATES]; -+}; -+ - struct minstrel_ht_sta { - struct ieee80211_sta *sta; - -@@ -175,16 +190,14 @@ struct minstrel_ht_sta { - /* tx flags to add for frames for this sta */ - u32 tx_flags; - -- u8 sample_wait; -- u8 sample_tries; -- u8 sample_count; -+ unsigned long sample_time; -+ struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX]; -+ -+ u8 sample_seq; - - enum minstrel_sample_mode sample_mode; - u16 sample_rate; - -- /* current MCS group to be sampled */ -- u8 sample_group; -- - u8 band; - - /* Bitfield of supported MCS rates of all groups */ diff --git a/package/kernel/mac80211/patches/subsys/350-mac80211-minstrel_ht-show-sampling-rates-in-debugfs.patch b/package/kernel/mac80211/patches/subsys/350-mac80211-minstrel_ht-show-sampling-rates-in-debugfs.patch deleted file mode 100644 index 041ba31a3..000000000 --- a/package/kernel/mac80211/patches/subsys/350-mac80211-minstrel_ht-show-sampling-rates-in-debugfs.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Felix Fietkau -Date: Sat, 23 Jan 2021 00:10:34 +0100 -Subject: [PATCH] mac80211: minstrel_ht: show sampling rates in debugfs - -This makes it easier to see what rates are going to be tested next - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c -+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c -@@ -32,6 +32,18 @@ minstrel_stats_release(struct inode *ino - return 0; - } - -+static bool -+minstrel_ht_is_sample_rate(struct minstrel_ht_sta *mi, int idx) -+{ -+ int type, i; -+ -+ for (type = 0; type < ARRAY_SIZE(mi->sample); type++) -+ for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) -+ if (mi->sample[type].cur_sample_rates[i] == idx) -+ return true; -+ return false; -+} -+ - static char * - minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) - { -@@ -84,6 +96,7 @@ minstrel_ht_stats_dump(struct minstrel_h - *(p++) = (idx == mi->max_tp_rate[2]) ? 'C' : ' '; - *(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' '; - *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; -+ *(p++) = minstrel_ht_is_sample_rate(mi, idx) ? 'S' : ' '; - - if (gflags & IEEE80211_TX_RC_MCS) { - p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j); -@@ -145,9 +158,9 @@ minstrel_ht_stats_open(struct inode *ino - - p += sprintf(p, "\n"); - p += sprintf(p, -- " best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n"); -+ " best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n"); - p += sprintf(p, -- "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n"); -+ "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n"); - - p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); - for (i = 0; i < MINSTREL_CCK_GROUP; i++) -@@ -228,6 +241,7 @@ minstrel_ht_stats_csv_dump(struct minstr - p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C" : "")); - p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D" : "")); - p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P" : "")); -+ p += sprintf(p, "%s", (minstrel_ht_is_sample_rate(mi, idx) ? "S" : "")); - - if (gflags & IEEE80211_TX_RC_MCS) { - p += sprintf(p, ",MCS%-2u,", (mg->streams - 1) * 8 + j); diff --git a/package/kernel/mac80211/patches/subsys/351-mac80211-minstrel_ht-remove-sample-rate-switching-co.patch b/package/kernel/mac80211/patches/subsys/351-mac80211-minstrel_ht-remove-sample-rate-switching-co.patch deleted file mode 100644 index 8170ff85f..000000000 --- a/package/kernel/mac80211/patches/subsys/351-mac80211-minstrel_ht-remove-sample-rate-switching-co.patch +++ /dev/null @@ -1,279 +0,0 @@ -From: Felix Fietkau -Date: Sat, 23 Jan 2021 07:18:26 +0100 -Subject: [PATCH] mac80211: minstrel_ht: remove sample rate switching code for - constrained devices - -This was added to mitigate the effects of too much sampling on devices that -use a static global fallback table instead of configurable multi-rate retry. -Now that the sampling algorithm is improved, this code path no longer performs -any better than the standard probing on affected devices. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -648,27 +648,6 @@ __minstrel_ht_get_sample_rate(struct min - return 0; - } - --static void --minstrel_ht_rate_sample_switch(struct minstrel_priv *mp, -- struct minstrel_ht_sta *mi) --{ -- u16 rate; -- -- /* -- * Use rate switching instead of probing packets for devices with -- * little control over retry fallback behavior -- */ -- if (mp->hw->max_rates > 1) -- return; -- -- rate = __minstrel_ht_get_sample_rate(mi, MINSTREL_SAMPLE_TYPE_INC); -- if (!rate) -- return; -- -- mi->sample_rate = rate; -- mi->sample_mode = MINSTREL_SAMPLE_ACTIVE; --} -- - static inline int - minstrel_ewma(int old, int new, int weight) - { -@@ -1012,8 +991,7 @@ minstrel_ht_refill_sample_rates(struct m - * higher throughput rates, even if the probablity is a bit lower - */ - static void --minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, -- bool sample) -+minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) - { - struct minstrel_mcs_group_data *mg; - struct minstrel_rate_stats *mrs; -@@ -1023,18 +1001,6 @@ minstrel_ht_update_stats(struct minstrel - u16 index; - bool ht_supported = mi->sta->ht_cap.ht_supported; - -- mi->sample_mode = MINSTREL_SAMPLE_IDLE; -- -- if (sample) { -- mi->total_packets_cur = mi->total_packets - -- mi->total_packets_last; -- mi->total_packets_last = mi->total_packets; -- } -- if (!mp->sample_switch) -- sample = false; -- if (mi->total_packets_cur < SAMPLE_SWITCH_THR && mp->sample_switch != 1) -- sample = false; -- - if (mi->ampdu_packets > 0) { - if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN)) - mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len, -@@ -1148,16 +1114,12 @@ minstrel_ht_update_stats(struct minstrel - minstrel_ht_prob_rate_reduce_streams(mi); - minstrel_ht_refill_sample_rates(mi); - -- if (sample) -- minstrel_ht_rate_sample_switch(mp, mi); -- - #ifdef CPTCFG_MAC80211_DEBUGFS - /* use fixed index if set */ - if (mp->fixed_rate_idx != -1) { - for (i = 0; i < 4; i++) - mi->max_tp_rate[i] = mp->fixed_rate_idx; - mi->max_prob_rate = mp->fixed_rate_idx; -- mi->sample_mode = MINSTREL_SAMPLE_IDLE; - } - #endif - -@@ -1247,11 +1209,10 @@ minstrel_ht_tx_status(void *priv, struct - struct ieee80211_tx_info *info = st->info; - struct minstrel_ht_sta *mi = priv_sta; - struct ieee80211_tx_rate *ar = info->status.rates; -- struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL; -+ struct minstrel_rate_stats *rate, *rate2; - struct minstrel_priv *mp = priv; - u32 update_interval = mp->update_interval; - bool last, update = false; -- bool sample_status = false; - int i; - - /* This packet was aggregated but doesn't carry status info */ -@@ -1278,49 +1239,18 @@ minstrel_ht_tx_status(void *priv, struct - mi->ampdu_packets++; - mi->ampdu_len += info->status.ampdu_len; - -- if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) -- rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); -- - last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]); - for (i = 0; !last; i++) { - last = (i == IEEE80211_TX_MAX_RATES - 1) || - !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]); - - rate = minstrel_ht_get_stats(mp, mi, &ar[i]); -- if (rate == rate_sample) -- sample_status = true; -- - if (last) - rate->success += info->status.ampdu_ack_len; - - rate->attempts += ar[i].count * info->status.ampdu_len; - } - -- switch (mi->sample_mode) { -- case MINSTREL_SAMPLE_IDLE: -- if (mp->hw->max_rates > 1 || -- mi->total_packets_cur < SAMPLE_SWITCH_THR) -- update_interval /= 2; -- break; -- -- case MINSTREL_SAMPLE_ACTIVE: -- if (!sample_status) -- break; -- -- mi->sample_mode = MINSTREL_SAMPLE_PENDING; -- update = true; -- break; -- -- case MINSTREL_SAMPLE_PENDING: -- if (sample_status) -- break; -- -- update = true; -- minstrel_ht_update_stats(mp, mi, false); -- break; -- } -- -- - if (mp->hw->max_rates > 1) { - /* - * check for sudden death of spatial multiplexing, -@@ -1343,7 +1273,7 @@ minstrel_ht_tx_status(void *priv, struct - - if (time_after(jiffies, mi->last_stats_update + update_interval)) { - update = true; -- minstrel_ht_update_stats(mp, mi, true); -+ minstrel_ht_update_stats(mp, mi); - } - - if (update) -@@ -1522,18 +1452,14 @@ static void - minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) - { - struct ieee80211_sta_rates *rates; -- u16 first_rate = mi->max_tp_rate[0]; - int i = 0; - -- if (mi->sample_mode == MINSTREL_SAMPLE_ACTIVE) -- first_rate = mi->sample_rate; -- - rates = kzalloc(sizeof(*rates), GFP_ATOMIC); - if (!rates) - return; - - /* Start with max_tp_rate[0] */ -- minstrel_ht_set_rate(mp, mi, rates, i++, first_rate); -+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]); - - if (mp->hw->max_rates >= 3) { - /* At least 3 tx rates supported, use max_tp_rate[1] next */ -@@ -1592,11 +1518,6 @@ minstrel_ht_get_rate(void *priv, struct - (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) - return; - -- if (mp->hw->max_rates == 1 && mp->sample_switch && -- (mi->total_packets_cur >= SAMPLE_SWITCH_THR || -- mp->sample_switch == 1)) -- return; -- - if (time_is_before_jiffies(mi->sample_time)) - return; - -@@ -1810,7 +1731,7 @@ minstrel_ht_update_caps(void *priv, stru - minstrel_ht_update_ofdm(mp, mi, sband, sta); - - /* create an initial rate table with the lowest supported rates */ -- minstrel_ht_update_stats(mp, mi, true); -+ minstrel_ht_update_stats(mp, mi); - minstrel_ht_update_rates(mp, mi); - } - -@@ -1926,8 +1847,6 @@ minstrel_ht_alloc(struct ieee80211_hw *h - if (!mp) - return NULL; - -- mp->sample_switch = -1; -- - /* contention window settings - * Just an approximation. Using the per-queue values would complicate - * the calculations and is probably unnecessary */ -@@ -1947,7 +1866,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h - mp->has_mrr = true; - - mp->hw = hw; -- mp->update_interval = HZ / 10; -+ mp->update_interval = HZ / 20; - - minstrel_ht_init_cck_rates(mp); - for (i = 0; i < ARRAY_SIZE(mp->hw->wiphy->bands); i++) -@@ -1965,8 +1884,6 @@ static void minstrel_ht_add_debugfs(stru - mp->fixed_rate_idx = (u32) -1; - debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir, - &mp->fixed_rate_idx); -- debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir, -- &mp->sample_switch); - } - #endif - ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -75,7 +75,6 @@ - struct minstrel_priv { - struct ieee80211_hw *hw; - bool has_mrr; -- u32 sample_switch; - unsigned int cw_min; - unsigned int cw_max; - unsigned int max_retry; -@@ -147,12 +146,6 @@ struct minstrel_mcs_group_data { - struct minstrel_rate_stats rates[MCS_GROUP_RATES]; - }; - --enum minstrel_sample_mode { -- MINSTREL_SAMPLE_IDLE, -- MINSTREL_SAMPLE_ACTIVE, -- MINSTREL_SAMPLE_PENDING, --}; -- - struct minstrel_sample_category { - u8 sample_group; - u16 sample_rates[MINSTREL_SAMPLE_RATES]; -@@ -182,23 +175,19 @@ struct minstrel_ht_sta { - unsigned int overhead_legacy; - unsigned int overhead_legacy_rtscts; - -- unsigned int total_packets_last; -- unsigned int total_packets_cur; - unsigned int total_packets; - unsigned int sample_packets; - - /* tx flags to add for frames for this sta */ - u32 tx_flags; - -- unsigned long sample_time; -- struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX]; -+ u8 band; - - u8 sample_seq; -- -- enum minstrel_sample_mode sample_mode; - u16 sample_rate; - -- u8 band; -+ unsigned long sample_time; -+ struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX]; - - /* Bitfield of supported MCS rates of all groups */ - u16 supported[MINSTREL_GROUPS_NB]; diff --git a/package/kernel/mac80211/patches/subsys/352-mac80211-minstrel_ht-fix-regression-in-the-max_prob_.patch b/package/kernel/mac80211/patches/subsys/352-mac80211-minstrel_ht-fix-regression-in-the-max_prob_.patch deleted file mode 100644 index a366a921d..000000000 --- a/package/kernel/mac80211/patches/subsys/352-mac80211-minstrel_ht-fix-regression-in-the-max_prob_.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Felix Fietkau -Date: Tue, 26 Jan 2021 16:40:52 +0100 -Subject: [PATCH] mac80211: minstrel_ht: fix regression in the max_prob_rate - fix - -Since mi->max_prob_rate is overwritten after the loop that calls -minstrel_ht_set_best_prob_rate, the new best rate needs to be written to *dest - -Fixes: a7fca4e4037f ("mac80211: minstrel_ht: fix max probability rate selection") -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -545,7 +545,7 @@ minstrel_ht_set_best_prob_rate(struct mi - cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, - mrs->prob_avg); - if (cur_tp_avg > tmp_tp_avg) -- mi->max_prob_rate = index; -+ *dest = index; - - max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group, - max_gpr_idx, diff --git a/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch b/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch deleted file mode 100644 index 8d094a363..000000000 --- a/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch +++ /dev/null @@ -1,60 +0,0 @@ -From: Johannes Berg -Date: Fri, 19 Mar 2021 23:28:01 +0100 -Subject: [PATCH] mac80211: don't apply flow control on management frames - -In some cases (depending on the driver, but it's true e.g. for -iwlwifi) we're using an internal TXQ for management packets, -mostly to simplify the code and to have a place to queue them. -However, it appears that in certain cases we can confuse the -code and management frames are dropped, which is certainly not -what we want. - -Short-circuit the processing of management frames. To keep the -impact minimal, only put them on the frags queue and check the -tid == management only for doing that and to skip the airtime -fairness checks, if applicable. - -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -5,7 +5,7 @@ - * Copyright 2006-2007 Jiri Benc - * Copyright 2007 Johannes Berg - * Copyright 2013-2014 Intel Mobile Communications GmbH -- * Copyright (C) 2018-2020 Intel Corporation -+ * Copyright (C) 2018-2021 Intel Corporation - * - * Transmit and frame generation functions. - */ -@@ -1401,8 +1401,17 @@ static void ieee80211_txq_enqueue(struct - ieee80211_set_skb_enqueue_time(skb); - - spin_lock_bh(&fq->lock); -- fq_tin_enqueue(fq, tin, flow_idx, skb, -- fq_skb_free_func); -+ /* -+ * For management frames, don't really apply codel etc., -+ * we don't want to apply any shaping or anything we just -+ * want to simplify the driver API by having them on the -+ * txqi. -+ */ -+ if (unlikely(txqi->txq.tid == IEEE80211_NUM_TIDS)) -+ __skb_queue_tail(&txqi->frags, skb); -+ else -+ fq_tin_enqueue(fq, tin, flow_idx, skb, -+ fq_skb_free_func); - spin_unlock_bh(&fq->lock); - } - -@@ -3844,6 +3853,9 @@ bool ieee80211_txq_airtime_check(struct - if (!txq->sta) - return true; - -+ if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) -+ return true; -+ - sta = container_of(txq->sta, struct sta_info, sta); - if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < - sta->airtime[txq->ac].aql_limit_low) diff --git a/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch b/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch deleted file mode 100644 index 5bc1469a3..000000000 --- a/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch +++ /dev/null @@ -1,21 +0,0 @@ -From: Lorenzo Bianconi -Date: Mon, 8 Mar 2021 23:01:49 +0100 -Subject: [PATCH] mac80211: set sk_pacing_shift for 802.3 txpath - -Similar to 802.11 txpath, set socket sk_pacing_shift for 802.3 tx path. - -Signed-off-by: Lorenzo Bianconi ---- - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -4171,6 +4171,9 @@ static bool ieee80211_tx_8023(struct iee - unsigned long flags; - int q = info->hw_queue; - -+ if (sta) -+ sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift); -+ - if (ieee80211_queue_skb(local, sdata, sta, skb)) - return true; - diff --git a/package/kernel/mac80211/patches/subsys/373-mac80211-support-Rx-timestamp-calculation-for-all-pr.patch b/package/kernel/mac80211/patches/subsys/373-mac80211-support-Rx-timestamp-calculation-for-all-pr.patch deleted file mode 100644 index 117fb35fc..000000000 --- a/package/kernel/mac80211/patches/subsys/373-mac80211-support-Rx-timestamp-calculation-for-all-pr.patch +++ /dev/null @@ -1,134 +0,0 @@ -From: Avraham Stern -Date: Sun, 6 Dec 2020 14:54:45 +0200 -Subject: [PATCH] mac80211: support Rx timestamp calculation for all preamble - types - -Add support for calculating the Rx timestamp for HE frames. -Since now all frame types are supported, allow setting the Rx -timestamp regardless of the frame type. - -Signed-off-by: Avraham Stern -Signed-off-by: Luca Coelho -Link: https://lore.kernel.org/r/iwlwifi.20201206145305.4786559af475.Ia54486bb0a12e5351f9d5c60ef6fcda7c9e7141c@changeid -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1587,13 +1587,8 @@ ieee80211_have_rx_timestamp(struct ieee8 - { - WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START && - status->flag & RX_FLAG_MACTIME_END); -- if (status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END)) -- return true; -- /* can't handle non-legacy preamble yet */ -- if (status->flag & RX_FLAG_MACTIME_PLCP_START && -- status->encoding == RX_ENC_LEGACY) -- return true; -- return false; -+ return !!(status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END | -+ RX_FLAG_MACTIME_PLCP_START)); - } - - void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata); ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -3665,6 +3665,7 @@ u64 ieee80211_calculate_rx_timestamp(str - u64 ts = status->mactime; - struct rate_info ri; - u16 rate; -+ u8 n_ltf; - - if (WARN_ON(!ieee80211_have_rx_timestamp(status))) - return 0; -@@ -3675,11 +3676,58 @@ u64 ieee80211_calculate_rx_timestamp(str - - /* Fill cfg80211 rate info */ - switch (status->encoding) { -+ case RX_ENC_HE: -+ ri.flags |= RATE_INFO_FLAGS_HE_MCS; -+ ri.mcs = status->rate_idx; -+ ri.nss = status->nss; -+ ri.he_ru_alloc = status->he_ru; -+ if (status->enc_flags & RX_ENC_FLAG_SHORT_GI) -+ ri.flags |= RATE_INFO_FLAGS_SHORT_GI; -+ -+ /* -+ * See P802.11ax_D6.0, section 27.3.4 for -+ * VHT PPDU format. -+ */ -+ if (status->flag & RX_FLAG_MACTIME_PLCP_START) { -+ mpdu_offset += 2; -+ ts += 36; -+ -+ /* -+ * TODO: -+ * For HE MU PPDU, add the HE-SIG-B. -+ * For HE ER PPDU, add 8us for the HE-SIG-A. -+ * For HE TB PPDU, add 4us for the HE-STF. -+ * Add the HE-LTF durations - variable. -+ */ -+ } -+ -+ break; - case RX_ENC_HT: - ri.mcs = status->rate_idx; - ri.flags |= RATE_INFO_FLAGS_MCS; - if (status->enc_flags & RX_ENC_FLAG_SHORT_GI) - ri.flags |= RATE_INFO_FLAGS_SHORT_GI; -+ -+ /* -+ * See P802.11REVmd_D3.0, section 19.3.2 for -+ * HT PPDU format. -+ */ -+ if (status->flag & RX_FLAG_MACTIME_PLCP_START) { -+ mpdu_offset += 2; -+ if (status->enc_flags & RX_ENC_FLAG_HT_GF) -+ ts += 24; -+ else -+ ts += 32; -+ -+ /* -+ * Add Data HT-LTFs per streams -+ * TODO: add Extension HT-LTFs, 4us per LTF -+ */ -+ n_ltf = ((ri.mcs >> 3) & 3) + 1; -+ n_ltf = n_ltf == 3 ? 4 : n_ltf; -+ ts += n_ltf * 4; -+ } -+ - break; - case RX_ENC_VHT: - ri.flags |= RATE_INFO_FLAGS_VHT_MCS; -@@ -3687,6 +3735,23 @@ u64 ieee80211_calculate_rx_timestamp(str - ri.nss = status->nss; - if (status->enc_flags & RX_ENC_FLAG_SHORT_GI) - ri.flags |= RATE_INFO_FLAGS_SHORT_GI; -+ -+ /* -+ * See P802.11REVmd_D3.0, section 21.3.2 for -+ * VHT PPDU format. -+ */ -+ if (status->flag & RX_FLAG_MACTIME_PLCP_START) { -+ mpdu_offset += 2; -+ ts += 36; -+ -+ /* -+ * Add VHT-LTFs per streams -+ */ -+ n_ltf = (ri.nss != 1) && (ri.nss % 2) ? -+ ri.nss + 1 : ri.nss; -+ ts += 4 * n_ltf; -+ } -+ - break; - default: - WARN_ON(1); -@@ -3710,7 +3775,6 @@ u64 ieee80211_calculate_rx_timestamp(str - ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift)); - - if (status->flag & RX_FLAG_MACTIME_PLCP_START) { -- /* TODO: handle HT/VHT preambles */ - if (status->band == NL80211_BAND_5GHZ) { - ts += 20 << shift; - mpdu_offset += 2; diff --git a/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch b/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch deleted file mode 100644 index 031f8e163..000000000 --- a/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch +++ /dev/null @@ -1,126 +0,0 @@ -From: Felix Fietkau -Date: Thu, 17 Jun 2021 17:56:54 +0200 -Subject: [PATCH] mac80211: move A-MPDU session check from minstrel_ht to - mac80211 - -This avoids calling back into tx handlers from within the rate control module. -Preparation for deferring rate control until tx dequeue - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -6160,6 +6160,11 @@ enum rate_control_capabilities { - * otherwise the NSS difference doesn't bother us. - */ - RATE_CTRL_CAPA_VHT_EXT_NSS_BW = BIT(0), -+ /** -+ * @RATE_CTRL_CAPA_AMPDU_TRIGGER: -+ * mac80211 should start A-MPDU sessions on tx -+ */ -+ RATE_CTRL_CAPA_AMPDU_TRIGGER = BIT(1), - }; - - struct rate_control_ops { ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1153,29 +1153,6 @@ minstrel_downgrade_prob_rate(struct mins - } - - static void --minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) --{ -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -- struct sta_info *sta = container_of(pubsta, struct sta_info, sta); -- u16 tid; -- -- if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) -- return; -- -- if (unlikely(!ieee80211_is_data_qos(hdr->frame_control))) -- return; -- -- if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) -- return; -- -- tid = ieee80211_get_tid(hdr); -- if (likely(sta->ampdu_mlme.tid_tx[tid])) -- return; -- -- ieee80211_start_tx_ba_session(pubsta, tid, 0); --} -- --static void - minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, - void *priv_sta, struct ieee80211_tx_status *st) - { -@@ -1477,10 +1454,6 @@ minstrel_ht_get_rate(void *priv, struct - struct minstrel_priv *mp = priv; - u16 sample_idx; - -- if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && -- !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate))) -- minstrel_aggr_check(sta, txrc->skb); -- - info->flags |= mi->tx_flags; - - #ifdef CPTCFG_MAC80211_DEBUGFS -@@ -1894,6 +1867,7 @@ static u32 minstrel_ht_get_expected_thro - - static const struct rate_control_ops mac80211_minstrel_ht = { - .name = "minstrel_ht", -+ .capa = RATE_CTRL_CAPA_AMPDU_TRIGGER, - .tx_status_ext = minstrel_ht_tx_status, - .get_rate = minstrel_ht_get_rate, - .rate_init = minstrel_ht_rate_init, ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3931,6 +3931,29 @@ void ieee80211_txq_schedule_start(struct - } - EXPORT_SYMBOL(ieee80211_txq_schedule_start); - -+static void -+ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, -+ struct sta_info *sta, -+ struct sk_buff *skb) -+{ -+ struct rate_control_ref *ref = sdata->local->rate_ctrl; -+ u16 tid; -+ -+ if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) -+ return; -+ -+ if (!sta || !sta->sta.ht_cap.ht_supported || -+ !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || -+ skb->protocol == sdata->control_port_protocol) -+ return; -+ -+ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; -+ if (likely(sta->ampdu_mlme.tid_tx[tid])) -+ return; -+ -+ ieee80211_start_tx_ba_session(&sta->sta, tid, 0); -+} -+ - void __ieee80211_subif_start_xmit(struct sk_buff *skb, - struct net_device *dev, - u32 info_flags, -@@ -3961,6 +3984,8 @@ void __ieee80211_subif_start_xmit(struct - skb_get_hash(skb); - } - -+ ieee80211_aggr_check(sdata, sta, skb); -+ - if (sta) { - struct ieee80211_fast_tx *fast_tx; - -@@ -4224,6 +4249,8 @@ static void ieee80211_8023_xmit(struct i - - memset(info, 0, sizeof(*info)); - -+ ieee80211_aggr_check(sdata, sta, skb); -+ - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); - if (tid_tx) { diff --git a/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch b/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch deleted file mode 100644 index cf84fca68..000000000 --- a/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch +++ /dev/null @@ -1,114 +0,0 @@ -From: Ryder Lee -Date: Fri, 28 May 2021 14:05:41 +0800 -Subject: [PATCH] mac80211: call ieee80211_tx_h_rate_ctrl() when dequeue - -Make ieee80211_tx_h_rate_ctrl() get called on dequeue to improve -performance since it reduces the turnaround time for rate control. - -Signed-off-by: Ryder Lee ---- - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1778,8 +1778,6 @@ static int invoke_tx_handlers_early(stru - CALL_TXH(ieee80211_tx_h_ps_buf); - CALL_TXH(ieee80211_tx_h_check_control_port_protocol); - CALL_TXH(ieee80211_tx_h_select_key); -- if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) -- CALL_TXH(ieee80211_tx_h_rate_ctrl); - - txh_done: - if (unlikely(res == TX_DROP)) { -@@ -1812,6 +1810,9 @@ static int invoke_tx_handlers_late(struc - goto txh_done; - } - -+ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) -+ CALL_TXH(ieee80211_tx_h_rate_ctrl); -+ - CALL_TXH(ieee80211_tx_h_michael_mic_add); - CALL_TXH(ieee80211_tx_h_sequence); - CALL_TXH(ieee80211_tx_h_fragment); -@@ -3382,15 +3383,21 @@ out: - * Can be called while the sta lock is held. Anything that can cause packets to - * be generated will cause deadlock! - */ --static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata, -- struct sta_info *sta, u8 pn_offs, -- struct ieee80211_key *key, -- struct sk_buff *skb) -+static ieee80211_tx_result -+ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata, -+ struct sta_info *sta, u8 pn_offs, -+ struct ieee80211_key *key, -+ struct ieee80211_tx_data *tx) - { -+ struct sk_buff *skb = tx->skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (void *)skb->data; - u8 tid = IEEE80211_NUM_TIDS; - -+ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL) && -+ ieee80211_tx_h_rate_ctrl(tx) != TX_CONTINUE) -+ return TX_DROP; -+ - if (key) - info->control.hw_key = &key->conf; - -@@ -3439,6 +3446,8 @@ static void ieee80211_xmit_fast_finish(s - break; - } - } -+ -+ return TX_CONTINUE; - } - - static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, -@@ -3542,24 +3551,17 @@ static bool ieee80211_xmit_fast(struct i - tx.sta = sta; - tx.key = fast_tx->key; - -- if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) { -- tx.skb = skb; -- r = ieee80211_tx_h_rate_ctrl(&tx); -- skb = tx.skb; -- tx.skb = NULL; -- -- if (r != TX_CONTINUE) { -- if (r != TX_QUEUED) -- kfree_skb(skb); -- return true; -- } -- } -- - if (ieee80211_queue_skb(local, sdata, sta, skb)) - return true; - -- ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, -- fast_tx->key, skb); -+ tx.skb = skb; -+ r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, -+ fast_tx->key, &tx); -+ tx.skb = NULL; -+ if (r == TX_DROP) { -+ kfree_skb(skb); -+ return true; -+ } - - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, -@@ -3670,8 +3672,12 @@ begin: - (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) - pn_offs = ieee80211_hdrlen(hdr->frame_control); - -- ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs, -- tx.key, skb); -+ r = ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs, -+ tx.key, &tx); -+ if (r != TX_CONTINUE) { -+ ieee80211_free_txskb(&local->hw, skb); -+ goto begin; -+ } - } else { - if (invoke_tx_handlers_late(&tx)) - goto begin; diff --git a/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch b/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch deleted file mode 100644 index 43a4a1334..000000000 --- a/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch +++ /dev/null @@ -1,119 +0,0 @@ -From: Ryder Lee -Date: Fri, 28 May 2021 14:05:43 +0800 -Subject: [PATCH] mac80211: add rate control support for encap offload - -The software rate control cannot deal with encap offload, so fix it. - -Signed-off-by: Ryder Lee ---- - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2024,6 +2024,15 @@ static inline void ieee80211_tx_skb(stru - ieee80211_tx_skb_tid(sdata, skb, 7); - } - -+static inline bool ieee80211_is_tx_data(struct sk_buff *skb) -+{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ -+ return info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP || -+ ieee80211_is_data(hdr->frame_control); -+} -+ - u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, - struct ieee802_11_elems *elems, - u64 filter, u32 crc, u8 *transmitter_bssid, ---- a/net/mac80211/rate.c -+++ b/net/mac80211/rate.c -@@ -297,15 +297,11 @@ void ieee80211_check_rate_mask(struct ie - static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) - { - struct sk_buff *skb = txrc->skb; -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- __le16 fc; -- -- fc = hdr->frame_control; - - return (info->flags & (IEEE80211_TX_CTL_NO_ACK | - IEEE80211_TX_CTL_USE_MINRATE)) || -- !ieee80211_is_data(fc); -+ !ieee80211_is_tx_data(skb); - } - - static void rc_send_low_basicrate(struct ieee80211_tx_rate *rate, -@@ -870,7 +866,6 @@ void ieee80211_get_tx_rates(struct ieee8 - int max_rates) - { - struct ieee80211_sub_if_data *sdata; -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_supported_band *sband; - -@@ -882,7 +877,7 @@ void ieee80211_get_tx_rates(struct ieee8 - sdata = vif_to_sdata(vif); - sband = sdata->local->hw.wiphy->bands[info->band]; - -- if (ieee80211_is_data(hdr->frame_control)) -+ if (ieee80211_is_tx_data(skb)) - rate_control_apply_mask(sdata, sta, sband, dest, max_rates); - - if (dest[0].idx < 0) ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -679,6 +679,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 - u32 len; - struct ieee80211_tx_rate_control txrc; - struct ieee80211_sta_rates *ratetbl = NULL; -+ bool encap = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - bool assoc = false; - - memset(&txrc, 0, sizeof(txrc)); -@@ -720,7 +721,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 - * just wants a probe response. - */ - if (tx->sdata->vif.bss_conf.use_short_preamble && -- (ieee80211_is_data(hdr->frame_control) || -+ (ieee80211_is_tx_data(tx->skb) || - (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) - txrc.short_preamble = true; - -@@ -742,7 +743,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 - "%s: Dropped data frame as no usable bitrate found while " - "scanning and associated. Target station: " - "%pM on %d GHz band\n", -- tx->sdata->name, hdr->addr1, -+ tx->sdata->name, -+ encap ? ((struct ethhdr *)hdr)->h_dest : hdr->addr1, - info->band ? 5 : 2)) - return TX_DROP; - -@@ -776,7 +778,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 - - if (txrc.reported_rate.idx < 0) { - txrc.reported_rate = tx->rate; -- if (tx->sta && ieee80211_is_data(hdr->frame_control)) -+ if (tx->sta && ieee80211_is_tx_data(tx->skb)) - tx->sta->tx_stats.last_rate = txrc.reported_rate; - } else if (tx->sta) - tx->sta->tx_stats.last_rate = txrc.reported_rate; -@@ -3660,8 +3662,16 @@ begin: - else - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - -- if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) -+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { -+ if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) { -+ r = ieee80211_tx_h_rate_ctrl(&tx); -+ if (r != TX_CONTINUE) { -+ ieee80211_free_txskb(&local->hw, skb); -+ goto begin; -+ } -+ } - goto encap_out; -+ } - - if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { - struct sta_info *sta = container_of(txq->sta, struct sta_info, diff --git a/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch b/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch deleted file mode 100644 index d4b327c69..000000000 --- a/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Felix Fietkau -Date: Thu, 17 Jun 2021 12:05:54 +0200 -Subject: [PATCH] mac80211: minstrel_ht: fix sample time check - -We need to skip sampling if the next sample time is after jiffies, not before. -This patch fixes an issue where in some cases only very little sampling (or none -at all) is performed, leading to really bad data rates - -Fixes: 80d55154b2f8 ("mac80211: minstrel_ht: significantly redesign the rate probing strategy") -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1466,7 +1466,7 @@ minstrel_ht_get_rate(void *priv, struct - (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) - return; - -- if (time_is_before_jiffies(mi->sample_time)) -+ if (time_is_after_jiffies(mi->sample_time)) - return; - - mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL; diff --git a/package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch b/package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch deleted file mode 100644 index a5ad377e6..000000000 --- a/package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch +++ /dev/null @@ -1,51 +0,0 @@ -From: Felix Fietkau -Date: Sat, 19 Jun 2021 12:10:14 +0200 -Subject: [PATCH] mac80211: remove iwlwifi specific workaround that broke sta - NDP tx - -Sending nulldata packets is important for sw AP link probing and detecting -4-address mode links. The checks that dropped these packets were apparently -added to work around an iwlwifi firmware bug with multi-TID aggregation. - -Fixes: 41cbb0f5a295 ("mac80211: add support for HE") -Cc: stable@vger.kernel.org -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -@@ -1085,6 +1085,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv - if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA)) - return -1; - -+ if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->he_cap.has_he) -+ return -1; -+ - if (unlikely(ieee80211_is_probe_resp(fc))) - iwl_mvm_probe_resp_set_noa(mvm, skb); - ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1094,11 +1094,6 @@ void ieee80211_send_nullfunc(struct ieee - struct ieee80211_hdr_3addr *nullfunc; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - -- /* Don't send NDPs when STA is connected HE */ -- if (sdata->vif.type == NL80211_IFTYPE_STATION && -- !(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) -- return; -- - skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, - !ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP)); - if (!skb) -@@ -1130,10 +1125,6 @@ static void ieee80211_send_4addr_nullfun - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) - return; - -- /* Don't send NDPs when connected HE */ -- if (!(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) -- return; -- - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); - if (!skb) - return; diff --git a/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch deleted file mode 100644 index 2ad083f15..000000000 --- a/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch +++ /dev/null @@ -1,112 +0,0 @@ -From: Felix Fietkau -Date: Tue, 29 Jun 2021 13:25:09 +0200 -Subject: [PATCH] mac80211: fix starting aggregation sessions on mesh - interfaces - -The logic for starting aggregation sessions was recently moved from minstrel_ht -to mac80211, into the subif tx handler just after the sta lookup. -Unfortunately this didn't work for mesh interfaces, since the sta lookup is -deferred until a much later point in time on those. -Fix this by also calling the aggregation check right after the deferred sta -lookup. - -Fixes: 08a46c642001 ("mac80211: move A-MPDU session check from minstrel_ht to mac80211") -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1159,6 +1159,29 @@ static bool ieee80211_tx_prep_agg(struct - return queued; - } - -+static void -+ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, -+ struct sta_info *sta, -+ struct sk_buff *skb) -+{ -+ struct rate_control_ref *ref = sdata->local->rate_ctrl; -+ u16 tid; -+ -+ if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) -+ return; -+ -+ if (!sta || !sta->sta.ht_cap.ht_supported || -+ !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || -+ skb->protocol == sdata->control_port_protocol) -+ return; -+ -+ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; -+ if (likely(sta->ampdu_mlme.tid_tx[tid])) -+ return; -+ -+ ieee80211_start_tx_ba_session(&sta->sta, tid, 0); -+} -+ - /* - * initialises @tx - * pass %NULL for the station if unknown, a valid pointer if known -@@ -1172,6 +1195,7 @@ ieee80211_tx_prepare(struct ieee80211_su - struct ieee80211_local *local = sdata->local; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ bool aggr_check = false; - int tid; - - memset(tx, 0, sizeof(*tx)); -@@ -1200,8 +1224,10 @@ ieee80211_tx_prepare(struct ieee80211_su - } else if (tx->sdata->control_port_protocol == tx->skb->protocol) { - tx->sta = sta_info_get_bss(sdata, hdr->addr1); - } -- if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) -+ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) { - tx->sta = sta_info_get(sdata, hdr->addr1); -+ aggr_check = true; -+ } - } - - if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && -@@ -1211,8 +1237,12 @@ ieee80211_tx_prepare(struct ieee80211_su - struct tid_ampdu_tx *tid_tx; - - tid = ieee80211_get_tid(hdr); -- - tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); -+ if (!tid_tx && aggr_check) { -+ ieee80211_aggr_check(sdata, tx->sta, skb); -+ tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); -+ } -+ - if (tid_tx) { - bool queued; - -@@ -3947,29 +3977,6 @@ void ieee80211_txq_schedule_start(struct - } - EXPORT_SYMBOL(ieee80211_txq_schedule_start); - --static void --ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, -- struct sta_info *sta, -- struct sk_buff *skb) --{ -- struct rate_control_ref *ref = sdata->local->rate_ctrl; -- u16 tid; -- -- if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) -- return; -- -- if (!sta || !sta->sta.ht_cap.ht_supported || -- !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || -- skb->protocol == sdata->control_port_protocol) -- return; -- -- tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; -- if (likely(sta->ampdu_mlme.tid_tx[tid])) -- return; -- -- ieee80211_start_tx_ba_session(&sta->sta, tid, 0); --} -- - void __ieee80211_subif_start_xmit(struct sk_buff *skb, - struct net_device *dev, - u32 info_flags, diff --git a/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch b/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch deleted file mode 100644 index b21b671c1..000000000 --- a/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch +++ /dev/null @@ -1,111 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 9 Jan 2021 18:57:51 +0100 -Subject: [PATCH] mac80211: introduce aql_enable node in debugfs - -Introduce aql_enable node in debugfs in order to enable/disable aql. -This is useful for debugging purpose. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/e7a934d5d84e4796c4f97ea5de4e66c824296b07.1610214851.git.lorenzo@kernel.org -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/debugfs.c -+++ b/net/mac80211/debugfs.c -@@ -281,6 +281,56 @@ static const struct file_operations aql_ - .llseek = default_llseek, - }; - -+static ssize_t aql_enable_read(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ char buf[3]; -+ int len; -+ -+ len = scnprintf(buf, sizeof(buf), "%d\n", -+ !static_key_false(&aql_disable.key)); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ bool aql_disabled = static_key_false(&aql_disable.key); -+ char buf[3]; -+ size_t len; -+ -+ if (count > sizeof(buf)) -+ return -EINVAL; -+ -+ if (copy_from_user(buf, user_buf, count)) -+ return -EFAULT; -+ -+ buf[sizeof(buf) - 1] = '\0'; -+ len = strlen(buf); -+ if (len > 0 && buf[len - 1] == '\n') -+ buf[len - 1] = 0; -+ -+ if (buf[0] == '0' && buf[1] == '\0') { -+ if (!aql_disabled) -+ static_branch_inc(&aql_disable); -+ } else if (buf[0] == '1' && buf[1] == '\0') { -+ if (aql_disabled) -+ static_branch_dec(&aql_disable); -+ } else { -+ return -EINVAL; -+ } -+ -+ return count; -+} -+ -+static const struct file_operations aql_enable_ops = { -+ .write = aql_enable_write, -+ .read = aql_enable_read, -+ .open = simple_open, -+ .llseek = default_llseek, -+}; -+ - static ssize_t force_tx_status_read(struct file *file, - char __user *user_buf, - size_t count, -@@ -569,6 +619,7 @@ void debugfs_hw_add(struct ieee80211_loc - DEBUGFS_ADD(power); - DEBUGFS_ADD(hw_conf); - DEBUGFS_ADD_MODE(force_tx_status, 0600); -+ DEBUGFS_ADD_MODE(aql_enable, 0600); - - if (local->ops->wake_tx_queue) - DEBUGFS_ADD_MODE(aqm, 0600); ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1140,6 +1140,8 @@ enum mac80211_scan_state { - SCAN_ABORT, - }; - -+DECLARE_STATIC_KEY_FALSE(aql_disable); -+ - struct ieee80211_local { - /* embed the driver visible part. - * don't cast (use the static inlines below), but we keep ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3887,6 +3887,8 @@ void __ieee80211_schedule_txq(struct iee - } - EXPORT_SYMBOL(__ieee80211_schedule_txq); - -+DEFINE_STATIC_KEY_FALSE(aql_disable); -+ - bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, - struct ieee80211_txq *txq) - { -@@ -3896,6 +3898,9 @@ bool ieee80211_txq_airtime_check(struct - if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) - return true; - -+ if (static_branch_unlikely(&aql_disable)) -+ return true; -+ - if (!txq->sta) - return true; - diff --git a/package/kernel/mac80211/patches/subsys/381-mac80211-rearrange-struct-txq_info-for-fewer-holes.patch b/package/kernel/mac80211/patches/subsys/381-mac80211-rearrange-struct-txq_info-for-fewer-holes.patch deleted file mode 100644 index 708ad6f46..000000000 --- a/package/kernel/mac80211/patches/subsys/381-mac80211-rearrange-struct-txq_info-for-fewer-holes.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Johannes Berg -Date: Fri, 18 Jun 2021 13:41:44 +0300 -Subject: [PATCH] mac80211: rearrange struct txq_info for fewer holes - -We can slightly decrease the size of struct txq_info by -rearranging some fields for fewer holes, so do that. - -Signed-off-by: Johannes Berg -Signed-off-by: Luca Coelho -Link: https://lore.kernel.org/r/iwlwifi.20210618133832.1bf019a1fe2e.Ib54622b8d6dc1a9a7dc484e573c073119450538b@changeid -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -5,7 +5,7 @@ - * Copyright 2006-2007 Jiri Benc - * Copyright 2007-2010 Johannes Berg - * Copyright 2013-2015 Intel Mobile Communications GmbH -- * Copyright (C) 2018-2020 Intel Corporation -+ * Copyright (C) 2018-2021 Intel Corporation - */ - - #ifndef IEEE80211_I_H -@@ -848,9 +848,12 @@ struct txq_info { - struct fq_tin tin; - struct codel_vars def_cvars; - struct codel_stats cstats; -- struct sk_buff_head frags; -- struct list_head schedule_order; -+ - u16 schedule_round; -+ struct list_head schedule_order; -+ -+ struct sk_buff_head frags; -+ - unsigned long flags; - - /* keep last! */ diff --git a/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch b/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch deleted file mode 100644 index ba78f7a14..000000000 --- a/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch +++ /dev/null @@ -1,1277 +0,0 @@ -From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= -Date: Wed, 23 Jun 2021 15:47:55 +0200 -Subject: [PATCH] mac80211: Switch to a virtual time-based airtime scheduler -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This switches the airtime scheduler in mac80211 to use a virtual -time-based scheduler instead of the round-robin scheduler used before. -This has a couple of advantages: - -- No need to sync up the round-robin scheduler in firmware/hardware with - the round-robin airtime scheduler. - -- If several stations are eligible for transmission we can schedule both - of them; no need to hard-block the scheduling rotation until the head - of the queue has used up its quantum. - -- The check of whether a station is eligible for transmission becomes - simpler (in ieee80211_txq_may_transmit()). - -The drawback is that scheduling becomes slightly more expensive, as we -need to maintain an rbtree of TXQs sorted by virtual time. This means -that ieee80211_register_airtime() becomes O(logN) in the number of -currently scheduled TXQs because it can change the order of the -scheduled stations. We mitigate this overhead by only resorting when a -station changes position in the tree, and hopefully N rarely grows too -big (it's only TXQs currently backlogged, not all associated stations), -so it shouldn't be too big of an issue. - -To prevent divisions in the fast path, we maintain both station sums and -pre-computed reciprocals of the sums. This turns the fast-path operation -into a multiplication, with divisions only happening as the number of -active stations change (to re-compute the current sum of all active -station weights). To prevent this re-computation of the reciprocal from -happening too frequently, we use a time-based notion of station -activity, instead of updating the weight every time a station gets -scheduled or de-scheduled. As queues can oscillate between empty and -occupied quite frequently, this can significantly cut down on the number -of re-computations. It also has the added benefit of making the station -airtime calculation independent on whether the queue happened to have -drained at the time an airtime value was accounted. - -Co-developed-by: Yibo Zhao -Signed-off-by: Yibo Zhao -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20210623134755.235545-1-toke@redhat.com -Signed-off-by: Johannes Berg ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -6552,9 +6552,6 @@ static inline void ieee80211_txq_schedul - { - } - --void __ieee80211_schedule_txq(struct ieee80211_hw *hw, -- struct ieee80211_txq *txq, bool force); -- - /** - * ieee80211_schedule_txq - schedule a TXQ for transmission - * -@@ -6567,11 +6564,7 @@ void __ieee80211_schedule_txq(struct iee - * The driver may call this function if it has buffered packets for - * this TXQ internally. - */ --static inline void --ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq) --{ -- __ieee80211_schedule_txq(hw, txq, true); --} -+void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq); - - /** - * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq() -@@ -6583,12 +6576,8 @@ ieee80211_schedule_txq(struct ieee80211_ - * The driver may set force=true if it has buffered packets for this TXQ - * internally. - */ --static inline void --ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq, -- bool force) --{ -- __ieee80211_schedule_txq(hw, txq, force); --} -+void ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq, -+ bool force); - - /** - * ieee80211_txq_may_transmit - check whether TXQ is allowed to transmit ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -1442,6 +1442,38 @@ static void sta_apply_mesh_params(struct - #endif - } - -+static void sta_apply_airtime_params(struct ieee80211_local *local, -+ struct sta_info *sta, -+ struct station_parameters *params) -+{ -+ u8 ac; -+ -+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -+ struct airtime_sched_info *air_sched = &local->airtime[ac]; -+ struct airtime_info *air_info = &sta->airtime[ac]; -+ struct txq_info *txqi; -+ u8 tid; -+ -+ spin_lock_bh(&air_sched->lock); -+ for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) { -+ if (air_info->weight == params->airtime_weight || -+ !sta->sta.txq[tid] || -+ ac != ieee80211_ac_from_tid(tid)) -+ continue; -+ -+ airtime_weight_set(air_info, params->airtime_weight); -+ -+ txqi = to_txq_info(sta->sta.txq[tid]); -+ if (RB_EMPTY_NODE(&txqi->schedule_order)) -+ continue; -+ -+ ieee80211_update_airtime_weight(local, air_sched, -+ 0, true); -+ } -+ spin_unlock_bh(&air_sched->lock); -+ } -+} -+ - static int sta_apply_parameters(struct ieee80211_local *local, - struct sta_info *sta, - struct station_parameters *params) -@@ -1629,7 +1661,8 @@ static int sta_apply_parameters(struct i - sta_apply_mesh_params(local, sta, params); - - if (params->airtime_weight) -- sta->airtime_weight = params->airtime_weight; -+ sta_apply_airtime_params(local, sta, params); -+ - - /* set the STA state after all sta info from usermode has been set */ - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) || ---- a/net/mac80211/debugfs.c -+++ b/net/mac80211/debugfs.c -@@ -216,14 +216,14 @@ static ssize_t aql_txq_limit_read(struct - "VI %u %u\n" - "BE %u %u\n" - "BK %u %u\n", -- local->aql_txq_limit_low[IEEE80211_AC_VO], -- local->aql_txq_limit_high[IEEE80211_AC_VO], -- local->aql_txq_limit_low[IEEE80211_AC_VI], -- local->aql_txq_limit_high[IEEE80211_AC_VI], -- local->aql_txq_limit_low[IEEE80211_AC_BE], -- local->aql_txq_limit_high[IEEE80211_AC_BE], -- local->aql_txq_limit_low[IEEE80211_AC_BK], -- local->aql_txq_limit_high[IEEE80211_AC_BK]); -+ local->airtime[IEEE80211_AC_VO].aql_txq_limit_low, -+ local->airtime[IEEE80211_AC_VO].aql_txq_limit_high, -+ local->airtime[IEEE80211_AC_VI].aql_txq_limit_low, -+ local->airtime[IEEE80211_AC_VI].aql_txq_limit_high, -+ local->airtime[IEEE80211_AC_BE].aql_txq_limit_low, -+ local->airtime[IEEE80211_AC_BE].aql_txq_limit_high, -+ local->airtime[IEEE80211_AC_BK].aql_txq_limit_low, -+ local->airtime[IEEE80211_AC_BK].aql_txq_limit_high); - return simple_read_from_buffer(user_buf, count, ppos, - buf, len); - } -@@ -255,11 +255,11 @@ static ssize_t aql_txq_limit_write(struc - if (ac >= IEEE80211_NUM_ACS) - return -EINVAL; - -- q_limit_low_old = local->aql_txq_limit_low[ac]; -- q_limit_high_old = local->aql_txq_limit_high[ac]; -+ q_limit_low_old = local->airtime[ac].aql_txq_limit_low; -+ q_limit_high_old = local->airtime[ac].aql_txq_limit_high; - -- local->aql_txq_limit_low[ac] = q_limit_low; -- local->aql_txq_limit_high[ac] = q_limit_high; -+ local->airtime[ac].aql_txq_limit_low = q_limit_low; -+ local->airtime[ac].aql_txq_limit_high = q_limit_high; - - mutex_lock(&local->sta_mtx); - list_for_each_entry(sta, &local->sta_list, list) { -@@ -382,6 +382,46 @@ static const struct file_operations forc - .llseek = default_llseek, - }; - -+static ssize_t airtime_read(struct file *file, -+ char __user *user_buf, -+ size_t count, -+ loff_t *ppos) -+{ -+ struct ieee80211_local *local = file->private_data; -+ char buf[200]; -+ u64 v_t[IEEE80211_NUM_ACS]; -+ u64 wt[IEEE80211_NUM_ACS]; -+ int len = 0, ac; -+ -+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -+ spin_lock_bh(&local->airtime[ac].lock); -+ v_t[ac] = local->airtime[ac].v_t; -+ wt[ac] = local->airtime[ac].weight_sum; -+ spin_unlock_bh(&local->airtime[ac].lock); -+ } -+ len = scnprintf(buf, sizeof(buf), -+ "\tVO VI BE BK\n" -+ "Virt-t\t%-10llu %-10llu %-10llu %-10llu\n" -+ "Weight\t%-10llu %-10llu %-10llu %-10llu\n", -+ v_t[0], -+ v_t[1], -+ v_t[2], -+ v_t[3], -+ wt[0], -+ wt[1], -+ wt[2], -+ wt[3]); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, -+ buf, len); -+} -+ -+static const struct file_operations airtime_ops = { -+ .read = airtime_read, -+ .open = simple_open, -+ .llseek = default_llseek, -+}; -+ - #ifdef CONFIG_PM - static ssize_t reset_write(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -@@ -624,7 +664,11 @@ void debugfs_hw_add(struct ieee80211_loc - if (local->ops->wake_tx_queue) - DEBUGFS_ADD_MODE(aqm, 0600); - -- DEBUGFS_ADD_MODE(airtime_flags, 0600); -+ if (wiphy_ext_feature_isset(local->hw.wiphy, -+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) { -+ DEBUGFS_ADD_MODE(airtime, 0600); -+ DEBUGFS_ADD_MODE(airtime_flags, 0600); -+ } - - DEBUGFS_ADD(aql_txq_limit); - debugfs_create_u32("aql_threshold", 0600, ---- a/net/mac80211/debugfs_netdev.c -+++ b/net/mac80211/debugfs_netdev.c -@@ -513,6 +513,34 @@ static ssize_t ieee80211_if_fmt_aqm( - } - IEEE80211_IF_FILE_R(aqm); - -+static ssize_t ieee80211_if_fmt_airtime( -+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) -+{ -+ struct ieee80211_local *local = sdata->local; -+ struct ieee80211_txq *txq = sdata->vif.txq; -+ struct airtime_info *air_info; -+ int len; -+ -+ if (!txq) -+ return 0; -+ -+ spin_lock_bh(&local->airtime[txq->ac].lock); -+ air_info = to_airtime_info(txq); -+ len = scnprintf(buf, -+ buflen, -+ "RX: %llu us\nTX: %llu us\nWeight: %u\n" -+ "Virt-T: %lld us\n", -+ air_info->rx_airtime, -+ air_info->tx_airtime, -+ air_info->weight, -+ air_info->v_t); -+ spin_unlock_bh(&local->airtime[txq->ac].lock); -+ -+ return len; -+} -+ -+IEEE80211_IF_FILE_R(airtime); -+ - IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX); - - /* IBSS attributes */ -@@ -661,8 +689,10 @@ static void add_common_files(struct ieee - - if (sdata->local->ops->wake_tx_queue && - sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && -- sdata->vif.type != NL80211_IFTYPE_NAN) -+ sdata->vif.type != NL80211_IFTYPE_NAN) { - DEBUGFS_ADD(aqm); -+ DEBUGFS_ADD(airtime); -+ } - } - - static void add_sta_files(struct ieee80211_sub_if_data *sdata) ---- a/net/mac80211/debugfs_sta.c -+++ b/net/mac80211/debugfs_sta.c -@@ -202,7 +202,7 @@ static ssize_t sta_airtime_read(struct f - size_t bufsz = 400; - char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf; - u64 rx_airtime = 0, tx_airtime = 0; -- s64 deficit[IEEE80211_NUM_ACS]; -+ u64 v_t[IEEE80211_NUM_ACS]; - ssize_t rv; - int ac; - -@@ -210,18 +210,18 @@ static ssize_t sta_airtime_read(struct f - return -ENOMEM; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -- spin_lock_bh(&local->active_txq_lock[ac]); -+ spin_lock_bh(&local->airtime[ac].lock); - rx_airtime += sta->airtime[ac].rx_airtime; - tx_airtime += sta->airtime[ac].tx_airtime; -- deficit[ac] = sta->airtime[ac].deficit; -- spin_unlock_bh(&local->active_txq_lock[ac]); -+ v_t[ac] = sta->airtime[ac].v_t; -+ spin_unlock_bh(&local->airtime[ac].lock); - } - - p += scnprintf(p, bufsz + buf - p, - "RX: %llu us\nTX: %llu us\nWeight: %u\n" -- "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n", -- rx_airtime, tx_airtime, sta->airtime_weight, -- deficit[0], deficit[1], deficit[2], deficit[3]); -+ "Virt-T: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n", -+ rx_airtime, tx_airtime, sta->airtime[0].weight, -+ v_t[0], v_t[1], v_t[2], v_t[3]); - - rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); - kfree(buf); -@@ -236,11 +236,11 @@ static ssize_t sta_airtime_write(struct - int ac; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -- spin_lock_bh(&local->active_txq_lock[ac]); -+ spin_lock_bh(&local->airtime[ac].lock); - sta->airtime[ac].rx_airtime = 0; - sta->airtime[ac].tx_airtime = 0; -- sta->airtime[ac].deficit = sta->airtime_weight; -- spin_unlock_bh(&local->active_txq_lock[ac]); -+ sta->airtime[ac].v_t = 0; -+ spin_unlock_bh(&local->airtime[ac].lock); - } - - return count; -@@ -263,10 +263,10 @@ static ssize_t sta_aql_read(struct file - return -ENOMEM; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -- spin_lock_bh(&local->active_txq_lock[ac]); -+ spin_lock_bh(&local->airtime[ac].lock); - q_limit_l[ac] = sta->airtime[ac].aql_limit_low; - q_limit_h[ac] = sta->airtime[ac].aql_limit_high; -- spin_unlock_bh(&local->active_txq_lock[ac]); -+ spin_unlock_bh(&local->airtime[ac].lock); - q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending); - } - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -840,20 +840,16 @@ enum txq_info_flags { - * @def_flow: used as a fallback flow when a packet destined to @tin hashes to - * a fq_flow which is already owned by a different tin - * @def_cvars: codel vars for @def_flow -- * @frags: used to keep fragments created after dequeue - * @schedule_order: used with ieee80211_local->active_txqs -- * @schedule_round: counter to prevent infinite loops on TXQ scheduling -+ * @frags: used to keep fragments created after dequeue - */ - struct txq_info { - struct fq_tin tin; - struct codel_vars def_cvars; - struct codel_stats cstats; -- -- u16 schedule_round; -- struct list_head schedule_order; -+ struct rb_node schedule_order; - - struct sk_buff_head frags; -- - unsigned long flags; - - /* keep last! */ -@@ -930,6 +926,8 @@ struct ieee80211_sub_if_data { - struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; - struct mac80211_qos_map __rcu *qos_map; - -+ struct airtime_info airtime[IEEE80211_NUM_ACS]; -+ - struct work_struct csa_finalize_work; - bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ - struct cfg80211_chan_def csa_chandef; -@@ -1143,6 +1141,44 @@ enum mac80211_scan_state { - SCAN_ABORT, - }; - -+/** -+ * struct airtime_sched_info - state used for airtime scheduling and AQL -+ * -+ * @lock: spinlock that protects all the fields in this struct -+ * @active_txqs: rbtree of currently backlogged queues, sorted by virtual time -+ * @schedule_pos: the current position maintained while a driver walks the tree -+ * with ieee80211_next_txq() -+ * @active_list: list of struct airtime_info structs that were active within -+ * the last AIRTIME_ACTIVE_DURATION (100 ms), used to compute -+ * weight_sum -+ * @last_weight_update: used for rate limiting walking active_list -+ * @last_schedule_time: tracks the last time a transmission was scheduled; used -+ * for catching up v_t if no stations are eligible for -+ * transmission. -+ * @v_t: global virtual time; queues with v_t < this are eligible for -+ * transmission -+ * @weight_sum: total sum of all active stations used for dividing airtime -+ * @weight_sum_reciprocal: reciprocal of weight_sum (to avoid divisions in fast -+ * path - see comment above -+ * IEEE80211_RECIPROCAL_DIVISOR_64) -+ * @aql_txq_limit_low: AQL limit when total outstanding airtime -+ * is < IEEE80211_AQL_THRESHOLD -+ * @aql_txq_limit_high: AQL limit when total outstanding airtime -+ * is > IEEE80211_AQL_THRESHOLD -+ */ -+struct airtime_sched_info { -+ spinlock_t lock; -+ struct rb_root_cached active_txqs; -+ struct rb_node *schedule_pos; -+ struct list_head active_list; -+ u64 last_weight_update; -+ u64 last_schedule_activity; -+ u64 v_t; -+ u64 weight_sum; -+ u64 weight_sum_reciprocal; -+ u32 aql_txq_limit_low; -+ u32 aql_txq_limit_high; -+}; - DECLARE_STATIC_KEY_FALSE(aql_disable); - - struct ieee80211_local { -@@ -1156,13 +1192,8 @@ struct ieee80211_local { - struct codel_params cparams; - - /* protects active_txqs and txqi->schedule_order */ -- spinlock_t active_txq_lock[IEEE80211_NUM_ACS]; -- struct list_head active_txqs[IEEE80211_NUM_ACS]; -- u16 schedule_round[IEEE80211_NUM_ACS]; -- -+ struct airtime_sched_info airtime[IEEE80211_NUM_ACS]; - u16 airtime_flags; -- u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; -- u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; - u32 aql_threshold; - atomic_t aql_total_pending_airtime; - -@@ -1581,6 +1612,125 @@ static inline bool txq_has_queue(struct - return !(skb_queue_empty(&txqi->frags) && !txqi->tin.backlog_packets); - } - -+static inline struct airtime_info *to_airtime_info(struct ieee80211_txq *txq) -+{ -+ struct ieee80211_sub_if_data *sdata; -+ struct sta_info *sta; -+ -+ if (txq->sta) { -+ sta = container_of(txq->sta, struct sta_info, sta); -+ return &sta->airtime[txq->ac]; -+ } -+ -+ sdata = vif_to_sdata(txq->vif); -+ return &sdata->airtime[txq->ac]; -+} -+ -+/* To avoid divisions in the fast path, we keep pre-computed reciprocals for -+ * airtime weight calculations. There are two different weights to keep track -+ * of: The per-station weight and the sum of weights per phy. -+ * -+ * For the per-station weights (kept in airtime_info below), we use 32-bit -+ * reciprocals with a devisor of 2^19. This lets us keep the multiplications and -+ * divisions for the station weights as 32-bit operations at the cost of a bit -+ * of rounding error for high weights; but the choice of divisor keeps rounding -+ * errors <10% for weights <2^15, assuming no more than 8ms of airtime is -+ * reported at a time. -+ * -+ * For the per-phy sum of weights the values can get higher, so we use 64-bit -+ * operations for those with a 32-bit divisor, which should avoid any -+ * significant rounding errors. -+ */ -+#define IEEE80211_RECIPROCAL_DIVISOR_64 0x100000000ULL -+#define IEEE80211_RECIPROCAL_SHIFT_64 32 -+#define IEEE80211_RECIPROCAL_DIVISOR_32 0x80000U -+#define IEEE80211_RECIPROCAL_SHIFT_32 19 -+ -+static inline void airtime_weight_set(struct airtime_info *air_info, u16 weight) -+{ -+ if (air_info->weight == weight) -+ return; -+ -+ air_info->weight = weight; -+ if (weight) { -+ air_info->weight_reciprocal = -+ IEEE80211_RECIPROCAL_DIVISOR_32 / weight; -+ } else { -+ air_info->weight_reciprocal = 0; -+ } -+} -+ -+static inline void airtime_weight_sum_set(struct airtime_sched_info *air_sched, -+ int weight_sum) -+{ -+ if (air_sched->weight_sum == weight_sum) -+ return; -+ -+ air_sched->weight_sum = weight_sum; -+ if (air_sched->weight_sum) { -+ air_sched->weight_sum_reciprocal = IEEE80211_RECIPROCAL_DIVISOR_64; -+ do_div(air_sched->weight_sum_reciprocal, air_sched->weight_sum); -+ } else { -+ air_sched->weight_sum_reciprocal = 0; -+ } -+} -+ -+/* A problem when trying to enforce airtime fairness is that we want to divide -+ * the airtime between the currently *active* stations. However, basing this on -+ * the instantaneous queue state of stations doesn't work, as queues tend to -+ * oscillate very quickly between empty and occupied, leading to the scheduler -+ * thinking only a single station is active when deciding whether to allow -+ * transmission (and thus not throttling correctly). -+ * -+ * To fix this we use a timer-based notion of activity: a station is considered -+ * active if it has been scheduled within the last 100 ms; we keep a separate -+ * list of all the stations considered active in this manner, and lazily update -+ * the total weight of active stations from this list (filtering the stations in -+ * the list by their 'last active' time). -+ * -+ * We add one additional safeguard to guard against stations that manage to get -+ * scheduled every 100 ms but don't transmit a lot of data, and thus don't use -+ * up any airtime. Such stations would be able to get priority for an extended -+ * period of time if they do start transmitting at full capacity again, and so -+ * we add an explicit maximum for how far behind a station is allowed to fall in -+ * the virtual airtime domain. This limit is set to a relatively high value of -+ * 20 ms because the main mechanism for catching up idle stations is the active -+ * state as described above; i.e., the hard limit should only be hit in -+ * pathological cases. -+ */ -+#define AIRTIME_ACTIVE_DURATION (100 * NSEC_PER_MSEC) -+#define AIRTIME_MAX_BEHIND 20000 /* 20 ms */ -+ -+static inline bool airtime_is_active(struct airtime_info *air_info, u64 now) -+{ -+ return air_info->last_scheduled >= now - AIRTIME_ACTIVE_DURATION; -+} -+ -+static inline void airtime_set_active(struct airtime_sched_info *air_sched, -+ struct airtime_info *air_info, u64 now) -+{ -+ air_info->last_scheduled = now; -+ air_sched->last_schedule_activity = now; -+ list_move_tail(&air_info->list, &air_sched->active_list); -+} -+ -+static inline bool airtime_catchup_v_t(struct airtime_sched_info *air_sched, -+ u64 v_t, u64 now) -+{ -+ air_sched->v_t = v_t; -+ return true; -+} -+ -+static inline void init_airtime_info(struct airtime_info *air_info, -+ struct airtime_sched_info *air_sched) -+{ -+ atomic_set(&air_info->aql_tx_pending, 0); -+ air_info->aql_limit_low = air_sched->aql_txq_limit_low; -+ air_info->aql_limit_high = air_sched->aql_txq_limit_high; -+ airtime_weight_set(air_info, IEEE80211_DEFAULT_AIRTIME_WEIGHT); -+ INIT_LIST_HEAD(&air_info->list); -+} -+ - static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) - { - return ether_addr_equal(raddr, addr) || -@@ -1821,6 +1971,14 @@ int ieee80211_tx_control_port(struct wip - u64 *cookie); - int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, - const u8 *buf, size_t len); -+void ieee80211_resort_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq); -+void ieee80211_unschedule_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq, -+ bool purge); -+void ieee80211_update_airtime_weight(struct ieee80211_local *local, -+ struct airtime_sched_info *air_sched, -+ u64 now, bool force); - - /* HT */ - void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -2067,6 +2067,9 @@ int ieee80211_if_add(struct ieee80211_lo - } - } - -+ for (i = 0; i < IEEE80211_NUM_ACS; i++) -+ init_airtime_info(&sdata->airtime[i], &local->airtime[i]); -+ - ieee80211_set_default_queues(sdata); - - sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -693,10 +693,13 @@ struct ieee80211_hw *ieee80211_alloc_hw_ - spin_lock_init(&local->queue_stop_reason_lock); - - for (i = 0; i < IEEE80211_NUM_ACS; i++) { -- INIT_LIST_HEAD(&local->active_txqs[i]); -- spin_lock_init(&local->active_txq_lock[i]); -- local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L; -- local->aql_txq_limit_high[i] = -+ struct airtime_sched_info *air_sched = &local->airtime[i]; -+ -+ air_sched->active_txqs = RB_ROOT_CACHED; -+ INIT_LIST_HEAD(&air_sched->active_list); -+ spin_lock_init(&air_sched->lock); -+ air_sched->aql_txq_limit_low = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L; -+ air_sched->aql_txq_limit_high = - IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H; - } - ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -1573,12 +1573,8 @@ static void sta_ps_start(struct sta_info - - for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) { - struct ieee80211_txq *txq = sta->sta.txq[tid]; -- struct txq_info *txqi = to_txq_info(txq); - -- spin_lock(&local->active_txq_lock[txq->ac]); -- if (!list_empty(&txqi->schedule_order)) -- list_del_init(&txqi->schedule_order); -- spin_unlock(&local->active_txq_lock[txq->ac]); -+ ieee80211_unschedule_txq(&local->hw, txq, false); - - if (txq_has_queue(txq)) - set_bit(tid, &sta->txq_buffered_tids); ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -426,15 +426,11 @@ struct sta_info *sta_info_alloc(struct i - if (sta_prepare_rate_control(local, sta, gfp)) - goto free_txq; - -- sta->airtime_weight = IEEE80211_DEFAULT_AIRTIME_WEIGHT; - - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - skb_queue_head_init(&sta->ps_tx_buf[i]); - skb_queue_head_init(&sta->tx_filtered[i]); -- sta->airtime[i].deficit = sta->airtime_weight; -- atomic_set(&sta->airtime[i].aql_tx_pending, 0); -- sta->airtime[i].aql_limit_low = local->aql_txq_limit_low[i]; -- sta->airtime[i].aql_limit_high = local->aql_txq_limit_high[i]; -+ init_airtime_info(&sta->airtime[i], &local->airtime[i]); - } - - for (i = 0; i < IEEE80211_NUM_TIDS; i++) -@@ -1898,24 +1894,59 @@ void ieee80211_sta_set_buffered(struct i - } - EXPORT_SYMBOL(ieee80211_sta_set_buffered); - --void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid, -- u32 tx_airtime, u32 rx_airtime) -+void ieee80211_register_airtime(struct ieee80211_txq *txq, -+ u32 tx_airtime, u32 rx_airtime) - { -- struct sta_info *sta = container_of(pubsta, struct sta_info, sta); -- struct ieee80211_local *local = sta->sdata->local; -- u8 ac = ieee80211_ac_from_tid(tid); -+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); -+ struct ieee80211_local *local = sdata->local; -+ u64 weight_sum, weight_sum_reciprocal; -+ struct airtime_sched_info *air_sched; -+ struct airtime_info *air_info; - u32 airtime = 0; - -- if (sta->local->airtime_flags & AIRTIME_USE_TX) -+ air_sched = &local->airtime[txq->ac]; -+ air_info = to_airtime_info(txq); -+ -+ if (local->airtime_flags & AIRTIME_USE_TX) - airtime += tx_airtime; -- if (sta->local->airtime_flags & AIRTIME_USE_RX) -+ if (local->airtime_flags & AIRTIME_USE_RX) - airtime += rx_airtime; - -- spin_lock_bh(&local->active_txq_lock[ac]); -- sta->airtime[ac].tx_airtime += tx_airtime; -- sta->airtime[ac].rx_airtime += rx_airtime; -- sta->airtime[ac].deficit -= airtime; -- spin_unlock_bh(&local->active_txq_lock[ac]); -+ /* Weights scale so the unit weight is 256 */ -+ airtime <<= 8; -+ -+ spin_lock_bh(&air_sched->lock); -+ -+ air_info->tx_airtime += tx_airtime; -+ air_info->rx_airtime += rx_airtime; -+ -+ if (air_sched->weight_sum) { -+ weight_sum = air_sched->weight_sum; -+ weight_sum_reciprocal = air_sched->weight_sum_reciprocal; -+ } else { -+ weight_sum = air_info->weight; -+ weight_sum_reciprocal = air_info->weight_reciprocal; -+ } -+ -+ /* Round the calculation of global vt */ -+ air_sched->v_t += (u64)((airtime + (weight_sum >> 1)) * -+ weight_sum_reciprocal) >> IEEE80211_RECIPROCAL_SHIFT_64; -+ air_info->v_t += (u32)((airtime + (air_info->weight >> 1)) * -+ air_info->weight_reciprocal) >> IEEE80211_RECIPROCAL_SHIFT_32; -+ ieee80211_resort_txq(&local->hw, txq); -+ -+ spin_unlock_bh(&air_sched->lock); -+} -+ -+void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid, -+ u32 tx_airtime, u32 rx_airtime) -+{ -+ struct ieee80211_txq *txq = pubsta->txq[tid]; -+ -+ if (!txq) -+ return; -+ -+ ieee80211_register_airtime(txq, tx_airtime, rx_airtime); - } - EXPORT_SYMBOL(ieee80211_sta_register_airtime); - -@@ -2364,7 +2395,7 @@ void sta_set_sinfo(struct sta_info *sta, - } - - if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT))) { -- sinfo->airtime_weight = sta->airtime_weight; -+ sinfo->airtime_weight = sta->airtime[0].weight; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT); - } - ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -135,18 +135,25 @@ enum ieee80211_agg_stop_reason { - #define AIRTIME_USE_TX BIT(0) - #define AIRTIME_USE_RX BIT(1) - -+ - struct airtime_info { - u64 rx_airtime; - u64 tx_airtime; -- s64 deficit; -+ u64 v_t; -+ u64 last_scheduled; -+ struct list_head list; - atomic_t aql_tx_pending; /* Estimated airtime for frames pending */ - u32 aql_limit_low; - u32 aql_limit_high; -+ u32 weight_reciprocal; -+ u16 weight; - }; - - void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, - struct sta_info *sta, u8 ac, - u16 tx_airtime, bool tx_completed); -+void ieee80211_register_airtime(struct ieee80211_txq *txq, -+ u32 tx_airtime, u32 rx_airtime); - - struct sta_info; - -@@ -515,7 +522,6 @@ struct ieee80211_fragment_cache { - * @tid_seq: per-TID sequence numbers for sending to this STA - * @airtime: per-AC struct airtime_info describing airtime statistics for this - * station -- * @airtime_weight: station weight for airtime fairness calculation purposes - * @ampdu_mlme: A-MPDU state machine state - * @mesh: mesh STA information - * @debugfs_dir: debug filesystem directory dentry -@@ -646,7 +652,6 @@ struct sta_info { - u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; - - struct airtime_info airtime[IEEE80211_NUM_ACS]; -- u16 airtime_weight; - - /* - * Aggregation information, locked with lock. ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -972,6 +972,25 @@ static void __ieee80211_tx_status(struct - if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) - ieee80211_frame_acked(sta, skb); - -+ } else if (wiphy_ext_feature_isset(local->hw.wiphy, -+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) { -+ struct ieee80211_sub_if_data *sdata; -+ struct ieee80211_txq *txq; -+ u32 airtime; -+ -+ /* Account airtime to multicast queue */ -+ sdata = ieee80211_sdata_from_skb(local, skb); -+ -+ if (sdata && (txq = sdata->vif.txq)) { -+ airtime = info->status.tx_time ?: -+ ieee80211_calc_expected_tx_airtime(hw, -+ &sdata->vif, -+ NULL, -+ skb->len, -+ false); -+ -+ ieee80211_register_airtime(txq, airtime, 0); -+ } - } - - /* SNMP counters ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1489,7 +1490,7 @@ void ieee80211_txq_init(struct ieee80211 - codel_vars_init(&txqi->def_cvars); - codel_stats_init(&txqi->cstats); - __skb_queue_head_init(&txqi->frags); -- INIT_LIST_HEAD(&txqi->schedule_order); -+ RB_CLEAR_NODE(&txqi->schedule_order); - - txqi->txq.vif = &sdata->vif; - -@@ -1533,9 +1534,7 @@ void ieee80211_txq_purge(struct ieee8021 - ieee80211_purge_tx_queue(&local->hw, &txqi->frags); - spin_unlock_bh(&fq->lock); - -- spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]); -- list_del_init(&txqi->schedule_order); -- spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]); -+ ieee80211_unschedule_txq(&local->hw, &txqi->txq, true); - } - - void ieee80211_txq_set_params(struct ieee80211_local *local) -@@ -3797,102 +3796,259 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue); - struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac) - { - struct ieee80211_local *local = hw_to_local(hw); -+ struct airtime_sched_info *air_sched; -+ u64 now = ktime_get_boottime_ns(); - struct ieee80211_txq *ret = NULL; -- struct txq_info *txqi = NULL, *head = NULL; -- bool found_eligible_txq = false; -+ struct airtime_info *air_info; -+ struct txq_info *txqi = NULL; -+ struct rb_node *node; -+ bool first = false; - -- spin_lock_bh(&local->active_txq_lock[ac]); -+ air_sched = &local->airtime[ac]; -+ spin_lock_bh(&air_sched->lock); - -- begin: -- txqi = list_first_entry_or_null(&local->active_txqs[ac], -- struct txq_info, -- schedule_order); -- if (!txqi) -+ node = air_sched->schedule_pos; -+ -+begin: -+ if (!node) { -+ node = rb_first_cached(&air_sched->active_txqs); -+ first = true; -+ } else { -+ node = rb_next(node); -+ } -+ -+ if (!node) - goto out; - -- if (txqi == head) { -- if (!found_eligible_txq) -- goto out; -- else -- found_eligible_txq = false; -+ txqi = container_of(node, struct txq_info, schedule_order); -+ air_info = to_airtime_info(&txqi->txq); -+ -+ if (air_info->v_t > air_sched->v_t && -+ (!first || !airtime_catchup_v_t(air_sched, air_info->v_t, now))) -+ goto out; -+ -+ if (!ieee80211_txq_airtime_check(hw, &txqi->txq)) { -+ first = false; -+ goto begin; - } - -- if (!head) -- head = txqi; -+ air_sched->schedule_pos = node; -+ air_sched->last_schedule_activity = now; -+ ret = &txqi->txq; -+out: -+ spin_unlock_bh(&air_sched->lock); -+ return ret; -+} -+EXPORT_SYMBOL(ieee80211_next_txq); - -- if (txqi->txq.sta) { -- struct sta_info *sta = container_of(txqi->txq.sta, -- struct sta_info, sta); -- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); -- s64 deficit = sta->airtime[txqi->txq.ac].deficit; -+static void __ieee80211_insert_txq(struct rb_root_cached *root, -+ struct txq_info *txqi) -+{ -+ struct rb_node **new = &root->rb_root.rb_node; -+ struct airtime_info *old_air, *new_air; -+ struct rb_node *parent = NULL; -+ struct txq_info *__txqi; -+ bool leftmost = true; -+ -+ while (*new) { -+ parent = *new; -+ __txqi = rb_entry(parent, struct txq_info, schedule_order); -+ old_air = to_airtime_info(&__txqi->txq); -+ new_air = to_airtime_info(&txqi->txq); - -- if (aql_check) -- found_eligible_txq = true; -+ if (new_air->v_t <= old_air->v_t) { -+ new = &parent->rb_left; -+ } else { -+ new = &parent->rb_right; -+ leftmost = false; -+ } -+ } - -- if (deficit < 0) -- sta->airtime[txqi->txq.ac].deficit += -- sta->airtime_weight; -- -- if (deficit < 0 || !aql_check) { -- list_move_tail(&txqi->schedule_order, -- &local->active_txqs[txqi->txq.ac]); -- goto begin; -+ rb_link_node(&txqi->schedule_order, parent, new); -+ rb_insert_color_cached(&txqi->schedule_order, root, leftmost); -+} -+ -+void ieee80211_resort_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq) -+{ -+ struct airtime_info *air_info = to_airtime_info(txq); -+ struct ieee80211_local *local = hw_to_local(hw); -+ struct txq_info *txqi = to_txq_info(txq); -+ struct airtime_sched_info *air_sched; -+ -+ air_sched = &local->airtime[txq->ac]; -+ -+ lockdep_assert_held(&air_sched->lock); -+ -+ if (!RB_EMPTY_NODE(&txqi->schedule_order)) { -+ struct airtime_info *a_prev = NULL, *a_next = NULL; -+ struct txq_info *t_prev, *t_next; -+ struct rb_node *n_prev, *n_next; -+ -+ /* Erasing a node can cause an expensive rebalancing operation, -+ * so we check the previous and next nodes first and only remove -+ * and re-insert if the current node is not already in the -+ * correct position. -+ */ -+ if ((n_prev = rb_prev(&txqi->schedule_order)) != NULL) { -+ t_prev = container_of(n_prev, struct txq_info, -+ schedule_order); -+ a_prev = to_airtime_info(&t_prev->txq); -+ } -+ -+ if ((n_next = rb_next(&txqi->schedule_order)) != NULL) { -+ t_next = container_of(n_next, struct txq_info, -+ schedule_order); -+ a_next = to_airtime_info(&t_next->txq); - } -+ -+ if ((!a_prev || a_prev->v_t <= air_info->v_t) && -+ (!a_next || a_next->v_t > air_info->v_t)) -+ return; -+ -+ if (air_sched->schedule_pos == &txqi->schedule_order) -+ air_sched->schedule_pos = n_prev; -+ -+ rb_erase_cached(&txqi->schedule_order, -+ &air_sched->active_txqs); -+ RB_CLEAR_NODE(&txqi->schedule_order); -+ __ieee80211_insert_txq(&air_sched->active_txqs, txqi); - } -+} -+ -+void ieee80211_update_airtime_weight(struct ieee80211_local *local, -+ struct airtime_sched_info *air_sched, -+ u64 now, bool force) -+{ -+ struct airtime_info *air_info, *tmp; -+ u64 weight_sum = 0; -+ -+ if (unlikely(!now)) -+ now = ktime_get_boottime_ns(); -+ -+ lockdep_assert_held(&air_sched->lock); -+ -+ if (!force && (air_sched->last_weight_update < -+ now - AIRTIME_ACTIVE_DURATION)) -+ return; -+ -+ list_for_each_entry_safe(air_info, tmp, -+ &air_sched->active_list, list) { -+ if (airtime_is_active(air_info, now)) -+ weight_sum += air_info->weight; -+ else -+ list_del_init(&air_info->list); -+ } -+ airtime_weight_sum_set(air_sched, weight_sum); -+ air_sched->last_weight_update = now; -+} - -+void ieee80211_schedule_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq) -+ __acquires(txq_lock) __releases(txq_lock) -+{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ struct txq_info *txqi = to_txq_info(txq); -+ struct airtime_sched_info *air_sched; -+ u64 now = ktime_get_boottime_ns(); -+ struct airtime_info *air_info; -+ u8 ac = txq->ac; -+ bool was_active; - -- if (txqi->schedule_round == local->schedule_round[ac]) -+ air_sched = &local->airtime[ac]; -+ air_info = to_airtime_info(txq); -+ -+ spin_lock_bh(&air_sched->lock); -+ was_active = airtime_is_active(air_info, now); -+ airtime_set_active(air_sched, air_info, now); -+ -+ if (!RB_EMPTY_NODE(&txqi->schedule_order)) - goto out; - -- list_del_init(&txqi->schedule_order); -- txqi->schedule_round = local->schedule_round[ac]; -- ret = &txqi->txq; -+ /* If the station has been inactive for a while, catch up its v_t so it -+ * doesn't get indefinite priority; see comment above the definition of -+ * AIRTIME_MAX_BEHIND. -+ */ -+ if ((!was_active && air_info->v_t < air_sched->v_t) || -+ air_info->v_t < air_sched->v_t - AIRTIME_MAX_BEHIND) -+ air_info->v_t = air_sched->v_t; -+ -+ ieee80211_update_airtime_weight(local, air_sched, now, !was_active); -+ __ieee80211_insert_txq(&air_sched->active_txqs, txqi); - - out: -- spin_unlock_bh(&local->active_txq_lock[ac]); -- return ret; -+ spin_unlock_bh(&air_sched->lock); - } --EXPORT_SYMBOL(ieee80211_next_txq); -+EXPORT_SYMBOL(ieee80211_schedule_txq); - --void __ieee80211_schedule_txq(struct ieee80211_hw *hw, -- struct ieee80211_txq *txq, -- bool force) -+static void __ieee80211_unschedule_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq, -+ bool purge) - { - struct ieee80211_local *local = hw_to_local(hw); - struct txq_info *txqi = to_txq_info(txq); -+ struct airtime_sched_info *air_sched; -+ struct airtime_info *air_info; - -- spin_lock_bh(&local->active_txq_lock[txq->ac]); -+ air_sched = &local->airtime[txq->ac]; -+ air_info = to_airtime_info(&txqi->txq); - -- if (list_empty(&txqi->schedule_order) && -- (force || !skb_queue_empty(&txqi->frags) || -- txqi->tin.backlog_packets)) { -- /* If airtime accounting is active, always enqueue STAs at the -- * head of the list to ensure that they only get moved to the -- * back by the airtime DRR scheduler once they have a negative -- * deficit. A station that already has a negative deficit will -- * get immediately moved to the back of the list on the next -- * call to ieee80211_next_txq(). -- */ -- if (txqi->txq.sta && local->airtime_flags && -- wiphy_ext_feature_isset(local->hw.wiphy, -- NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) -- list_add(&txqi->schedule_order, -- &local->active_txqs[txq->ac]); -- else -- list_add_tail(&txqi->schedule_order, -- &local->active_txqs[txq->ac]); -+ lockdep_assert_held(&air_sched->lock); -+ -+ if (purge) { -+ list_del_init(&air_info->list); -+ ieee80211_update_airtime_weight(local, air_sched, 0, true); - } - -- spin_unlock_bh(&local->active_txq_lock[txq->ac]); -+ if (RB_EMPTY_NODE(&txqi->schedule_order)) -+ return; -+ -+ if (air_sched->schedule_pos == &txqi->schedule_order) -+ air_sched->schedule_pos = rb_prev(&txqi->schedule_order); -+ -+ if (!purge) -+ airtime_set_active(air_sched, air_info, -+ ktime_get_boottime_ns()); -+ -+ rb_erase_cached(&txqi->schedule_order, -+ &air_sched->active_txqs); -+ RB_CLEAR_NODE(&txqi->schedule_order); -+} -+ -+void ieee80211_unschedule_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq, -+ bool purge) -+ __acquires(txq_lock) __releases(txq_lock) -+{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ -+ spin_lock_bh(&local->airtime[txq->ac].lock); -+ __ieee80211_unschedule_txq(hw, txq, purge); -+ spin_unlock_bh(&local->airtime[txq->ac].lock); -+} -+ -+void ieee80211_return_txq(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq, bool force) -+{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ struct txq_info *txqi = to_txq_info(txq); -+ -+ spin_lock_bh(&local->airtime[txq->ac].lock); -+ -+ if (!RB_EMPTY_NODE(&txqi->schedule_order) && !force && -+ !txq_has_queue(txq)) -+ __ieee80211_unschedule_txq(hw, txq, false); -+ -+ spin_unlock_bh(&local->airtime[txq->ac].lock); - } --EXPORT_SYMBOL(__ieee80211_schedule_txq); -+EXPORT_SYMBOL(ieee80211_return_txq); - - DEFINE_STATIC_KEY_FALSE(aql_disable); - - bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, - struct ieee80211_txq *txq) - { -- struct sta_info *sta; -+ struct airtime_info *air_info = to_airtime_info(txq); - struct ieee80211_local *local = hw_to_local(hw); - - if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) -@@ -3907,15 +4063,12 @@ bool ieee80211_txq_airtime_check(struct - if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) - return true; - -- sta = container_of(txq->sta, struct sta_info, sta); -- if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < -- sta->airtime[txq->ac].aql_limit_low) -+ if (atomic_read(&air_info->aql_tx_pending) < air_info->aql_limit_low) - return true; - - if (atomic_read(&local->aql_total_pending_airtime) < - local->aql_threshold && -- atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < -- sta->airtime[txq->ac].aql_limit_high) -+ atomic_read(&air_info->aql_tx_pending) < air_info->aql_limit_high) - return true; - - return false; -@@ -3925,60 +4078,59 @@ EXPORT_SYMBOL(ieee80211_txq_airtime_chec - bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, - struct ieee80211_txq *txq) - { -+ struct txq_info *first_txqi = NULL, *txqi = to_txq_info(txq); - struct ieee80211_local *local = hw_to_local(hw); -- struct txq_info *iter, *tmp, *txqi = to_txq_info(txq); -- struct sta_info *sta; -- u8 ac = txq->ac; -+ struct airtime_sched_info *air_sched; -+ struct airtime_info *air_info; -+ struct rb_node *node = NULL; -+ bool ret = false; -+ u64 now; - -- spin_lock_bh(&local->active_txq_lock[ac]); - -- if (!txqi->txq.sta) -- goto out; -+ if (!ieee80211_txq_airtime_check(hw, txq)) -+ return false; -+ -+ air_sched = &local->airtime[txq->ac]; -+ spin_lock_bh(&air_sched->lock); - -- if (list_empty(&txqi->schedule_order)) -+ if (RB_EMPTY_NODE(&txqi->schedule_order)) - goto out; - -- list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac], -- schedule_order) { -- if (iter == txqi) -- break; -+ now = ktime_get_boottime_ns(); - -- if (!iter->txq.sta) { -- list_move_tail(&iter->schedule_order, -- &local->active_txqs[ac]); -- continue; -- } -- sta = container_of(iter->txq.sta, struct sta_info, sta); -- if (sta->airtime[ac].deficit < 0) -- sta->airtime[ac].deficit += sta->airtime_weight; -- list_move_tail(&iter->schedule_order, &local->active_txqs[ac]); -+ /* Like in ieee80211_next_txq(), make sure the first station in the -+ * scheduling order is eligible for transmission to avoid starvation. -+ */ -+ node = rb_first_cached(&air_sched->active_txqs); -+ if (node) { -+ first_txqi = container_of(node, struct txq_info, -+ schedule_order); -+ air_info = to_airtime_info(&first_txqi->txq); -+ -+ if (air_sched->v_t < air_info->v_t) -+ airtime_catchup_v_t(air_sched, air_info->v_t, now); - } - -- sta = container_of(txqi->txq.sta, struct sta_info, sta); -- if (sta->airtime[ac].deficit >= 0) -- goto out; -- -- sta->airtime[ac].deficit += sta->airtime_weight; -- list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]); -- spin_unlock_bh(&local->active_txq_lock[ac]); -+ air_info = to_airtime_info(&txqi->txq); -+ if (air_info->v_t <= air_sched->v_t) { -+ air_sched->last_schedule_activity = now; -+ ret = true; -+ } - -- return false; - out: -- if (!list_empty(&txqi->schedule_order)) -- list_del_init(&txqi->schedule_order); -- spin_unlock_bh(&local->active_txq_lock[ac]); -- -- return true; -+ spin_unlock_bh(&air_sched->lock); -+ return ret; - } - EXPORT_SYMBOL(ieee80211_txq_may_transmit); - - void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac) - { - struct ieee80211_local *local = hw_to_local(hw); -+ struct airtime_sched_info *air_sched = &local->airtime[ac]; - -- spin_lock_bh(&local->active_txq_lock[ac]); -- local->schedule_round[ac]++; -- spin_unlock_bh(&local->active_txq_lock[ac]); -+ spin_lock_bh(&air_sched->lock); -+ air_sched->schedule_pos = NULL; -+ spin_unlock_bh(&air_sched->lock); - } - EXPORT_SYMBOL(ieee80211_txq_schedule_start); - diff --git a/package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch b/package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch deleted file mode 100644 index 5a82f00c9..000000000 --- a/package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Felix Fietkau -Date: Fri, 2 Jul 2021 06:57:53 +0200 -Subject: [PATCH] mac80211: fix enabling 4-address mode on a sta vif after - assoc - -Notify the driver about the 4-address mode change and also send a nulldata -packet to the AP to notify it about the change - -Fixes: 1ff4e8f2dec8 ("mac80211: notify the driver when a sta uses 4-address mode") -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -152,6 +152,8 @@ static int ieee80211_change_iface(struct - struct vif_params *params) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct ieee80211_local *local = sdata->local; -+ struct sta_info *sta; - int ret; - - ret = ieee80211_if_change_type(sdata, type); -@@ -162,7 +164,24 @@ static int ieee80211_change_iface(struct - RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); - ieee80211_check_fast_rx_iface(sdata); - } else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) { -+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -+ -+ if (params->use_4addr == ifmgd->use_4addr) -+ return 0; -+ - sdata->u.mgd.use_4addr = params->use_4addr; -+ if (!ifmgd->associated) -+ return 0; -+ -+ mutex_lock(&local->sta_mtx); -+ sta = sta_info_get(sdata, ifmgd->bssid); -+ if (sta) -+ drv_sta_set_4addr(local, sdata, &sta->sta, -+ params->use_4addr); -+ mutex_unlock(&local->sta_mtx); -+ -+ if (params->use_4addr) -+ ieee80211_send_4addr_nullfunc(local, sdata); - } - - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2224,6 +2224,8 @@ void ieee80211_dynamic_ps_timer(struct t - void ieee80211_send_nullfunc(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - bool powersave); -+void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata); - void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, - struct ieee80211_hdr *hdr, bool ack, u16 tx_time); - ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1115,8 +1115,8 @@ void ieee80211_send_nullfunc(struct ieee - ieee80211_tx_skb(sdata, skb); - } - --static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, -- struct ieee80211_sub_if_data *sdata) -+void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata) - { - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; diff --git a/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch b/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch deleted file mode 100644 index 0c9ae3595..000000000 --- a/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch +++ /dev/null @@ -1,398 +0,0 @@ -From: Carl Huang -Date: Thu, 3 Dec 2020 05:37:26 -0500 -Subject: [PATCH] nl80211: add common API to configure SAR power limitations - -NL80211_CMD_SET_SAR_SPECS is added to configure SAR from -user space. NL80211_ATTR_SAR_SPEC is used to pass the SAR -power specification when used with NL80211_CMD_SET_SAR_SPECS. - -Wireless driver needs to register SAR type, supported frequency -ranges to wiphy, so user space can query it. The index in -frequency range is used to specify which sub band the power -limitation applies to. The SAR type is for compatibility, so later -other SAR mechanism can be implemented without breaking the user -space SAR applications. - -Normal process is user space queries the SAR capability, and -gets the index of supported frequency ranges and associates the -power limitation with this index and sends to kernel. - -Here is an example of message send to kernel: -8c 00 00 00 08 00 01 00 00 00 00 00 38 00 2b 81 -08 00 01 00 00 00 00 00 2c 00 02 80 14 00 00 80 -08 00 02 00 00 00 00 00 08 00 01 00 38 00 00 00 -14 00 01 80 08 00 02 00 01 00 00 00 08 00 01 00 -48 00 00 00 - -NL80211_CMD_SET_SAR_SPECS: 0x8c -NL80211_ATTR_WIPHY: 0x01(phy idx is 0) -NL80211_ATTR_SAR_SPEC: 0x812b (NLA_NESTED) -NL80211_SAR_ATTR_TYPE: 0x00 (NL80211_SAR_TYPE_POWER) -NL80211_SAR_ATTR_SPECS: 0x8002 (NLA_NESTED) -freq range 0 power: 0x38 in 0.25dbm unit (14dbm) -freq range 1 power: 0x48 in 0.25dbm unit (18dbm) - -Signed-off-by: Carl Huang -Reviewed-by: Brian Norris -Reviewed-by: Abhishek Kumar -Link: https://lore.kernel.org/r/20201203103728.3034-2-cjhuang@codeaurora.org -[minor edits, NLA parse cleanups] -Signed-off-by: Johannes Berg ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1737,6 +1737,54 @@ struct station_info { - u8 connected_to_as; - }; - -+/** -+ * struct cfg80211_sar_sub_specs - sub specs limit -+ * @power: power limitation in 0.25dbm -+ * @freq_range_index: index the power limitation applies to -+ */ -+struct cfg80211_sar_sub_specs { -+ s32 power; -+ u32 freq_range_index; -+}; -+ -+/** -+ * struct cfg80211_sar_specs - sar limit specs -+ * @type: it's set with power in 0.25dbm or other types -+ * @num_sub_specs: number of sar sub specs -+ * @sub_specs: memory to hold the sar sub specs -+ */ -+struct cfg80211_sar_specs { -+ enum nl80211_sar_type type; -+ u32 num_sub_specs; -+ struct cfg80211_sar_sub_specs sub_specs[]; -+}; -+ -+ -+/** -+ * @struct cfg80211_sar_chan_ranges - sar frequency ranges -+ * @start_freq: start range edge frequency -+ * @end_freq: end range edge frequency -+ */ -+struct cfg80211_sar_freq_ranges { -+ u32 start_freq; -+ u32 end_freq; -+}; -+ -+/** -+ * struct cfg80211_sar_capa - sar limit capability -+ * @type: it's set via power in 0.25dbm or other types -+ * @num_freq_ranges: number of frequency ranges -+ * @freq_ranges: memory to hold the freq ranges. -+ * -+ * Note: WLAN driver may append new ranges or split an existing -+ * range to small ones and then append them. -+ */ -+struct cfg80211_sar_capa { -+ enum nl80211_sar_type type; -+ u32 num_freq_ranges; -+ const struct cfg80211_sar_freq_ranges *freq_ranges; -+}; -+ - #if IS_ENABLED(CPTCFG_CFG80211) - /** - * cfg80211_get_station - retrieve information about a given station -@@ -4259,6 +4307,8 @@ struct cfg80211_ops { - struct cfg80211_tid_config *tid_conf); - int (*reset_tid_config)(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, u8 tids); -+ int (*set_sar_specs)(struct wiphy *wiphy, -+ struct cfg80211_sar_specs *sar); - }; - - /* -@@ -5030,6 +5080,8 @@ struct wiphy { - - u8 max_data_retry_count; - -+ const struct cfg80211_sar_capa *sar_capa; -+ - char priv[] __aligned(NETDEV_ALIGN); - }; - ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -405,6 +405,18 @@ nl80211_unsol_bcast_probe_resp_policy[NL - .len = IEEE80211_MAX_DATA_LEN } - }; - -+static const struct nla_policy -+sar_specs_policy[NL80211_SAR_ATTR_SPECS_MAX + 1] = { -+ [NL80211_SAR_ATTR_SPECS_POWER] = { .type = NLA_S32 }, -+ [NL80211_SAR_ATTR_SPECS_RANGE_INDEX] = {.type = NLA_U32 }, -+}; -+ -+static const struct nla_policy -+sar_policy[NL80211_SAR_ATTR_MAX + 1] = { -+ [NL80211_SAR_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_SAR_TYPE), -+ [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy), -+}; -+ - static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { - [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, - [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, -@@ -739,6 +751,7 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_SAE_PWE] = - NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK, - NL80211_SAE_PWE_BOTH), -+ [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy), - [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, - }; - -@@ -2117,6 +2130,56 @@ fail: - return -ENOBUFS; - } - -+static int -+nl80211_put_sar_specs(struct cfg80211_registered_device *rdev, -+ struct sk_buff *msg) -+{ -+ struct nlattr *sar_capa, *specs, *sub_freq_range; -+ u8 num_freq_ranges; -+ int i; -+ -+ if (!rdev->wiphy.sar_capa) -+ return 0; -+ -+ num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges; -+ -+ sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC); -+ if (!sar_capa) -+ return -ENOSPC; -+ -+ if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type)) -+ goto fail; -+ -+ specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS); -+ if (!specs) -+ goto fail; -+ -+ /* report supported freq_ranges */ -+ for (i = 0; i < num_freq_ranges; i++) { -+ sub_freq_range = nla_nest_start(msg, i + 1); -+ if (!sub_freq_range) -+ goto fail; -+ -+ if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ, -+ rdev->wiphy.sar_capa->freq_ranges[i].start_freq)) -+ goto fail; -+ -+ if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ, -+ rdev->wiphy.sar_capa->freq_ranges[i].end_freq)) -+ goto fail; -+ -+ nla_nest_end(msg, sub_freq_range); -+ } -+ -+ nla_nest_end(msg, specs); -+ nla_nest_end(msg, sar_capa); -+ -+ return 0; -+fail: -+ nla_nest_cancel(msg, sar_capa); -+ return -ENOBUFS; -+} -+ - struct nl80211_dump_wiphy_state { - s64 filter_wiphy; - long start; -@@ -2366,6 +2429,8 @@ static int nl80211_send_wiphy(struct cfg - CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST); - CMD(update_connect_params, UPDATE_CONNECT_PARAMS); - CMD(update_ft_ies, UPDATE_FT_IES); -+ if (rdev->wiphy.sar_capa) -+ CMD(set_sar_specs, SET_SAR_SPECS); - } - #undef CMD - -@@ -2691,6 +2756,11 @@ static int nl80211_send_wiphy(struct cfg - - if (nl80211_put_tid_config_support(rdev, msg)) - goto nla_put_failure; -+ state->split_start++; -+ break; -+ case 16: -+ if (nl80211_put_sar_specs(rdev, msg)) -+ goto nla_put_failure; - - /* done */ - state->split_start = 0; -@@ -14713,6 +14783,111 @@ static void nl80211_post_doit(__genl_con - } - } - -+static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev, -+ struct cfg80211_sar_specs *sar_specs, -+ struct nlattr *spec[], int index) -+{ -+ u32 range_index, i; -+ -+ if (!sar_specs || !spec) -+ return -EINVAL; -+ -+ if (!spec[NL80211_SAR_ATTR_SPECS_POWER] || -+ !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]) -+ return -EINVAL; -+ -+ range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]); -+ -+ /* check if range_index exceeds num_freq_ranges */ -+ if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges) -+ return -EINVAL; -+ -+ /* check if range_index duplicates */ -+ for (i = 0; i < index; i++) { -+ if (sar_specs->sub_specs[i].freq_range_index == range_index) -+ return -EINVAL; -+ } -+ -+ sar_specs->sub_specs[index].power = -+ nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]); -+ -+ sar_specs->sub_specs[index].freq_range_index = range_index; -+ -+ return 0; -+} -+ -+static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info) -+{ -+ struct cfg80211_registered_device *rdev = info->user_ptr[0]; -+ struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1]; -+ struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1]; -+ struct cfg80211_sar_specs *sar_spec; -+ enum nl80211_sar_type type; -+ struct nlattr *spec_list; -+ u32 specs; -+ int rem, err; -+ -+ if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs) -+ return -EOPNOTSUPP; -+ -+ if (!info->attrs[NL80211_ATTR_SAR_SPEC]) -+ return -EINVAL; -+ -+ nla_parse_nested(tb, NL80211_SAR_ATTR_MAX, -+ info->attrs[NL80211_ATTR_SAR_SPEC], -+ NULL, NULL); -+ -+ if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS]) -+ return -EINVAL; -+ -+ type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]); -+ if (type != rdev->wiphy.sar_capa->type) -+ return -EINVAL; -+ -+ specs = 0; -+ nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) -+ specs++; -+ -+ if (specs > rdev->wiphy.sar_capa->num_freq_ranges) -+ return -EINVAL; -+ -+ sar_spec = kzalloc(sizeof(*sar_spec) + -+ specs * sizeof(struct cfg80211_sar_sub_specs), -+ GFP_KERNEL); -+ if (!sar_spec) -+ return -ENOMEM; -+ -+ sar_spec->type = type; -+ specs = 0; -+ nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) { -+ nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX, -+ spec_list, NULL, NULL); -+ -+ switch (type) { -+ case NL80211_SAR_TYPE_POWER: -+ if (nl80211_set_sar_sub_specs(rdev, sar_spec, -+ spec, specs)) { -+ err = -EINVAL; -+ goto error; -+ } -+ break; -+ default: -+ err = -EINVAL; -+ goto error; -+ } -+ specs++; -+ } -+ -+ sar_spec->num_sub_specs = specs; -+ -+ rdev->cur_cmd_info = info; -+ err = rdev_set_sar_specs(rdev, sar_spec); -+ rdev->cur_cmd_info = NULL; -+error: -+ kfree(sar_spec); -+ return err; -+} -+ - static __genl_const struct genl_ops nl80211_ops[] = { - { - .cmd = NL80211_CMD_GET_WIPHY, -@@ -15576,6 +15751,14 @@ static const struct genl_small_ops nl802 - .internal_flags = NL80211_FLAG_NEED_NETDEV | - NL80211_FLAG_NEED_RTNL, - }, -+ { -+ .cmd = NL80211_CMD_SET_SAR_SPECS, -+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, -+ .doit = nl80211_set_sar_specs, -+ .flags = GENL_UNS_ADMIN_PERM, -+ .internal_flags = NL80211_FLAG_NEED_WIPHY | -+ NL80211_FLAG_NEED_RTNL, -+ }, - }; - - static struct genl_family nl80211_fam __genl_ro_after_init = { ---- a/net/wireless/rdev-ops.h -+++ b/net/wireless/rdev-ops.h -@@ -1356,4 +1356,16 @@ static inline int rdev_reset_tid_config( - return ret; - } - -+static inline int rdev_set_sar_specs(struct cfg80211_registered_device *rdev, -+ struct cfg80211_sar_specs *sar) -+{ -+ int ret; -+ -+ trace_rdev_set_sar_specs(&rdev->wiphy, sar); -+ ret = rdev->ops->set_sar_specs(&rdev->wiphy, sar); -+ trace_rdev_return_int(&rdev->wiphy, ret); -+ -+ return ret; -+} -+ - #endif /* __CFG80211_RDEV_OPS */ ---- a/net/wireless/trace.h -+++ b/net/wireless/trace.h -@@ -3551,6 +3551,25 @@ TRACE_EVENT(rdev_reset_tid_config, - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", tids: 0x%x", - WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tids) - ); -+ -+TRACE_EVENT(rdev_set_sar_specs, -+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_sar_specs *sar), -+ TP_ARGS(wiphy, sar), -+ TP_STRUCT__entry( -+ WIPHY_ENTRY -+ __field(u16, type) -+ __field(u16, num) -+ ), -+ TP_fast_assign( -+ WIPHY_ASSIGN; -+ __entry->type = sar->type; -+ __entry->num = sar->num_sub_specs; -+ -+ ), -+ TP_printk(WIPHY_PR_FMT ", Set type:%d, num_specs:%d", -+ WIPHY_PR_ARG, __entry->type, __entry->num) -+); -+ - #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ - - #undef TRACE_INCLUDE_PATH diff --git a/package/kernel/mac80211/patches/subsys/385-mac80211-add-ieee80211_set_sar_specs.patch b/package/kernel/mac80211/patches/subsys/385-mac80211-add-ieee80211_set_sar_specs.patch deleted file mode 100644 index c351bc812..000000000 --- a/package/kernel/mac80211/patches/subsys/385-mac80211-add-ieee80211_set_sar_specs.patch +++ /dev/null @@ -1,51 +0,0 @@ -From: Carl Huang -Date: Thu, 3 Dec 2020 05:37:27 -0500 -Subject: [PATCH] mac80211: add ieee80211_set_sar_specs - -This change registers ieee80211_set_sar_specs to -mac80211_config_ops, so cfg80211 can call it. - -Signed-off-by: Carl Huang -Reviewed-by: Brian Norris -Reviewed-by: Abhishek Kumar -Link: https://lore.kernel.org/r/20201203103728.3034-3-cjhuang@codeaurora.org -Signed-off-by: Johannes Berg ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -4207,6 +4207,8 @@ struct ieee80211_ops { - struct ieee80211_vif *vif); - void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enabled); -+ int (*set_sar_specs)(struct ieee80211_hw *hw, -+ const struct cfg80211_sar_specs *sar); - void (*sta_set_decap_offload)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enabled); ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -4136,6 +4136,17 @@ static int ieee80211_reset_tid_config(st - return ret; - } - -+static int ieee80211_set_sar_specs(struct wiphy *wiphy, -+ struct cfg80211_sar_specs *sar) -+{ -+ struct ieee80211_local *local = wiphy_priv(wiphy); -+ -+ if (!local->ops->set_sar_specs) -+ return -EOPNOTSUPP; -+ -+ return local->ops->set_sar_specs(&local->hw, sar); -+} -+ - const struct cfg80211_ops mac80211_config_ops = { - .add_virtual_intf = ieee80211_add_iface, - .del_virtual_intf = ieee80211_del_iface, -@@ -4239,4 +4250,5 @@ const struct cfg80211_ops mac80211_confi - .probe_mesh_link = ieee80211_probe_mesh_link, - .set_tid_config = ieee80211_set_tid_config, - .reset_tid_config = ieee80211_reset_tid_config, -+ .set_sar_specs = ieee80211_set_sar_specs, - }; diff --git a/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch b/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch index f9c4caa51..d12c8ada3 100644 --- a/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch +++ b/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch @@ -5,7 +5,7 @@ and we should ignore this. --- a/net/wireless/core.c +++ b/net/wireless/core.c -@@ -614,21 +614,6 @@ static int wiphy_verify_combinations(str +@@ -634,21 +634,6 @@ static int wiphy_verify_combinations(str c->limits[j].max > 1)) return -EINVAL; diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch index b2ee61a6d..c4acfd143 100644 --- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch @@ -1,24 +1,24 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -3793,6 +3793,7 @@ struct mgmt_frame_regs { +@@ -3869,6 +3869,7 @@ struct mgmt_frame_regs { * (as advertised by the nl80211 feature flag.) * @get_tx_power: store the current TX power into the dbm variable; * return 0 if successful + * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary * - * @set_wds_peer: set the WDS peer for a WDS interface - * -@@ -4115,6 +4116,7 @@ struct cfg80211_ops { + * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting + * functions to adjust rfkill hw state +@@ -4202,6 +4203,7 @@ struct cfg80211_ops { enum nl80211_tx_power_setting type, int mbm); int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); + int (*set_antenna_gain)(struct wiphy *wiphy, int dbi); - int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, - const u8 *addr); + void (*rfkill_poll)(struct wiphy *wiphy); + --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1561,6 +1561,7 @@ enum ieee80211_smps_mode { +@@ -1566,6 +1566,7 @@ enum ieee80211_smps_mode { * * @power_level: requested transmit power (in dBm), backward compatibility * value only that is set to the minimum of all interfaces @@ -26,7 +26,7 @@ * * @chandef: the channel definition to tune to * @radar_enabled: whether radar detection is enabled -@@ -1581,6 +1582,7 @@ enum ieee80211_smps_mode { +@@ -1586,6 +1587,7 @@ enum ieee80211_smps_mode { struct ieee80211_conf { u32 flags; int power_level, dynamic_ps_timeout; @@ -36,9 +36,9 @@ u8 ps_dtim_period; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2560,6 +2560,9 @@ enum nl80211_commands { - * disassoc events to indicate that an immediate reconnect to the AP - * is desired. +@@ -2615,6 +2615,9 @@ enum nl80211_commands { + * switching on a different channel during CAC detection on the selected + * radar channel. * + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. @@ -46,9 +46,9 @@ * @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 +3060,8 @@ enum nl80211_attrs { +@@ -3123,6 +3126,8 @@ enum nl80211_attrs { - NL80211_ATTR_DISABLE_HE, + NL80211_ATTR_RADAR_BACKGROUND, + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2761,6 +2761,19 @@ static int ieee80211_get_tx_power(struct +@@ -2845,6 +2845,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -74,20 +74,20 @@ + return 0; +} + - static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, - const u8 *addr) + static void ieee80211_rfkill_poll(struct wiphy *wiphy) { -@@ -4202,6 +4215,7 @@ const struct cfg80211_ops mac80211_confi + struct ieee80211_local *local = wiphy_priv(wiphy); +@@ -4549,6 +4562,7 @@ const struct cfg80211_ops mac80211_confi .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, + .set_antenna_gain = ieee80211_set_antenna_gain, - .set_wds_peer = ieee80211_set_wds_peer, .rfkill_poll = ieee80211_rfkill_poll, CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) + CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1426,6 +1426,7 @@ struct ieee80211_local { +@@ -1444,6 +1444,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */ @@ -119,7 +119,7 @@ if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; -@@ -665,6 +671,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ +@@ -679,6 +685,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ IEEE80211_RADIOTAP_MCS_HAVE_BW; local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; @@ -129,32 +129,34 @@ local->hw.max_mtu = IEEE80211_MAX_DATA_LEN; --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -753,6 +753,7 @@ static const struct nla_policy nl80211_p - NL80211_SAE_PWE_BOTH), - [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy), - [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, +@@ -794,6 +794,7 @@ static const struct nla_policy nl80211_p + NLA_POLICY_NESTED(nl80211_mbssid_config_policy), + [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, + [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, + [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, }; /* policy for the key attributes */ -@@ -3318,6 +3319,20 @@ static int nl80211_set_wiphy(struct sk_b +@@ -3374,6 +3375,22 @@ static int nl80211_set_wiphy(struct sk_b if (result) - return result; + goto out; } + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { + int idx, dbi = 0; + -+ if (!rdev->ops->set_antenna_gain) -+ return -EOPNOTSUPP; ++ if (!rdev->ops->set_antenna_gain) { ++ result = -EOPNOTSUPP; ++ goto out; ++ } + + idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; + dbi = nla_get_u32(info->attrs[idx]); + + result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); + if (result) -+ return result; ++ goto out; + } - if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && - info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { + if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { + struct wireless_dev *txp_wdev = wdev; diff --git a/package/kernel/mac80211/patches/subsys/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch b/package/kernel/mac80211/patches/subsys/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch new file mode 100644 index 000000000..26af6a2fb --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch @@ -0,0 +1,29 @@ +--- a/backport-include/linux/of_net.h ++++ /dev/null +@@ -1,26 +0,0 @@ +-#ifndef _BP_OF_NET_H +-#define _BP_OF_NET_H +-#include_next +-#include +-#include +- +-/* The behavior of of_get_mac_address() changed in kernel 5.2, it now +- * returns an error code and not NULL in case of an error. +- */ +-#if LINUX_VERSION_IS_LESS(5,13,0) +-static inline int backport_of_get_mac_address(struct device_node *np, u8 *mac_out) +-{ +- const void *mac = of_get_mac_address(np); +- +- if (!mac) +- return -ENODEV; +- if (IS_ERR(mac)) +- return PTR_ERR(mac); +- ether_addr_copy(mac_out, mac); +- +- return 0; +-} +-#define of_get_mac_address LINUX_BACKPORT(of_get_mac_address) +-#endif /* < 5.2 */ +- +-#endif /* _BP_OF_NET_H */ diff --git a/package/kernel/mac80211/patches/subsys/999-mac80211-add-option-for-NSS-support.patch b/package/kernel/mac80211/patches/subsys/999-mac80211-add-option-for-NSS-support.patch deleted file mode 100644 index 0f3fa1411..000000000 --- a/package/kernel/mac80211/patches/subsys/999-mac80211-add-option-for-NSS-support.patch +++ /dev/null @@ -1,261 +0,0 @@ ---- a/net/mac80211/Kconfig 2019-01-03 21:03:17.839001000 +0800 -+++ b/net/mac80211/Kconfig 2019-01-03 21:04:43.931001000 +0800 -@@ -16,6 +16,13 @@ - - if MAC80211 != n - -+config MAC80211_NSS_SUPPORT -+ bool "Enable NSS support for IPQ platform" -+ default n -+ ---help--- -+ This option enables support for NSS in boards -+ like AP148. -+ - config MAC80211_HAS_RC - bool - ---- a/local-symbols 2019-01-03 21:24:00.087001000 +0800 -+++ b/local-symbols 2019-01-03 21:24:56.535001000 +0800 -@@ -47,6 +47,7 @@ LIB80211_CRYPT_CCMP= - LIB80211_CRYPT_TKIP= - LIB80211_DEBUG= - MAC80211= -+MAC80211_NSS_SUPPORT= - MAC80211_HAS_RC= - MAC80211_RC_MINSTREL= - MAC80211_RC_DEFAULT_MINSTREL= ---- a/net/mac80211/ieee80211_i.h 2019-01-03 21:04:57.527001000 +0800 -+++ b/net/mac80211/ieee80211_i.h 2019-01-03 21:05:44.827001000 +0800 -@@ -35,6 +35,10 @@ - - extern const struct cfg80211_ops mac80211_config_ops; - -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+#include -+#endif -+ - struct ieee80211_local; - - /* Maximum number of broadcast/multicast frames to buffer when some of the -@@ -988,6 +992,14 @@ struct ieee80211_sub_if_data { - - bool hw_80211_encap; - -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+ struct nss_virt_if_handle *nssctx; -+ -+ struct tasklet_struct ieee80211_nss_rq_tasklet; -+ struct sk_buff_head rq_for_nss; -+ int nss_rq_tasklet_pending; -+#endif -+ - /* must be last, dynamically sized area in this! */ - struct ieee80211_vif vif; - }; ---- a/net/mac80211/iface.c 2019-01-03 21:06:00.007001000 +0800 -+++ b/net/mac80211/iface.c 2019-01-03 21:08:49.535001000 +0800 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include "ieee80211_i.h" -@@ -26,6 +27,12 @@ - #include "wme.h" - #include "rate.h" - -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+bool is_nss_enable = true; -+module_param(is_nss_enable, bool, 0644); -+MODULE_PARM_DESC(is_nss_enable, "NSS enable module param"); -+#endif -+ - /** - * DOC: Interface list locking - * -@@ -695,6 +702,96 @@ - ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); - } - -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+#define case_rtn_string(val) case val: return #val -+ -+static const char *nss_tx_status_str(nss_tx_status_t status) -+{ -+ switch (status) { -+ case_rtn_string(NSS_TX_SUCCESS); -+ case_rtn_string(NSS_TX_FAILURE); -+ case_rtn_string(NSS_TX_FAILURE_QUEUE); -+ case_rtn_string(NSS_TX_FAILURE_NOT_READY); -+ case_rtn_string(NSS_TX_FAILURE_TOO_LARGE); -+ case_rtn_string(NSS_TX_FAILURE_TOO_SHORT); -+ case_rtn_string(NSS_TX_FAILURE_NOT_SUPPORTED); -+ case_rtn_string(NSS_TX_FAILURE_BAD_PARAM); -+ case_rtn_string(NSS_TX_FAILURE_NOT_ENABLED); -+ case_rtn_string(NSS_TX_FAILURE_SYNC_BAD_PARAM); -+ case_rtn_string(NSS_TX_FAILURE_SYNC_TIMEOUT); -+ case_rtn_string(NSS_TX_FAILURE_SYNC_FW_ERR); -+ default: -+ return "Unknown NSS TX status"; -+ } -+} -+ -+static void ieee80211_nss_rq_tasklet(unsigned long _txp) -+{ -+ struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *)_txp; -+ struct sk_buff *skb; -+ int ret; -+ -+ while ((skb = __skb_dequeue(&sdata->rq_for_nss)) != NULL) { -+ skb_push(skb, ETH_HLEN); -+ -+ ret = nss_virt_if_tx_buf(sdata->nssctx, skb); -+ if (unlikely(ret)) { -+ sdata_err(sdata, "NSS TX failed with error[%d]: %s\n", ret, -+ nss_tx_status_str(ret)); -+ -+ skb_pull(skb, ETH_HLEN); -+ netif_receive_skb(skb); -+ } -+ } -+ -+ skb = skb_peek(&sdata->rq_for_nss); -+ if (!skb) { -+ sdata->nss_rq_tasklet_pending = 0; -+ } -+ else { -+ sdata->nss_rq_tasklet_pending = 1; -+ tasklet_schedule(&sdata->ieee80211_nss_rq_tasklet); -+ } -+} -+ -+static int ieee80211_init_nss(struct net_device *dev) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ -+ sdata->nssctx = nss_virt_if_create_sync(dev); -+ if (sdata->nssctx) { -+ sdata_info(sdata, "Created a NSS virtual interface.\n"); -+ -+ __skb_queue_head_init(&sdata->rq_for_nss); -+ tasklet_init(&sdata->ieee80211_nss_rq_tasklet, ieee80211_nss_rq_tasklet, -+ (unsigned long)sdata); -+ sdata_info(sdata, "RX-Q and tasklet initialized.\n"); -+ } -+ else { -+ sdata->nssctx = NULL; -+ sdata_err(sdata, "Failed to create a NSS virtual interface\n"); -+ } -+ -+ return 0; -+} -+ -+static void ieee80211_uninit_nss(struct net_device *dev) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ -+ ieee80211_uninit(dev); -+ -+ if (sdata->nssctx) { -+ nss_virt_if_destroy_sync(sdata->nssctx); -+ sdata_info(sdata, "Destroyed NSS virtual interface\n"); -+ -+ tasklet_kill(&sdata->ieee80211_nss_rq_tasklet); -+ __skb_queue_purge(&sdata->rq_for_nss); -+ sdata_info(sdata, "RX-Q purged.\n"); -+ } -+} -+#endif -+ - #if LINUX_VERSION_IS_GEQ(5,2,0) - static u16 ieee80211_netdev_select_queue(struct net_device *dev, - struct sk_buff *skb, -@@ -742,7 +839,12 @@ - static const struct net_device_ops ieee80211_dataif_ops = { - .ndo_open = ieee80211_open, - .ndo_stop = ieee80211_stop, -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+ .ndo_init = ieee80211_init_nss, -+ .ndo_uninit = ieee80211_uninit_nss, -+#else - .ndo_uninit = ieee80211_uninit, -+#endif - .ndo_start_xmit = ieee80211_subif_start_xmit, - .ndo_set_rx_mode = ieee80211_set_multicast_list, - .ndo_set_mac_address = ieee80211_change_mac, ---- a/net/mac80211/rx.c 2019-01-03 21:09:29.503001000 +0800 -+++ b/net/mac80211/rx.c 2019-01-03 21:17:42.463001000 +0800 -@@ -32,6 +32,10 @@ - #include "wme.h" - #include "rate.h" - -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+extern bool is_nss_enable; -+#endif -+ - static inline void ieee80211_rx_stats(struct net_device *dev, u32 len) - { - struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); -@@ -2604,6 +2608,21 @@ - ether_addr_copy(ehdr->h_dest, sdata->vif.addr); - - /* deliver to local stack */ -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+ if (likely(is_nss_enable && sdata->nssctx)) { -+ __skb_queue_tail(&sdata->rq_for_nss, skb); -+ if(!sdata->nss_rq_tasklet_pending) { -+ sdata->nss_rq_tasklet_pending = 1; -+ tasklet_schedule(&sdata->ieee80211_nss_rq_tasklet); -+ } -+ } -+ else { -+ if (rx->list) -+ list_add_tail(&skb->list, rx->list); -+ else -+ netif_receive_skb(skb); -+ } -+#else - if (rx->list) - #if LINUX_VERSION_IS_GEQ(4,19,0) - list_add_tail(&skb->list, rx->list); -@@ -2612,6 +2631,7 @@ - #endif - else - netif_receive_skb(skb); -+#endif - } - } - -@@ -4461,6 +4481,21 @@ - /* deliver to local stack */ - skb->protocol = eth_type_trans(skb, fast_rx->dev); - memset(skb->cb, 0, sizeof(skb->cb)); -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+ if (likely(is_nss_enable && rx->sdata->nssctx)) { -+ __skb_queue_tail(&rx->sdata->rq_for_nss, skb); -+ if(!rx->sdata->nss_rq_tasklet_pending) { -+ rx->sdata->nss_rq_tasklet_pending = 1; -+ tasklet_schedule(&rx->sdata->ieee80211_nss_rq_tasklet); -+ } -+ } -+ else { -+ if (rx->list) -+ list_add_tail(&skb->list, rx->list); -+ else -+ netif_receive_skb(skb); -+ } -+#else - if (rx->list) - #if LINUX_VERSION_IS_GEQ(4,19,0) - list_add_tail(&skb->list, rx->list); -@@ -4469,7 +4504,7 @@ - #endif - else - netif_receive_skb(skb); -- -+#endif - } - - static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, \ No newline at end of file diff --git a/package/kernel/mac80211/patches/subsys/999-mac80211-nss-classify-tx.patch b/package/kernel/mac80211/patches/subsys/999-mac80211-nss-classify-tx.patch deleted file mode 100644 index b03b94d21..000000000 --- a/package/kernel/mac80211/patches/subsys/999-mac80211-nss-classify-tx.patch +++ /dev/null @@ -1,45 +0,0 @@ ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -38,6 +38,11 @@ - #include "wme.h" - #include "rate.h" - -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+#include -+#include -+#endif -+ - /* misc utils */ - - static inline void ieee80211_tx_stats(struct net_device *dev, u32 len) -@@ -3561,6 +3566,30 @@ void __ieee80211_subif_start_xmit(struct - netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, - struct net_device *dev) - { -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+ /* Packets from NSS does not have valid protocol, priority and other -+ * network stack values. Derive required parameters (priority -+ * and network_header) from payload for QoS header. -+ * XXX: Here the assumption is that packet are in 802.3 format. -+ * As of now priority is handled only for IPv4 and IPv6. -+ */ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ -+ if (sdata->nssctx && likely(!skb->protocol)) { -+ skb_set_network_header(skb, 14); -+ switch (((struct ethhdr *)skb->data)->h_proto) { -+ case htons(ETH_P_IP): -+ skb->priority = (ipv4_get_dsfield(ip_hdr(skb)) & -+ 0xfc) >> 5; -+ break; -+ case htons(ETH_P_IPV6): -+ skb->priority = (ipv6_get_dsfield(ipv6_hdr(skb)) & -+ 0xfc) >> 5; -+ break; -+ } -+ } -+#endif -+ - if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) { - struct sk_buff_head queue; - diff --git a/package/kernel/mac80211/patches/subsys/999-mac80211-xmit-busy.patch b/package/kernel/mac80211/patches/subsys/999-mac80211-xmit-busy.patch deleted file mode 100644 index 1b5723f5f..000000000 --- a/package/kernel/mac80211/patches/subsys/999-mac80211-xmit-busy.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1580,7 +1580,16 @@ static bool ieee80211_tx_frags(struct ie - return true; - } - } else { -- -+#ifdef CPTCFG_MAC80211_NSS_SUPPORT -+ if (skb_queue_len(&local->pending[q]) >= 1000) { -+ spin_unlock_irqrestore( -+ &local->queue_stop_reason_lock, -+ flags); -+ ieee80211_purge_tx_queue(&local->hw, -+ skbs); -+ return false; -+ } -+#endif - /* - * Since queue is stopped, queue up frames for - * later transmission from the tx-pending diff --git a/package/kernel/mac80211/realtek.mk b/package/kernel/mac80211/realtek.mk index 75cb94d7b..44c6c25b0 100644 --- a/package/kernel/mac80211/realtek.mk +++ b/package/kernel/mac80211/realtek.mk @@ -27,6 +27,8 @@ config-y += STAGING config-$(call config_package,rtw88) += RTW88 RTW88_CORE RTW88_PCI config-y += RTW88_8822BE RTW88_8822CE RTW88_8723DE +config-$(CONFIG_PACKAGE_RTW88_DEBUG) += RTW88_DEBUG +config-$(CONFIG_PACKAGE_RTW88_DEBUGFS) += RTW88_DEBUGFS define KernelPackage/rtl818x/Default $(call KernelPackage/mac80211/Default) @@ -175,6 +177,22 @@ define KernelPackage/rtl8xxxu/description Please report your results! endef +define KernelPackage/rtw88/config + config PACKAGE_RTW88_DEBUG + bool "Realtek wireless debugging (rtw88)" + depends on PACKAGE_kmod-rtw88 + help + Enable debugging output for rtw88 devices + + config PACKAGE_RTW88_DEBUGFS + bool "Enable rtw88 debugfS support" + select KERNEL_DEBUG_FS + depends on PACKAGE_kmod-rtw88 + help + Select this to see extensive information about + the internal state of rtw88 in debugfs. +endef + define KernelPackage/rtw88 $(call KernelPackage/mac80211/Default) TITLE:=Realtek RTL8822BE/RTL8822CE/RTL8723DE