diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index e25151e2fc..f6ad06452f 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.4.56-1 +PKG_VERSION:=5.10.16-1 PKG_RELEASE:=1 -PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.4.56/ -PKG_HASH:=6030c2427e04f976cf53330087d0fdbb60ead7e1fecbd85e6f8e97ec0ed9a2eb +PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.10.16/ +PKG_HASH:=12856db780c5023edc47e2d18486eb3346bb7c82f1f2fc48deb3b163142f7d2d PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) @@ -35,6 +35,7 @@ PKG_DRIVERS = \ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_kmod-mac80211 \ + CONFIG_PACKAGE_CFG80211_TESTMODE \ CONFIG_PACKAGE_MAC80211_DEBUGFS \ CONFIG_PACKAGE_MAC80211_MESH \ CONFIG_PACKAGE_MAC80211_TRACING \ @@ -56,7 +57,6 @@ config_package=$(if $(CONFIG_PACKAGE_kmod-$(1)),m) config-y:= \ WLAN \ - NL80211_TESTMODE \ CFG80211_WEXT \ CFG80211_CERTIFICATION_ONUS \ MAC80211_RC_MINSTREL \ @@ -80,6 +80,7 @@ config-y:= \ WLAN_VENDOR_ZYDAS \ config-$(call config_package,cfg80211) += CFG80211 +config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE config-$(call config_package,mac80211) += MAC80211 config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH @@ -108,6 +109,20 @@ define KernelPackage/cfg80211/description cfg80211 is the Linux wireless LAN (802.11) configuration API. endef +define KernelPackage/cfg80211/config + if PACKAGE_kmod-cfg80211 + + config PACKAGE_CFG80211_TESTMODE + bool "Enable testmode command support" + default n + help + This is typically used for tests and calibration during + manufacturing, or vendor specific debugging features + + endif +endef + + define KernelPackage/mac80211 $(call KernelPackage/mac80211/Default) TITLE:=Linux 802.11 Wireless Networking Stack @@ -250,7 +265,7 @@ endef define KernelPackage/mac80211-hwsim $(call KernelPackage/mac80211/Default) TITLE:=mac80211 HW simulation device - DEPENDS+= +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + DEPENDS+= +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko AUTOLOAD:=$(call AutoProbe,mac80211_hwsim) endef @@ -259,7 +274,7 @@ endef define KernelPackage/mt7601u $(call KernelPackage/mac80211/Default) TITLE:=MT7601U-based USB dongles Wireless Driver - DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT @USB_SUPPORT +kmod-usb-core +mt7601u-firmware + DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT @USB_SUPPORT +kmod-usb-core +mt7601u-firmware FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko AUTOLOAD:=$(call AutoProbe,mt7601u) endef @@ -275,7 +290,7 @@ endef define KernelPackage/p54-common $(call KernelPackage/p54/Default) - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +kmod-lib-crc-ccitt +@DRIVER_11W_SUPPORT + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +kmod-lib-crc-ccitt TITLE+= (COMMON) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54common.ko endef @@ -373,7 +388,7 @@ $(eval $(call Download,zd1211rw)) define KernelPackage/zd1211rw $(call KernelPackage/mac80211/Default) TITLE:=Zydas ZD1211 support - DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211 +@DRIVER_11W_SUPPORT + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211 FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/zydas/zd1211rw/zd1211rw.ko AUTOLOAD:=$(call AutoProbe,zd1211rw) endef diff --git a/package/kernel/mac80211/ath.mk b/package/kernel/mac80211/ath.mk index eaeb21211c..d65a8ebaff 100644 --- a/package/kernel/mac80211/ath.mk +++ b/package/kernel/mac80211/ath.mk @@ -1,12 +1,13 @@ PKG_DRIVERS += \ ath ath5k ath6kl ath6kl-sdio ath6kl-usb ath9k ath9k-common ath9k-htc ath10k \ - carl9170 owl-loader ar5523 + carl9170 owl-loader ar5523 wil6210 PKG_CONFIG_DEPENDS += \ CONFIG_PACKAGE_ATH_DEBUG \ CONFIG_PACKAGE_ATH_DFS \ CONFIG_PACKAGE_ATH_SPECTRAL \ CONFIG_PACKAGE_ATH_DYNACK \ + CONFIG_ATH9K_HWRNG \ CONFIG_ATH9K_SUPPORT_PCOEM \ CONFIG_ATH9K_TX99 \ CONFIG_ATH10K_LEDS \ @@ -20,7 +21,8 @@ ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS ATH10K_DEBUGFS \ CARL9170_DEBUGFS \ ATH5K_DEBUG \ - ATH6KL_DEBUG + ATH6KL_DEBUG \ + WIL6210_DEBUGFS endif ifdef CONFIG_PACKAGE_MAC80211_TRACING @@ -28,7 +30,8 @@ ifdef CONFIG_PACKAGE_MAC80211_TRACING ATH10K_TRACING \ ATH6KL_TRACING \ ATH_TRACEPOINTS \ - ATH5K_TRACER + ATH5K_TRACER \ + WIL6210_TRACING endif config-$(call config_package,ath) += ATH_CARDS ATH_COMMON ATH_REG_DYNAMIC_USER_REG_HINTS @@ -43,6 +46,7 @@ config-$(CONFIG_TARGET_ath79) += ATH9K_AHB config-$(CONFIG_TARGET_ipq40xx) += ATH10K_AHB config-$(CONFIG_PCI) += ATH9K_PCI config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD +config-$(CONFIG_ATH9K_HWRNG) += ATH9K_HWRNG config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM config-$(CONFIG_ATH9K_TX99) += ATH9K_TX99 config-$(CONFIG_ATH9K_UBNTHSR) += ATH9K_UBNTHSR @@ -66,6 +70,8 @@ config-$(call config_package,ath6kl-usb) += ATH6KL_USB config-$(call config_package,carl9170) += CARL9170 config-$(call config_package,ar5523) += AR5523 +config-$(call config_package,wil6210) += WIL6210 + define KernelPackage/ath/config if PACKAGE_kmod-ath config ATH_USER_REGD @@ -132,7 +138,7 @@ define KernelPackage/ath5k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 5xxx wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath5k - DEPENDS+= @(PCI_SUPPORT||TARGET_ath25) +kmod-ath +@DRIVER_11W_SUPPORT + DEPENDS+= @(PCI_SUPPORT||TARGET_ath25) +kmod-ath FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko AUTOLOAD:=$(call AutoProbe,ath5k) endef @@ -184,7 +190,7 @@ define KernelPackage/ath9k-common TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc) URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k HIDDEN:=1 - DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79 +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79 +kmod-ath +@DRIVER_11N_SUPPORT FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko @@ -207,6 +213,12 @@ endef define KernelPackage/ath9k/config + config ATH9K_HWRNG + bool "Add wireless noise as source of randomness to kernel entropy pool" + depends on PACKAGE_kmod-ath9k + select PACKAGE_kmod-random-core + default n + config ATH9K_SUPPORT_PCOEM bool "Support chips used in PC OEM cards" depends on PACKAGE_kmod-ath9k @@ -242,7 +254,7 @@ define KernelPackage/ath10k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 802.11ac wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath10k - DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT \ + DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT \ +ATH10K_THERMAL:kmod-hwmon-core +ATH10K_THERMAL:kmod-thermal FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \ @@ -273,7 +285,7 @@ endef define KernelPackage/carl9170 $(call KernelPackage/mac80211/Default) TITLE:=Driver for Atheros AR9170 USB sticks - DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +carl9170-firmware + DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT +carl9170-firmware FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko AUTOLOAD:=$(call AutoProbe,carl9170) endef @@ -302,3 +314,11 @@ define KernelPackage/ar5523 FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ar5523/ar5523.ko AUTOLOAD:=$(call AutoProbe,ar5523) endef + +define KernelPackage/wil6210 + $(call KernelPackage/mac80211/Default) + TITLE:=QCA/Wilocity 60g WiFi card wil6210 support + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +wil6210-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/wil6210/wil6210.ko + AUTOLOAD:=$(call AutoProbe,wil6210) +endef diff --git a/package/kernel/mac80211/broadcom.mk b/package/kernel/mac80211/broadcom.mk index 268a6e6cee..0e2db6a749 100644 --- a/package/kernel/mac80211/broadcom.mk +++ b/package/kernel/mac80211/broadcom.mk @@ -433,7 +433,7 @@ define KernelPackage/brcmfmac $(call KernelPackage/mac80211/Default) TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 - DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT \ + DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT \ +kmod-brcmutil +BRCMFMAC_SDIO:kmod-mmc @!TARGET_uml \ +BRCMFMAC_USB:kmod-usb-core +BRCMFMAC_USB:brcmfmac-firmware-usb FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 813fa851e7..8e6092483e 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -28,11 +28,13 @@ drv_mac80211_init_device_config() { config_add_string path phy 'macaddr:macaddr' config_add_string hwmode config_add_string tx_burst + config_add_string distance config_add_int beacon_int chanbw frag rts - config_add_int rxantenna txantenna antenna_gain txpower distance + config_add_int rxantenna txantenna antenna_gain txpower config_add_boolean noscan ht_coex acs_exclude_dfs config_add_array ht_capab config_add_array channels + config_add_array scan_list config_add_boolean \ rxldpc \ short_gi_80 \ @@ -100,7 +102,6 @@ mac80211_hostapd_setup_base() { json_select config [ "$auto_channel" -gt 0 ] && channel=acs_survey - [ "$auto_channel" -gt 0 ] && json_get_values channel_list channels [ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs [ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && @@ -108,6 +109,10 @@ mac80211_hostapd_setup_base() { json_get_vars noscan ht_coex vendor_vht json_get_values ht_capab_list ht_capab tx_burst + json_get_values channel_list channels + + [ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \ + channel_list="$channel" set_default noscan 0 @@ -117,8 +122,8 @@ mac80211_hostapd_setup_base() { ieee80211n=1 ht_capab= case "$htmode" in - VHT20|HT20) ;; - HT40*|VHT40|VHT80|VHT160) + VHT20|HT20|HE20) ;; + HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160) case "$hwmode" in a) case "$(( ($channel / 4) % 2 ))" in @@ -188,19 +193,21 @@ mac80211_hostapd_setup_base() { # 802.11ac enable_ac=0 + vht_oper_chwidth=0 + vht_center_seg0= + idx="$channel" case "$htmode" in - VHT20) enable_ac=1;; - VHT40) + VHT20|HE20) enable_ac=1;; + VHT40|HE40) case "$(( ($channel / 4) % 2 ))" in 1) idx=$(($channel + 2));; 0) idx=$(($channel - 2));; esac enable_ac=1 - append base_cfg "vht_oper_chwidth=0" "$N" - append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N" + vht_center_seg0=$idx ;; - VHT80) + VHT80|HE80) case "$(( ($channel / 4) % 4 ))" in 1) idx=$(($channel + 6));; 2) idx=$(($channel + 2));; @@ -208,19 +215,20 @@ mac80211_hostapd_setup_base() { 0) idx=$(($channel - 6));; esac enable_ac=1 - append base_cfg "vht_oper_chwidth=1" "$N" - append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N" + vht_oper_chwidth=1 + vht_center_seg0=$idx ;; - VHT160) + VHT160|HE160) case "$channel" in 36|40|44|48|52|56|60|64) idx=50;; 100|104|108|112|116|120|124|128) idx=114;; esac enable_ac=1 - append base_cfg "vht_oper_chwidth=2" "$N" - append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N" + vht_oper_chwidth=2 + vht_center_seg0=$idx ;; esac + [ "$hwmode" = "a" ] || enable_ac=0 if [ "$enable_ac" != "0" -o "$vendor_vht" = "1" ]; then json_get_vars \ @@ -249,6 +257,9 @@ mac80211_hostapd_setup_base() { vht_cap="$(($vht_cap | $cap))" done + append base_cfg "vht_oper_chwidth=$vht_oper_chwidth" "$N" + append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" + cap_rx_stbc=$((($vht_cap >> 8) & 7)) [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))" @@ -319,6 +330,25 @@ mac80211_hostapd_setup_base() { [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N" fi + # 802.11ax + enable_ax=0 + case "$htmode" in + HE*) enable_ax=1 ;; + esac + + if [ "$enable_ax" != "0" ]; then + append base_cfg "ieee80211ax=1" "$N" + [ "$hwmode" = "a" ] && { + append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N" + append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" + } + append base_cfg "he_default_pe_duration=4" "$N" + append base_cfg "he_rts_threshold=1023" "$N" + append base_cfg "he_su_beamformer=1" "$N" + append base_cfg "he_su_beamformee=1" "$N" + append base_cfg "he_mu_beamformer=1" "$N" + fi + hostapd_prepare_device_config "$hostapd_conf_file" nl80211 cat >> "$hostapd_conf_file" </dev/null 2>&1 - iw phy "$phy" set antenna_gain $antenna_gain - iw phy "$phy" set distance "$distance" + iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 + iw phy "$phy" set distance "$distance" >/dev/null 2>&1 if [ -n "$txpower" ]; then iw phy "$phy" set txpower fixed "${txpower%%.*}00" @@ -954,8 +996,8 @@ drv_mac80211_setup() { OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5) if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then mac80211_vap_cleanup hostapd "${OLDAPLIST}" - [ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap || return fi + [ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap local add_ap=0 local primary_ap=${NEWAPLIST%% *} [ -n "$hostapd_ctrl" ] && { @@ -966,22 +1008,25 @@ drv_mac80211_setup() { no_reload=$? if [ "$no_reload" != "0" ]; then mac80211_vap_cleanup hostapd "${OLDAPLIST}" - [ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap || return + mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" + mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" + sleep 2 + mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap + for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif fi } fi if [ "$no_reload" != "0" ]; then add_ap=1 ubus wait_for hostapd - ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}" - local hostapd_pid=$(ubus call service list '{"name": "hostapd"}' | jsonfilter -l 1 -e "@['hostapd'].instances['hostapd'].pid") - wireless_add_process "$hostapd_pid" "/usr/sbin/hostapd" 1 + local hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")" + ret="$?" + [ "$ret" != 0 -o -z "$hostapd_res" ] && { + wireless_setup_failed HOSTAPD_START_FAILED + return + } + wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 fi - ret="$?" - [ "$ret" != 0 ] && { - wireless_setup_failed HOSTAPD_START_FAILED - return - } } uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}" uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}" @@ -1029,8 +1074,6 @@ list_phy_interfaces() { } drv_mac80211_teardown() { - wireless_process_kill_all - json_select data json_get_vars phy json_select .. diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh index 1d7f11f37c..5c4f08252d 100644 --- a/package/kernel/mac80211/files/lib/wifi/mac80211.sh +++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh @@ -88,6 +88,12 @@ detect_mac80211() { iw phy "$dev" info | grep -q 'VHT Capabilities' && htmode="VHT80" } + iw phy "$dev" info | grep -q '\* 5.... MHz \[' && { + mode_band="ad" + channel=$(iw phy "$dev" info | grep '\* 5.... MHz \[' | grep '(disabled)' -v -m 1 | sed 's/[^[]*\[\|\|\].*//g') + iw phy "$dev" info | grep -q 'Capabilities:' && htmode="HT20" + } + [ -n "$htmode" ] && ht_capab="set wireless.radio${devidx}.htmode=$htmode" path="$(mac80211_phy_to_path "$dev")" @@ -104,6 +110,7 @@ detect_mac80211() { set wireless.radio${devidx}.hwmode=11${mode_band} ${dev_id} ${ht_capab} + set wireless.radio${devidx}.country=US set wireless.radio${devidx}.disabled=0 set wireless.default_radio${devidx}=wifi-iface diff --git a/package/kernel/mac80211/intel.mk b/package/kernel/mac80211/intel.mk index a8ae4ff7c7..8bab727a41 100644 --- a/package/kernel/mac80211/intel.mk +++ b/package/kernel/mac80211/intel.mk @@ -15,7 +15,7 @@ config-$(call config_package,ipw2200) += IPW2200 define KernelPackage/iwlwifi $(call KernelPackage/mac80211/Default) - DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT + DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT TITLE:=Intel AGN Wireless support FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/iwlwifi.ko \ diff --git a/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch index 3bb046e843..de6f9d9bb0 100644 --- a/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch +++ b/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch @@ -1,7 +1,7 @@ --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig -@@ -87,6 +87,12 @@ config ATH10K_TRACING - ---help--- +@@ -86,6 +86,12 @@ config ATH10K_TRACING + help Select this to ath10k use tracing infrastructure. +config ATH10K_THERMAL diff --git a/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch b/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch index 155f4fc365..d1d6c9e2e3 100644 --- a/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch +++ b/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch @@ -11,7 +11,7 @@ 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 -@@ -104,6 +104,7 @@ static void owl_fw_cb(const struct firmw +@@ -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); @@ -19,7 +19,7 @@ Signed-off-by: Christian Lamparter struct pci_bus *bus; complete(&ctx->eeprom_load); -@@ -119,6 +120,16 @@ static void owl_fw_cb(const struct firmw +@@ -118,6 +119,16 @@ static void owl_fw_cb(const struct firmw goto release; } @@ -36,7 +36,7 @@ Signed-off-by: Christian Lamparter if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size)) goto release; -@@ -138,8 +149,14 @@ release: +@@ -137,8 +148,14 @@ release: static const char *owl_get_eeprom_name(struct pci_dev *pdev) { struct device *dev = &pdev->dev; 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 e7df0e14be..db10c45104 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 @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile -@@ -14,10 +14,10 @@ ath-objs := main.o \ +@@ -15,10 +15,10 @@ ath-objs := main.o \ regd.o \ hw.o \ key.o \ 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 7824eab6cb..bf87d3551a 100644 --- a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch @@ -79,7 +79,7 @@ + config ATH_DEBUG bool "Atheros wireless debugging" - ---help--- + help --- a/local-symbols +++ b/local-symbols @@ -85,6 +85,7 @@ ADM8211= diff --git a/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch b/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch index 2043083158..ed616b7532 100644 --- a/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch +++ b/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch @@ -4,15 +4,15 @@ NL80211_RRF_NO_OFDM) /* We allow IBSS on these on a case by case basis by regulatory domain */ --#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ -+#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ +-#define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ ++#define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ + REG_RULE(5260-10, 5350+10, 80, 0, 30,\ NL80211_RRF_NO_IR) - #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ + #define ATH_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ NL80211_RRF_NO_IR) @@ -62,57 +63,56 @@ static struct reg_dmn_pair_mapping *ath_ - #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ - ATH9K_5GHZ_5725_5850 + #define ATH_5GHZ_NO_MIDBAND ATH_5GHZ_5150_5350, \ + ATH_5GHZ_5725_5850 +#define REGD_RULES(...) \ + .reg_rules = { __VA_ARGS__ }, \ @@ -25,8 +25,8 @@ .alpha2 = "99", - .reg_rules = { + REGD_RULES( - ATH9K_2GHZ_ALL, - ATH9K_5GHZ_ALL, + ATH_2GHZ_ALL, + ATH_5GHZ_ALL, - } + ) }; @@ -37,9 +37,9 @@ .alpha2 = "99", - .reg_rules = { + REGD_RULES( - ATH9K_2GHZ_CH01_11, - ATH9K_2GHZ_CH12_13, - ATH9K_5GHZ_NO_MIDBAND, + ATH_2GHZ_CH01_11, + ATH_2GHZ_CH12_13, + ATH_5GHZ_NO_MIDBAND, - } + ) }; @@ -50,8 +50,8 @@ .alpha2 = "99", - .reg_rules = { + REGD_RULES( - ATH9K_2GHZ_CH01_11, - ATH9K_5GHZ_NO_MIDBAND, + ATH_2GHZ_CH01_11, + ATH_5GHZ_NO_MIDBAND, - } + ) }; @@ -62,8 +62,8 @@ .alpha2 = "99", - .reg_rules = { + REGD_RULES( - ATH9K_2GHZ_CH01_11, - ATH9K_5GHZ_ALL, + ATH_2GHZ_CH01_11, + ATH_5GHZ_ALL, - } + ) }; @@ -74,9 +74,9 @@ .alpha2 = "99", - .reg_rules = { + REGD_RULES( - ATH9K_2GHZ_CH01_11, - ATH9K_2GHZ_CH12_13, - ATH9K_5GHZ_ALL, + ATH_2GHZ_CH01_11, + ATH_2GHZ_CH12_13, + ATH_5GHZ_ALL, - } + ) }; 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 8bb1d6c813..c6dc184e28 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 -@@ -3039,6 +3039,8 @@ void regulatory_hint_country_ie(struct w +@@ -3252,6 +3252,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; -@@ -3290,6 +3292,7 @@ static bool is_wiphy_all_set_reg_flag(en +@@ -3503,6 +3505,7 @@ static bool is_wiphy_all_set_reg_flag(en void regulatory_hint_disconnect(void) { diff --git a/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch index bdf784968f..17dd8f6597 100644 --- a/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -831,6 +831,7 @@ static const struct ieee80211_iface_limi +@@ -830,6 +830,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_AP) }, { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) }, diff --git a/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch index 57d3363274..92fb90c165 100644 --- a/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch +++ b/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch @@ -11,7 +11,7 @@ drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c -@@ -822,6 +822,97 @@ static const struct file_operations fops +@@ -803,6 +803,97 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -109,7 +109,7 @@ drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ /* debugfs: queues etc */ -@@ -1016,6 +1107,8 @@ ath5k_debug_init_device(struct ath5k_hw +@@ -997,6 +1088,8 @@ ath5k_debug_init_device(struct ath5k_hw debugfs_create_file("queue", 0600, phydir, ah, &fops_queue); debugfs_create_bool("32khz_clock", 0600, phydir, &ah->ah_use_32khz_clock); diff --git a/package/kernel/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch b/package/kernel/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch new file mode 100644 index 0000000000..ea94b52385 --- /dev/null +++ b/package/kernel/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch @@ -0,0 +1,34 @@ +From d946085ff5a331de64e91a2e3c96b9ca79d740f5 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 15 Jun 2020 00:10:34 +0200 +Subject: [PATCH] ath9k: enabled MFP capability unconditionally + +ath9k will already fallback on software-crypto for chipsets not +supporting IEEE802.11w (MFP). So advertising MFP is not dependent +on disabling HW crypto for all traffic entirely. + +Signed-off-by: David Bauer +--- + drivers/net/wireless/ath/ath9k/init.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- 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 + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ++ ieee80211_hw_set(hw, MFP_CAPABLE); + + if (ath9k_ps_enable) + ieee80211_hw_set(hw, SUPPORTS_PS); +@@ -939,9 +940,6 @@ static void ath9k_set_hw_capab(struct at + IEEE80211_RADIOTAP_MCS_HAVE_STBC; + } + +- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) +- ieee80211_hw_set(hw, MFP_CAPABLE); +- + hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_P2P_GO_CTWIN; diff --git a/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch index 7c60191d48..76cb63a5c8 100644 --- a/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch @@ -62,7 +62,7 @@ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -521,6 +521,12 @@ enum { +@@ -522,6 +522,12 @@ enum { ATH9K_RESET_COLD, }; @@ -75,7 +75,7 @@ struct ath9k_hw_version { u32 magic; u16 devid; -@@ -809,6 +815,8 @@ struct ath_hw { +@@ -810,6 +816,8 @@ struct ath_hw { u32 ah_flags; s16 nf_override; @@ -84,7 +84,7 @@ bool reset_power_on; bool htc_reset_init; -@@ -1074,6 +1082,7 @@ void ath9k_hw_check_nav(struct ath_hw *a +@@ -1076,6 +1084,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); @@ -125,7 +125,7 @@ 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 -@@ -528,6 +528,11 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -531,6 +531,11 @@ irqreturn_t ath_isr(int irq, void *dev) if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) return IRQ_HANDLED; diff --git a/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch index 64bd6cacfd..0d938a3730 100644 --- a/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -722,6 +722,7 @@ struct ath_spec_scan { +@@ -723,6 +723,7 @@ struct ath_spec_scan { * @config_pci_powersave: * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC * @@ -8,7 +8,7 @@ * @spectral_scan_config: set parameters for spectral scan and enable/disable it * @spectral_scan_trigger: trigger a spectral scan run * @spectral_scan_wait: wait for a spectral scan run to finish -@@ -744,6 +745,7 @@ struct ath_hw_ops { +@@ -745,6 +746,7 @@ struct ath_hw_ops { struct ath_hw_antcomb_conf *antconf); void (*antdiv_comb_conf_set)(struct ath_hw *ah, struct ath_hw_antcomb_conf *antconf); @@ -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 -@@ -819,7 +819,8 @@ static void ath9k_init_txpower_limits(st +@@ -818,7 +818,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); @@ -66,7 +66,7 @@ static const struct ieee80211_iface_limit if_limits[] = { @@ -1015,6 +1016,18 @@ static void ath9k_set_hw_capab(struct at - wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); } +static void ath_get_initial_entropy(struct ath_softc *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 -@@ -1320,9 +1320,30 @@ void ar5008_hw_init_rate_txpower(struct +@@ -1349,9 +1349,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, -@@ -1337,6 +1358,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ +@@ -1366,6 +1387,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ if (ret) return ret; diff --git a/package/kernel/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch index 48cc171134..466767adb9 100644 --- a/package/kernel/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch +++ b/package/kernel/mac80211/patches/ath/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 -@@ -949,55 +949,6 @@ static bool ar5008_hw_ani_control_new(st +@@ -978,55 +978,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/ath/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch index bc5c1ab4ef..7e3e1236f7 100644 --- a/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch +++ b/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch @@ -337,9 +337,9 @@ #include "btcoex.h" +#include "hsr.h" - u8 ath9k_parse_mpdudensity(u8 mpdudensity) - { -@@ -649,6 +650,7 @@ void ath_reset_work(struct work_struct * + 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 * 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; -@@ -727,6 +729,11 @@ static int ath9k_start(struct ieee80211_ +@@ -730,6 +732,11 @@ static int ath9k_start(struct ieee80211_ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } diff --git a/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch index 72b99050c4..8e0041e3ef 100644 --- a/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch +++ b/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch @@ -13,7 +13,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -758,6 +764,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -757,6 +763,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_hw; diff --git a/package/kernel/mac80211/patches/ath/560-ath9k-fix-transmitting-to-stations-in-dynamic-SMPS-m.patch b/package/kernel/mac80211/patches/ath/560-ath9k-fix-transmitting-to-stations-in-dynamic-SMPS-m.patch new file mode 100644 index 0000000000..68f3a31548 --- /dev/null +++ b/package/kernel/mac80211/patches/ath/560-ath9k-fix-transmitting-to-stations-in-dynamic-SMPS-m.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Sun, 14 Feb 2021 19:45:50 +0100 +Subject: [PATCH] ath9k: fix transmitting to stations in dynamic SMPS mode + +When transmitting to a receiver in dynamic SMPS mode, all transmissions that +use multiple spatial streams need to be sent using CTS-to-self or RTS/CTS to +give the receiver's extra chains some time to wake up. +This fixes the tx rate getting stuck at <= MCS7 for some clients, especially +Intel ones, which make aggressive use of SMPS. + +Cc: stable@vger.kernel.org +Reported-by: Martin Kennedy +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -179,7 +179,8 @@ struct ath_frame_info { + s8 txq; + u8 keyix; + u8 rtscts_rate; +- u8 retries : 7; ++ u8 retries : 6; ++ u8 dyn_smps : 1; + u8 baw_tracked : 1; + u8 tx_power; + enum ath9k_key_type keytype:2; +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -1271,6 +1271,11 @@ static void ath_buf_set_rate(struct ath_ + is_40, is_sgi, is_sp); + if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) + info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; ++ if (rix >= 8 && fi->dyn_smps) { ++ info->rates[i].RateFlags |= ++ ATH9K_RATESERIES_RTS_CTS; ++ info->flags |= ATH9K_TXDESC_CTSENA; ++ } + + info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, + is_40, false); +@@ -2114,6 +2119,7 @@ static void setup_frame_info(struct ieee + fi->keyix = an->ps_key; + else + fi->keyix = ATH9K_TXKEYIX_INVALID; ++ fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC; + fi->keytype = keytype; + fi->framelen = framelen; + fi->tx_power = txpower; diff --git a/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch index 69c29f15ee..e004acc340 100644 --- a/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/ath/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 -@@ -3074,6 +3074,16 @@ int ath10k_core_register(struct ath10k * +@@ -3189,6 +3189,16 @@ int ath10k_core_register(struct ath10k * queue_work(ar->workqueue, &ar->register_work); diff --git a/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch b/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch index 91acc710f8..abce361673 100644 --- a/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch +++ b/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch @@ -26,7 +26,7 @@ Forwarded: https://patchwork.kernel.org/patch/11367055/ --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -2226,7 +2226,7 @@ struct htt_rx_chan_info { +@@ -2242,7 +2242,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. */ diff --git a/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch index d7abdc82dd..1fedd337ac 100644 --- a/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch +++ b/package/kernel/mac80211/patches/ath/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 -@@ -8677,6 +8677,21 @@ static int ath10k_mac_init_rd(struct ath +@@ -9713,6 +9713,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[] = { -@@ -9003,6 +9018,12 @@ int ath10k_mac_register(struct ath10k *a +@@ -10062,6 +10077,12 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; diff --git a/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch b/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch deleted file mode 100644 index c99ba55955..0000000000 --- a/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch +++ /dev/null @@ -1,144 +0,0 @@ -From: Sebastian Gottschall - -current handling of peer_bw_rxnss_override parameter is based on guessing the VHT160/8080 capability by rx rate. this is wrong and may lead -to a non initialized peer_bw_rxnss_override parameter which is required since VHT160 operation mode only supports 2x2 chainmasks in addition the original code -initialized the parameter with wrong masked values. -This patch uses the peer phymode and peer nss information for correct initialisation of the peer_bw_rxnss_override parameter. -if this peer information is not available, we initialize the parameter by minimum nss which is suggested by QCA as temporary workaround according -to the QCA sourcecodes. - -Signed-off-by: Sebastian Gottschall - -v2: remove debug messages -v3: apply some cosmetics, update documentation -v4: fix compile warning and truncate nss to maximum of 2x2 since current chipsets only support 2x2 at vht160 -v5: handle maximum nss for chipsets supportig vht160 with 1x1 only -v7: use more simple code variant and take care about hw/sw chainmask configuration -v8: fix some code style issues -v9: use SM/MS macros from code.h to simplify shift/mask handling ---- - drivers/net/wireless/ath/ath10k/mac.c | 54 +++++++++++++++++++-------- - drivers/net/wireless/ath/ath10k/wmi.c | 7 +--- - drivers/net/wireless/ath/ath10k/wmi.h | 14 ++++++- - 3 files changed, 52 insertions(+), 23 deletions(-) ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -2515,7 +2515,7 @@ static void ath10k_peer_assoc_h_vht(stru - const u16 *vht_mcs_mask; - u8 ampdu_factor; - u8 max_nss, vht_mcs; -- int i; -+ int i, nss160; - - if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) - return; -@@ -2575,23 +2575,45 @@ static void ath10k_peer_assoc_h_vht(stru - __le16_to_cpu(vht_cap->vht_mcs.tx_highest); - arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit( - __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask); -+ arg->peer_bw_rxnss_override = 0; -+ nss160 = 1; /* 1x1 default config for VHT160 */ - -- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n", -- sta->addr, arg->peer_max_mpdu, arg->peer_flags); -+ /* only local 4x4 configuration do support 2x2 for VHT160, -+ * everything else must use 1x1 -+ */ - -- if (arg->peer_vht_rates.rx_max_rate && -- (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) { -- switch (arg->peer_vht_rates.rx_max_rate) { -- case 1560: -- /* Must be 2x2 at 160Mhz is all it can do. */ -- arg->peer_bw_rxnss_override = 2; -- break; -- case 780: -- /* Can only do 1x1 at 160Mhz (Long Guard Interval) */ -- arg->peer_bw_rxnss_override = 1; -- break; -- } -+ if (ar->cfg_rx_chainmask == 15) -+ nss160 = arg->peer_num_spatial_streams <= 2 ? 1 : 2; -+ -+ /* if peer provides 1x1 nss160 information using max rate -+ * vht information, we reduce local nss160 to 1x1. -+ * consider that it has been observed that some client -+ * devices provide zero here, no matter which transmission -+ * rate is possible. in that case the local nss configuration -+ * will be used at maxmimum configuration possible. (see above) -+ */ -+ -+ if (arg->peer_vht_rates.rx_max_rate == 780) -+ nss160 = 1; -+ -+ /* in case if peer is connected with vht160 or vht80+80, -+ * we need to properly adjust rxnss parameters otherwise -+ * firmware will raise a assert -+ */ -+ switch (arg->peer_phymode) { -+ case MODE_11AC_VHT80_80: -+ arg->peer_bw_rxnss_override = BW_NSS_FWCONF_80_80(nss160); -+ /* fall through */ -+ case MODE_11AC_VHT160: -+ arg->peer_bw_rxnss_override |= BW_NSS_FWCONF_160(nss160); -+ break; -+ default: -+ break; - } -+ -+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x peer_bw_rxnss_override 0x%x\n", -+ sta->addr, arg->peer_max_mpdu, arg->peer_flags, -+ arg->peer_bw_rxnss_override); - } - - static void ath10k_peer_assoc_h_qos(struct ath10k *ar, -@@ -2743,9 +2765,9 @@ static int ath10k_peer_assoc_prepare(str - ath10k_peer_assoc_h_crypto(ar, vif, sta, arg); - ath10k_peer_assoc_h_rates(ar, vif, sta, arg); - ath10k_peer_assoc_h_ht(ar, vif, sta, arg); -+ ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); - ath10k_peer_assoc_h_vht(ar, vif, sta, arg); - ath10k_peer_assoc_h_qos(ar, vif, sta, arg); -- ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); - - return 0; - } ---- a/drivers/net/wireless/ath/ath10k/wmi.c -+++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -7552,12 +7552,7 @@ ath10k_wmi_peer_assoc_fill_10_4(struct a - struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf; - - ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg); -- if (arg->peer_bw_rxnss_override) -- cmd->peer_bw_rxnss_override = -- __cpu_to_le32((arg->peer_bw_rxnss_override - 1) | -- BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET)); -- else -- cmd->peer_bw_rxnss_override = 0; -+ cmd->peer_bw_rxnss_override = __cpu_to_le32(arg->peer_bw_rxnss_override); - } - - static int ---- a/drivers/net/wireless/ath/ath10k/wmi.h -+++ b/drivers/net/wireless/ath/ath10k/wmi.h -@@ -6478,7 +6478,19 @@ struct wmi_10_2_peer_assoc_complete_cmd - __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */ - } __packed; - --#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31 -+#define BW_NSS_FWCONF_MAP_ENABLE BIT(31) -+#define BW_NSS_FWCONF_MAP_160MHZ_LSB (0) -+#define BW_NSS_FWCONF_MAP_160MHZ_MASK (0x00000007) -+#define BW_NSS_FWCONF_MAP_80_80MHZ_LSB (3) -+#define BW_NSS_FWCONF_MAP_80_80MHZ_MASK (0x00000038) -+#define BW_NSS_FWCONF_MAP_MASK (0x0000003F) -+ -+#define GET_BW_NSS_FWCONF_160(x) (MS(x, BW_NSS_FWCONF_MAP_160MHZ) + 1) -+#define GET_BW_NSS_FWCONF_80_80(x) (MS(x, BW_NSS_FWCONF_MAP_80_80MHZ) + 1) -+ -+/* Values defined to set 160 MHz Bandwidth NSS Mapping into FW*/ -+#define BW_NSS_FWCONF_160(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_160MHZ)) -+#define BW_NSS_FWCONF_80_80(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_80_80MHZ)) - - struct wmi_10_4_peer_assoc_complete_cmd { - struct wmi_10_2_peer_assoc_complete_cmd cmd; diff --git a/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch b/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch deleted file mode 100644 index d955bde3c5..0000000000 --- a/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: Sebastian Gottschall - -starting with firmware 10.4.3.4.x series QCA changed the handling of the channel property band_center_freq1 and band_center_freq2 in vht160 operation mode -likelly for backward compatiblity with vht80 only capable clients. -this patch adjusts the handling to get vht160 to work again with official qca firmwares newer than 3.3 -consider that this patch will not work with older firmwares anymore. to avoid undefined behaviour this we disable vht160 capability for outdated firmwares -Signed-off-by: Sebastian Gottschall - -v2: fix trailing whitespace issue and fix some typos within the commit note ---- - drivers/net/wireless/ath/ath10k/mac.c | 7 ------- - drivers/net/wireless/ath/ath10k/wmi.c | 11 ++++++++--- - 2 files changed, 8 insertions(+), 10 deletions(-) ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -4578,13 +4578,6 @@ static struct ieee80211_sta_vht_cap ath1 - vht_cap.cap |= val; - } - -- /* Currently the firmware seems to be buggy, don't enable 80+80 -- * mode until that's resolved. -- */ -- if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && -- (ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0) -- vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; -- - mcs_map = 0; - for (i = 0; i < 8; i++) { - if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) ---- a/drivers/net/wireless/ath/ath10k/wmi.c -+++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -1700,13 +1700,18 @@ void ath10k_wmi_put_wmi_channel(struct w - flags |= WMI_CHAN_FLAG_HT40_PLUS; - if (arg->chan_radar) - flags |= WMI_CHAN_FLAG_DFS; -- -+ ch->band_center_freq2 = 0; - ch->mhz = __cpu_to_le32(arg->freq); - ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1); - if (arg->mode == MODE_11AC_VHT80_80) - ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2); -- else -- ch->band_center_freq2 = 0; -+ if (arg->mode == MODE_11AC_VHT160) { -+ if (arg->freq < arg->band_center_freq1) -+ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1 - 40); -+ else -+ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1 + 40); -+ ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq1); -+ } - ch->min_power = arg->min_power; - ch->max_power = arg->max_power; - ch->reg_power = arg->max_reg_power; diff --git a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch index 9cd393d520..ab7cb669bb 100644 --- a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch +++ b/package/kernel/mac80211/patches/ath/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 -@@ -71,6 +71,16 @@ config ATH10K_DEBUGFS +@@ -70,6 +70,16 @@ config ATH10K_DEBUGFS If unsure, say Y to make it easier to debug problems. @@ -124,7 +124,7 @@ v13: WCN36XX= --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -24,6 +24,7 @@ +@@ -25,6 +25,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); -@@ -60,6 +61,7 @@ static const struct ath10k_hw_params ath +@@ -61,6 +62,7 @@ static const struct ath10k_hw_params ath .dev_id = QCA988X_2_0_DEVICE_ID, .bus = ATH10K_BUS_PCI, .name = "qca988x hw2.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, -@@ -337,6 +340,7 @@ static const struct ath10k_hw_params ath +@@ -335,6 +338,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, -@@ -378,6 +382,7 @@ static const struct ath10k_hw_params ath +@@ -375,6 +379,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, -@@ -426,6 +431,7 @@ static const struct ath10k_hw_params ath +@@ -422,6 +427,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, -@@ -2791,6 +2797,10 @@ int ath10k_core_start(struct ath10k *ar, +@@ -2904,6 +2910,10 @@ int ath10k_core_start(struct ath10k *ar, goto err_hif_stop; } @@ -183,7 +183,7 @@ v13: return 0; err_hif_stop: -@@ -3047,9 +3057,18 @@ static void ath10k_core_register_work(st +@@ -3162,9 +3172,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: -@@ -3095,6 +3114,8 @@ void ath10k_core_unregister(struct ath10 +@@ -3210,6 +3229,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" -@@ -1170,6 +1171,13 @@ struct ath10k { +@@ -1237,6 +1238,13 @@ struct ath10k { } testmode; struct { @@ -233,11 +233,11 @@ v13: + + struct { /* protected by data_lock */ + u32 rx_crc_err_drop; u32 fw_crash_counter; - u32 fw_warm_reset_counter; --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h -@@ -514,6 +514,7 @@ struct ath10k_hw_params { +@@ -517,6 +517,7 @@ struct ath10k_hw_params { const char *name; u32 patch_load_addr; int uart_pin; @@ -397,7 +397,7 @@ v13: +#endif /* _LEDS_H_ */ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -23,6 +23,7 @@ +@@ -24,6 +24,7 @@ #include "wmi-tlv.h" #include "wmi-ops.h" #include "wow.h" @@ -407,10 +407,10 @@ v13: /* Rates */ --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h -@@ -217,7 +217,10 @@ struct wmi_ops { - struct sk_buff *(*gen_bb_timing) - (struct ath10k *ar, +@@ -226,7 +226,10 @@ struct wmi_ops { const struct wmi_bb_timing_cfg_arg *arg); + struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar, + const struct wmi_per_peer_per_tid_cfg_arg *arg); + struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num, + u32 input, u32 pull_type, u32 intr_mode); @@ -418,7 +418,7 @@ v13: }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); -@@ -1090,6 +1093,35 @@ ath10k_wmi_force_fw_hang(struct ath10k * +@@ -1122,6 +1125,35 @@ ath10k_wmi_force_fw_hang(struct ath10k * return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); } @@ -456,7 +456,7 @@ v13: { --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c -@@ -4382,6 +4382,8 @@ static const struct wmi_ops wmi_tlv_ops +@@ -4585,6 +4585,8 @@ static const struct wmi_ops wmi_tlv_ops .gen_echo = ath10k_wmi_tlv_op_gen_echo, .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, @@ -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 -@@ -7372,6 +7372,49 @@ ath10k_wmi_op_gen_peer_set_param(struct +@@ -7468,6 +7468,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) -@@ -9029,6 +9072,9 @@ static const struct wmi_ops wmi_ops = { +@@ -9156,6 +9199,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 */ -@@ -9099,6 +9145,8 @@ static const struct wmi_ops wmi_10_1_ops +@@ -9226,6 +9272,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 */ -@@ -9171,6 +9219,8 @@ static const struct wmi_ops wmi_10_2_ops +@@ -9298,6 +9346,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 */ }; -@@ -9242,6 +9292,8 @@ static const struct wmi_ops wmi_10_2_4_o +@@ -9369,6 +9419,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 */ -@@ -9322,6 +9374,8 @@ static const struct wmi_ops wmi_10_4_ops +@@ -9450,6 +9502,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 -@@ -3005,6 +3005,41 @@ enum wmi_10_4_feature_mask { +@@ -3027,6 +3027,41 @@ enum wmi_10_4_feature_mask { }; diff --git a/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch index cfca3d9020..f7569df33c 100644 --- a/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch +++ b/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch @@ -16,16 +16,16 @@ Signed-off-by: Mathias Kresin --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -1219,6 +1219,10 @@ struct ath10k { - struct ath10k_bus_params bus_param; - struct completion peer_delete_done; +@@ -1290,6 +1290,10 @@ struct ath10k { + bool coex_support; + int coex_gpio_pin; +#ifdef CPTCFG_MAC80211_LEDS + const char *led_default_trigger; +#endif + /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); }; --- a/drivers/net/wireless/ath/ath10k/leds.c +++ b/drivers/net/wireless/ath/ath10k/leds.c @@ -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 -@@ -9035,7 +9035,7 @@ int ath10k_mac_register(struct ath10k *a +@@ -10079,7 +10079,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/ath/980-ath10k-fix-max-antenna-gain-unit.patch b/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch index f60163f941..e951e011e6 100644 --- a/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch +++ b/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch @@ -20,7 +20,7 @@ Forwarded: https://patchwork.kernel.org/patch/10986723/ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1041,7 +1041,7 @@ static int ath10k_monitor_vdev_start(str +@@ -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; @@ -29,7 +29,7 @@ Forwarded: https://patchwork.kernel.org/patch/10986723/ reinit_completion(&ar->vdev_setup_done); reinit_completion(&ar->vdev_delete_done); -@@ -1487,7 +1487,7 @@ static int ath10k_vdev_start_restart(str +@@ -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; @@ -38,7 +38,7 @@ Forwarded: https://patchwork.kernel.org/patch/10986723/ if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { arg.ssid = arvif->u.ap.ssid; -@@ -3168,7 +3168,7 @@ static int ath10k_update_channel_list(st +@@ -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; diff --git a/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch index 9fbb254127..a149ce1216 100644 --- a/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch +++ b/package/kernel/mac80211/patches/ath/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 -@@ -1009,6 +1009,40 @@ static inline int ath10k_vdev_setup_sync +@@ -1006,6 +1006,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; -@@ -1041,7 +1075,8 @@ static int ath10k_monitor_vdev_start(str +@@ -1038,7 +1072,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); -@@ -1487,7 +1522,8 @@ static int ath10k_vdev_start_restart(str +@@ -1484,7 +1519,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; -@@ -3168,7 +3204,8 @@ static int ath10k_update_channel_list(st +@@ -3255,7 +3291,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/brcm/101-v5.5-0001-brcmfmac-don-t-WARN-when-there-are-no-requests.patch b/package/kernel/mac80211/patches/brcm/101-v5.5-0001-brcmfmac-don-t-WARN-when-there-are-no-requests.patch deleted file mode 100644 index a1311e0a49..0000000000 --- a/package/kernel/mac80211/patches/brcm/101-v5.5-0001-brcmfmac-don-t-WARN-when-there-are-no-requests.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 1524cbf3621576c639405e7aabeac415f9617c8d Mon Sep 17 00:00:00 2001 -From: Adrian Ratiu -Date: Wed, 25 Sep 2019 16:44:57 +0300 -Subject: [PATCH] brcmfmac: don't WARN when there are no requests - -When n_reqs == 0 there is nothing to do so it doesn't make sense to -search for requests and issue a warning because none is found. - -Signed-off-by: Martyn Welch -Signed-off-by: Adrian Ratiu -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c -@@ -57,6 +57,10 @@ static int brcmf_pno_remove_request(stru - - mutex_lock(&pi->req_lock); - -+ /* Nothing to do if we have no requests */ -+ if (pi->n_reqs == 0) -+ goto done; -+ - /* find request */ - for (i = 0; i < pi->n_reqs; i++) { - if (pi->reqs[i]->reqid == reqid) diff --git a/package/kernel/mac80211/patches/brcm/101-v5.5-0002-brcmfmac-fix-suspend-resume-when-power-is-cut-off.patch b/package/kernel/mac80211/patches/brcm/101-v5.5-0002-brcmfmac-fix-suspend-resume-when-power-is-cut-off.patch deleted file mode 100644 index eafc96b901..0000000000 --- a/package/kernel/mac80211/patches/brcm/101-v5.5-0002-brcmfmac-fix-suspend-resume-when-power-is-cut-off.patch +++ /dev/null @@ -1,109 +0,0 @@ -From e0ae4bac22effbd644add326f658a3aeeb8d45ee Mon Sep 17 00:00:00 2001 -From: Adrian Ratiu -Date: Wed, 25 Sep 2019 16:44:58 +0300 -Subject: [PATCH] brcmfmac: fix suspend/resume when power is cut off - -brcmfmac assumed the wifi device always remains powered on and thus -hardcoded the MMC_PM_KEEP_POWER flag expecting the wifi device to -remain on even during suspend/resume cycles. - -This is not always the case, some appliances cut power to everything -connected via SDIO for efficiency reasons and this leads to wifi not -being usable after coming out of suspend because the device was not -correctly reinitialized. - -So we check for the keep_power capability and if it's not present then -we remove the device and probe it again during resume to mirror what's -happening in hardware and ensure correct reinitialization in the case -when MMC_PM_KEEP_POWER is not supported. - -Suggested-by: Gustavo Padovan -Signed-off-by: Adrian Ratiu -Signed-off-by: Kalle Valo ---- - .../broadcom/brcm80211/brcmfmac/bcmsdh.c | 53 ++++++++++++++----- - 1 file changed, 39 insertions(+), 14 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -@@ -1108,7 +1108,8 @@ static int brcmf_ops_sdio_suspend(struct - struct sdio_func *func; - struct brcmf_bus *bus_if; - struct brcmf_sdio_dev *sdiodev; -- mmc_pm_flag_t sdio_flags; -+ mmc_pm_flag_t pm_caps, sdio_flags; -+ int ret = 0; - - func = container_of(dev, struct sdio_func, dev); - brcmf_dbg(SDIO, "Enter: F%d\n", func->num); -@@ -1119,19 +1120,33 @@ static int brcmf_ops_sdio_suspend(struct - bus_if = dev_get_drvdata(dev); - sdiodev = bus_if->bus_priv.sdio; - -- brcmf_sdiod_freezer_on(sdiodev); -- brcmf_sdio_wd_timer(sdiodev->bus, 0); -+ pm_caps = sdio_get_host_pm_caps(func); - -- sdio_flags = MMC_PM_KEEP_POWER; -- if (sdiodev->wowl_enabled) { -- if (sdiodev->settings->bus.sdio.oob_irq_supported) -- enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); -- else -- sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; -+ if (pm_caps & MMC_PM_KEEP_POWER) { -+ /* preserve card power during suspend */ -+ brcmf_sdiod_freezer_on(sdiodev); -+ brcmf_sdio_wd_timer(sdiodev->bus, 0); -+ -+ sdio_flags = MMC_PM_KEEP_POWER; -+ if (sdiodev->wowl_enabled) { -+ if (sdiodev->settings->bus.sdio.oob_irq_supported) -+ enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); -+ else -+ sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; -+ } -+ -+ if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags)) -+ brcmf_err("Failed to set pm_flags %x\n", sdio_flags); -+ -+ } else { -+ /* power will be cut so remove device, probe again in resume */ -+ brcmf_sdiod_intr_unregister(sdiodev); -+ ret = brcmf_sdiod_remove(sdiodev); -+ if (ret) -+ brcmf_err("Failed to remove device on suspend\n"); - } -- if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags)) -- brcmf_err("Failed to set pm_flags %x\n", sdio_flags); -- return 0; -+ -+ return ret; - } - - static int brcmf_ops_sdio_resume(struct device *dev) -@@ -1139,13 +1154,23 @@ static int brcmf_ops_sdio_resume(struct - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; - struct sdio_func *func = container_of(dev, struct sdio_func, dev); -+ mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(func); -+ int ret = 0; - - brcmf_dbg(SDIO, "Enter: F%d\n", func->num); - if (func->num != 2) - return 0; - -- brcmf_sdiod_freezer_off(sdiodev); -- return 0; -+ if (!(pm_caps & MMC_PM_KEEP_POWER)) { -+ /* bus was powered off and device removed, probe again */ -+ ret = brcmf_sdiod_probe(sdiodev); -+ if (ret) -+ brcmf_err("Failed to probe device on resume\n"); -+ } else { -+ brcmf_sdiod_freezer_off(sdiodev); -+ } -+ -+ return ret; - } - - static const struct dev_pm_ops brcmf_sdio_pm_ops = { diff --git a/package/kernel/mac80211/patches/brcm/103-v5.5-brcmfmac-remove-set-but-not-used-variable-mpnum-nsp-.patch b/package/kernel/mac80211/patches/brcm/103-v5.5-brcmfmac-remove-set-but-not-used-variable-mpnum-nsp-.patch deleted file mode 100644 index 25b3ceb959..0000000000 --- a/package/kernel/mac80211/patches/brcm/103-v5.5-brcmfmac-remove-set-but-not-used-variable-mpnum-nsp-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 7af496b9eb0433bc4cb478c9a46f85509cdb5541 Mon Sep 17 00:00:00 2001 -From: zhengbin -Date: Sat, 16 Nov 2019 15:22:47 +0800 -Subject: [PATCH] brcmfmac: remove set but not used variable - 'mpnum','nsp','nmp' - -Fixes gcc '-Wunused-but-set-variable' warning: - -drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c: In function brcmf_chip_dmp_get_regaddr: -drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:790:5: warning: variable mpnum set but not used [-Wunused-but-set-variable] -drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c: In function brcmf_chip_dmp_erom_scan: -drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:866:10: warning: variable nsp set but not used [-Wunused-but-set-variable] -drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c: In function brcmf_chip_dmp_erom_scan: -drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:866:5: warning: variable nmp set but not used [-Wunused-but-set-variable] - -Reported-by: Hulk Robot -Signed-off-by: zhengbin -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -@@ -778,7 +778,6 @@ static int brcmf_chip_dmp_get_regaddr(st - { - u8 desc; - u32 val, szdesc; -- u8 mpnum = 0; - u8 stype, sztype, wraptype; - - *regbase = 0; -@@ -786,7 +785,6 @@ static int brcmf_chip_dmp_get_regaddr(st - - val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc); - if (desc == DMP_DESC_MASTER_PORT) { -- mpnum = (val & DMP_MASTER_PORT_NUM) >> DMP_MASTER_PORT_NUM_S; - wraptype = DMP_SLAVE_TYPE_MWRAP; - } else if (desc == DMP_DESC_ADDRESS) { - /* revert erom address */ -@@ -854,7 +852,7 @@ int brcmf_chip_dmp_erom_scan(struct brcm - u8 desc_type = 0; - u32 val; - u16 id; -- u8 nmp, nsp, nmw, nsw, rev; -+ u8 nmw, nsw, rev; - u32 base, wrap; - int err; - -@@ -880,8 +878,6 @@ int brcmf_chip_dmp_erom_scan(struct brcm - return -EFAULT; - - /* only look at cores with master port(s) */ -- nmp = (val & DMP_COMP_NUM_MPORT) >> DMP_COMP_NUM_MPORT_S; -- nsp = (val & DMP_COMP_NUM_SPORT) >> DMP_COMP_NUM_SPORT_S; - nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S; - nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S; - rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S; diff --git a/package/kernel/mac80211/patches/brcm/112-v5.6-brcmfmac-set-interface-carrier-to-off-by-default.patch b/package/kernel/mac80211/patches/brcm/112-v5.6-brcmfmac-set-interface-carrier-to-off-by-default.patch deleted file mode 100644 index bb4782a7a4..0000000000 --- a/package/kernel/mac80211/patches/brcm/112-v5.6-brcmfmac-set-interface-carrier-to-off-by-default.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 8d9627b05b2c33e4468e65739eb7caf9c3f274d8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 10 Dec 2019 12:35:55 +0100 -Subject: [PATCH] brcmfmac: set interface carrier to off by default -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It's important as brcmfmac creates one main interface for each PHY and -doesn't allow deleting it. Not setting carrier could result in other -subsystems misbehaving (e.g. LEDs "netdev" trigger turning LED on). - -Signed-off-by: Rafał Miłecki -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -678,6 +678,8 @@ int brcmf_net_attach(struct brcmf_if *if - goto fail; - } - -+ netif_carrier_off(ndev); -+ - netdev_set_priv_destructor(ndev, brcmf_cfg80211_free_netdev); - brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); - return 0; diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0001-brcmfmac-reset-two-D11-cores-if-chip-has-two-D11-cor.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0001-brcmfmac-reset-two-D11-cores-if-chip-has-two-D11-cor.patch deleted file mode 100644 index 19bf41ad9b..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0001-brcmfmac-reset-two-D11-cores-if-chip-has-two-D11-cor.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 1b8d2e0a9e4221b99eea375c079507ce8ef655f5 Mon Sep 17 00:00:00 2001 -From: Wright Feng -Date: Thu, 12 Dec 2019 00:52:45 +0100 -Subject: [PATCH 1/7] brcmfmac: reset two D11 cores if chip has two D11 cores - -There are two D11 cores in RSDB chips like 4359. We have to reset two -D11 cores simutaneously before firmware download, or the firmware may -not be initialized correctly and cause "fw initialized failed" error. - -Signed-off-by: Wright Feng -Signed-off-by: Soeren Moch -Reviewed-by: Chi-Hsien Lin -Signed-off-by: Kalle Valo ---- - .../broadcom/brcm80211/brcmfmac/chip.c | 50 +++++++++++++++++++ - .../broadcom/brcm80211/brcmfmac/chip.h | 1 + - .../broadcom/brcm80211/brcmfmac/pcie.c | 2 +- - 3 files changed, 52 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -@@ -433,11 +433,25 @@ static void brcmf_chip_ai_resetcore(stru - { - struct brcmf_chip_priv *ci; - int count; -+ struct brcmf_core *d11core2 = NULL; -+ struct brcmf_core_priv *d11priv2 = NULL; - - ci = core->chip; - -+ /* special handle two D11 cores reset */ -+ if (core->pub.id == BCMA_CORE_80211) { -+ d11core2 = brcmf_chip_get_d11core(&ci->pub, 1); -+ if (d11core2) { -+ brcmf_dbg(INFO, "found two d11 cores, reset both\n"); -+ d11priv2 = container_of(d11core2, -+ struct brcmf_core_priv, pub); -+ } -+ } -+ - /* must disable first to work for arbitrary current core state */ - brcmf_chip_ai_coredisable(core, prereset, reset); -+ if (d11priv2) -+ brcmf_chip_ai_coredisable(d11priv2, prereset, reset); - - count = 0; - while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) & -@@ -449,9 +463,30 @@ static void brcmf_chip_ai_resetcore(stru - usleep_range(40, 60); - } - -+ if (d11priv2) { -+ count = 0; -+ while (ci->ops->read32(ci->ctx, -+ d11priv2->wrapbase + BCMA_RESET_CTL) & -+ BCMA_RESET_CTL_RESET) { -+ ci->ops->write32(ci->ctx, -+ d11priv2->wrapbase + BCMA_RESET_CTL, -+ 0); -+ count++; -+ if (count > 50) -+ break; -+ usleep_range(40, 60); -+ } -+ } -+ - ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, - postreset | BCMA_IOCTL_CLK); - ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); -+ -+ if (d11priv2) { -+ ci->ops->write32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL, -+ postreset | BCMA_IOCTL_CLK); -+ ci->ops->read32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL); -+ } - } - - char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len) -@@ -1109,6 +1144,21 @@ void brcmf_chip_detach(struct brcmf_chip - kfree(chip); - } - -+struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit) -+{ -+ struct brcmf_chip_priv *chip; -+ struct brcmf_core_priv *core; -+ -+ chip = container_of(pub, struct brcmf_chip_priv, pub); -+ list_for_each_entry(core, &chip->cores, list) { -+ if (core->pub.id == BCMA_CORE_80211) { -+ if (unit-- == 0) -+ return &core->pub; -+ } -+ } -+ return NULL; -+} -+ - struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid) - { - struct brcmf_chip_priv *chip; ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h -@@ -74,6 +74,7 @@ struct brcmf_chip *brcmf_chip_attach(voi - const struct brcmf_buscore_ops *ops); - void brcmf_chip_detach(struct brcmf_chip *chip); - struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid); -+struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit); - struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip); - struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub); - bool brcmf_chip_iscoreup(struct brcmf_core *core); ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -@@ -78,7 +78,7 @@ static const struct brcmf_firmware_mappi - BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), - }; - --#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ -+#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */ - - #define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024) - diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0002-brcmfmac-set-F2-blocksize-and-watermark-for-4359.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0002-brcmfmac-set-F2-blocksize-and-watermark-for-4359.patch deleted file mode 100644 index 37ba7f360b..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0002-brcmfmac-set-F2-blocksize-and-watermark-for-4359.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 172f6854551d48d1c9530f84513b421db944e714 Mon Sep 17 00:00:00 2001 -From: Chung-Hsien Hsu -Date: Thu, 12 Dec 2019 00:52:46 +0100 -Subject: [PATCH 2/7] brcmfmac: set F2 blocksize and watermark for 4359 - -Set F2 blocksize to 256 bytes and watermark to 0x40 for 4359. Also -enable and configure F1 MesBusyCtrl. It fixes DMA error while having -UDP bi-directional traffic. - -Signed-off-by: Chung-Hsien Hsu -[slightly adapted for rebase on mainline linux] -Signed-off-by: Soeren Moch -Reviewed-by: Chi-Hsien Lin -Signed-off-by: Kalle Valo ---- - .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 +++++- - .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 15 +++++++++++++++ - 2 files changed, 20 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -@@ -43,6 +43,7 @@ - - #define SDIO_FUNC1_BLOCKSIZE 64 - #define SDIO_FUNC2_BLOCKSIZE 512 -+#define SDIO_4359_FUNC2_BLOCKSIZE 256 - /* Maximum milliseconds to wait for F2 to come up */ - #define SDIO_WAIT_F2RDY 3000 - -@@ -903,6 +904,7 @@ static void brcmf_sdiod_host_fixup(struc - static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) - { - int ret = 0; -+ unsigned int f2_blksz = SDIO_FUNC2_BLOCKSIZE; - - sdio_claim_host(sdiodev->func1); - -@@ -912,7 +914,9 @@ static int brcmf_sdiod_probe(struct brcm - sdio_release_host(sdiodev->func1); - goto out; - } -- ret = sdio_set_block_size(sdiodev->func2, SDIO_FUNC2_BLOCKSIZE); -+ if (sdiodev->func2->device == SDIO_DEVICE_ID_BROADCOM_4359) -+ f2_blksz = SDIO_4359_FUNC2_BLOCKSIZE; -+ ret = sdio_set_block_size(sdiodev->func2, f2_blksz); - if (ret) { - brcmf_err("Failed to set F2 blocksize\n"); - sdio_release_host(sdiodev->func1); ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -42,6 +42,8 @@ - #define DEFAULT_F2_WATERMARK 0x8 - #define CY_4373_F2_WATERMARK 0x40 - #define CY_43012_F2_WATERMARK 0x60 -+#define CY_4359_F2_WATERMARK 0x40 -+#define CY_4359_F1_MESBUSYCTRL (CY_4359_F2_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB) - - #ifdef DEBUG - -@@ -4208,6 +4210,19 @@ static void brcmf_sdio_firmware_callback - brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, - &err); - break; -+ case SDIO_DEVICE_ID_BROADCOM_4359: -+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n", -+ CY_4359_F2_WATERMARK); -+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, -+ CY_4359_F2_WATERMARK, &err); -+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL, -+ &err); -+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB; -+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, -+ &err); -+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, -+ CY_4359_F1_MESBUSYCTRL, &err); -+ break; - default: - brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, - DEFAULT_F2_WATERMARK, &err); diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0003-brcmfmac-fix-rambase-for-4359-9.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0003-brcmfmac-fix-rambase-for-4359-9.patch deleted file mode 100644 index 7e4e32ffdd..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0003-brcmfmac-fix-rambase-for-4359-9.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 6647274ed995a172369cb04754eb5f8b85f68f6d Mon Sep 17 00:00:00 2001 -From: Soeren Moch -Date: Thu, 12 Dec 2019 00:52:47 +0100 -Subject: [PATCH 3/7] brcmfmac: fix rambase for 4359/9 - -Newer 4359 chip revisions need a different rambase address. -This fixes firmware download on such devices which fails otherwise. - -Signed-off-by: Soeren Moch -Acked-by: Chi-Hsien Lin -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -@@ -712,7 +712,6 @@ static u32 brcmf_chip_tcm_rambase(struct - case BRCM_CC_43569_CHIP_ID: - case BRCM_CC_43570_CHIP_ID: - case BRCM_CC_4358_CHIP_ID: -- case BRCM_CC_4359_CHIP_ID: - case BRCM_CC_43602_CHIP_ID: - case BRCM_CC_4371_CHIP_ID: - return 0x180000; -@@ -722,6 +721,8 @@ static u32 brcmf_chip_tcm_rambase(struct - case BRCM_CC_4366_CHIP_ID: - case BRCM_CC_43664_CHIP_ID: - return 0x200000; -+ case BRCM_CC_4359_CHIP_ID: -+ return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; - case CY_CC_4373_CHIP_ID: - return 0x160000; - default: diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch deleted file mode 100644 index cd7ccb0439..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch +++ /dev/null @@ -1,42 +0,0 @@ -From c12c8913d79c49ceccb38f42714d25b783833758 Mon Sep 17 00:00:00 2001 -From: Soeren Moch -Date: Thu, 12 Dec 2019 00:52:48 +0100 -Subject: [PATCH 4/7] brcmfmac: make errors when setting roaming parameters - non-fatal - -4359 dongles do not support setting roaming parameters (error -52). -Do not fail the 80211 configuration in this case. - -Signed-off-by: Soeren Moch -Acked-by: Chi-Hsien Lin -Signed-off-by: Kalle Valo ---- - .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -5944,19 +5944,17 @@ static s32 brcmf_dongle_roam(struct brcm - roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); - err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER, - (void *)roamtrigger, sizeof(roamtrigger)); -- if (err) { -+ if (err) - bphy_err(drvr, "WLC_SET_ROAM_TRIGGER error (%d)\n", err); -- goto roam_setup_done; -- } - - roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); - roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); - err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA, - (void *)roam_delta, sizeof(roam_delta)); -- if (err) { -+ if (err) - bphy_err(drvr, "WLC_SET_ROAM_DELTA error (%d)\n", err); -- goto roam_setup_done; -- } -+ -+ return 0; - - roam_setup_done: - return err; diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0005-brcmfmac-add-support-for-BCM4359-SDIO-chipset.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0005-brcmfmac-add-support-for-BCM4359-SDIO-chipset.patch deleted file mode 100644 index 0001fb17a7..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0005-brcmfmac-add-support-for-BCM4359-SDIO-chipset.patch +++ /dev/null @@ -1,75 +0,0 @@ -From d4aef159394d5940bd7158ab789969dab82f7c76 Mon Sep 17 00:00:00 2001 -From: Soeren Moch -Date: Thu, 12 Dec 2019 00:52:49 +0100 -Subject: [PATCH 5/7] brcmfmac: add support for BCM4359 SDIO chipset - -BCM4359 is a 2x2 802.11 abgn+ac Dual-Band HT80 combo chip and it -supports Real Simultaneous Dual Band feature. - -Based on a similar patch by: Wright Feng - -Signed-off-by: Soeren Moch -Acked-by: Chi-Hsien Lin -Acked-by: Ulf Hansson -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 ++ - drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + - drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ - include/linux/mmc/sdio_ids.h | 2 ++ - 4 files changed, 7 insertions(+) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -@@ -973,8 +973,10 @@ static const struct sdio_device_id brcmf - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455), - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356), -+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359), - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_4373), - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_43012), -+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_89359), - { /* end: all zeroes */ } - }; - MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c -@@ -1408,6 +1408,7 @@ bool brcmf_chip_sr_capable(struct brcmf_ - addr = CORE_CC_REG(base, sr_control0); - reg = chip->ops->read32(chip->ctx, addr); - return (reg & CC_SR_CTL0_ENABLE_MASK) != 0; -+ case BRCM_CC_4359_CHIP_ID: - case CY_CC_43012_CHIP_ID: - addr = CORE_CC_REG(pmu->base, retention_ctl); - reg = chip->ops->read32(chip->ctx, addr); ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -616,6 +616,7 @@ BRCMF_FW_DEF(43455, "brcmfmac43455-sdio" - BRCMF_FW_DEF(43456, "brcmfmac43456-sdio"); - BRCMF_FW_DEF(4354, "brcmfmac4354-sdio"); - BRCMF_FW_DEF(4356, "brcmfmac4356-sdio"); -+BRCMF_FW_DEF(4359, "brcmfmac4359-sdio"); - BRCMF_FW_DEF(4373, "brcmfmac4373-sdio"); - BRCMF_FW_DEF(43012, "brcmfmac43012-sdio"); - -@@ -638,6 +639,7 @@ static const struct brcmf_firmware_mappi - BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455), - BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), - BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), -+ BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), - BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373), - BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012) - }; ---- a/include/linux/mmc/sdio_ids.h -+++ b/include/linux/mmc/sdio_ids.h -@@ -41,8 +41,10 @@ - #define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf - #define SDIO_DEVICE_ID_BROADCOM_4354 0x4354 - #define SDIO_DEVICE_ID_BROADCOM_4356 0x4356 -+#define SDIO_DEVICE_ID_BROADCOM_4359 0x4359 - #define SDIO_DEVICE_ID_CYPRESS_4373 0x4373 - #define SDIO_DEVICE_ID_CYPRESS_43012 43012 -+#define SDIO_DEVICE_ID_CYPRESS_89359 0x4355 - - #define SDIO_VENDOR_ID_INTEL 0x0089 - #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402 diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch deleted file mode 100644 index d00c59c07c..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 837482e69a3f0d7cbc73922020012f83635f5ddb Mon Sep 17 00:00:00 2001 -From: Wright Feng -Date: Thu, 12 Dec 2019 00:52:50 +0100 -Subject: [PATCH 6/7] brcmfmac: add RSDB condition when setting interface - combinations - -With firmware RSDB feature -1. The maximum support interface is four. -2. The maximum difference channel is two. -3. The maximum interfaces of {station/p2p client/AP} are two. -4. The maximum interface of p2p device is one. - -Signed-off-by: Wright Feng -Signed-off-by: Soeren Moch -Reviewed-by: Chi-Hsien Lin -Signed-off-by: Kalle Valo ---- - .../broadcom/brcm80211/brcmfmac/cfg80211.c | 54 ++++++++++++++++--- - 1 file changed, 46 insertions(+), 8 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6452,6 +6452,9 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = - * #STA <= 1, #AP <= 1, channels = 1, 2 total - * #AP <= 4, matching BI, channels = 1, 4 total - * -+ * no p2p and rsdb: -+ * #STA <= 2, #AP <= 2, channels = 2, 4 total -+ * - * p2p, no mchan, and mbss: - * - * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total -@@ -6463,6 +6466,10 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = - * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total - * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total - * #AP <= 4, matching BI, channels = 1, 4 total -+ * -+ * p2p, rsdb, and no mbss: -+ * #STA <= 2, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 2, AP <= 2, -+ * channels = 2, 4 total - */ - static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) - { -@@ -6470,13 +6477,14 @@ static int brcmf_setup_ifmodes(struct wi - struct ieee80211_iface_limit *c0_limits = NULL; - struct ieee80211_iface_limit *p2p_limits = NULL; - struct ieee80211_iface_limit *mbss_limits = NULL; -- bool mbss, p2p; -+ bool mbss, p2p, rsdb; - int i, c, n_combos; - - mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); - p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); -+ rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); - -- n_combos = 1 + !!p2p + !!mbss; -+ n_combos = 1 + !!(p2p && !rsdb) + !!mbss; - combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL); - if (!combo) - goto err; -@@ -6487,16 +6495,36 @@ static int brcmf_setup_ifmodes(struct wi - - c = 0; - i = 0; -- c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL); -+ if (p2p && rsdb) -+ c0_limits = kcalloc(4, sizeof(*c0_limits), GFP_KERNEL); -+ else if (p2p) -+ c0_limits = kcalloc(3, sizeof(*c0_limits), GFP_KERNEL); -+ else -+ c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); - if (!c0_limits) - goto err; -- c0_limits[i].max = 1; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -- if (p2p) { -+ if (p2p && rsdb) { -+ combo[c].num_different_channels = 2; -+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | -+ BIT(NL80211_IFTYPE_P2P_GO) | -+ BIT(NL80211_IFTYPE_P2P_DEVICE); -+ c0_limits[i].max = 2; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -+ c0_limits[i].max = 1; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); -+ c0_limits[i].max = 2; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | -+ BIT(NL80211_IFTYPE_P2P_GO); -+ c0_limits[i].max = 2; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); -+ combo[c].max_interfaces = 5; -+ } else if (p2p) { - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) - combo[c].num_different_channels = 2; - else - combo[c].num_different_channels = 1; -+ c0_limits[i].max = 1; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); - wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_DEVICE); -@@ -6505,16 +6533,26 @@ static int brcmf_setup_ifmodes(struct wi - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); -+ combo[c].max_interfaces = i; -+ } else if (rsdb) { -+ combo[c].num_different_channels = 2; -+ c0_limits[i].max = 2; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -+ c0_limits[i].max = 2; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); -+ combo[c].max_interfaces = 3; - } else { - combo[c].num_different_channels = 1; - c0_limits[i].max = 1; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -+ c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); -+ combo[c].max_interfaces = i; - } -- combo[c].max_interfaces = i; - combo[c].n_limits = i; - combo[c].limits = c0_limits; - -- if (p2p) { -+ if (p2p && !rsdb) { - c++; - i = 0; - p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL); diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch deleted file mode 100644 index 9c211a68d0..0000000000 --- a/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 2635853ce4ab7654a77ab7080fb56de83408606b Mon Sep 17 00:00:00 2001 -From: Wright Feng -Date: Thu, 12 Dec 2019 00:52:51 +0100 -Subject: [PATCH 7/7] brcmfmac: not set mbss in vif if firmware does not - support MBSS - -With RSDB mode, FMAC and firmware are able to create 2 or more AP, -so we should not set mbss in vif structure if firmware does not -support MBSS feature. - -Signed-off-by: Wright Feng -Signed-off-by: Soeren Moch -Reviewed-by: Chi-Hsien Lin -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -5301,6 +5301,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v - struct brcmf_cfg80211_vif *vif_walk; - struct brcmf_cfg80211_vif *vif; - bool mbss; -+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); - - brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n", - sizeof(*vif)); -@@ -5313,7 +5314,8 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v - - brcmf_init_prof(&vif->profile); - -- if (type == NL80211_IFTYPE_AP) { -+ if (type == NL80211_IFTYPE_AP && -+ brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { - mbss = false; - list_for_each_entry(vif_walk, &cfg->vif_list, list) { - if (vif_walk->wdev.iftype == NL80211_IFTYPE_AP) { diff --git a/package/kernel/mac80211/patches/brcm/116-v5.6-brcmfmac-Keep-OOB-wake-interrupt-disabled-when-it-sh.patch b/package/kernel/mac80211/patches/brcm/116-v5.6-brcmfmac-Keep-OOB-wake-interrupt-disabled-when-it-sh.patch deleted file mode 100644 index f579e16a7f..0000000000 --- a/package/kernel/mac80211/patches/brcm/116-v5.6-brcmfmac-Keep-OOB-wake-interrupt-disabled-when-it-sh.patch +++ /dev/null @@ -1,66 +0,0 @@ -From a32de68edab7b73ded850bcf76cdf6858e92a7e5 Mon Sep 17 00:00:00 2001 -From: Dmitry Osipenko -Date: Sun, 15 Dec 2019 21:42:24 +0300 -Subject: [PATCH] brcmfmac: Keep OOB wake-interrupt disabled when it shouldn't - be enabled - -NVIDIA Tegra SoCs do not like when OOB wake is enabled and WiFi interface -is in DOWN state during suspend. This results in a CPU hang on programming -OOB wake-up state of the GPIO controller during of system's suspend. - -The solution is trivial: don't enable wake for the OOB interrupt when it -should be disabled. - -This fixes hang on Tegra20 (Acer A500) and Tegra30 (Nexus 7) devices which -are using BCM4329 and BCM4330 WiFi chips respectively. - -Signed-off-by: Dmitry Osipenko -Signed-off-by: Kalle Valo ---- - .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 10 +++++----- - .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 - - 2 files changed, 5 insertions(+), 6 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -@@ -120,7 +120,7 @@ int brcmf_sdiod_intr_register(struct brc - brcmf_err("enable_irq_wake failed %d\n", ret); - return ret; - } -- sdiodev->irq_wake = true; -+ disable_irq_wake(pdata->oob_irq_nr); - - sdio_claim_host(sdiodev->func1); - -@@ -179,10 +179,6 @@ void brcmf_sdiod_intr_unregister(struct - sdio_release_host(sdiodev->func1); - - sdiodev->oob_irq_requested = false; -- if (sdiodev->irq_wake) { -- disable_irq_wake(pdata->oob_irq_nr); -- sdiodev->irq_wake = false; -- } - free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev); - sdiodev->irq_en = false; - sdiodev->oob_irq_requested = false; -@@ -1173,6 +1169,10 @@ static int brcmf_ops_sdio_resume(struct - if (ret) - brcmf_err("Failed to probe device on resume\n"); - } else { -+ if (sdiodev->wowl_enabled && -+ sdiodev->settings->bus.sdio.oob_irq_supported) -+ disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); -+ - brcmf_sdiod_freezer_off(sdiodev); - } - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h -@@ -178,7 +178,6 @@ struct brcmf_sdio_dev { - bool sd_irq_requested; - bool irq_en; /* irq enable flags */ - spinlock_t irq_en_lock; -- bool irq_wake; /* irq wake enable flags */ - bool sg_support; - uint max_request_size; - ushort max_segment_count; diff --git a/package/kernel/mac80211/patches/brcm/117-v5.6-brcmfmac-use-true-false-for-bool-variable.patch b/package/kernel/mac80211/patches/brcm/117-v5.6-brcmfmac-use-true-false-for-bool-variable.patch deleted file mode 100644 index 0eb169c2d3..0000000000 --- a/package/kernel/mac80211/patches/brcm/117-v5.6-brcmfmac-use-true-false-for-bool-variable.patch +++ /dev/null @@ -1,27 +0,0 @@ -From b92c017deda819e45a0f054f6df6b53e645d7fe4 Mon Sep 17 00:00:00 2001 -From: zhengbin -Date: Tue, 24 Dec 2019 22:16:06 +0800 -Subject: [PATCH] brcmfmac: use true,false for bool variable - -Fixes coccicheck warning: - -drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c:911:2-24: WARNING: Assignment of 0/1 to bool variable - -Reported-by: Hulk Robot -Signed-off-by: zhengbin -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c -@@ -908,7 +908,7 @@ static u8 brcmf_fws_hdrpush(struct brcmf - wlh += wlh[1] + 2; - - if (entry->send_tim_signal) { -- entry->send_tim_signal = 0; -+ entry->send_tim_signal = false; - wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; - wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; - wlh[2] = entry->mac_handle; diff --git a/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch b/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch deleted file mode 100644 index d52a7a1cc0..0000000000 --- a/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 24332f8068ff6df7f16aefee45d514de1de4de80 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 26 Dec 2019 14:30:49 +0100 -Subject: [PATCH] brcmfmac: simplify building interface combinations -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Move similar/duplicated code out of combination specific code blocks. -This simplifies code a bit and allows adding more combinations later. -A list of combinations remains unchanged. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Kalle Valo ---- - .../broadcom/brcm80211/brcmfmac/cfg80211.c | 43 ++++++------------- - 1 file changed, 14 insertions(+), 29 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6479,12 +6479,13 @@ static int brcmf_setup_ifmodes(struct wi - struct ieee80211_iface_limit *c0_limits = NULL; - struct ieee80211_iface_limit *p2p_limits = NULL; - struct ieee80211_iface_limit *mbss_limits = NULL; -- bool mbss, p2p, rsdb; -+ bool mbss, p2p, rsdb, mchan; - int i, c, n_combos; - - mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); - p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); - rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); -+ mchan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN); - - n_combos = 1 + !!(p2p && !rsdb) + !!mbss; - combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL); -@@ -6494,6 +6495,10 @@ static int brcmf_setup_ifmodes(struct wi - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); -+ if (p2p) -+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | -+ BIT(NL80211_IFTYPE_P2P_GO) | -+ BIT(NL80211_IFTYPE_P2P_DEVICE); - - c = 0; - i = 0; -@@ -6505,48 +6510,28 @@ static int brcmf_setup_ifmodes(struct wi - c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); - if (!c0_limits) - goto err; -- if (p2p && rsdb) { -- combo[c].num_different_channels = 2; -- wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | -- BIT(NL80211_IFTYPE_P2P_GO) | -- BIT(NL80211_IFTYPE_P2P_DEVICE); -- c0_limits[i].max = 2; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -+ -+ combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan)); -+ c0_limits[i].max = 1 + rsdb; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -+ if (p2p) { - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); -- c0_limits[i].max = 2; -+ c0_limits[i].max = 1 + rsdb; - c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); -+ } -+ if (p2p && rsdb) { - c0_limits[i].max = 2; - c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); - combo[c].max_interfaces = 5; - } else if (p2p) { -- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) -- combo[c].num_different_channels = 2; -- else -- combo[c].num_different_channels = 1; -- c0_limits[i].max = 1; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -- wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | -- BIT(NL80211_IFTYPE_P2P_GO) | -- BIT(NL80211_IFTYPE_P2P_DEVICE); -- c0_limits[i].max = 1; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); -- c0_limits[i].max = 1; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | -- BIT(NL80211_IFTYPE_P2P_GO); - combo[c].max_interfaces = i; - } else if (rsdb) { -- combo[c].num_different_channels = 2; -- c0_limits[i].max = 2; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); - c0_limits[i].max = 2; - c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); - combo[c].max_interfaces = 3; - } else { -- combo[c].num_different_channels = 1; -- c0_limits[i].max = 1; -- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); - combo[c].max_interfaces = i; diff --git a/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch b/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch deleted file mode 100644 index 08fa1544ec..0000000000 --- a/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch +++ /dev/null @@ -1,345 +0,0 @@ -From 20f2c5fa3af060401c72e444999470a4cab641cf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 26 Dec 2019 14:30:50 +0100 -Subject: [PATCH] brcmfmac: add initial support for monitor mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Report monitor interface availability using cfg80211 and support it in -the add_virtual_intf() and del_virtual_intf() callbacks. This new -feature is conditional and depends on firmware flagging monitor packets. -Receiving monitor frames is already handled by the brcmf_netif_mon_rx(). - -Signed-off-by: Rafał Miłecki -Signed-off-by: Kalle Valo ---- - .../broadcom/brcm80211/brcmfmac/cfg80211.c | 112 ++++++++++++++++-- - .../broadcom/brcm80211/brcmfmac/core.c | 68 ++++++++++- - .../broadcom/brcm80211/brcmfmac/core.h | 2 + - .../broadcom/brcm80211/brcmfmac/feature.c | 1 + - .../broadcom/brcm80211/brcmfmac/feature.h | 2 + - .../broadcom/brcm80211/brcmfmac/fwil.h | 2 + - 6 files changed, 174 insertions(+), 13 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -619,6 +620,82 @@ static bool brcmf_is_ibssmode(struct brc - return vif->wdev.iftype == NL80211_IFTYPE_ADHOC; - } - -+/** -+ * brcmf_mon_add_vif() - create monitor mode virtual interface -+ * -+ * @wiphy: wiphy device of new interface. -+ * @name: name of the new interface. -+ */ -+static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy, -+ const char *name) -+{ -+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); -+ struct brcmf_cfg80211_vif *vif; -+ struct net_device *ndev; -+ struct brcmf_if *ifp; -+ int err; -+ -+ if (cfg->pub->mon_if) { -+ err = -EEXIST; -+ goto err_out; -+ } -+ -+ vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_MONITOR); -+ if (IS_ERR(vif)) { -+ err = PTR_ERR(vif); -+ goto err_out; -+ } -+ -+ ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, ether_setup); -+ if (!ndev) { -+ err = -ENOMEM; -+ goto err_free_vif; -+ } -+ ndev->type = ARPHRD_IEEE80211_RADIOTAP; -+ ndev->ieee80211_ptr = &vif->wdev; -+ ndev->needs_free_netdev = true; -+ ndev->priv_destructor = brcmf_cfg80211_free_netdev; -+ SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); -+ -+ ifp = netdev_priv(ndev); -+ ifp->vif = vif; -+ ifp->ndev = ndev; -+ ifp->drvr = cfg->pub; -+ -+ vif->ifp = ifp; -+ vif->wdev.netdev = ndev; -+ -+ err = brcmf_net_mon_attach(ifp); -+ if (err) { -+ brcmf_err("Failed to attach %s device\n", ndev->name); -+ free_netdev(ndev); -+ goto err_free_vif; -+ } -+ -+ cfg->pub->mon_if = ifp; -+ -+ return &vif->wdev; -+ -+err_free_vif: -+ brcmf_free_vif(vif); -+err_out: -+ return ERR_PTR(err); -+} -+ -+static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) -+{ -+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); -+ struct net_device *ndev = wdev->netdev; -+ -+ ndev->netdev_ops->ndo_stop(ndev); -+ -+ brcmf_net_detach(ndev, true); -+ -+ cfg->pub->mon_if = NULL; -+ -+ return 0; -+} -+ - static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, - const char *name, - unsigned char name_assign_type, -@@ -641,9 +718,10 @@ static struct wireless_dev *brcmf_cfg802 - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: -- case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - return ERR_PTR(-EOPNOTSUPP); -+ case NL80211_IFTYPE_MONITOR: -+ return brcmf_mon_add_vif(wiphy, name); - case NL80211_IFTYPE_AP: - wdev = brcmf_ap_add_vif(wiphy, name, params); - break; -@@ -826,9 +904,10 @@ int brcmf_cfg80211_del_iface(struct wiph - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: -- case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - return -EOPNOTSUPP; -+ case NL80211_IFTYPE_MONITOR: -+ return brcmf_mon_del_vif(wiphy, wdev); - case NL80211_IFTYPE_AP: - return brcmf_cfg80211_del_ap_iface(wiphy, wdev); - case NL80211_IFTYPE_P2P_CLIENT: -@@ -6479,9 +6558,10 @@ static int brcmf_setup_ifmodes(struct wi - struct ieee80211_iface_limit *c0_limits = NULL; - struct ieee80211_iface_limit *p2p_limits = NULL; - struct ieee80211_iface_limit *mbss_limits = NULL; -- bool mbss, p2p, rsdb, mchan; -- int i, c, n_combos; -+ bool mon_flag, mbss, p2p, rsdb, mchan; -+ int i, c, n_combos, n_limits; - -+ mon_flag = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FLAG); - mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); - p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); - rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); -@@ -6495,6 +6575,8 @@ static int brcmf_setup_ifmodes(struct wi - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); -+ if (mon_flag) -+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); - if (p2p) - wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | -@@ -6502,18 +6584,18 @@ static int brcmf_setup_ifmodes(struct wi - - c = 0; - i = 0; -- if (p2p && rsdb) -- c0_limits = kcalloc(4, sizeof(*c0_limits), GFP_KERNEL); -- else if (p2p) -- c0_limits = kcalloc(3, sizeof(*c0_limits), GFP_KERNEL); -- else -- c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); -+ n_limits = 1 + mon_flag + (p2p ? 2 : 0) + (rsdb || !p2p); -+ c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL); - if (!c0_limits) - goto err; - - combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan)); - c0_limits[i].max = 1 + rsdb; - c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); -+ if (mon_flag) { -+ c0_limits[i].max = 1; -+ c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); -+ } - if (p2p) { - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); -@@ -6562,14 +6644,20 @@ static int brcmf_setup_ifmodes(struct wi - if (mbss) { - c++; - i = 0; -- mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL); -+ n_limits = 1 + mon_flag; -+ mbss_limits = kcalloc(n_limits, sizeof(*mbss_limits), -+ GFP_KERNEL); - if (!mbss_limits) - goto err; - mbss_limits[i].max = 4; - mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP); -+ if (mon_flag) { -+ mbss_limits[i].max = 1; -+ mbss_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); -+ } - combo[c].beacon_int_infra_match = true; - combo[c].num_different_channels = 1; -- combo[c].max_interfaces = 4; -+ combo[c].max_interfaces = 4 + mon_flag; - combo[c].n_limits = i; - combo[c].limits = mbss_limits; - } ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -690,7 +690,7 @@ fail: - return -EBADE; - } - --static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) -+void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) - { - if (ndev->reg_state == NETREG_REGISTERED) { - if (rtnl_locked) -@@ -703,6 +703,72 @@ static void brcmf_net_detach(struct net_ - } - } - -+static int brcmf_net_mon_open(struct net_device *ndev) -+{ -+ struct brcmf_if *ifp = netdev_priv(ndev); -+ struct brcmf_pub *drvr = ifp->drvr; -+ u32 monitor; -+ int err; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_MONITOR, &monitor); -+ if (err) { -+ bphy_err(drvr, "BRCMF_C_GET_MONITOR error (%d)\n", err); -+ return err; -+ } else if (monitor) { -+ bphy_err(drvr, "Monitor mode is already enabled\n"); -+ return -EEXIST; -+ } -+ -+ monitor = 3; -+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); -+ if (err) -+ bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err); -+ -+ return err; -+} -+ -+static int brcmf_net_mon_stop(struct net_device *ndev) -+{ -+ struct brcmf_if *ifp = netdev_priv(ndev); -+ struct brcmf_pub *drvr = ifp->drvr; -+ u32 monitor; -+ int err; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ monitor = 0; -+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); -+ if (err) -+ bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err); -+ -+ return err; -+} -+ -+static const struct net_device_ops brcmf_netdev_ops_mon = { -+ .ndo_open = brcmf_net_mon_open, -+ .ndo_stop = brcmf_net_mon_stop, -+}; -+ -+int brcmf_net_mon_attach(struct brcmf_if *ifp) -+{ -+ struct brcmf_pub *drvr = ifp->drvr; -+ struct net_device *ndev; -+ int err; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ ndev = ifp->ndev; -+ ndev->netdev_ops = &brcmf_netdev_ops_mon; -+ -+ err = register_netdevice(ndev); -+ if (err) -+ bphy_err(drvr, "Failed to register %s device\n", ndev->name); -+ -+ return err; -+} -+ - void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) - { - struct net_device *ndev; ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h -@@ -210,6 +210,8 @@ void brcmf_txflowblock_if(struct brcmf_i - void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); - void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); - void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb); -+void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked); -+int brcmf_net_mon_attach(struct brcmf_if *ifp); - void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); - int __init brcmf_core_init(void); - void __exit brcmf_core_exit(void); ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c -@@ -38,6 +38,7 @@ static const struct brcmf_feat_fwcap brc - { BRCMF_FEAT_MCHAN, "mchan" }, - { BRCMF_FEAT_P2P, "p2p" }, - { BRCMF_FEAT_MONITOR, "monitor" }, -+ { BRCMF_FEAT_MONITOR_FLAG, "rtap" }, - { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" }, - { BRCMF_FEAT_DOT11H, "802.11h" } - }; ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h -@@ -23,6 +23,7 @@ - * GSCAN: enhanced scan offload feature. - * FWSUP: Firmware supplicant. - * MONITOR: firmware can pass monitor packets to host. -+ * MONITOR_FLAG: firmware flags monitor packets. - * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header - * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header - * DOT11H: firmware supports 802.11h -@@ -43,6 +44,7 @@ - BRCMF_FEAT_DEF(GSCAN) \ - BRCMF_FEAT_DEF(FWSUP) \ - BRCMF_FEAT_DEF(MONITOR) \ -+ BRCMF_FEAT_DEF(MONITOR_FLAG) \ - BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \ - BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \ - BRCMF_FEAT_DEF(DOT11H) ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h -@@ -49,6 +49,8 @@ - #define BRCMF_C_GET_PM 85 - #define BRCMF_C_SET_PM 86 - #define BRCMF_C_GET_REVINFO 98 -+#define BRCMF_C_GET_MONITOR 107 -+#define BRCMF_C_SET_MONITOR 108 - #define BRCMF_C_GET_CURR_RATESET 114 - #define BRCMF_C_GET_AP 117 - #define BRCMF_C_SET_AP 118 diff --git a/package/kernel/mac80211/patches/brcm/120-v5.6-brcmfmac-Remove-always-false-idx-0-statement.patch b/package/kernel/mac80211/patches/brcm/120-v5.6-brcmfmac-Remove-always-false-idx-0-statement.patch deleted file mode 100644 index 9efa762830..0000000000 --- a/package/kernel/mac80211/patches/brcm/120-v5.6-brcmfmac-Remove-always-false-idx-0-statement.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 627b0d094240c38393b2f2d40626c33a8fff6103 Mon Sep 17 00:00:00 2001 -From: yuehaibing -Date: Wed, 8 Jan 2020 21:57:48 +0800 -Subject: [PATCH] brcmfmac: Remove always false 'idx < 0' statement - -idx is declared as u32, it will never less than 0. - -Signed-off-by: yuehaibing -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c -@@ -365,7 +365,7 @@ brcmf_msgbuf_get_pktid(struct device *de - struct brcmf_msgbuf_pktid *pktid; - struct sk_buff *skb; - -- if (idx < 0 || idx >= pktids->array_size) { -+ if (idx >= pktids->array_size) { - brcmf_err("Invalid packet id %d (max %d)\n", idx, - pktids->array_size); - return NULL; diff --git a/package/kernel/mac80211/patches/brcm/300-brcmfmac-add-stub-for-monitor-interface-xmit.patch b/package/kernel/mac80211/patches/brcm/300-brcmfmac-add-stub-for-monitor-interface-xmit.patch deleted file mode 100644 index 8280918fa2..0000000000 --- a/package/kernel/mac80211/patches/brcm/300-brcmfmac-add-stub-for-monitor-interface-xmit.patch +++ /dev/null @@ -1,100 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 27 Mar 2020 13:40:50 +0100 -Subject: [PATCH] brcmfmac: add stub for monitor interface xmit -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -According to the struct net_device_ops documentation .ndo_start_xmit is -"Required; cannot be NULL.". Missing it may crash kernel easily: - -[ 341.216709] Unable to handle kernel NULL pointer dereference at virtual address 00000000 -[ 341.224836] pgd = 26088755 -[ 341.227544] [00000000] *pgd=00000000 -[ 341.231135] Internal error: Oops: 80000007 [#1] SMP ARM -[ 341.236367] Modules linked in: pppoe ppp_async iptable_nat brcmfmac xt_state xt_nat xt_conntrack xt_REDIRECT xt_MASQU -[ 341.304689] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.24 #0 -[ 341.310621] Hardware name: BCM5301X -[ 341.314116] PC is at 0x0 -[ 341.316664] LR is at dev_hard_start_xmit+0x8c/0x11c -[ 341.321546] pc : [<00000000>] lr : [] psr: 60000113 -[ 341.327821] sp : c0801c30 ip : c610cf00 fp : c08048e4 -[ 341.333051] r10: c073a63a r9 : c08044dc r8 : c6c04e00 -[ 341.338283] r7 : 00000000 r6 : c60f5000 r5 : 00000000 r4 : c6a9c3c0 -[ 341.344820] r3 : 00000000 r2 : bf25a13c r1 : c60f5000 r0 : c6a9c3c0 -[ 341.351358] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none -[ 341.358504] Control: 10c5387d Table: 0611c04a DAC: 00000051 -[ 341.364257] Process swapper/0 (pid: 0, stack limit = 0xc68ed0ca) -[ 341.370271] Stack: (0xc0801c30 to 0xc0802000) -[ 341.374633] 1c20: c6e7d480 c0802d00 c60f5050 c0801c6c -[ 341.382825] 1c40: c60f5000 c6a9c3c0 c6f90000 c6f9005c c6c04e00 c60f5000 00000000 c6f9005c -[ 341.391015] 1c60: 00000000 c04a033c 00f90200 00000010 c6a9c3c0 c6a9c3c0 c6f90000 00000000 -[ 341.399205] 1c80: 00000000 00000000 00000000 c046a7ac c6f9005c 00000001 fffffff4 00000000 -[ 341.407395] 1ca0: c6f90200 00000000 c60f5000 c0479550 00000000 c6f90200 c6a9c3c0 16000000 -[ 341.415586] 1cc0: 0000001c 6f4ad52f c6197040 b6df9387 36000000 c0520404 c073a80c c6a9c3c0 -[ 341.423777] 1ce0: 00000000 c6d643c0 c6a9c3c0 c0800024 00000001 00000001 c6d643c8 c6a9c3c0 -[ 341.431967] 1d00: c081b9c0 c7abca80 c610c840 c081b9c0 0000001c 00400000 c6bc5e6c c0522fb4 -[ 341.440157] 1d20: c6d64400 00000004 c6bc5e0a 00000000 c60f5000 c7abca80 c081b9c0 c0522f54 -[ 341.448348] 1d40: c6a9c3c0 c7abca80 c0803e48 c0549c94 c610c828 0000000a c0801d74 00000003 -[ 341.456538] 1d60: c6ec8f0a 00000000 c60f5000 c7abca80 c081b9c0 c0548520 0000000a 00000000 -[ 341.464728] 1d80: 00000000 003a0000 00000000 00000000 00000000 00000000 00000000 00000000 -[ 341.472919] 1da0: 000002ff 00000000 00000000 16000000 00000000 00000000 00000000 00000000 -[ 341.481110] 1dc0: 00000000 0000008f 00000000 00000000 00000000 2d132a69 c6bc5e40 00000000 -[ 341.489300] 1de0: c6bc5e40 c6a9c3c0 00000000 c6ec8e50 00000001 c054b070 00000001 00000000 -[ 341.497490] 1e00: c0807200 c6bc5e00 00000000 ffffe000 00000100 c054aea4 00000000 00000000 -[ 341.505681] 1e20: 00000122 00400000 c0802d00 c0172e80 6f56a70e ffffffff 6f56a70e c7eb9cc0 -[ 341.513871] 1e40: c7eb82c0 00000000 c0801e60 c017309c 00000000 00000000 07780000 c07382c0 -[ 341.522061] 1e60: 00000000 c7eb9cc0 c0739cc0 c0803f74 c0801e70 c0801e70 c0801ea4 c013d380 -[ 341.530253] 1e80: 00000000 000000a0 00000001 c0802084 c0802080 40000001 ffffe000 00000100 -[ 341.538443] 1ea0: c0802080 c01021e8 c8803100 10c5387d 00000000 c07341f0 c0739880 0000000a -[ 341.546633] 1ec0: c0734180 00001017 c0802d00 c062aa98 00200002 c062aa60 c8803100 c073984c -[ 341.554823] 1ee0: 00000000 00000001 00000000 c7810000 c8803100 10c5387d 00000000 c011c188 -[ 341.563014] 1f00: c073984c c015f0f8 c0804244 c0815ae4 c880210c c8802100 c0801f40 c037c584 -[ 341.571204] 1f20: c01035f8 60000013 ffffffff c0801f74 c080afd4 c0800000 10c5387d c0101a8c -[ 341.579395] 1f40: 00000000 004ac9dc c7eba4b4 c010ee60 ffffe000 c0803e68 c0803ea8 00000001 -[ 341.587587] 1f60: c080afd4 c062ca20 10c5387d 00000000 00000000 c0801f90 c01035f4 c01035f8 -[ 341.595776] 1f80: 60000013 ffffffff 00000051 00000000 ffffe000 c013ff50 000000ce c0803e40 -[ 341.603967] 1fa0: c082216c 00000000 00000001 c072ba38 10c5387d c0140214 c0822184 c0700df8 -[ 341.612157] 1fc0: ffffffff ffffffff 00000000 c070058c c072ba38 2d162e71 00000000 c0700330 -[ 341.620348] 1fe0: 00000051 10c0387d 000000ff 00a521d0 413fc090 00000000 00000000 00000000 -[ 341.628558] [] (dev_hard_start_xmit) from [] (sch_direct_xmit+0xe4/0x2bc) -[ 341.637106] [] (sch_direct_xmit) from [] (__dev_queue_xmit+0x6a4/0x72c) -[ 341.645481] [] (__dev_queue_xmit) from [] (ip6_finish_output2+0x18c/0x434) -[ 341.654112] [] (ip6_finish_output2) from [] (ip6_output+0x5c/0xd0) -[ 341.662053] [] (ip6_output) from [] (mld_sendpack+0x1a0/0x1a8) -[ 341.669640] [] (mld_sendpack) from [] (mld_ifc_timer_expire+0x1cc/0x2e4) -[ 341.678111] [] (mld_ifc_timer_expire) from [] (call_timer_fn.constprop.3+0x24/0x98) -[ 341.687527] [] (call_timer_fn.constprop.3) from [] (run_timer_softirq+0x1a8/0x1e4) -[ 341.696860] [] (run_timer_softirq) from [] (__do_softirq+0x120/0x2b0) -[ 341.705066] [] (__do_softirq) from [] (irq_exit+0x78/0x84) -[ 341.712317] [] (irq_exit) from [] (__handle_domain_irq+0x60/0xb4) -[ 341.720179] [] (__handle_domain_irq) from [] (gic_handle_irq+0x4c/0x90) -[ 341.728549] [] (gic_handle_irq) from [] (__irq_svc+0x6c/0x90) - -Fixes: 20f2c5fa3af0 ("brcmfmac: add initial support for monitor mode") -Signed-off-by: Rafał Miłecki ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -746,9 +746,18 @@ static int brcmf_net_mon_stop(struct net - return err; - } - -+static netdev_tx_t brcmf_net_mon_start_xmit(struct sk_buff *skb, -+ struct net_device *ndev) -+{ -+ dev_kfree_skb_any(skb); -+ -+ return NETDEV_TX_OK; -+} -+ - static const struct net_device_ops brcmf_netdev_ops_mon = { - .ndo_open = brcmf_net_mon_open, - .ndo_stop = brcmf_net_mon_stop, -+ .ndo_start_xmit = brcmf_net_mon_start_xmit, - }; - - int brcmf_net_mon_attach(struct brcmf_if *ifp) diff --git a/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch b/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch index b3f30943ab..09ef50526f 100644 --- a/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch +++ b/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch @@ -22,7 +22,7 @@ static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); MODULE_PARM_DESC(bad_frames_preempt, -@@ -2867,10 +2872,10 @@ static int b43_gpio_init(struct b43_wlde +@@ -2869,10 +2874,10 @@ static int b43_gpio_init(struct b43_wlde u32 mask, set; b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); diff --git a/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch b/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch index a8dbefb5d9..e395d48202 100644 --- a/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch +++ b/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch @@ -11,7 +11,7 @@ b43-$(CPTCFG_B43_LEDS) += leds.o --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c -@@ -2000,10 +2000,12 @@ static void b43_do_interrupt_thread(stru +@@ -2001,10 +2001,12 @@ static void b43_do_interrupt_thread(stru dma_reason[0], dma_reason[1], dma_reason[2], dma_reason[3], dma_reason[4], dma_reason[5]); 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 cd7b7583c9..52ae7a8eba 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 @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c -@@ -1642,7 +1642,7 @@ static void b43_write_beacon_template(st +@@ -1643,7 +1643,7 @@ static void b43_write_beacon_template(st len, ram_offset, shm_size_offset, rate); /* Write the PHY TX control parameters. */ @@ -9,7 +9,7 @@ antenna = b43_antenna_to_phyctl(antenna); ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); /* We can't send beacons with short preamble. Would get PHY errors. */ -@@ -3282,8 +3282,8 @@ static int b43_chip_init(struct b43_wlde +@@ -3284,8 +3284,8 @@ static int b43_chip_init(struct b43_wlde /* Select the antennae */ if (phy->ops->set_rx_antenna) @@ -20,7 +20,7 @@ if (phy->type == B43_PHYTYPE_B) { value16 = b43_read16(dev, 0x005E); -@@ -3983,7 +3983,6 @@ static int b43_op_config(struct ieee8021 +@@ -3985,7 +3985,6 @@ static int b43_op_config(struct ieee8021 struct b43_wldev *dev = wl->current_dev; struct b43_phy *phy = &dev->phy; struct ieee80211_conf *conf = &hw->conf; @@ -28,7 +28,7 @@ int err = 0; mutex_lock(&wl->mutex); -@@ -4026,11 +4025,9 @@ static int b43_op_config(struct ieee8021 +@@ -4028,11 +4027,9 @@ static int b43_op_config(struct ieee8021 } /* Antennas for RX and management frame TX. */ @@ -42,7 +42,7 @@ if (wl->radio_enabled != phy->radio_on) { if (wl->radio_enabled) { -@@ -5174,6 +5171,47 @@ static int b43_op_get_survey(struct ieee +@@ -5176,6 +5173,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, -@@ -5195,6 +5233,8 @@ static const struct ieee80211_ops b43_hw +@@ -5197,6 +5235,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. -@@ -5496,6 +5536,8 @@ static int b43_one_core_attach(struct b4 +@@ -5498,6 +5538,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; -@@ -5590,6 +5632,9 @@ static struct b43_wl *b43_wireless_init( +@@ -5592,6 +5634,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/814-b43-only-use-gpio-0-1-for-led.patch b/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch index 2aa7612878..9cb0a32fd4 100644 --- a/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch +++ b/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c -@@ -2884,6 +2884,14 @@ static int b43_gpio_init(struct b43_wlde +@@ -2886,6 +2886,14 @@ static int b43_gpio_init(struct b43_wlde } else if (dev->dev->chip_id == 0x5354) { /* Don't allow overtaking buttons GPIOs */ set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */ 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 c18a5bfa4a..dc2295db1b 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,7 +13,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1554,6 +1554,7 @@ int __init brcmf_core_init(void) +@@ -1557,6 +1557,7 @@ int __init brcmf_core_init(void) { if (!schedule_work(&brcmf_driver_work)) return -EBUSY; diff --git a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch index 37ebb5190b..7b4cb250f9 100644 --- a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +++ b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -705,8 +705,36 @@ static struct wireless_dev *brcmf_cfg802 +@@ -715,8 +715,36 @@ static struct wireless_dev *brcmf_cfg802 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_pub *drvr = cfg->pub; struct wireless_dev *wdev; 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 988ece1f5f..e640849e6a 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 -@@ -2874,6 +2874,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2958,6 +2958,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 2613171a86..9658bda1c1 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 @@ -49,7 +49,7 @@ Signed-off-by: Rafał Miłecki void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, struct brcmf_mp_device *settings) { -@@ -30,6 +60,8 @@ void brcmf_of_probe(struct device *dev, +@@ -43,6 +73,8 @@ void brcmf_of_probe(struct device *dev, of_node_put(root); } diff --git a/package/kernel/mac80211/patches/brcm/998-survey.patch b/package/kernel/mac80211/patches/brcm/998-survey.patch index 3c52cec0b9..9e9f4bbf8f 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 -@@ -2826,6 +2826,63 @@ done: +@@ -2910,6 +2910,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) { -@@ -2915,6 +2972,7 @@ static s32 brcmf_inform_single_bss(struc +@@ -3005,6 +3062,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; -@@ -2939,6 +2997,17 @@ static s32 brcmf_inform_single_bss(struc +@@ -3029,6 +3087,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()); -@@ -5356,6 +5425,7 @@ static struct cfg80211_ops brcmf_cfg8021 +@@ -5515,6 +5584,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 -@@ -1352,6 +1352,8 @@ int brcmf_attach(struct device *dev) +@@ -1356,6 +1356,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); -@@ -1434,6 +1436,12 @@ void brcmf_detach(struct device *dev) +@@ -1438,6 +1440,12 @@ void brcmf_detach(struct device *dev) if (drvr == NULL) return; diff --git a/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch b/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch index 0e51b0ffbc..68db4f72d3 100644 --- a/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch +++ b/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c -@@ -11482,6 +11482,15 @@ static const struct attribute_group ipw_ +@@ -11470,6 +11470,15 @@ static const struct attribute_group ipw_ .attrs = ipw_sysfs_entries, }; @@ -16,7 +16,7 @@ #ifdef CPTCFG_IPW2200_PROMISCUOUS static int ipw_prom_open(struct net_device *dev) { -@@ -11530,15 +11539,6 @@ static netdev_tx_t ipw_prom_hard_start_x +@@ -11518,15 +11527,6 @@ static netdev_tx_t ipw_prom_hard_start_x return NETDEV_TX_OK; } diff --git a/package/kernel/mac80211/patches/build/050-lib80211_option.patch b/package/kernel/mac80211/patches/build/050-lib80211_option.patch index 1578286c2b..c1b1bc757f 100644 --- a/package/kernel/mac80211/patches/build/050-lib80211_option.patch +++ b/package/kernel/mac80211/patches/build/050-lib80211_option.patch @@ -1,6 +1,6 @@ --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig -@@ -186,7 +186,7 @@ config CFG80211_WEXT_EXPORT +@@ -188,7 +188,7 @@ config CFG80211_WEXT_EXPORT endif # CFG80211 config LIB80211 @@ -9,7 +9,7 @@ depends on m default n help -@@ -196,18 +196,18 @@ config LIB80211 +@@ -198,19 +198,19 @@ config LIB80211 Drivers should select this themselves if needed. config LIB80211_CRYPT_WEP @@ -22,6 +22,7 @@ - tristate + tristate "lib80211 CCMP support" depends on m + depends on CRYPTO depends on CRYPTO_AES depends on CRYPTO_CCM 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 290d254238..ff2ce2071f 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,6 +1,6 @@ --- a/local-symbols +++ b/local-symbols -@@ -412,43 +412,6 @@ USB_SIERRA_NET= +@@ -437,43 +437,6 @@ USB_SIERRA_NET= USB_VL600= USB_NET_CH9200= USB_NET_AQC111= @@ -69,7 +69,7 @@ depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE - select SSB_SDIOHOST + depends on SSB_SDIOHOST - ---help--- + help Broadcom 43xx device support for Soft-MAC SDIO devices. @@ -96,13 +96,13 @@ config B43_SDIO @@ -90,7 +90,7 @@ config B43_PHY_G --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c -@@ -2851,7 +2851,7 @@ static struct ssb_device *b43_ssb_gpio_d +@@ -2853,7 +2853,7 @@ static struct ssb_device *b43_ssb_gpio_d { struct ssb_bus *bus = dev->dev->sdev->bus; @@ -99,7 +99,7 @@ return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); #else return bus->chipco.dev; -@@ -4868,7 +4868,7 @@ static int b43_wireless_core_init(struct +@@ -4870,7 +4870,7 @@ static int b43_wireless_core_init(struct } if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ @@ -117,7 +117,7 @@ - select SSB + depends on SSB depends on FW_LOADER - ---help--- + help b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and @@ -25,15 +25,15 @@ config B43LEGACY config B43LEGACY_PCI_AUTOSELECT @@ -140,7 +140,7 @@ # LED support --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c -@@ -1906,7 +1906,7 @@ static int b43legacy_gpio_init(struct b4 +@@ -1907,7 +1907,7 @@ static int b43legacy_gpio_init(struct b4 if (dev->dev->id.revision >= 2) mask |= 0x0010; /* FIXME: This is redundant. */ @@ -149,7 +149,7 @@ pcidev = bus->pcicore.dev; #endif gpiodev = bus->chipco.dev ? : pcidev; -@@ -1925,7 +1925,7 @@ static void b43legacy_gpio_cleanup(struc +@@ -1926,7 +1926,7 @@ static void b43legacy_gpio_cleanup(struc struct ssb_bus *bus = dev->dev->bus; struct ssb_device *gpiodev, *pcidev = NULL; @@ -160,8 +160,8 @@ gpiodev = bus->chipco.dev ? : pcidev; --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h -@@ -22,7 +22,7 @@ struct brcms_led { - bool active_low; +@@ -24,7 +24,7 @@ struct brcms_led { + struct gpio_desc *gpiod; }; -#ifdef CPTCFG_BCMA_DRIVER_GPIO @@ -192,7 +192,7 @@ select BRCMUTIL --- a/Kconfig.local +++ b/Kconfig.local -@@ -1240,117 +1240,6 @@ config BACKPORTED_USB_NET_CH9200 +@@ -1315,117 +1315,6 @@ config BACKPORTED_USB_NET_CH9200 config BACKPORTED_USB_NET_AQC111 tristate default USB_NET_AQC111 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 new file mode 100644 index 0000000000..a50a195285 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch @@ -0,0 +1,51 @@ +From patchwork Thu Dec 27 14:05:26 2018 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: Tom Psyborg +X-Patchwork-Id: 10743707 +X-Patchwork-Delegate: kvalo@adurom.com +From: =?utf-8?q?Tomislav_Po=C5=BEega?= +To: linux-wireless@vger.kernel.org +Cc: kvalo@codeaurora.org, hauke@hauke-m.de, nbd@nbd.name, + john@phrozen.org, sgruszka@redhat.com, daniel@makrotopia.org +Subject: [PATCH 2/2] rt2x00: define RF5592 in init_eeprom routine +Date: Thu, 27 Dec 2018 15:05:26 +0100 +Message-Id: <1545919526-4074-2-git-send-email-pozega.tomislav@gmail.com> +X-Mailer: git-send-email 1.7.0.4 +In-Reply-To: <1545919526-4074-1-git-send-email-pozega.tomislav@gmail.com> +References: <1545919526-4074-1-git-send-email-pozega.tomislav@gmail.com> +MIME-Version: 1.0 +Sender: linux-wireless-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless@vger.kernel.org +X-Virus-Scanned: ClamAV using ClamSMTP + +This patch fixes following crash on Linksys EA2750 during 5GHz wifi +init: + +[ 7.955153] rt2800pci 0000:01:00.0: card - bus=0x1, slot = 0x0 irq=4 +[ 7.962259] rt2800pci 0000:01:00.0: loaded eeprom from mtd device "Factory" +[ 7.969435] ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 5592, rev 0222 detected +[ 7.977348] ieee80211 phy0: rt2800_init_eeprom: Error - Invalid RF chipset 0x0000 detected +[ 7.985793] ieee80211 phy0: rt2x00lib_probe_dev: Error - Failed to allocate device +[ 7.993569] CPU 0 Unable to handle kernel paging request at virtual address 00000024, epc == 800c8f54, ra == 80249ff8 +[ 8.004408] Oops[#1]: + +Signed-off-by: Tomislav Požega +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +--- 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 + rf = RF3853; + else if (rt2x00_rt(rt2x00dev, RT5350)) + rf = RF5350; ++ else if (rt2x00_rt(rt2x00dev, RT5592)) ++ rf = RF5592; + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + 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 0c6e5a03b0..e74d9a9aa0 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 -@@ -313,6 +313,7 @@ RT2X00_LIB_FIRMWARE= +@@ -332,6 +332,7 @@ RT2X00_LIB_FIRMWARE= RT2X00_LIB_CRYPTO= RT2X00_LIB_LEDS= RT2X00_LIB_DEBUGFS= @@ -25,7 +25,7 @@ + select RT2X00_LIB_EEPROM select RT2800_LIB select RT2800_LIB_MMIO - ---help--- + help @@ -266,6 +268,9 @@ config RT2X00_LIB_FIRMWARE config RT2X00_LIB_CRYPTO bool @@ -95,7 +95,7 @@ /* Firmware functions */ static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) { -@@ -166,7 +153,6 @@ static const struct rt2800_ops rt2800soc +@@ -167,7 +154,6 @@ static const struct rt2800_ops rt2800soc .register_multiread = rt2x00mmio_register_multiread, .register_multiwrite = rt2x00mmio_register_multiwrite, .regbusy_read = rt2x00mmio_regbusy_read, @@ -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 -@@ -1418,6 +1418,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de +@@ -1406,6 +1406,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. */ -@@ -1561,6 +1565,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ +@@ -1549,6 +1553,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ * Free the driver data. */ kfree(rt2x00dev->drv_data); diff --git a/package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch b/package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch index 43754c43c2..7338eb15b2 100644 --- a/package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch +++ b/package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch @@ -17,7 +17,7 @@ Signed-off-by: John Crispin select RT2800_LIB select RT2800_LIB_MMIO + select MTD if SOC_RT288X || SOC_RT305X - ---help--- + help This adds support for Ralink WiSoC devices. Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. --- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c diff --git a/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch index 35714c04d2..38f8b77176 100644 --- a/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +++ b/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c -@@ -223,10 +223,17 @@ static int rt2800soc_probe(struct platfo +@@ -224,10 +224,17 @@ static int rt2800soc_probe(struct platfo return rt2x00soc_probe(pdev, &rt2800soc_ops); } 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 fb6647350e..039c6f6afc 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" -@@ -9531,6 +9532,17 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9530,6 +9531,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 d909a2e6c6..88d6dd559b 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 -@@ -1356,7 +1356,7 @@ static inline void rt2x00lib_set_if_comb +@@ -1344,7 +1344,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 70f8d06e24..fca1fb2cd4 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 @@ -31,7 +31,7 @@ Tested-by: Christoph Krapp static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; -@@ -1211,6 +1224,10 @@ static int rt2x00lib_probe_hw(struct rt2 +@@ -1210,6 +1223,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 df234fe0df..20452cd8a7 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 -@@ -4359,6 +4359,45 @@ static void rt2800_config_channel(struct +@@ -4356,6 +4356,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); -@@ -9560,7 +9599,8 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9559,7 +9598,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, -@@ -9571,6 +9611,18 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9570,6 +9610,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 4addb8e545..6be847478e 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 -@@ -8422,6 +8422,56 @@ static void rt2800_init_rfcsr_5592(struc +@@ -8419,6 +8419,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) { -@@ -9029,6 +9079,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9026,6 +9076,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 8041580411..3ed0ff7ef5 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 -@@ -8472,6 +8472,155 @@ static void rt2800_rf_self_txdc_cal(stru +@@ -8469,6 +8469,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) { -@@ -9079,6 +9228,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9076,6 +9225,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 89a4ccb961..77be986d18 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 -@@ -8621,6 +8621,70 @@ static void rt2800_r_calibration(struct +@@ -8618,6 +8618,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) { -@@ -9230,6 +9294,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9227,6 +9291,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 9a03efdef8..7352ad036c 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 -@@ -8685,6 +8685,384 @@ static void rt2800_rxdcoc_calibration(st +@@ -8682,6 +8682,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) { -@@ -9297,6 +9675,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9294,6 +9672,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 fc5e4ca5d7..fe0961baa7 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 -@@ -9063,6 +9063,943 @@ restore_value: +@@ -9060,6 +9060,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) { -@@ -9675,6 +10612,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9672,6 +10609,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/990-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch b/package/kernel/mac80211/patches/rt2x00/990-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch new file mode 100644 index 0000000000..76114fe9ae --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/990-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch @@ -0,0 +1,139 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -78,6 +78,9 @@ struct rt2800_ops { + int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); + __le32 *(*drv_get_txwi)(struct queue_entry *entry); + unsigned int (*drv_get_dma_done)(struct data_queue *queue); ++ int (*hw_get_chippkg)(void); ++ int (*hw_get_chipver)(void); ++ int (*hw_get_chipeco)(void); + }; + + static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev, +@@ -195,6 +198,27 @@ static inline unsigned int rt2800_drv_ge + return rt2800ops->drv_get_dma_done(queue); + } + ++static inline int rt2800_hw_get_chippkg(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ return rt2800ops->hw_get_chippkg(); ++} ++ ++static inline int rt2800_hw_get_chipver(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ return rt2800ops->hw_get_chipver(); ++} ++ ++static inline int rt2800_hw_get_chipeco(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ return rt2800ops->hw_get_chipeco(); ++} ++ + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1); +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -286,6 +286,10 @@ static int rt2800pci_read_eeprom(struct + return retval; + } + ++static int rt2800pci_get_chippkg(void) { return 0; } ++static int rt2800pci_get_chipver(void) { return 0; } ++static int rt2800pci_get_chipeco(void) { return 0; } ++ + static const struct ieee80211_ops rt2800pci_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, +@@ -328,6 +332,9 @@ static const struct rt2800_ops rt2800pci + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, + .drv_get_dma_done = rt2800mmio_get_dma_done, ++ .hw_get_chippkg = rt2800pci_get_chippkg, ++ .hw_get_chipver = rt2800pci_get_chipver, ++ .hw_get_chipeco = rt2800pci_get_chipeco, + }; + + static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -27,6 +27,12 @@ + #include "rt2800lib.h" + #include "rt2800mmio.h" + ++/* Needed to probe CHIP_VER register on MT7620 */ ++#ifdef CONFIG_SOC_MT7620 ++#include ++#include ++#endif ++ + /* Allow hardware encryption to be disabled. */ + static bool modparam_nohwcrypt; + module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444); +@@ -118,6 +124,27 @@ static int rt2800soc_write_firmware(stru + return 0; + } + ++#ifdef CONFIG_SOC_MT7620 ++static int rt2800soc_get_chippkg(void) ++{ ++ return mt7620_get_pkg(); ++} ++ ++static int rt2800soc_get_chipver(void) ++{ ++ return mt7620_get_chipver(); ++} ++ ++static int rt2800soc_get_chipeco(void) ++{ ++ return mt7620_get_eco(); ++} ++#else ++static int rt2800soc_get_chippkg(void) { return 0; } ++static int rt2800soc_get_chipver(void) { return 0; } ++static int rt2800soc_get_chipeco(void) { return 0; } ++#endif ++ + static const struct ieee80211_ops rt2800soc_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, +@@ -159,6 +186,9 @@ static const struct rt2800_ops rt2800soc + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, + .drv_get_dma_done = rt2800mmio_get_dma_done, ++ .hw_get_chippkg = rt2800soc_get_chippkg, ++ .hw_get_chipver = rt2800soc_get_chipver, ++ .hw_get_chipeco = rt2800soc_get_chipeco, + }; + + static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -628,6 +628,10 @@ static int rt2800usb_probe_hw(struct rt2 + return 0; + } + ++static int rt2800usb_get_chippkg(void) { return 0; } ++static int rt2800usb_get_chipver(void) { return 0; } ++static int rt2800usb_get_chipeco(void) { return 0; } ++ + static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, +@@ -671,6 +675,9 @@ static const struct rt2800_ops rt2800usb + .drv_init_registers = rt2800usb_init_registers, + .drv_get_txwi = rt2800usb_get_txwi, + .drv_get_dma_done = rt2800usb_get_dma_done, ++ .hw_get_chippkg = rt2800usb_get_chippkg, ++ .hw_get_chipver = rt2800usb_get_chipver, ++ .hw_get_chipeco = rt2800usb_get_chipeco, + }; + + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { 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 new file mode 100644 index 0000000000..3de00b2267 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/991-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch @@ -0,0 +1,408 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h +@@ -1042,6 +1042,11 @@ + #define MIMO_PS_CFG_RX_STBY_POL FIELD32(0x00000010) + #define MIMO_PS_CFG_RX_RX_STBY0 FIELD32(0x00000020) + ++#define BB_PA_MODE_CFG0 0x1214 ++#define BB_PA_MODE_CFG1 0x1218 ++#define RF_PA_MODE_CFG0 0x121C ++#define RF_PA_MODE_CFG1 0x1220 ++ + /* + * EDCA_AC0_CFG: + */ +--- 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 + rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4); + rt2800_rfcsr_write(rt2x00dev, 19, rfcsr); + +- /* Default: XO=20MHz , SDM mode */ +- rfcsr = rt2800_rfcsr_read(rt2x00dev, 16); +- rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80); +- rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); +- +- rfcsr = rt2800_rfcsr_read(rt2x00dev, 21); +- rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1); +- rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ /* Default: XO=20MHz , SDM mode */ ++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 16); ++ rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); ++ ++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 21); ++ rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1); ++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); ++ } + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620, +@@ -3726,18 +3728,23 @@ static void rt2800_config_channel_rf7620 + rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20); + } + +- if (conf_is_ht40(conf)) { +- rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08); +- rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08); +- } else { +- rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28); +- rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ if (conf_is_ht40(conf)) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08); ++ } else { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28); ++ } + } + +- rfcsr = rt2800_rfcsr_read(rt2x00dev, 28); +- rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40, +- conf_is_ht40(conf) && (rf->channel == 11)); +- rt2800_rfcsr_write(rt2x00dev, 28, rfcsr); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) == 2) { ++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 28); ++ rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40, ++ conf_is_ht40(conf) && (rf->channel == 11)); ++ rt2800_rfcsr_write(rt2x00dev, 28, rfcsr); ++ } + + if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) { + if (conf_is_ht40(conf)) { +@@ -3837,25 +3844,29 @@ static void rt2800_config_alc(struct rt2 + if (i == 10000) + rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n"); + +- if (chan->center_freq > 2457) { +- bbp = rt2800_bbp_read(rt2x00dev, 30); +- bbp = 0x40; +- rt2800_bbp_write(rt2x00dev, 30, bbp); +- rt2800_rfcsr_write(rt2x00dev, 39, 0); +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) +- rt2800_rfcsr_write(rt2x00dev, 42, 0xfb); +- else +- rt2800_rfcsr_write(rt2x00dev, 42, 0x7b); +- } else { +- bbp = rt2800_bbp_read(rt2x00dev, 30); +- bbp = 0x1f; +- rt2800_bbp_write(rt2x00dev, 30, bbp); +- rt2800_rfcsr_write(rt2x00dev, 39, 0x80); +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) +- rt2800_rfcsr_write(rt2x00dev, 42, 0xdb); +- else +- rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ if (chan->center_freq > 2457) { ++ bbp = rt2800_bbp_read(rt2x00dev, 30); ++ bbp = 0x40; ++ rt2800_bbp_write(rt2x00dev, 30, bbp); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0); ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) ++ rt2800_rfcsr_write(rt2x00dev, 42, 0xfb); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x7b); ++ } else { ++ bbp = rt2800_bbp_read(rt2x00dev, 30); ++ bbp = 0x1f; ++ rt2800_bbp_write(rt2x00dev, 30, bbp); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) ++ rt2800_rfcsr_write(rt2x00dev, 42, 0xdb); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); ++ } + } ++ + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl); + + rt2800_vco_calibration(rt2x00dev); +@@ -5887,18 +5898,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)) { +- rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401); +- rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000); +- rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +- rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000); +- rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); +- rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0); +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C); +- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C666C); +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, +- 0x3630363A); +- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT, +- 0x3630363A); ++ if (rt2800_hw_get_chipver(rt2x00dev) <= 1) { ++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, ++ 0x00000000); ++ rt2800_register_write(rt2x00dev, BB_PA_MODE_CFG0, ++ 0x000055FF); ++ rt2800_register_write(rt2x00dev, BB_PA_MODE_CFG1, ++ 0x00550055); ++ rt2800_register_write(rt2x00dev, RF_PA_MODE_CFG0, ++ 0x000055FF); ++ rt2800_register_write(rt2x00dev, RF_PA_MODE_CFG1, ++ 0x00550055); ++ } else { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); ++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000); ++ rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); ++ rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, ++ 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, ++ 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, ++ 0x3630363A); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT, ++ 0x3630363A); ++ } + 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 + rt2800_bbp_write(rt2x00dev, 188, 0x00); + rt2800_bbp_write(rt2x00dev, 189, 0x00); + +- rt2800_bbp_write(rt2x00dev, 91, 0x06); +- rt2800_bbp_write(rt2x00dev, 92, 0x04); +- rt2800_bbp_write(rt2x00dev, 93, 0x54); +- rt2800_bbp_write(rt2x00dev, 99, 0x50); +- rt2800_bbp_write(rt2x00dev, 148, 0x84); +- rt2800_bbp_write(rt2x00dev, 167, 0x80); +- rt2800_bbp_write(rt2x00dev, 178, 0xFF); +- rt2800_bbp_write(rt2x00dev, 106, 0x13); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_bbp_write(rt2x00dev, 91, 0x06); ++ rt2800_bbp_write(rt2x00dev, 92, 0x04); ++ rt2800_bbp_write(rt2x00dev, 93, 0x54); ++ rt2800_bbp_write(rt2x00dev, 99, 0x50); ++ rt2800_bbp_write(rt2x00dev, 148, 0x84); ++ rt2800_bbp_write(rt2x00dev, 167, 0x80); ++ rt2800_bbp_write(rt2x00dev, 178, 0xFF); ++ rt2800_bbp_write(rt2x00dev, 106, 0x13); ++ } + + /* 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 + rt2800_rfcsr_write(rt2x00dev, 42, 0x5B); + rt2800_rfcsr_write(rt2x00dev, 43, 0x00); + +- rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +- if (rt2800_clk_is_20mhz(rt2x00dev)) +- rt2800_rfcsr_write(rt2x00dev, 13, 0x03); +- else +- rt2800_rfcsr_write(rt2x00dev, 13, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 14, 0x7C); +- rt2800_rfcsr_write(rt2x00dev, 16, 0x80); +- rt2800_rfcsr_write(rt2x00dev, 17, 0x99); +- rt2800_rfcsr_write(rt2x00dev, 18, 0x99); +- rt2800_rfcsr_write(rt2x00dev, 19, 0x09); +- rt2800_rfcsr_write(rt2x00dev, 20, 0x50); +- rt2800_rfcsr_write(rt2x00dev, 21, 0xB0); +- rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 23, 0x06); +- rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 25, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 26, 0x5D); +- rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 28, 0x61); +- rt2800_rfcsr_write(rt2x00dev, 29, 0xB5); +- rt2800_rfcsr_write(rt2x00dev, 43, 0x02); +- +- rt2800_rfcsr_write(rt2x00dev, 28, 0x62); +- rt2800_rfcsr_write(rt2x00dev, 29, 0xAD); +- rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x21); ++ if (rt2800_clk_is_20mhz(rt2x00dev)) ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x03); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x7C); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 17, 0x99); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x99); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x09); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0x50); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0xB0); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x06); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x5D); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x61); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xB5); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x02); ++ } ++ ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x62); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xAD); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ } + + /* 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 + + rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5); + +- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); +- rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0x67); +- rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0x69); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF); +- rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27); +- rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x20); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); +- +- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); +- +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); +- +- /* Initialize RF channel register for DRQFN */ +- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0x67); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0x69); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); ++ } ++ ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 0 && ++ rt2800_hw_get_chipver(rt2x00dev) == 1) { ++ /* Initialize RF channel register for DRQFN */ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); ++ } + + /* 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 + rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00); + +- rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08); +- rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04); +- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20); ++ } + +- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); +- rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); ++ } + + rt2800_r_calibration(rt2x00dev); + rt2800_rf_self_txdc_cal(rt2x00dev); 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 new file mode 100644 index 0000000000..31a7baeee7 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch @@ -0,0 +1,183 @@ +--- 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/subsys/090-wireless-Use-linux-stddef.h-instead-of-stddef.h.patch b/package/kernel/mac80211/patches/subsys/090-wireless-Use-linux-stddef.h-instead-of-stddef.h.patch deleted file mode 100644 index c81cc063c6..0000000000 --- a/package/kernel/mac80211/patches/subsys/090-wireless-Use-linux-stddef.h-instead-of-stddef.h.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e1f04bf9d38633f0bf9d041089366fea0ad22623 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Thu, 21 May 2020 19:50:05 +0200 -Subject: [PATCH] wireless: Use linux/stddef.h instead of stddef.h - -When compiling inside the kernel include linux/stddef.h instead of -stddef.h. When I compile this header file in backports for power PC I -run into a conflict with ptrdiff_t. I was unable to reproduce this in -mainline kernel. I still would like to fix this problem in the kernel. - -Fixes: 6989310f5d43 ("wireless: Use offsetof instead of custom macro.") -Signed-off-by: Hauke Mehrtens ---- - include/uapi/linux/wireless.h | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/include/uapi/linux/wireless.h -+++ b/include/uapi/linux/wireless.h -@@ -74,7 +74,11 @@ - #include /* for "struct sockaddr" et al */ - #include /* for IFNAMSIZ and co... */ - --#include /* for offsetof */ -+#ifdef __KERNEL__ -+# include /* for offsetof */ -+#else -+# include /* for offsetof */ -+#endif - - /***************************** VERSION *****************************/ - /* diff --git a/package/kernel/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch index 5fe7616143..7b036e4e4c 100644 --- a/package/kernel/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch +++ b/package/kernel/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch @@ -8,7 +8,7 @@ wpa.o \ scan.o offchannel.o \ ht.o agg-tx.o agg-rx.o \ -@@ -18,8 +17,8 @@ mac80211-y := \ +@@ -19,8 +18,8 @@ mac80211-y := \ rate.o \ michael.o \ tkip.o \ @@ -64,7 +64,7 @@ - aead_request_set_ad(aead_req, sg[0].length); - - crypto_aead_encrypt(aead_req); -- kzfree(aead_req); +- kfree_sensitive(aead_req); - - return 0; -} @@ -99,7 +99,7 @@ - aead_request_set_ad(aead_req, sg[0].length); - - err = crypto_aead_decrypt(aead_req); -- kzfree(aead_req); +- kfree_sensitive(aead_req); - - return err; -} @@ -654,7 +654,7 @@ - depends on CRYPTO_GCM depends on CRYPTO_CMAC depends on CRC32 - ---help--- + help --- a/net/mac80211/aes_gmac.h +++ b/net/mac80211/aes_gmac.h @@ -12,10 +12,22 @@ @@ -687,7 +687,7 @@ #endif /* AES_GMAC_H */ --- a/net/mac80211/key.h +++ b/net/mac80211/key.h -@@ -88,7 +88,7 @@ struct ieee80211_key { +@@ -89,7 +89,7 @@ struct ieee80211_key { * Management frames. */ u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; 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 8e0fddd10a..665231a040 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,11 +2,11 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1172,7 +1172,6 @@ static int ieee80211_stop_ap(struct wiph +@@ -1288,7 +1288,6 @@ static int ieee80211_stop_ap(struct wiph sdata->vif.bss_conf.ftmr_params = NULL; __sta_info_flush(sdata, true); - ieee80211_free_keys(sdata, true); sdata->vif.bss_conf.enable_beacon = false; - sdata->vif.bss_conf.ssid_len = 0; + sdata->beacon_rate_set = false; diff --git a/package/kernel/mac80211/patches/subsys/130-disable-fils.patch b/package/kernel/mac80211/patches/subsys/130-disable-fils.patch index f370dd52ee..9c6e971f9d 100644 --- a/package/kernel/mac80211/patches/subsys/130-disable-fils.patch +++ b/package/kernel/mac80211/patches/subsys/130-disable-fils.patch @@ -21,7 +21,7 @@ Disable FILS support, since it pulls in crypto hash support * FILS AEAD for (Re)Association Request/Response frames --- a/net/mac80211/main.c +++ b/net/mac80211/main.c -@@ -571,7 +571,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ +@@ -591,7 +591,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ NL80211_FEATURE_MAC_ON_CREATE | NL80211_FEATURE_USERSPACE_MPM | NL80211_FEATURE_FULL_AP_CLIENT_STATE; diff --git a/package/kernel/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch b/package/kernel/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch index 02e523878e..c3bf7ccc7a 100644 --- a/package/kernel/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch +++ b/package/kernel/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch @@ -11,14 +11,13 @@ Signed-off-by: Felix Fietkau --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c -@@ -19,50 +19,126 @@ +@@ -19,67 +19,151 @@ #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ #define AAD_LEN 20 -static const u8 zero[CMAC_TLEN_256]; -void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, -- const u8 *data, size_t data_len, u8 *mic) +void gf_mulx(u8 *pad) +{ + int i, carry; @@ -34,9 +33,7 @@ Signed-off-by: Felix Fietkau +void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac, + size_t mac_len) - { -- SHASH_DESC_ON_STACK(desc, tfm); -- u8 out[AES_BLOCK_SIZE]; ++{ + u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; + const u8 *pos, *end; + size_t i, e, left, total_len; @@ -88,30 +85,48 @@ Signed-off-by: Felix Fietkau + crypto_cipher_encrypt_one(tfm, pad, pad); + memcpy(mac, pad, mac_len); +} ++ ++ ++void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic) + { +- SHASH_DESC_ON_STACK(desc, tfm); +- u8 out[AES_BLOCK_SIZE]; ++ const u8 *addr[4]; ++ size_t len[4]; ++ u8 zero[CMAC_TLEN]; + const __le16 *fc; - desc->tfm = tfm; - +- - crypto_shash_init(desc); - crypto_shash_update(desc, aad, AAD_LEN); -- crypto_shash_update(desc, data, data_len - CMAC_TLEN); -- crypto_shash_finup(desc, zero, CMAC_TLEN, out); -+void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, -+ const u8 *data, size_t data_len, u8 *mic) -+{ -+ const u8 *addr[3]; -+ size_t len[3]; -+ u8 zero[CMAC_TLEN]; -+ + memset(zero, 0, CMAC_TLEN); + addr[0] = aad; + len[0] = AAD_LEN; -+ addr[1] = data; -+ len[1] = data_len - CMAC_TLEN; -+ addr[2] = zero; -+ len[2] = CMAC_TLEN; - + fc = (const __le16 *)aad; + if (ieee80211_is_beacon(*fc)) { + /* mask Timestamp field to zero */ +- crypto_shash_update(desc, zero, 8); +- crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN); ++ addr[1] = zero; ++ len[1] = 8; ++ addr[2] = data + 8; ++ len[2] = data_len - 8 - CMAC_TLEN; ++ addr[3] = zero; ++ len[3] = CMAC_TLEN; ++ aes_cmac_vector(tfm, 4, addr, len, mic, CMAC_TLEN); + } else { +- crypto_shash_update(desc, data, data_len - CMAC_TLEN); ++ addr[1] = data; ++ len[1] = data_len - CMAC_TLEN; ++ addr[2] = zero; ++ len[2] = CMAC_TLEN; ++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); + } +- crypto_shash_finup(desc, zero, CMAC_TLEN, out); +- - memcpy(mic, out, CMAC_TLEN); -+ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); } -void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, @@ -119,25 +134,41 @@ Signed-off-by: Felix Fietkau const u8 *data, size_t data_len, u8 *mic) { - SHASH_DESC_ON_STACK(desc, tfm); -+ const u8 *addr[3]; -+ size_t len[3]; ++ const u8 *addr[4]; ++ size_t len[4]; + u8 zero[CMAC_TLEN_256]; -+ -+ memset(zero, 0, CMAC_TLEN_256); -+ addr[0] = aad; -+ len[0] = AAD_LEN; -+ addr[1] = data; -+ len[1] = data_len - CMAC_TLEN_256; -+ addr[2] = zero; -+ len[2] = CMAC_TLEN_256; + const __le16 *fc; - desc->tfm = tfm; - - crypto_shash_init(desc); - crypto_shash_update(desc, aad, AAD_LEN); -- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); ++ memset(zero, 0, CMAC_TLEN_256); ++ addr[0] = aad; ++ len[0] = AAD_LEN; ++ addr[1] = data; + fc = (const __le16 *)aad; + if (ieee80211_is_beacon(*fc)) { + /* mask Timestamp field to zero */ +- crypto_shash_update(desc, zero, 8); +- crypto_shash_update(desc, data + 8, +- data_len - 8 - CMAC_TLEN_256); ++ addr[1] = zero; ++ len[1] = 8; ++ addr[2] = data + 8; ++ len[2] = data_len - 8 - CMAC_TLEN_256; ++ addr[3] = zero; ++ len[3] = CMAC_TLEN_256; ++ aes_cmac_vector(tfm, 4, addr, len, mic, CMAC_TLEN_256); + } else { +- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); ++ addr[1] = data; ++ len[1] = data_len - CMAC_TLEN_256; ++ addr[2] = zero; ++ len[2] = CMAC_TLEN_256; ++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); + } - crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic); -+ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); } -struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], @@ -188,7 +219,7 @@ Signed-off-by: Felix Fietkau #endif /* AES_CMAC_H */ --- a/net/mac80211/key.h +++ b/net/mac80211/key.h -@@ -93,7 +93,7 @@ struct ieee80211_key { +@@ -94,7 +94,7 @@ struct ieee80211_key { } ccmp; struct { u8 rx_pn[IEEE80211_CMAC_PN_LEN]; diff --git a/package/kernel/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch b/package/kernel/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch index 2a9c09b4ad..df67d2f101 100644 --- a/package/kernel/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch +++ b/package/kernel/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch @@ -6,5 +6,5 @@ depends on CRYPTO_AES - depends on CRYPTO_CMAC depends on CRC32 - ---help--- + help This option enables the hardware independent IEEE 802.11 diff --git a/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch b/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch deleted file mode 100644 index fa12232f1b..0000000000 --- a/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -4048,6 +4048,12 @@ out: - netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, - struct net_device *dev) - { -+#if defined(sk_pacing_shift) || LINUX_VERSION_IS_GEQ(4,15,0) -+ if (skb->sk && sk_fullsock(skb->sk) && -+ skb->sk->sk_pacing_shift != 6) -+ skb->sk->sk_pacing_shift = 6; -+#endif -+ - if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) { - struct sk_buff_head queue; - 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 3c5d1d63a8..8a717558a7 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 -@@ -314,7 +314,7 @@ void ieee80211_restart_hw(struct ieee802 +@@ -321,7 +321,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) { -@@ -373,7 +373,7 @@ static int ieee80211_ifa_changed(struct +@@ -380,7 +380,7 @@ static int ieee80211_ifa_changed(struct } #endif @@ -18,7 +18,7 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, unsigned long data, void *arg) { -@@ -1267,14 +1267,14 @@ int ieee80211_register_hw(struct ieee802 +@@ -1301,14 +1301,14 @@ int ieee80211_register_hw(struct ieee802 rtnl_unlock(); @@ -35,7 +35,7 @@ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; result = register_inet6addr_notifier(&local->ifa6_notifier); if (result) -@@ -1283,13 +1283,13 @@ int ieee80211_register_hw(struct ieee802 +@@ -1317,13 +1317,13 @@ int ieee80211_register_hw(struct ieee802 return 0; @@ -52,7 +52,7 @@ fail_ifa: #endif wiphy_unregister(local->hw.wiphy); -@@ -1317,10 +1317,10 @@ void ieee80211_unregister_hw(struct ieee +@@ -1351,10 +1351,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 2f7f7015e6..80f995737b 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 -@@ -2318,7 +2318,7 @@ static int ieee80211_scan(struct wiphy * +@@ -2442,7 +2442,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-mac80211-optimize-skb-resizing.patch b/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch deleted file mode 100644 index 49c0542c47..0000000000 --- a/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch +++ /dev/null @@ -1,201 +0,0 @@ -From: Felix Fietkau -Date: Sun, 17 Mar 2019 18:11:30 +0100 -Subject: [PATCH] mac80211: optimize skb resizing - -When forwarding unicast packets from ethernet to batman-adv over 802.11s -(with forwarding disabled), the typical required headroom to transmit -encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) + -2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes. - -On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head -for every packet, since mac80211 also tries to allocate 16 bytes status -headroom for radiotap headers. - -This patch fixes these unnecessary reallocations by only requiring the extra -status headroom in ieee80211_tx_monitor() -If however a reallocation happens before that call, the status headroom gets -added there as well, in order to avoid double reallocation. - -The patch also cleans up the code by moving the headroom calculation to -ieee80211_skb_resize. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1782,6 +1782,9 @@ int ieee80211_tx_control_port(struct wip - const u8 *dest, __be16 proto, bool unencrypted); - int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, - const u8 *buf, size_t len); -+int ieee80211_skb_resize(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct sk_buff *skb, int hdrlen, int hdr_add); - - /* HT */ - void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -814,6 +814,11 @@ void ieee80211_tx_monitor(struct ieee802 - struct net_device *prev_dev = NULL; - int rtap_len; - -+ if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) { -+ dev_kfree_skb(skb); -+ return; -+ } -+ - /* send frame to monitor interfaces now */ - rtap_len = ieee80211_tx_radiotap_len(info, status); - if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1943,37 +1943,53 @@ static bool ieee80211_tx(struct ieee8021 - } - - /* device xmit handlers */ -- --static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, -- struct sk_buff *skb, -- int head_need, bool may_encrypt) -+int ieee80211_skb_resize(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct sk_buff *skb, int hdr_len, int hdr_extra) - { -- struct ieee80211_local *local = sdata->local; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; -- bool enc_tailroom; -- int tail_need = 0; -- -- hdr = (struct ieee80211_hdr *) skb->data; -- enc_tailroom = may_encrypt && -- (sdata->crypto_tx_tailroom_needed_cnt || -- ieee80211_is_mgmt(hdr->frame_control)); -- -- if (enc_tailroom) { -- tail_need = IEEE80211_ENCRYPT_TAILROOM; -- tail_need -= skb_tailroom(skb); -- tail_need = max_t(int, tail_need, 0); -+ int head_need, head_max; -+ int tail_need, tail_max; -+ bool enc_tailroom = false; -+ -+ if (sdata && !hdr_len && -+ !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) { -+ hdr = (struct ieee80211_hdr *) skb->data; -+ enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt || -+ ieee80211_is_mgmt(hdr->frame_control)); -+ hdr_len += sdata->encrypt_headroom; -+ } -+ -+ head_need = head_max = hdr_len; -+ tail_need = tail_max = 0; -+ if (!sdata) { -+ head_need = head_max = local->tx_headroom; -+ } else { -+ head_max += hdr_extra; -+ head_max += max_t(int, local->tx_headroom, -+ local->hw.extra_tx_headroom); -+ head_need += local->hw.extra_tx_headroom; -+ -+ tail_max = IEEE80211_ENCRYPT_TAILROOM; -+ if (enc_tailroom) -+ tail_need = tail_max; - } - - if (skb_cloned(skb) && - (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) || - !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom)) - I802_DEBUG_INC(local->tx_expand_skb_head_cloned); -- else if (head_need || tail_need) -+ else if (head_need > skb_headroom(skb) || -+ tail_need > skb_tailroom(skb)) - I802_DEBUG_INC(local->tx_expand_skb_head); - else - return 0; - -- if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { -+ head_max = max_t(int, 0, head_max - skb_headroom(skb)); -+ tail_max = max_t(int, 0, tail_max - skb_tailroom(skb)); -+ -+ if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) { - wiphy_debug(local->hw.wiphy, - "failed to reallocate TX buffer\n"); - return -ENOMEM; -@@ -1989,18 +2005,8 @@ void ieee80211_xmit(struct ieee80211_sub - struct ieee80211_local *local = sdata->local; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; -- int headroom; -- bool may_encrypt; -- -- may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); - -- headroom = local->tx_headroom; -- if (may_encrypt) -- headroom += sdata->encrypt_headroom; -- headroom -= skb_headroom(skb); -- headroom = max_t(int, 0, headroom); -- -- if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { -+ if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) { - ieee80211_free_txskb(&local->hw, skb); - return; - } -@@ -2790,29 +2796,13 @@ static struct sk_buff *ieee80211_build_h - } - - skb_pull(skb, skip_header_bytes); -- head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); -+ head_need = hdrlen + encaps_len + meshhdrlen; - -- /* -- * So we need to modify the skb header and hence need a copy of -- * that. The head_need variable above doesn't, so far, include -- * the needed header space that we don't need right away. If we -- * can, then we don't reallocate right now but only after the -- * frame arrives at the master device (if it does...) -- * -- * If we cannot, however, then we will reallocate to include all -- * the ever needed space. Also, if we need to reallocate it anyway, -- * make it big enough for everything we may ever need. -- */ -- -- if (head_need > 0 || skb_cloned(skb)) { -- head_need += sdata->encrypt_headroom; -- head_need += local->tx_headroom; -- head_need = max_t(int, 0, head_need); -- if (ieee80211_skb_resize(sdata, skb, head_need, true)) { -- ieee80211_free_txskb(&local->hw, skb); -- skb = NULL; -- return ERR_PTR(-ENOMEM); -- } -+ if (ieee80211_skb_resize(local, sdata, skb, head_need, -+ sdata->encrypt_headroom)) { -+ ieee80211_free_txskb(&local->hw, skb); -+ skb = NULL; -+ return ERR_PTR(-ENOMEM); - } - - if (encaps_data) -@@ -3427,7 +3417,6 @@ static bool ieee80211_xmit_fast(struct i - struct ieee80211_local *local = sdata->local; - u16 ethertype = (skb->data[12] << 8) | skb->data[13]; - int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); -- int hw_headroom = sdata->local->hw.extra_tx_headroom; - struct ethhdr eth; - struct ieee80211_tx_info *info; - struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; -@@ -3479,10 +3468,7 @@ static bool ieee80211_xmit_fast(struct i - * as the may-encrypt argument for the resize to not account for - * more room than we already have in 'extra_head' - */ -- if (unlikely(ieee80211_skb_resize(sdata, skb, -- max_t(int, extra_head + hw_headroom - -- skb_headroom(skb), 0), -- false))) { -+ if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) { - kfree_skb(skb); - return true; - } diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-minstrel-remove-divisions-in-tx-status-path.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-minstrel-remove-divisions-in-tx-status-path.patch deleted file mode 100644 index 91fb92f1b2..0000000000 --- a/package/kernel/mac80211/patches/subsys/301-mac80211-minstrel-remove-divisions-in-tx-status-path.patch +++ /dev/null @@ -1,61 +0,0 @@ -From: Felix Fietkau -Date: Sat, 28 Sep 2019 15:44:06 +0200 -Subject: [PATCH] mac80211: minstrel: remove divisions in tx status path - -Use a slightly different threshold for downgrading spatial streams to -make it easier to calculate without divisions. -Slightly reduces CPU overhead. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel.c -+++ b/net/mac80211/rc80211_minstrel.c -@@ -289,8 +289,7 @@ minstrel_tx_status(void *priv, struct ie - if (mi->sample_deferred > 0) - mi->sample_deferred--; - -- if (time_after(jiffies, mi->last_stats_update + -- (mp->update_interval * HZ) / 1000)) -+ if (time_after(jiffies, mi->last_stats_update + mp->update_interval)) - minstrel_update_stats(mp, mi); - } - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -970,23 +970,21 @@ minstrel_ht_tx_status(void *priv, struct - */ - rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); - if (rate->attempts > 30 && -- MINSTREL_FRAC(rate->success, rate->attempts) < -- MINSTREL_FRAC(20, 100)) { -+ rate->success < rate->attempts / 4) { - minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); - update = true; - } - - rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); - if (rate2->attempts > 30 && -- MINSTREL_FRAC(rate2->success, rate2->attempts) < -- MINSTREL_FRAC(20, 100)) { -+ rate2->success < rate2->attempts / 4) { - minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); - update = true; - } - } - - if (time_after(jiffies, mi->last_stats_update + -- (mp->update_interval / 2 * HZ) / 1000)) { -+ mp->update_interval / 2)) { - update = true; - minstrel_ht_update_stats(mp, mi, true); - } -@@ -1666,7 +1664,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h - mp->has_mrr = true; - - mp->hw = hw; -- mp->update_interval = 100; -+ mp->update_interval = HZ / 10; - - minstrel_ht_init_cck_rates(mp); - diff --git a/package/kernel/mac80211/patches/subsys/302-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch b/package/kernel/mac80211/patches/subsys/302-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch deleted file mode 100644 index 78e8527a5c..0000000000 --- a/package/kernel/mac80211/patches/subsys/302-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch +++ /dev/null @@ -1,235 +0,0 @@ -From: Felix Fietkau -Date: Sat, 28 Sep 2019 15:46:06 +0200 -Subject: [PATCH] mac80211: minstrel_ht: replace rate stats ewma with a - better moving average - -Rate success probability usually fluctuates a lot under normal conditions. -With a simple EWMA, noise and fluctuation can be reduced by increasing the -window length, but that comes at the cost of introducing lag on sudden -changes. - -This change replaces the EWMA implementation with a moving average that's -designed to significantly reduce lag while keeping a bigger window size -by being better at filtering out noise. - -It is only slightly more expensive than the simple EWMA and still avoids -divisions in its calculation. - -The algorithm is adapted from an implementation intended for a completely -different field (stock market trading), where the tradeoff of lag vs -noise filtering is equally important. - -The algorithm works in the same way as the "smoothing filter" from -http://www.stockspotter.com/files/PredictiveIndicators.pdf adapted for -fixed-point math with some constants, using only addition, bit shifts -and multiplication - -To better make use of the filtering and bigger window size, the update -interval is cut in half. - -For testing, the algorithm can be reverted to the older one via debugfs - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel.c -+++ b/net/mac80211/rc80211_minstrel.c -@@ -157,14 +157,18 @@ minstrel_update_rates(struct minstrel_pr - * Recalculate statistics and counters of a given rate - */ - void --minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) -+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 (unlikely(!mrs->att_hist)) { -+ if (mp->new_avg) { -+ mrs->prob_ewma = minstrel_filter_avg_add(&mrs->avg, -+ cur_prob); -+ } else if (unlikely(!mrs->att_hist)) { - mrs->prob_ewma = cur_prob; - } else { - /*update exponential weighted moving avarage */ -@@ -200,7 +204,7 @@ minstrel_update_stats(struct minstrel_pr - struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; - - /* Update statistics of success probability per rate */ -- minstrel_calc_rate_stats(mrs); -+ minstrel_calc_rate_stats(mp, mrs); - - /* Sample less often below the 10% chance of success. - * Sample less often above the 95% chance of success. */ -@@ -289,7 +293,8 @@ minstrel_tx_status(void *priv, struct ie - if (mi->sample_deferred > 0) - mi->sample_deferred--; - -- if (time_after(jiffies, mi->last_stats_update + mp->update_interval)) -+ if (time_after(jiffies, mi->last_stats_update + -+ mp->update_interval / (mp->new_avg ? 2 : 1))) - minstrel_update_stats(mp, mi); - } - ---- a/net/mac80211/rc80211_minstrel.h -+++ b/net/mac80211/rc80211_minstrel.h -@@ -19,6 +19,21 @@ - #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 -@@ -32,6 +47,41 @@ minstrel_ewma(int old, int new, int weig - return old + incr; - } - -+struct minstrel_avg_ctx { -+ s32 prev[2]; -+}; -+ -+static inline int minstrel_filter_avg_add(struct minstrel_avg_ctx *ctx, s32 in) -+{ -+ s32 out_1 = ctx->prev[0]; -+ s32 out_2 = ctx->prev[1]; -+ 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: -+ ctx->prev[1] = out_1; -+ ctx->prev[0] = val; -+ -+ return val; -+} -+ - struct minstrel_rate_stats { - /* current / last sampling period attempts/success counters */ - u16 attempts, last_attempts; -@@ -40,6 +90,8 @@ struct minstrel_rate_stats { - /* total attempts/success counters */ - u32 att_hist, succ_hist; - -+ struct minstrel_avg_ctx avg; -+ - /* prob_ewma - exponential weighted moving average of prob */ - u16 prob_ewma; - -@@ -95,6 +147,7 @@ struct minstrel_sta_info { - struct minstrel_priv { - struct ieee80211_hw *hw; - bool has_mrr; -+ bool new_avg; - u32 sample_switch; - unsigned int cw_min; - unsigned int cw_max; -@@ -126,7 +179,8 @@ extern const struct rate_control_ops mac - 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_rate_stats *mrs); -+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_ewma); - - /* debugfs */ ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -737,7 +737,7 @@ minstrel_ht_update_stats(struct minstrel - - mrs = &mg->rates[i]; - mrs->retry_updated = false; -- minstrel_calc_rate_stats(mrs); -+ minstrel_calc_rate_stats(mp, mrs); - cur_prob = mrs->prob_ewma; - - if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) -@@ -773,6 +773,8 @@ minstrel_ht_update_stats(struct minstrel - - /* try to sample all available rates during each interval */ - mi->sample_count *= 8; -+ if (mp->new_avg) -+ mi->sample_count /= 2; - - if (sample) - minstrel_ht_rate_sample_switch(mp, mi); -@@ -889,6 +891,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; - bool last, update = false; - bool sample_status = false; - int i; -@@ -943,6 +946,10 @@ 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)) -+ update_interval /= 2; - break; - - case MINSTREL_SAMPLE_ACTIVE: -@@ -983,8 +990,7 @@ minstrel_ht_tx_status(void *priv, struct - } - } - -- if (time_after(jiffies, mi->last_stats_update + -- mp->update_interval / 2)) { -+ if (time_after(jiffies, mi->last_stats_update + update_interval)) { - update = true; - minstrel_ht_update_stats(mp, mi, true); - } -@@ -1665,6 +1671,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h - - mp->hw = hw; - mp->update_interval = HZ / 10; -+ mp->new_avg = true; - - minstrel_ht_init_cck_rates(mp); - -@@ -1682,6 +1689,8 @@ 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 - diff --git a/package/kernel/mac80211/patches/subsys/303-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch b/package/kernel/mac80211/patches/subsys/303-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch deleted file mode 100644 index f4c4bdb94e..0000000000 --- a/package/kernel/mac80211/patches/subsys/303-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch +++ /dev/null @@ -1,424 +0,0 @@ -From: Felix Fietkau -Date: Tue, 8 Oct 2019 18:54:46 +0200 -Subject: [PATCH] mac80211: minstrel_ht: rename prob_ewma to prob_avg, use it - for the new average - -Reduces per-rate data structure size - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/rc80211_minstrel.c -+++ b/net/mac80211/rc80211_minstrel.c -@@ -70,7 +70,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, - } - - /* return current EMWA throughput */ --int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma) -+int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg) - { - int usecs; - -@@ -79,13 +79,13 @@ int minstrel_get_tp_avg(struct minstrel_ - usecs = 1000000; - - /* reset thr. below 10% success */ -- if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100)) -+ if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100)) - return 0; - -- if (prob_ewma > MINSTREL_FRAC(90, 100)) -+ if (prob_avg > MINSTREL_FRAC(90, 100)) - return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs)); - else -- return MINSTREL_TRUNC(100000 * (prob_ewma / usecs)); -+ return MINSTREL_TRUNC(100000 * (prob_avg / usecs)); - } - - /* find & sort topmost throughput rates */ -@@ -98,8 +98,8 @@ minstrel_sort_best_tp_rates(struct minst - - 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_ewma) <= -- minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma)) -+ 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; - } - -@@ -166,15 +166,15 @@ minstrel_calc_rate_stats(struct minstrel - mrs->sample_skipped = 0; - cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); - if (mp->new_avg) { -- mrs->prob_ewma = minstrel_filter_avg_add(&mrs->avg, -- cur_prob); -+ minstrel_filter_avg_add(&mrs->prob_avg, -+ &mrs->prob_avg_1, cur_prob); - } else if (unlikely(!mrs->att_hist)) { -- mrs->prob_ewma = cur_prob; -+ mrs->prob_avg = cur_prob; - } else { - /*update exponential weighted moving avarage */ -- mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, -- cur_prob, -- EWMA_LEVEL); -+ mrs->prob_avg = minstrel_ewma(mrs->prob_avg, -+ cur_prob, -+ EWMA_LEVEL); - } - mrs->att_hist += mrs->attempts; - mrs->succ_hist += mrs->success; -@@ -208,8 +208,8 @@ minstrel_update_stats(struct minstrel_pr - - /* Sample less often below the 10% chance of success. - * Sample less often above the 95% chance of success. */ -- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || -- mrs->prob_ewma < MINSTREL_FRAC(10, 100)) { -+ 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; -@@ -229,14 +229,14 @@ minstrel_update_stats(struct minstrel_pr - * 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_ewma >= MINSTREL_FRAC(95, 100)) { -- tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma); -+ 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_ewma); -+ tmp_mrs->prob_avg); - if (tmp_cur_tp >= tmp_prob_tp) - tmp_prob_rate = i; - } else { -- if (mrs->prob_ewma >= tmp_mrs->prob_ewma) -+ if (mrs->prob_avg >= tmp_mrs->prob_avg) - tmp_prob_rate = i; - } - } -@@ -426,7 +426,7 @@ minstrel_get_rate(void *priv, struct iee - * 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_ewma > MINSTREL_FRAC(95, 100))) -+ (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100))) - return; - - mi->prev_sample = true; -@@ -577,7 +577,7 @@ static u32 minstrel_get_expected_through - * computing cur_tp - */ - tmp_mrs = &mi->r[idx].stats; -- tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10; -+ 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; ---- a/net/mac80211/rc80211_minstrel.h -+++ b/net/mac80211/rc80211_minstrel.h -@@ -47,14 +47,10 @@ minstrel_ewma(int old, int new, int weig - return old + incr; - } - --struct minstrel_avg_ctx { -- s32 prev[2]; --}; -- --static inline int minstrel_filter_avg_add(struct minstrel_avg_ctx *ctx, s32 in) -+static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) - { -- s32 out_1 = ctx->prev[0]; -- s32 out_2 = ctx->prev[1]; -+ s32 out_1 = *prev_1; -+ s32 out_2 = *prev_2; - s32 val; - - if (!in) -@@ -76,8 +72,8 @@ static inline int minstrel_filter_avg_ad - val = 1; - - out: -- ctx->prev[1] = out_1; -- ctx->prev[0] = val; -+ *prev_2 = out_1; -+ *prev_1 = val; - - return val; - } -@@ -90,10 +86,9 @@ struct minstrel_rate_stats { - /* total attempts/success counters */ - u32 att_hist, succ_hist; - -- struct minstrel_avg_ctx avg; -- -- /* prob_ewma - exponential weighted moving average of prob */ -- u16 prob_ewma; -+ /* prob_avg - moving average of prob */ -+ u16 prob_avg; -+ u16 prob_avg_1; - - /* maximum retry counts */ - u8 retry_count; -@@ -181,7 +176,7 @@ void minstrel_add_sta_debugfs(void *priv - /* 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_ewma); -+int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg); - - /* debugfs */ - int minstrel_stats_open(struct inode *inode, struct file *file); ---- a/net/mac80211/rc80211_minstrel_debugfs.c -+++ b/net/mac80211/rc80211_minstrel_debugfs.c -@@ -90,8 +90,8 @@ minstrel_stats_open(struct inode *inode, - 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_ewma); -- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); -+ 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 " -@@ -147,8 +147,8 @@ minstrel_stats_csv_open(struct inode *in - 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_ewma); -- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); -+ 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", ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -346,12 +346,12 @@ minstrel_ht_avg_ampdu_len(struct minstre - */ - int - minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, -- int prob_ewma) -+ int prob_avg) - { - unsigned int nsecs = 0; - - /* do not account throughput if sucess prob is below 10% */ -- if (prob_ewma < MINSTREL_FRAC(10, 100)) -+ if (prob_avg < MINSTREL_FRAC(10, 100)) - return 0; - - if (group != MINSTREL_CCK_GROUP) -@@ -365,11 +365,11 @@ minstrel_ht_get_tp_avg(struct minstrel_h - * account for collision related packet error rate fluctuation - * (prob is scaled - see MINSTREL_FRAC above) - */ -- if (prob_ewma > MINSTREL_FRAC(90, 100)) -+ if (prob_avg > MINSTREL_FRAC(90, 100)) - return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000) - / nsecs)); - else -- return MINSTREL_TRUNC(100000 * ((prob_ewma * 1000) / nsecs)); -+ return MINSTREL_TRUNC(100000 * ((prob_avg * 1000) / nsecs)); - } - - /* -@@ -389,13 +389,13 @@ minstrel_ht_sort_best_tp_rates(struct mi - - cur_group = index / MCS_GROUP_RATES; - cur_idx = index % MCS_GROUP_RATES; -- cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma; -+ 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_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; -+ 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 (cur_tp_avg < tmp_tp_avg || -@@ -432,7 +432,7 @@ minstrel_ht_set_best_prob_rate(struct mi - - tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; - tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; -- tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; -+ 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 -@@ -444,11 +444,11 @@ minstrel_ht_set_best_prob_rate(struct mi - - 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_ewma; -+ max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; - -- if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) { -+ if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) { - cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, -- mrs->prob_ewma); -+ mrs->prob_avg); - if (cur_tp_avg > tmp_tp_avg) - mi->max_prob_rate = index; - -@@ -458,9 +458,9 @@ minstrel_ht_set_best_prob_rate(struct mi - if (cur_tp_avg > max_gpr_tp_avg) - mg->max_group_prob_rate = index; - } else { -- if (mrs->prob_ewma > tmp_prob) -+ if (mrs->prob_avg > tmp_prob) - mi->max_prob_rate = index; -- if (mrs->prob_ewma > max_gpr_prob) -+ if (mrs->prob_avg > max_gpr_prob) - mg->max_group_prob_rate = index; - } - } -@@ -482,12 +482,12 @@ minstrel_ht_assign_best_tp_rates(struct - - tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; - tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; -- tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; -+ 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_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; -+ 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); - - if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) { -@@ -518,7 +518,7 @@ minstrel_ht_prob_rate_reduce_streams(str - continue; - - tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; -- tmp_prob = mi->groups[group].rates[tmp_idx].prob_ewma; -+ tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg; - - if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) && - (minstrel_mcs_groups[group].streams < tmp_max_streams)) { -@@ -623,7 +623,7 @@ minstrel_ht_rate_sample_switch(struct mi - * 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_ewma > MINSTREL_FRAC(75, 100); -+ 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); -@@ -738,7 +738,7 @@ minstrel_ht_update_stats(struct minstrel - mrs = &mg->rates[i]; - mrs->retry_updated = false; - minstrel_calc_rate_stats(mp, mrs); -- cur_prob = mrs->prob_ewma; -+ cur_prob = mrs->prob_avg; - - if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) - continue; -@@ -1012,7 +1012,7 @@ minstrel_calc_retransmit(struct minstrel - unsigned int overhead = 0, overhead_rtscts = 0; - - mrs = minstrel_get_ratestats(mi, index); -- if (mrs->prob_ewma < MINSTREL_FRAC(1, 10)) { -+ if (mrs->prob_avg < MINSTREL_FRAC(1, 10)) { - mrs->retry_count = 1; - mrs->retry_count_rtscts = 1; - return; -@@ -1069,7 +1069,7 @@ minstrel_ht_set_rate(struct minstrel_pri - if (!mrs->retry_updated) - minstrel_calc_retransmit(mp, mi, index); - -- if (mrs->prob_ewma < MINSTREL_FRAC(20, 100) || !mrs->retry_count) { -+ if (mrs->prob_avg < MINSTREL_FRAC(20, 100) || !mrs->retry_count) { - ratetbl->rate[offset].count = 2; - ratetbl->rate[offset].count_rts = 2; - ratetbl->rate[offset].count_cts = 2; -@@ -1103,11 +1103,11 @@ minstrel_ht_set_rate(struct minstrel_pri - } - - static inline int --minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate) -+minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate) - { - int group = rate / MCS_GROUP_RATES; - rate %= MCS_GROUP_RATES; -- return mi->groups[group].rates[rate].prob_ewma; -+ return mi->groups[group].rates[rate].prob_avg; - } - - static int -@@ -1119,7 +1119,7 @@ minstrel_ht_get_max_amsdu_len(struct min - unsigned int duration; - - /* Disable A-MSDU if max_prob_rate is bad */ -- if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100)) -+ if (mi->groups[group].rates[rate].prob_avg < MINSTREL_FRAC(50, 100)) - return 1; - - duration = g->duration[rate]; -@@ -1142,7 +1142,7 @@ minstrel_ht_get_max_amsdu_len(struct min - * data packet size - */ - if (duration > MCS_DURATION(1, 0, 260) || -- (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) < -+ (minstrel_ht_get_prob_avg(mi, mi->max_tp_rate[0]) < - MINSTREL_FRAC(75, 100))) - return 3200; - -@@ -1247,7 +1247,7 @@ minstrel_get_sample_rate(struct minstrel - * rate, to avoid wasting airtime. - */ - sample_dur = minstrel_get_duration(sample_idx); -- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || -+ if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || - minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur) - return -1; - -@@ -1711,7 +1711,7 @@ static u32 minstrel_ht_get_expected_thro - - 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_ewma; -+ prob = mi->groups[i].rates[j].prob_avg; - - /* convert tp_avg from pkt per second in kbps */ - tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10; ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -119,6 +119,6 @@ struct minstrel_ht_sta_priv { - - 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_ewma); -+ int prob_avg); - - #endif ---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c -+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c -@@ -98,8 +98,8 @@ minstrel_ht_stats_dump(struct minstrel_h - p += sprintf(p, "%6u ", tx_time); - - tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); -- tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); -- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); -+ tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg); -+ eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); - - p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u" - " %3u %3u %-3u " -@@ -243,8 +243,8 @@ minstrel_ht_stats_csv_dump(struct minstr - p += sprintf(p, "%u,", tx_time); - - tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); -- tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); -- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); -+ tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg); -+ eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); - - p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u," - "%u,%llu,%llu,", diff --git a/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch index d65e52f631..d09d70725e 100644 --- a/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch +++ b/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch @@ -28,7 +28,7 @@ Signed-off-by: Johannes Berg --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -325,6 +325,7 @@ struct sta_info *sta_info_alloc(struct i +@@ -357,6 +357,7 @@ struct sta_info *sta_info_alloc(struct i INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); diff --git a/package/kernel/mac80211/patches/subsys/305-mac80211-fix-tx-status-for-no-ack-cases.patch b/package/kernel/mac80211/patches/subsys/305-mac80211-fix-tx-status-for-no-ack-cases.patch deleted file mode 100644 index 078478174c..0000000000 --- a/package/kernel/mac80211/patches/subsys/305-mac80211-fix-tx-status-for-no-ack-cases.patch +++ /dev/null @@ -1,82 +0,0 @@ -From: Markus Theil -Date: Wed, 18 Dec 2019 15:27:36 +0100 -Subject: [PATCH] mac80211: fix tx status for no ack cases - -Before this patch, frames which where successfully transmitted without -requiring acks where accounted as lost frames. - -Signed-off-by: Markus Theil -Link: https://lore.kernel.org/r/20191218142736.15843-1-markus.theil@tu-ilmenau.de -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -880,6 +880,7 @@ static void __ieee80211_tx_status(struct - int rates_idx; - bool send_to_cooked; - bool acked; -+ bool noack_success; - struct ieee80211_bar *bar; - int shift = 0; - int tid = IEEE80211_NUM_TIDS; -@@ -897,6 +898,8 @@ static void __ieee80211_tx_status(struct - clear_sta_flag(sta, WLAN_STA_SP); - - acked = !!(info->flags & IEEE80211_TX_STAT_ACK); -+ noack_success = !!(info->flags & -+ IEEE80211_TX_STAT_NOACK_TRANSMITTED); - - /* mesh Peer Service Period support */ - if (ieee80211_vif_is_mesh(&sta->sdata->vif) && -@@ -961,12 +964,12 @@ static void __ieee80211_tx_status(struct - ieee80211_handle_filtered_frame(local, sta, skb); - return; - } else { -- if (!acked) -+ if (!acked && !noack_success) - sta->status_stats.retry_failed++; - sta->status_stats.retry_count += retry_count; - - if (ieee80211_is_data_present(fc)) { -- if (!acked) -+ if (!acked && !noack_success) - sta->status_stats.msdu_failed[tid]++; - - sta->status_stats.msdu_retries[tid] += -@@ -993,7 +996,7 @@ static void __ieee80211_tx_status(struct - info->status.tx_time, 0); - - if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { -- if (info->flags & IEEE80211_TX_STAT_ACK) { -+ if (acked) { - if (sta->status_stats.lost_packets) - sta->status_stats.lost_packets = 0; - -@@ -1001,6 +1004,8 @@ static void __ieee80211_tx_status(struct - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) - sta->status_stats.last_tdls_pkt_time = - jiffies; -+ } else if (noack_success) { -+ /* nothing to do here, do not account as lost */ - } else { - ieee80211_lost_packet(sta, info); - } -@@ -1127,7 +1132,7 @@ void ieee80211_tx_status_ext(struct ieee - - sta = container_of(pubsta, struct sta_info, sta); - -- if (!acked) -+ if (!acked && !noack_success) - sta->status_stats.retry_failed++; - sta->status_stats.retry_count += retry_count; - -@@ -1142,6 +1147,8 @@ void ieee80211_tx_status_ext(struct ieee - sta->status_stats.last_tdls_pkt_time = jiffies; - } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) { - return; -+ } else if (noack_success) { -+ /* nothing to do here, do not account as lost */ - } else { - ieee80211_lost_packet(sta, info); - } diff --git a/package/kernel/mac80211/patches/subsys/306-mac80211-move-store-skb-ack-code-to-its-own-function.patch b/package/kernel/mac80211/patches/subsys/306-mac80211-move-store-skb-ack-code-to-its-own-function.patch deleted file mode 100644 index 4f0a699c80..0000000000 --- a/package/kernel/mac80211/patches/subsys/306-mac80211-move-store-skb-ack-code-to-its-own-function.patch +++ /dev/null @@ -1,78 +0,0 @@ -From: John Crispin -Date: Tue, 29 Oct 2019 10:13:02 +0100 -Subject: [PATCH] mac80211: move store skb ack code to its own function - -This patch moves the code handling SKBTX_WIFI_STATUS inside the TX path -into an extra function. This allows us to reuse it inside the 802.11 encap -offloading datapath. - -Signed-off-by: John Crispin -Link: https://lore.kernel.org/r/20191029091304.7330-2-john@phrozen.org -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -2445,6 +2445,33 @@ static int ieee80211_lookup_ra_sta(struc - return 0; - } - -+static int ieee80211_store_ack_skb(struct ieee80211_local *local, -+ struct sk_buff *skb, -+ u32 *info_flags) -+{ -+ struct sk_buff *ack_skb = skb_clone_sk(skb); -+ u16 info_id = 0; -+ -+ if (ack_skb) { -+ unsigned long flags; -+ int id; -+ -+ spin_lock_irqsave(&local->ack_status_lock, flags); -+ id = idr_alloc(&local->ack_status_frames, ack_skb, -+ 1, 0x10000, GFP_ATOMIC); -+ spin_unlock_irqrestore(&local->ack_status_lock, flags); -+ -+ if (id >= 0) { -+ info_id = id; -+ *info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; -+ } else { -+ kfree_skb(ack_skb); -+ } -+ } -+ -+ return info_id; -+} -+ - /** - * ieee80211_build_hdr - build 802.11 header in the given frame - * @sdata: virtual interface to build the header for -@@ -2738,26 +2765,8 @@ static struct sk_buff *ieee80211_build_h - } - - if (unlikely(!multicast && skb->sk && -- skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) { -- struct sk_buff *ack_skb = skb_clone_sk(skb); -- -- if (ack_skb) { -- unsigned long flags; -- int id; -- -- spin_lock_irqsave(&local->ack_status_lock, flags); -- id = idr_alloc(&local->ack_status_frames, ack_skb, -- 1, 0x10000, GFP_ATOMIC); -- spin_unlock_irqrestore(&local->ack_status_lock, flags); -- -- if (id >= 0) { -- info_id = id; -- info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; -- } else { -- kfree_skb(ack_skb); -- } -- } -- } -+ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) -+ info_id = ieee80211_store_ack_skb(local, skb, &info_flags); - - /* - * If the skb is shared we need to obtain our own copy. diff --git a/package/kernel/mac80211/patches/subsys/307-mac80211-Shrink-the-size-of-ack_frame_id-to-make-roo.patch b/package/kernel/mac80211/patches/subsys/307-mac80211-Shrink-the-size-of-ack_frame_id-to-make-roo.patch deleted file mode 100644 index 10eb9d7008..0000000000 --- a/package/kernel/mac80211/patches/subsys/307-mac80211-Shrink-the-size-of-ack_frame_id-to-make-roo.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= -Date: Wed, 23 Oct 2019 11:59:00 +0200 -Subject: [PATCH] mac80211: Shrink the size of ack_frame_id to make room for - tx_time_est -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -To implement airtime queue limiting, we need to keep a running account of -the estimated airtime of all skbs queued into the device. Do to this -correctly, we need to store the airtime estimate into the skb so we can -decrease the outstanding balance when the skb is freed. This means that the -time estimate must be stored somewhere that will survive for the lifetime -of the skb. - -To get this, decrease the size of the ack_frame_id field to 6 bits, and -lower the size of the ID space accordingly. This leaves 10 bits for use for -tx_time_est, which is enough to store a maximum of 4096 us, if we shift the -values so they become units of 4us. - -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/157182474063.150713.16132669599100802716.stgit@toke.dk -Signed-off-by: Johannes Berg ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -967,6 +967,7 @@ ieee80211_rate_get_vht_nss(const struct - * @band: the band to transmit on (use for checking for races) - * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC - * @ack_frame_id: internal frame ID for TX status, used internally -+ * @tx_time_est: TX time estimate in units of 4us, used internally - * @control: union part for control data - * @control.rates: TX rates array to try - * @control.rts_cts_rate_idx: rate for RTS or CTS -@@ -1007,7 +1008,8 @@ struct ieee80211_tx_info { - - u8 hw_queue; - -- u16 ack_frame_id; -+ u16 ack_frame_id:6; -+ u16 tx_time_est:10; - - union { - struct { ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -3450,7 +3450,7 @@ int ieee80211_attach_ack_skb(struct ieee - - spin_lock_irqsave(&local->ack_status_lock, spin_flags); - id = idr_alloc(&local->ack_status_frames, ack_skb, -- 1, 0x10000, GFP_ATOMIC); -+ 1, 0x40, GFP_ATOMIC); - spin_unlock_irqrestore(&local->ack_status_lock, spin_flags); - - if (id < 0) { ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -2458,7 +2458,7 @@ static int ieee80211_store_ack_skb(struc - - spin_lock_irqsave(&local->ack_status_lock, flags); - id = idr_alloc(&local->ack_status_frames, ack_skb, -- 1, 0x10000, GFP_ATOMIC); -+ 1, 0x40, GFP_ATOMIC); - spin_unlock_irqrestore(&local->ack_status_lock, flags); - - if (id >= 0) { diff --git a/package/kernel/mac80211/patches/subsys/308-mac80211-Add-new-sta_info-getter-by-sta-vif-addrs.patch b/package/kernel/mac80211/patches/subsys/308-mac80211-Add-new-sta_info-getter-by-sta-vif-addrs.patch deleted file mode 100644 index a5a63d927d..0000000000 --- a/package/kernel/mac80211/patches/subsys/308-mac80211-Add-new-sta_info-getter-by-sta-vif-addrs.patch +++ /dev/null @@ -1,78 +0,0 @@ -From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= -Date: Tue, 12 Nov 2019 14:08:35 +0100 -Subject: [PATCH] mac80211: Add new sta_info getter by sta/vif addrs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In ieee80211_tx_status() we don't have an sdata struct when looking up the -destination sta. Instead, we just do a lookup by the vif addr that is the -source of the packet being completed. Factor this out into a new sta_info -getter helper, since we need to use it for accounting AQL as well. - -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20191112130835.382062-1-toke@redhat.com -[remove internal rcu_read_lock(), document instead] -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -210,6 +210,20 @@ struct sta_info *sta_info_get_bss(struct - return NULL; - } - -+struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local, -+ const u8 *sta_addr, const u8 *vif_addr) -+{ -+ struct rhlist_head *tmp; -+ struct sta_info *sta; -+ -+ for_each_sta_info(local, sta_addr, sta, tmp) { -+ if (ether_addr_equal(vif_addr, sta->sdata->vif.addr)) -+ return sta; -+ } -+ -+ return NULL; -+} -+ - struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, - int idx) - { ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -726,6 +726,10 @@ struct sta_info *sta_info_get(struct iee - struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, - const u8 *addr); - -+/* user must hold sta_mtx or be in RCU critical section */ -+struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local, -+ const u8 *sta_addr, const u8 *vif_addr); -+ - #define for_each_sta_info(local, _addr, _sta, _tmp) \ - rhl_for_each_entry_rcu(_sta, _tmp, \ - sta_info_hash_lookup(local, _addr), hash_node) ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -1085,19 +1085,13 @@ void ieee80211_tx_status(struct ieee8021 - .skb = skb, - .info = IEEE80211_SKB_CB(skb), - }; -- struct rhlist_head *tmp; - struct sta_info *sta; - - rcu_read_lock(); - -- for_each_sta_info(local, hdr->addr1, sta, tmp) { -- /* skip wrong virtual interface */ -- if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) -- continue; -- -+ sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2); -+ if (sta) - status.sta = &sta->sta; -- break; -- } - - __ieee80211_tx_status(hw, &status); - rcu_read_unlock(); diff --git a/package/kernel/mac80211/patches/subsys/309-mac80211-Import-airtime-calculation-code-from-mt76.patch b/package/kernel/mac80211/patches/subsys/309-mac80211-Import-airtime-calculation-code-from-mt76.patch deleted file mode 100644 index 7f049b8d0c..0000000000 --- a/package/kernel/mac80211/patches/subsys/309-mac80211-Import-airtime-calculation-code-from-mt76.patch +++ /dev/null @@ -1,690 +0,0 @@ -From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= -Date: Mon, 18 Nov 2019 22:06:08 -0800 -Subject: [PATCH] mac80211: Import airtime calculation code from mt76 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Felix recently added code to calculate airtime of packets to the mt76 -driver. Import this into mac80211 so we can use it for airtime queue limit -calculations. - -The airtime.c file is copied verbatim from the mt76 driver, and adjusted to -be usable in mac80211. This involves: - -- Switching to mac80211 data structures. -- Adding support for 160 MHz channels and HE mode. -- Moving the symbol and duration calculations around a bit to avoid - rounding with the higher rates and longer symbol times used for HE rates. - -The per-rate TX rate calculation is also split out to its own function so -it can be used directly for the AQL calculations later. - -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20191119060610.76681-3-kyan@google.com -[fix HE_GROUP_IDX() to use 3 * bw, since there are 3 _gi values] -Signed-off-by: Johannes Berg ---- - create mode 100644 net/mac80211/airtime.c - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -6419,4 +6419,33 @@ void ieee80211_nan_func_match(struct iee - struct cfg80211_nan_match_params *match, - gfp_t gfp); - -+/** -+ * ieee80211_calc_rx_airtime - calculate estimated transmission airtime for RX. -+ * -+ * This function calculates the estimated airtime usage of a frame based on the -+ * rate information in the RX status struct and the frame length. -+ * -+ * @hw: pointer as obtained from ieee80211_alloc_hw() -+ * @status: &struct ieee80211_rx_status containing the transmission rate -+ * information. -+ * @len: frame length in bytes -+ */ -+u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw, -+ struct ieee80211_rx_status *status, -+ int len); -+ -+/** -+ * ieee80211_calc_tx_airtime - calculate estimated transmission airtime for TX. -+ * -+ * This function calculates the estimated airtime usage of a frame based on the -+ * rate information in the TX info struct and the frame length. -+ * -+ * @hw: pointer as obtained from ieee80211_alloc_hw() -+ * @info: &struct ieee80211_tx_info of the frame. -+ * @len: frame length in bytes -+ */ -+u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw, -+ struct ieee80211_tx_info *info, -+ int len); -+ - #endif /* MAC80211_H */ ---- a/net/mac80211/Makefile -+++ b/net/mac80211/Makefile -@@ -31,7 +31,8 @@ mac80211-y := \ - chan.o \ - trace.o mlme.o \ - tdls.o \ -- ocb.o -+ ocb.o \ -+ airtime.o - - mac80211-$(CPTCFG_MAC80211_LEDS) += led.o - mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \ ---- /dev/null -+++ b/net/mac80211/airtime.c -@@ -0,0 +1,597 @@ -+// SPDX-License-Identifier: ISC -+/* -+ * Copyright (C) 2019 Felix Fietkau -+ */ -+ -+#include -+#include "ieee80211_i.h" -+#include "sta_info.h" -+ -+#define AVG_PKT_SIZE 1024 -+ -+/* Number of bits for an average sized packet */ -+#define MCS_NBITS (AVG_PKT_SIZE << 3) -+ -+/* Number of kilo-symbols (symbols * 1024) for a packet with (bps) bits per -+ * symbol. We use k-symbols to avoid rounding in the _TIME macros below. -+ */ -+#define MCS_N_KSYMS(bps) DIV_ROUND_UP(MCS_NBITS << 10, (bps)) -+ -+/* Transmission time (in 1024 * usec) for a packet containing (ksyms) * 1024 -+ * symbols. -+ */ -+#define MCS_SYMBOL_TIME(sgi, ksyms) \ -+ (sgi ? \ -+ ((ksyms) * 4 * 18) / 20 : /* 3.6 us per sym */ \ -+ ((ksyms) * 4) /* 4.0 us per sym */ \ -+ ) -+ -+/* Transmit duration for the raw data part of an average sized packet */ -+#define MCS_DURATION(streams, sgi, bps) \ -+ ((u32)MCS_SYMBOL_TIME(sgi, MCS_N_KSYMS((streams) * (bps)))) -+ -+#define MCS_DURATION_S(shift, streams, sgi, bps) \ -+ ((u16)((MCS_DURATION(streams, sgi, bps) >> shift))) -+ -+/* These should match the values in enum nl80211_he_gi */ -+#define HE_GI_08 0 -+#define HE_GI_16 1 -+#define HE_GI_32 2 -+ -+/* Transmission time (1024 usec) for a packet containing (ksyms) * k-symbols */ -+#define HE_SYMBOL_TIME(gi, ksyms) \ -+ (gi == HE_GI_08 ? \ -+ ((ksyms) * 16 * 17) / 20 : /* 13.6 us per sym */ \ -+ (gi == HE_GI_16 ? \ -+ ((ksyms) * 16 * 18) / 20 : /* 14.4 us per sym */ \ -+ ((ksyms) * 16) /* 16.0 us per sym */ \ -+ )) -+ -+/* Transmit duration for the raw data part of an average sized packet */ -+#define HE_DURATION(streams, gi, bps) \ -+ ((u32)HE_SYMBOL_TIME(gi, MCS_N_KSYMS((streams) * (bps)))) -+ -+#define HE_DURATION_S(shift, streams, gi, bps) \ -+ (HE_DURATION(streams, gi, bps) >> shift) -+ -+#define BW_20 0 -+#define BW_40 1 -+#define BW_80 2 -+#define BW_160 3 -+ -+/* -+ * Define group sort order: HT40 -> SGI -> #streams -+ */ -+#define IEEE80211_MAX_STREAMS 4 -+#define IEEE80211_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */ -+#define IEEE80211_VHT_STREAM_GROUPS 8 /* BW(=4) * SGI(=2) */ -+ -+#define IEEE80211_HE_MAX_STREAMS 8 -+#define IEEE80211_HE_STREAM_GROUPS 12 /* BW(=4) * GI(=3) */ -+ -+#define IEEE80211_HT_GROUPS_NB (IEEE80211_MAX_STREAMS * \ -+ IEEE80211_HT_STREAM_GROUPS) -+#define IEEE80211_VHT_GROUPS_NB (IEEE80211_MAX_STREAMS * \ -+ IEEE80211_VHT_STREAM_GROUPS) -+#define IEEE80211_HE_GROUPS_NB (IEEE80211_HE_MAX_STREAMS * \ -+ IEEE80211_HE_STREAM_GROUPS) -+#define IEEE80211_GROUPS_NB (IEEE80211_HT_GROUPS_NB + \ -+ IEEE80211_VHT_GROUPS_NB + \ -+ IEEE80211_HE_GROUPS_NB) -+ -+#define IEEE80211_HT_GROUP_0 0 -+#define IEEE80211_VHT_GROUP_0 (IEEE80211_HT_GROUP_0 + IEEE80211_HT_GROUPS_NB) -+#define IEEE80211_HE_GROUP_0 (IEEE80211_VHT_GROUP_0 + IEEE80211_VHT_GROUPS_NB) -+ -+#define MCS_GROUP_RATES 12 -+ -+#define HT_GROUP_IDX(_streams, _sgi, _ht40) \ -+ IEEE80211_HT_GROUP_0 + \ -+ IEEE80211_MAX_STREAMS * 2 * _ht40 + \ -+ IEEE80211_MAX_STREAMS * _sgi + \ -+ _streams - 1 -+ -+#define _MAX(a, b) (((a)>(b))?(a):(b)) -+ -+#define GROUP_SHIFT(duration) \ -+ _MAX(0, 16 - __builtin_clz(duration)) -+ -+/* MCS rate information for an MCS group */ -+#define __MCS_GROUP(_streams, _sgi, _ht40, _s) \ -+ [HT_GROUP_IDX(_streams, _sgi, _ht40)] = { \ -+ .shift = _s, \ -+ .duration = { \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 54 : 26), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 108 : 52), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 162 : 78), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 216 : 104), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 324 : 156), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 432 : 208), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 486 : 234), \ -+ MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 540 : 260) \ -+ } \ -+} -+ -+#define MCS_GROUP_SHIFT(_streams, _sgi, _ht40) \ -+ GROUP_SHIFT(MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26)) -+ -+#define MCS_GROUP(_streams, _sgi, _ht40) \ -+ __MCS_GROUP(_streams, _sgi, _ht40, \ -+ MCS_GROUP_SHIFT(_streams, _sgi, _ht40)) -+ -+#define VHT_GROUP_IDX(_streams, _sgi, _bw) \ -+ (IEEE80211_VHT_GROUP_0 + \ -+ IEEE80211_MAX_STREAMS * 2 * (_bw) + \ -+ IEEE80211_MAX_STREAMS * (_sgi) + \ -+ (_streams) - 1) -+ -+#define BW2VBPS(_bw, r4, r3, r2, r1) \ -+ (_bw == BW_160 ? r4 : _bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1) -+ -+#define __VHT_GROUP(_streams, _sgi, _bw, _s) \ -+ [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \ -+ .shift = _s, \ -+ .duration = { \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 234, 117, 54, 26)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 468, 234, 108, 52)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 702, 351, 162, 78)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 936, 468, 216, 104)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 1404, 702, 324, 156)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 1872, 936, 432, 208)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 2106, 1053, 486, 234)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 2340, 1170, 540, 260)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 2808, 1404, 648, 312)), \ -+ MCS_DURATION_S(_s, _streams, _sgi, \ -+ BW2VBPS(_bw, 3120, 1560, 720, 346)) \ -+ } \ -+} -+ -+#define VHT_GROUP_SHIFT(_streams, _sgi, _bw) \ -+ GROUP_SHIFT(MCS_DURATION(_streams, _sgi, \ -+ BW2VBPS(_bw, 243, 117, 54, 26))) -+ -+#define VHT_GROUP(_streams, _sgi, _bw) \ -+ __VHT_GROUP(_streams, _sgi, _bw, \ -+ VHT_GROUP_SHIFT(_streams, _sgi, _bw)) -+ -+ -+#define HE_GROUP_IDX(_streams, _gi, _bw) \ -+ (IEEE80211_HE_GROUP_0 + \ -+ IEEE80211_HE_MAX_STREAMS * 3 * (_bw) + \ -+ IEEE80211_HE_MAX_STREAMS * (_gi) + \ -+ (_streams) - 1) -+ -+#define __HE_GROUP(_streams, _gi, _bw, _s) \ -+ [HE_GROUP_IDX(_streams, _gi, _bw)] = { \ -+ .shift = _s, \ -+ .duration = { \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 979, 489, 230, 115)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 1958, 979, 475, 230)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 2937, 1468, 705, 345)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 3916, 1958, 936, 475)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 5875, 2937, 1411, 705)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 7833, 3916, 1872, 936)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 8827, 4406, 2102, 1051)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 9806, 4896, 2347, 1166)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 11764, 5875, 2808, 1411)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 13060, 6523, 3124, 1555)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 14702, 7344, 3513, 1756)), \ -+ HE_DURATION_S(_s, _streams, _gi, \ -+ BW2VBPS(_bw, 16329, 8164, 3902, 1944)) \ -+ } \ -+} -+ -+#define HE_GROUP_SHIFT(_streams, _gi, _bw) \ -+ GROUP_SHIFT(HE_DURATION(_streams, _gi, \ -+ BW2VBPS(_bw, 979, 489, 230, 115))) -+ -+#define HE_GROUP(_streams, _gi, _bw) \ -+ __HE_GROUP(_streams, _gi, _bw, \ -+ HE_GROUP_SHIFT(_streams, _gi, _bw)) -+struct mcs_group { -+ u8 shift; -+ u16 duration[MCS_GROUP_RATES]; -+}; -+ -+static const struct mcs_group airtime_mcs_groups[] = { -+ MCS_GROUP(1, 0, BW_20), -+ MCS_GROUP(2, 0, BW_20), -+ MCS_GROUP(3, 0, BW_20), -+ MCS_GROUP(4, 0, BW_20), -+ -+ MCS_GROUP(1, 1, BW_20), -+ MCS_GROUP(2, 1, BW_20), -+ MCS_GROUP(3, 1, BW_20), -+ MCS_GROUP(4, 1, BW_20), -+ -+ MCS_GROUP(1, 0, BW_40), -+ MCS_GROUP(2, 0, BW_40), -+ MCS_GROUP(3, 0, BW_40), -+ MCS_GROUP(4, 0, BW_40), -+ -+ MCS_GROUP(1, 1, BW_40), -+ MCS_GROUP(2, 1, BW_40), -+ MCS_GROUP(3, 1, BW_40), -+ MCS_GROUP(4, 1, BW_40), -+ -+ VHT_GROUP(1, 0, BW_20), -+ VHT_GROUP(2, 0, BW_20), -+ VHT_GROUP(3, 0, BW_20), -+ VHT_GROUP(4, 0, BW_20), -+ -+ VHT_GROUP(1, 1, BW_20), -+ VHT_GROUP(2, 1, BW_20), -+ VHT_GROUP(3, 1, BW_20), -+ VHT_GROUP(4, 1, BW_20), -+ -+ VHT_GROUP(1, 0, BW_40), -+ VHT_GROUP(2, 0, BW_40), -+ VHT_GROUP(3, 0, BW_40), -+ VHT_GROUP(4, 0, BW_40), -+ -+ VHT_GROUP(1, 1, BW_40), -+ VHT_GROUP(2, 1, BW_40), -+ VHT_GROUP(3, 1, BW_40), -+ VHT_GROUP(4, 1, BW_40), -+ -+ VHT_GROUP(1, 0, BW_80), -+ VHT_GROUP(2, 0, BW_80), -+ VHT_GROUP(3, 0, BW_80), -+ VHT_GROUP(4, 0, BW_80), -+ -+ VHT_GROUP(1, 1, BW_80), -+ VHT_GROUP(2, 1, BW_80), -+ VHT_GROUP(3, 1, BW_80), -+ VHT_GROUP(4, 1, BW_80), -+ -+ VHT_GROUP(1, 0, BW_160), -+ VHT_GROUP(2, 0, BW_160), -+ VHT_GROUP(3, 0, BW_160), -+ VHT_GROUP(4, 0, BW_160), -+ -+ VHT_GROUP(1, 1, BW_160), -+ VHT_GROUP(2, 1, BW_160), -+ VHT_GROUP(3, 1, BW_160), -+ VHT_GROUP(4, 1, BW_160), -+ -+ HE_GROUP(1, HE_GI_08, BW_20), -+ HE_GROUP(2, HE_GI_08, BW_20), -+ HE_GROUP(3, HE_GI_08, BW_20), -+ HE_GROUP(4, HE_GI_08, BW_20), -+ HE_GROUP(5, HE_GI_08, BW_20), -+ HE_GROUP(6, HE_GI_08, BW_20), -+ HE_GROUP(7, HE_GI_08, BW_20), -+ HE_GROUP(8, HE_GI_08, BW_20), -+ -+ HE_GROUP(1, HE_GI_16, BW_20), -+ HE_GROUP(2, HE_GI_16, BW_20), -+ HE_GROUP(3, HE_GI_16, BW_20), -+ HE_GROUP(4, HE_GI_16, BW_20), -+ HE_GROUP(5, HE_GI_16, BW_20), -+ HE_GROUP(6, HE_GI_16, BW_20), -+ HE_GROUP(7, HE_GI_16, BW_20), -+ HE_GROUP(8, HE_GI_16, BW_20), -+ -+ HE_GROUP(1, HE_GI_32, BW_20), -+ HE_GROUP(2, HE_GI_32, BW_20), -+ HE_GROUP(3, HE_GI_32, BW_20), -+ HE_GROUP(4, HE_GI_32, BW_20), -+ HE_GROUP(5, HE_GI_32, BW_20), -+ HE_GROUP(6, HE_GI_32, BW_20), -+ HE_GROUP(7, HE_GI_32, BW_20), -+ HE_GROUP(8, HE_GI_32, BW_20), -+ -+ HE_GROUP(1, HE_GI_08, BW_40), -+ HE_GROUP(2, HE_GI_08, BW_40), -+ HE_GROUP(3, HE_GI_08, BW_40), -+ HE_GROUP(4, HE_GI_08, BW_40), -+ HE_GROUP(5, HE_GI_08, BW_40), -+ HE_GROUP(6, HE_GI_08, BW_40), -+ HE_GROUP(7, HE_GI_08, BW_40), -+ HE_GROUP(8, HE_GI_08, BW_40), -+ -+ HE_GROUP(1, HE_GI_16, BW_40), -+ HE_GROUP(2, HE_GI_16, BW_40), -+ HE_GROUP(3, HE_GI_16, BW_40), -+ HE_GROUP(4, HE_GI_16, BW_40), -+ HE_GROUP(5, HE_GI_16, BW_40), -+ HE_GROUP(6, HE_GI_16, BW_40), -+ HE_GROUP(7, HE_GI_16, BW_40), -+ HE_GROUP(8, HE_GI_16, BW_40), -+ -+ HE_GROUP(1, HE_GI_32, BW_40), -+ HE_GROUP(2, HE_GI_32, BW_40), -+ HE_GROUP(3, HE_GI_32, BW_40), -+ HE_GROUP(4, HE_GI_32, BW_40), -+ HE_GROUP(5, HE_GI_32, BW_40), -+ HE_GROUP(6, HE_GI_32, BW_40), -+ HE_GROUP(7, HE_GI_32, BW_40), -+ HE_GROUP(8, HE_GI_32, BW_40), -+ -+ HE_GROUP(1, HE_GI_08, BW_80), -+ HE_GROUP(2, HE_GI_08, BW_80), -+ HE_GROUP(3, HE_GI_08, BW_80), -+ HE_GROUP(4, HE_GI_08, BW_80), -+ HE_GROUP(5, HE_GI_08, BW_80), -+ HE_GROUP(6, HE_GI_08, BW_80), -+ HE_GROUP(7, HE_GI_08, BW_80), -+ HE_GROUP(8, HE_GI_08, BW_80), -+ -+ HE_GROUP(1, HE_GI_16, BW_80), -+ HE_GROUP(2, HE_GI_16, BW_80), -+ HE_GROUP(3, HE_GI_16, BW_80), -+ HE_GROUP(4, HE_GI_16, BW_80), -+ HE_GROUP(5, HE_GI_16, BW_80), -+ HE_GROUP(6, HE_GI_16, BW_80), -+ HE_GROUP(7, HE_GI_16, BW_80), -+ HE_GROUP(8, HE_GI_16, BW_80), -+ -+ HE_GROUP(1, HE_GI_32, BW_80), -+ HE_GROUP(2, HE_GI_32, BW_80), -+ HE_GROUP(3, HE_GI_32, BW_80), -+ HE_GROUP(4, HE_GI_32, BW_80), -+ HE_GROUP(5, HE_GI_32, BW_80), -+ HE_GROUP(6, HE_GI_32, BW_80), -+ HE_GROUP(7, HE_GI_32, BW_80), -+ HE_GROUP(8, HE_GI_32, BW_80), -+ -+ HE_GROUP(1, HE_GI_08, BW_160), -+ HE_GROUP(2, HE_GI_08, BW_160), -+ HE_GROUP(3, HE_GI_08, BW_160), -+ HE_GROUP(4, HE_GI_08, BW_160), -+ HE_GROUP(5, HE_GI_08, BW_160), -+ HE_GROUP(6, HE_GI_08, BW_160), -+ HE_GROUP(7, HE_GI_08, BW_160), -+ HE_GROUP(8, HE_GI_08, BW_160), -+ -+ HE_GROUP(1, HE_GI_16, BW_160), -+ HE_GROUP(2, HE_GI_16, BW_160), -+ HE_GROUP(3, HE_GI_16, BW_160), -+ HE_GROUP(4, HE_GI_16, BW_160), -+ HE_GROUP(5, HE_GI_16, BW_160), -+ HE_GROUP(6, HE_GI_16, BW_160), -+ HE_GROUP(7, HE_GI_16, BW_160), -+ HE_GROUP(8, HE_GI_16, BW_160), -+ -+ HE_GROUP(1, HE_GI_32, BW_160), -+ HE_GROUP(2, HE_GI_32, BW_160), -+ HE_GROUP(3, HE_GI_32, BW_160), -+ HE_GROUP(4, HE_GI_32, BW_160), -+ HE_GROUP(5, HE_GI_32, BW_160), -+ HE_GROUP(6, HE_GI_32, BW_160), -+ HE_GROUP(7, HE_GI_32, BW_160), -+ HE_GROUP(8, HE_GI_32, BW_160), -+}; -+ -+static u32 -+ieee80211_calc_legacy_rate_duration(u16 bitrate, bool short_pre, -+ bool cck, int len) -+{ -+ u32 duration; -+ -+ if (cck) { -+ duration = 144 + 48; /* preamble + PLCP */ -+ if (short_pre) -+ duration >>= 1; -+ -+ duration += 10; /* SIFS */ -+ } else { -+ duration = 20 + 16; /* premable + SIFS */ -+ } -+ -+ len <<= 3; -+ duration += (len * 10) / bitrate; -+ -+ return duration; -+} -+ -+u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw, -+ struct ieee80211_rx_status *status, -+ int len) -+{ -+ struct ieee80211_supported_band *sband; -+ const struct ieee80211_rate *rate; -+ bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI; -+ bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE; -+ int bw, streams; -+ int group, idx; -+ u32 duration; -+ bool cck; -+ -+ switch (status->bw) { -+ case RATE_INFO_BW_20: -+ bw = BW_20; -+ break; -+ case RATE_INFO_BW_40: -+ bw = BW_40; -+ break; -+ case RATE_INFO_BW_80: -+ bw = BW_80; -+ break; -+ case RATE_INFO_BW_160: -+ bw = BW_160; -+ break; -+ default: -+ WARN_ON_ONCE(1); -+ return 0; -+ } -+ -+ switch (status->encoding) { -+ case RX_ENC_LEGACY: -+ if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ)) -+ return 0; -+ -+ sband = hw->wiphy->bands[status->band]; -+ if (!sband || status->rate_idx > sband->n_bitrates) -+ return 0; -+ -+ rate = &sband->bitrates[status->rate_idx]; -+ cck = rate->flags & IEEE80211_RATE_MANDATORY_B; -+ -+ return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp, -+ cck, len); -+ -+ case RX_ENC_VHT: -+ streams = status->nss; -+ idx = status->rate_idx; -+ group = VHT_GROUP_IDX(streams, sgi, bw); -+ break; -+ case RX_ENC_HT: -+ streams = ((status->rate_idx >> 3) & 3) + 1; -+ idx = status->rate_idx & 7; -+ group = HT_GROUP_IDX(streams, sgi, bw); -+ break; -+ case RX_ENC_HE: -+ streams = status->nss; -+ idx = status->rate_idx; -+ group = HE_GROUP_IDX(streams, status->he_gi, bw); -+ break; -+ default: -+ WARN_ON_ONCE(1); -+ return 0; -+ } -+ -+ if (WARN_ON_ONCE((status->encoding != RX_ENC_HE && streams > 4) || -+ (status->encoding == RX_ENC_HE && streams > 8))) -+ return 0; -+ -+ duration = airtime_mcs_groups[group].duration[idx]; -+ duration <<= airtime_mcs_groups[group].shift; -+ duration *= len; -+ duration /= AVG_PKT_SIZE; -+ duration /= 1024; -+ -+ duration += 36 + (streams << 2); -+ -+ return duration; -+} -+EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime); -+ -+static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw, -+ struct ieee80211_tx_rate *rate, -+ u8 band, int len) -+{ -+ struct ieee80211_rx_status stat = { -+ .band = band, -+ }; -+ -+ if (rate->idx < 0 || !rate->count) -+ return 0; -+ -+ if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) -+ stat.bw = RATE_INFO_BW_80; -+ else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) -+ stat.bw = RATE_INFO_BW_40; -+ else -+ stat.bw = RATE_INFO_BW_20; -+ -+ stat.enc_flags = 0; -+ if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -+ stat.enc_flags |= RX_ENC_FLAG_SHORTPRE; -+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI) -+ stat.enc_flags |= RX_ENC_FLAG_SHORT_GI; -+ -+ stat.rate_idx = rate->idx; -+ if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { -+ stat.encoding = RX_ENC_VHT; -+ stat.rate_idx = ieee80211_rate_get_vht_mcs(rate); -+ stat.nss = ieee80211_rate_get_vht_nss(rate); -+ } else if (rate->flags & IEEE80211_TX_RC_MCS) { -+ stat.encoding = RX_ENC_HT; -+ } else { -+ stat.encoding = RX_ENC_LEGACY; -+ } -+ -+ return ieee80211_calc_rx_airtime(hw, &stat, len); -+} -+ -+u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw, -+ struct ieee80211_tx_info *info, -+ int len) -+{ -+ u32 duration = 0; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { -+ struct ieee80211_tx_rate *rate = &info->status.rates[i]; -+ u32 cur_duration; -+ -+ cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, -+ info->band, len); -+ if (!cur_duration) -+ break; -+ -+ duration += cur_duration * rate->count; -+ } -+ -+ return duration; -+} -+EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime); -+ -+u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *pubsta, -+ int len) -+{ -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_chanctx_conf *conf; -+ int rateidx, shift = 0; -+ bool cck, short_pream; -+ u32 basic_rates; -+ u8 band = 0; -+ u16 rate; -+ -+ len += 38; /* Ethernet header length */ -+ -+ conf = rcu_dereference(vif->chanctx_conf); -+ if (conf) { -+ band = conf->def.chan->band; -+ shift = ieee80211_chandef_get_shift(&conf->def); -+ } -+ -+ if (pubsta) { -+ struct sta_info *sta = container_of(pubsta, struct sta_info, -+ sta); -+ -+ return ieee80211_calc_tx_airtime_rate(hw, -+ &sta->tx_stats.last_rate, -+ band, len); -+ } -+ -+ if (!conf) -+ return 0; -+ -+ /* No station to get latest rate from, so calculate the worst-case -+ * duration using the lowest configured basic rate. -+ */ -+ sband = hw->wiphy->bands[band]; -+ -+ basic_rates = vif->bss_conf.basic_rates; -+ short_pream = vif->bss_conf.use_short_preamble; -+ -+ rateidx = basic_rates ? ffs(basic_rates) - 1 : 0; -+ rate = sband->bitrates[rateidx].bitrate << shift; -+ cck = sband->bitrates[rateidx].flags & IEEE80211_RATE_MANDATORY_B; -+ -+ return ieee80211_calc_legacy_rate_duration(rate, short_pream, cck, len); -+} ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2253,6 +2253,10 @@ const char *ieee80211_get_reason_code_st - - extern const struct ethtool_ops ieee80211_ethtool_ops; - -+u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *pubsta, -+ int len); - #ifdef CPTCFG_MAC80211_NOINLINE - #define debug_noinline noinline - #else diff --git a/package/kernel/mac80211/patches/subsys/310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch b/package/kernel/mac80211/patches/subsys/310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch deleted file mode 100644 index a82849d80c..0000000000 --- a/package/kernel/mac80211/patches/subsys/310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch +++ /dev/null @@ -1,446 +0,0 @@ -From: Kan Yan -Date: Mon, 18 Nov 2019 22:06:09 -0800 -Subject: [PATCH] mac80211: Implement Airtime-based Queue Limit (AQL) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In order for the Fq_CoDel algorithm integrated in mac80211 layer to operate -effectively to control excessive queueing latency, the CoDel algorithm -requires an accurate measure of how long packets stays in the queue, AKA -sojourn time. The sojourn time measured at the mac80211 layer doesn't -include queueing latency in the lower layer (firmware/hardware) and CoDel -expects lower layer to have a short queue. However, most 802.11ac chipsets -offload tasks such TX aggregation to firmware or hardware, thus have a deep -lower layer queue. - -Without a mechanism to control the lower layer queue size, packets only -stay in mac80211 layer transiently before being sent to firmware queue. -As a result, the sojourn time measured by CoDel in the mac80211 layer is -almost always lower than the CoDel latency target, hence CoDel does little -to control the latency, even when the lower layer queue causes excessive -latency. - -The Byte Queue Limits (BQL) mechanism is commonly used to address the -similar issue with wired network interface. However, this method cannot be -applied directly to the wireless network interface. "Bytes" is not a -suitable measure of queue depth in the wireless network, as the data rate -can vary dramatically from station to station in the same network, from a -few Mbps to over Gbps. - -This patch implements an Airtime-based Queue Limit (AQL) to make CoDel work -effectively with wireless drivers that utilized firmware/hardware -offloading. AQL allows each txq to release just enough packets to the lower -layer to form 1-2 large aggregations to keep hardware fully utilized and -retains the rest of the frames in mac80211 layer to be controlled by the -CoDel algorithm. - -Signed-off-by: Kan Yan -[ Toke: Keep API to set pending airtime internal, fix nits in commit msg ] -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20191119060610.76681-4-kyan@google.com -Signed-off-by: Johannes Berg ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -2603,6 +2603,13 @@ enum wiphy_params_flags { - - #define IEEE80211_DEFAULT_AIRTIME_WEIGHT 256 - -+/* The per TXQ device queue limit in airtime */ -+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000 -+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000 -+ -+/* The per interface airtime threshold to switch to lower queue limit */ -+#define IEEE80211_AQL_THRESHOLD 24000 -+ - /** - * struct cfg80211_pmksa - PMK Security Association - * ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -5559,6 +5559,18 @@ void ieee80211_sta_register_airtime(stru - u32 tx_airtime, u32 rx_airtime); - - /** -+ * ieee80211_txq_airtime_check - check if a txq can send frame to device -+ * -+ * @hw: pointer obtained from ieee80211_alloc_hw() -+ * @txq: pointer obtained from station or virtual interface -+ * -+ * Return true if the AQL's airtime limit has not been reached and the txq can -+ * continue to send more packets to the device. Otherwise return false. -+ */ -+bool -+ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq); -+ -+/** - * ieee80211_iter_keys - iterate keys programmed into the device - * @hw: pointer obtained from ieee80211_alloc_hw() - * @vif: virtual interface to iterate, may be %NULL for all ---- a/net/mac80211/debugfs.c -+++ b/net/mac80211/debugfs.c -@@ -148,6 +148,87 @@ static const struct file_operations aqm_ - .llseek = default_llseek, - }; - -+static ssize_t aql_txq_limit_read(struct file *file, -+ char __user *user_buf, -+ size_t count, -+ loff_t *ppos) -+{ -+ struct ieee80211_local *local = file->private_data; -+ char buf[400]; -+ int len = 0; -+ -+ len = scnprintf(buf, sizeof(buf), -+ "AC AQL limit low AQL limit high\n" -+ "VO %u %u\n" -+ "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]); -+ return simple_read_from_buffer(user_buf, count, ppos, -+ buf, len); -+} -+ -+static ssize_t aql_txq_limit_write(struct file *file, -+ const char __user *user_buf, -+ size_t count, -+ loff_t *ppos) -+{ -+ struct ieee80211_local *local = file->private_data; -+ char buf[100]; -+ size_t len; -+ u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old; -+ struct sta_info *sta; -+ -+ 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 (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3) -+ return -EINVAL; -+ -+ 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]; -+ -+ local->aql_txq_limit_low[ac] = q_limit_low; -+ local->aql_txq_limit_high[ac] = q_limit_high; -+ -+ mutex_lock(&local->sta_mtx); -+ list_for_each_entry(sta, &local->sta_list, list) { -+ /* If a sta has customized queue limits, keep it */ -+ if (sta->airtime[ac].aql_limit_low == q_limit_low_old && -+ sta->airtime[ac].aql_limit_high == q_limit_high_old) { -+ sta->airtime[ac].aql_limit_low = q_limit_low; -+ sta->airtime[ac].aql_limit_high = q_limit_high; -+ } -+ } -+ mutex_unlock(&local->sta_mtx); -+ return count; -+} -+ -+static const struct file_operations aql_txq_limit_ops = { -+ .write = aql_txq_limit_write, -+ .read = aql_txq_limit_read, -+ .open = simple_open, -+ .llseek = default_llseek, -+}; -+ - static ssize_t force_tx_status_read(struct file *file, - char __user *user_buf, - size_t count, -@@ -441,6 +522,10 @@ void debugfs_hw_add(struct ieee80211_loc - debugfs_create_u16("airtime_flags", 0600, - phyd, &local->airtime_flags); - -+ DEBUGFS_ADD(aql_txq_limit); -+ debugfs_create_u32("aql_threshold", 0600, -+ phyd, &local->aql_threshold); -+ - statsd = debugfs_create_dir("statistics", phyd); - - /* if the dir failed, don't put all the other things into the root! */ ---- a/net/mac80211/debugfs_sta.c -+++ b/net/mac80211/debugfs_sta.c -@@ -198,10 +198,12 @@ static ssize_t sta_airtime_read(struct f - { - struct sta_info *sta = file->private_data; - struct ieee80211_local *local = sta->sdata->local; -- size_t bufsz = 200; -+ size_t bufsz = 400; - char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf; - u64 rx_airtime = 0, tx_airtime = 0; - s64 deficit[IEEE80211_NUM_ACS]; -+ u32 q_depth[IEEE80211_NUM_ACS]; -+ u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS]; - ssize_t rv; - int ac; - -@@ -213,19 +215,22 @@ static ssize_t sta_airtime_read(struct f - rx_airtime += sta->airtime[ac].rx_airtime; - tx_airtime += sta->airtime[ac].tx_airtime; - deficit[ac] = sta->airtime[ac].deficit; -+ 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]); -+ q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending); - } - - 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]); -+ "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n" -+ "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n" -+ "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n", -+ rx_airtime, tx_airtime, sta->airtime_weight, -+ deficit[0], deficit[1], deficit[2], deficit[3], -+ q_depth[0], q_depth[1], q_depth[2], q_depth[3], -+ q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1], -+ q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]), - - rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); - kfree(buf); -@@ -237,7 +242,25 @@ static ssize_t sta_airtime_write(struct - { - struct sta_info *sta = file->private_data; - struct ieee80211_local *local = sta->sdata->local; -- int ac; -+ u32 ac, q_limit_l, q_limit_h; -+ char _buf[100] = {}, *buf = _buf; -+ -+ if (count > sizeof(_buf)) -+ return -EINVAL; -+ -+ if (copy_from_user(buf, userbuf, count)) -+ return -EFAULT; -+ -+ buf[sizeof(_buf) - 1] = '\0'; -+ if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h) -+ != 3) -+ return -EINVAL; -+ -+ if (ac >= IEEE80211_NUM_ACS) -+ return -EINVAL; -+ -+ sta->airtime[ac].aql_limit_low = q_limit_l; -+ sta->airtime[ac].aql_limit_high = q_limit_h; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - spin_lock_bh(&local->active_txq_lock[ac]); ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1142,6 +1142,10 @@ struct ieee80211_local { - u16 schedule_round[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; - - const struct ieee80211_ops *ops; - ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -669,8 +669,16 @@ struct ieee80211_hw *ieee80211_alloc_hw_ - 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] = -+ IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H; - } -- local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX; -+ -+ local->airtime_flags = AIRTIME_USE_TX | -+ AIRTIME_USE_RX | -+ AIRTIME_USE_AQL; -+ local->aql_threshold = IEEE80211_AQL_THRESHOLD; -+ atomic_set(&local->aql_total_pending_airtime, 0); - - INIT_LIST_HEAD(&local->chanctx_list); - mutex_init(&local->chanctx_mtx); ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -412,6 +412,9 @@ struct sta_info *sta_info_alloc(struct 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]; - } - - for (i = 0; i < IEEE80211_NUM_TIDS; i++) -@@ -1914,6 +1917,41 @@ void ieee80211_sta_register_airtime(stru - } - EXPORT_SYMBOL(ieee80211_sta_register_airtime); - -+void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, -+ struct sta_info *sta, u8 ac, -+ u16 tx_airtime, bool tx_completed) -+{ -+ int tx_pending; -+ -+ if (!tx_completed) { -+ if (sta) -+ atomic_add(tx_airtime, -+ &sta->airtime[ac].aql_tx_pending); -+ -+ atomic_add(tx_airtime, &local->aql_total_pending_airtime); -+ return; -+ } -+ -+ if (sta) { -+ tx_pending = atomic_sub_return(tx_airtime, -+ &sta->airtime[ac].aql_tx_pending); -+ if (WARN_ONCE(tx_pending < 0, -+ "STA %pM AC %d txq pending airtime underflow: %u, %u", -+ sta->addr, ac, tx_pending, tx_airtime)) -+ atomic_cmpxchg(&sta->airtime[ac].aql_tx_pending, -+ tx_pending, 0); -+ } -+ -+ tx_pending = atomic_sub_return(tx_airtime, -+ &local->aql_total_pending_airtime); -+ if (WARN_ONCE(tx_pending < 0, -+ "Device %s AC %d pending airtime underflow: %u, %u", -+ wiphy_name(local->hw.wiphy), ac, tx_pending, -+ tx_airtime)) -+ atomic_cmpxchg(&local->aql_total_pending_airtime, -+ tx_pending, 0); -+} -+ - int sta_info_move_state(struct sta_info *sta, - enum ieee80211_sta_state new_state) - { ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -128,13 +128,21 @@ enum ieee80211_agg_stop_reason { - /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */ - #define AIRTIME_USE_TX BIT(0) - #define AIRTIME_USE_RX BIT(1) -+#define AIRTIME_USE_AQL BIT(2) - - struct airtime_info { - u64 rx_airtime; - u64 tx_airtime; - s64 deficit; -+ atomic_t aql_tx_pending; /* Estimated airtime for frames pending */ -+ u32 aql_limit_low; -+ u32 aql_limit_high; - }; - -+void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, -+ struct sta_info *sta, u8 ac, -+ u16 tx_airtime, bool tx_completed); -+ - struct sta_info; - - /** ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3700,7 +3700,8 @@ struct ieee80211_txq *ieee80211_next_txq - { - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_txq *ret = NULL; -- struct txq_info *txqi = NULL; -+ struct txq_info *txqi = NULL, *head = NULL; -+ bool found_eligible_txq = false; - - spin_lock_bh(&local->active_txq_lock[ac]); - -@@ -3711,13 +3712,30 @@ struct ieee80211_txq *ieee80211_next_txq - if (!txqi) - goto out; - -+ if (txqi == head) { -+ if (!found_eligible_txq) -+ goto out; -+ else -+ found_eligible_txq = false; -+ } -+ -+ if (!head) -+ head = txqi; -+ - if (txqi->txq.sta) { - struct sta_info *sta = container_of(txqi->txq.sta, -- struct sta_info, sta); -+ struct sta_info, sta); -+ bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); -+ s64 deficit = sta->airtime[txqi->txq.ac].deficit; - -- if (sta->airtime[txqi->txq.ac].deficit < 0) { -+ if (aql_check) -+ found_eligible_txq = true; -+ -+ 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; -@@ -3771,6 +3789,33 @@ void __ieee80211_schedule_txq(struct iee - } - EXPORT_SYMBOL(__ieee80211_schedule_txq); - -+bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, -+ struct ieee80211_txq *txq) -+{ -+ struct sta_info *sta; -+ struct ieee80211_local *local = hw_to_local(hw); -+ -+ if (!(local->airtime_flags & AIRTIME_USE_AQL)) -+ return true; -+ -+ if (!txq->sta) -+ 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) -+ 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) -+ return true; -+ -+ return false; -+} -+EXPORT_SYMBOL(ieee80211_txq_airtime_check); -+ - bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, - struct ieee80211_txq *txq) - { 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 new file mode 100644 index 0000000000..05a888006e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch @@ -0,0 +1,95 @@ +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/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch b/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch deleted file mode 100644 index 714a283558..0000000000 --- a/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch +++ /dev/null @@ -1,146 +0,0 @@ -From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= -Date: Mon, 18 Nov 2019 22:06:10 -0800 -Subject: [PATCH] mac80211: Use Airtime-based Queue Limits (AQL) on packet - dequeue -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The previous commit added the ability to throttle stations when they queue -too much airtime in the hardware. This commit enables the functionality by -calculating the expected airtime usage of each packet that is dequeued from -the TXQs in mac80211, and accounting that as pending airtime. - -The estimated airtime for each skb is stored in the tx_info, so we can -subtract the same amount from the running total when the skb is freed or -recycled. The throttling mechanism relies on this accounting to be -accurate (i.e., that we are not freeing skbs without subtracting any -airtime they were accounted for), so we put the subtraction into -ieee80211_report_used_skb(). As an optimisation, we also subtract the -airtime on regular TX completion, zeroing out the value stored in the -packet afterwards, to avoid having to do an expensive lookup of the station -from the packet data on every packet. - -This patch does *not* include any mechanism to wake a throttled TXQ again, -on the assumption that this will happen anyway as a side effect of whatever -freed the skb (most commonly a TX completion). - -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20191119060610.76681-5-kyan@google.com -Signed-off-by: Johannes Berg ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1060,6 +1060,22 @@ struct ieee80211_tx_info { - }; - }; - -+static inline u16 -+ieee80211_info_set_tx_time_est(struct ieee80211_tx_info *info, u16 tx_time_est) -+{ -+ /* We only have 10 bits in tx_time_est, so store airtime -+ * in increments of 4us and clamp the maximum to 2**12-1 -+ */ -+ info->tx_time_est = min_t(u16, tx_time_est, 4095) >> 2; -+ return info->tx_time_est << 2; -+} -+ -+static inline u16 -+ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info) -+{ -+ return info->tx_time_est << 2; -+} -+ - /** - * struct ieee80211_tx_status - extended tx staus info for rate control - * ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -669,12 +669,26 @@ static void ieee80211_report_used_skb(st - struct sk_buff *skb, bool dropped) - { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ u16 tx_time_est = ieee80211_info_get_tx_time_est(info); - struct ieee80211_hdr *hdr = (void *)skb->data; - bool acked = info->flags & IEEE80211_TX_STAT_ACK; - - if (dropped) - acked = false; - -+ if (tx_time_est) { -+ struct sta_info *sta; -+ -+ rcu_read_lock(); -+ -+ sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2); -+ ieee80211_sta_update_pending_airtime(local, sta, -+ skb_get_queue_mapping(skb), -+ tx_time_est, -+ true); -+ rcu_read_unlock(); -+ } -+ - if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) { - struct ieee80211_sub_if_data *sdata; - -@@ -884,6 +898,7 @@ static void __ieee80211_tx_status(struct - struct ieee80211_bar *bar; - int shift = 0; - int tid = IEEE80211_NUM_TIDS; -+ u16 tx_time_est; - - rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); - -@@ -995,6 +1010,17 @@ static void __ieee80211_tx_status(struct - ieee80211_sta_register_airtime(&sta->sta, tid, - info->status.tx_time, 0); - -+ if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { -+ /* Do this here to avoid the expensive lookup of the sta -+ * in ieee80211_report_used_skb(). -+ */ -+ ieee80211_sta_update_pending_airtime(local, sta, -+ skb_get_queue_mapping(skb), -+ tx_time_est, -+ true); -+ ieee80211_info_set_tx_time_est(info, 0); -+ } -+ - if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { - if (acked) { - if (sta->status_stats.lost_packets) ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3559,6 +3559,9 @@ struct sk_buff *ieee80211_tx_dequeue(str - - WARN_ON_ONCE(softirq_count() == 0); - -+ if (!ieee80211_txq_airtime_check(hw, txq)) -+ return NULL; -+ - begin: - spin_lock_bh(&fq->lock); - -@@ -3687,6 +3690,21 @@ begin: - } - - IEEE80211_SKB_CB(skb)->control.vif = vif; -+ -+ if (local->airtime_flags & AIRTIME_USE_AQL) { -+ u32 airtime; -+ -+ airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, -+ skb->len); -+ if (airtime) { -+ airtime = ieee80211_info_set_tx_time_est(info, airtime); -+ ieee80211_sta_update_pending_airtime(local, tx.sta, -+ txq->ac, -+ airtime, -+ false); -+ } -+ } -+ - return skb; - - out: 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 new file mode 100644 index 0000000000..de1f1bb7f5 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch @@ -0,0 +1,144 @@ +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 +@@ -855,7 +855,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-airtime-Fix-an-off-by-one-in-ieee80211_calc.patch b/package/kernel/mac80211/patches/subsys/312-mac80211-airtime-Fix-an-off-by-one-in-ieee80211_calc.patch deleted file mode 100644 index 4ff496c12e..0000000000 --- a/package/kernel/mac80211/patches/subsys/312-mac80211-airtime-Fix-an-off-by-one-in-ieee80211_calc.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Dan Carpenter -Date: Tue, 26 Nov 2019 15:09:39 +0300 -Subject: [PATCH] mac80211: airtime: Fix an off by one in - ieee80211_calc_rx_airtime() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This code was copied from mt76 and inherited an off by one bug from -there. The > should be >= so that we don't read one element beyond -the end of the array. - -Fixes: db3e1c40cf2f ("mac80211: Import airtime calculation code from mt76") -Reported-by: Toke Høiland-Jørgensen -Signed-off-by: Dan Carpenter -Acked-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20191126120910.ftr4t7me3by32aiz@kili.mountain -Signed-off-by: Johannes Berg ---- - ---- a/net/mac80211/airtime.c -+++ b/net/mac80211/airtime.c -@@ -442,7 +442,7 @@ u32 ieee80211_calc_rx_airtime(struct iee - return 0; - - sband = hw->wiphy->bands[status->band]; -- if (!sband || status->rate_idx > sband->n_bitrates) -+ if (!sband || status->rate_idx >= sband->n_bitrates) - return 0; - - rate = &sband->bitrates[status->rate_idx]; 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 new file mode 100644 index 0000000000..08e5cbb5b9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch @@ -0,0 +1,317 @@ +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-mac80211-Turn-AQL-into-an-NL80211_EXT_FEATURE.patch b/package/kernel/mac80211/patches/subsys/313-mac80211-Turn-AQL-into-an-NL80211_EXT_FEATURE.patch deleted file mode 100644 index e509802317..0000000000 --- a/package/kernel/mac80211/patches/subsys/313-mac80211-Turn-AQL-into-an-NL80211_EXT_FEATURE.patch +++ /dev/null @@ -1,253 +0,0 @@ -From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= -Date: Thu, 12 Dec 2019 12:14:37 +0100 -Subject: [PATCH] mac80211: Turn AQL into an NL80211_EXT_FEATURE -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Instead of just having an airtime flag in debugfs, turn AQL into a proper -NL80211_EXT_FEATURE, so drivers can turn it on when they are ready, and so -we also expose the presence of the feature to userspace. - -This also has the effect of flipping the default, so drivers have to opt in -to using AQL instead of getting it by default with TXQs. To keep -functionality the same as pre-patch, we set this feature for ath10k (which -is where it is needed the most). - -While we're at it, split out the debugfs interface so AQL gets its own -per-station debugfs file instead of using the 'airtime' file. - -[Johannes:] -This effectively disables AQL for iwlwifi, where it fixes a number of -issues: - * TSO in iwlwifi is causing underflows and associated warnings in AQL - * HE (802.11ax) rates aren't reported properly so at HE rates, AQL could - never have a valid estimate (it'd use 6 Mbps instead of up to 2400!) - -Signed-off-by: Toke Høiland-Jørgensen -Link: https://lore.kernel.org/r/20191212111437.224294-1-toke@redhat.com -Fixes: 3ace10f5b5ad ("mac80211: Implement Airtime-based Queue Limit (AQL)") -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -8873,6 +8873,7 @@ int ath10k_mac_register(struct ath10k *a - wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); - wiphy_ext_feature_set(ar->hw->wiphy, - NL80211_EXT_FEATURE_SET_SCAN_DWELL); -+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL); - - if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) || - test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map)) ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -5484,6 +5484,10 @@ enum nl80211_feature_flags { - * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in - * station mode (SAE password is passed as part of the connect command). - * -+ * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL) -+ * feature, which prevents bufferbloat by using the expected transmission -+ * time to limit the amount of data buffered in the hardware. -+ * - * @NUM_NL80211_EXT_FEATURES: number of extended features. - * @MAX_NL80211_EXT_FEATURES: highest extended feature index. - */ -@@ -5529,6 +5533,8 @@ enum nl80211_ext_feature_index { - NL80211_EXT_FEATURE_EXT_KEY_ID, - NL80211_EXT_FEATURE_STA_TX_PWR, - NL80211_EXT_FEATURE_SAE_OFFLOAD, -+ NL80211_EXT_FEATURE_VLAN_OFFLOAD, -+ NL80211_EXT_FEATURE_AQL, - - /* add new features before the definition below */ - NUM_NL80211_EXT_FEATURES, ---- a/net/mac80211/debugfs_sta.c -+++ b/net/mac80211/debugfs_sta.c -@@ -202,8 +202,6 @@ static ssize_t sta_airtime_read(struct f - char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf; - u64 rx_airtime = 0, tx_airtime = 0; - s64 deficit[IEEE80211_NUM_ACS]; -- u32 q_depth[IEEE80211_NUM_ACS]; -- u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS]; - ssize_t rv; - int ac; - -@@ -215,6 +213,56 @@ static ssize_t sta_airtime_read(struct f - 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]); -+ } -+ -+ 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]); -+ -+ rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); -+ kfree(buf); -+ return rv; -+} -+ -+static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf, -+ size_t count, loff_t *ppos) -+{ -+ struct sta_info *sta = file->private_data; -+ struct ieee80211_local *local = sta->sdata->local; -+ int ac; -+ -+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -+ spin_lock_bh(&local->active_txq_lock[ac]); -+ 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]); -+ } -+ -+ return count; -+} -+STA_OPS_RW(airtime); -+ -+static ssize_t sta_aql_read(struct file *file, char __user *userbuf, -+ size_t count, loff_t *ppos) -+{ -+ struct sta_info *sta = file->private_data; -+ struct ieee80211_local *local = sta->sdata->local; -+ size_t bufsz = 400; -+ char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf; -+ u32 q_depth[IEEE80211_NUM_ACS]; -+ u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS]; -+ ssize_t rv; -+ int ac; -+ -+ if (!buf) -+ return -ENOMEM; -+ -+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -+ spin_lock_bh(&local->active_txq_lock[ac]); - 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]); -@@ -222,12 +270,8 @@ static ssize_t sta_airtime_read(struct f - } - - 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" - "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n" - "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n", -- rx_airtime, tx_airtime, sta->airtime_weight, -- deficit[0], deficit[1], deficit[2], deficit[3], - q_depth[0], q_depth[1], q_depth[2], q_depth[3], - q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1], - q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]), -@@ -237,11 +281,10 @@ static ssize_t sta_airtime_read(struct f - return rv; - } - --static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf, -+static ssize_t sta_aql_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) - { - struct sta_info *sta = file->private_data; -- struct ieee80211_local *local = sta->sdata->local; - u32 ac, q_limit_l, q_limit_h; - char _buf[100] = {}, *buf = _buf; - -@@ -252,7 +295,7 @@ static ssize_t sta_airtime_write(struct - return -EFAULT; - - buf[sizeof(_buf) - 1] = '\0'; -- if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h) -+ if (sscanf(buf, "limit %u %u %u", &ac, &q_limit_l, &q_limit_h) - != 3) - return -EINVAL; - -@@ -262,17 +305,10 @@ static ssize_t sta_airtime_write(struct - sta->airtime[ac].aql_limit_low = q_limit_l; - sta->airtime[ac].aql_limit_high = q_limit_h; - -- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { -- spin_lock_bh(&local->active_txq_lock[ac]); -- 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]); -- } -- - return count; - } --STA_OPS_RW(airtime); -+STA_OPS_RW(aql); -+ - - static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -@@ -1002,6 +1038,10 @@ void ieee80211_sta_debugfs_add(struct st - NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) - DEBUGFS_ADD(airtime); - -+ if (wiphy_ext_feature_isset(local->hw.wiphy, -+ NL80211_EXT_FEATURE_AQL)) -+ DEBUGFS_ADD(aql); -+ - if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) - debugfs_create_x32("driver_buffered_tids", 0400, - sta->debugfs_dir, ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -674,9 +674,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ - IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H; - } - -- local->airtime_flags = AIRTIME_USE_TX | -- AIRTIME_USE_RX | -- AIRTIME_USE_AQL; -+ local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX; - local->aql_threshold = IEEE80211_AQL_THRESHOLD; - atomic_set(&local->aql_total_pending_airtime, 0); - ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -1923,6 +1923,9 @@ void ieee80211_sta_update_pending_airtim - { - int tx_pending; - -+ if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) -+ return; -+ - if (!tx_completed) { - if (sta) - atomic_add(tx_airtime, ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -128,7 +128,6 @@ enum ieee80211_agg_stop_reason { - /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */ - #define AIRTIME_USE_TX BIT(0) - #define AIRTIME_USE_RX BIT(1) --#define AIRTIME_USE_AQL BIT(2) - - struct airtime_info { - u64 rx_airtime; ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3691,7 +3691,7 @@ begin: - - IEEE80211_SKB_CB(skb)->control.vif = vif; - -- if (local->airtime_flags & AIRTIME_USE_AQL) { -+ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { - u32 airtime; - - airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, -@@ -3813,7 +3813,7 @@ bool ieee80211_txq_airtime_check(struct - struct sta_info *sta; - struct ieee80211_local *local = hw_to_local(hw); - -- if (!(local->airtime_flags & AIRTIME_USE_AQL)) -+ if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) - return true; - - if (!txq->sta) 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 new file mode 100644 index 0000000000..02486372e9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch @@ -0,0 +1,570 @@ +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 +@@ -839,7 +839,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 */ +@@ -859,7 +859,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) && +@@ -872,10 +872,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; + } + +@@ -893,7 +904,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 +@@ -4114,7 +4114,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); +@@ -4227,6 +4229,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); +@@ -4273,6 +4286,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) + { +@@ -4293,9 +4408,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 +@@ -4369,32 +4481,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; + +@@ -4406,12 +4492,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); +@@ -4420,62 +4500,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; + } +@@ -4529,6 +4561,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. +@@ -4766,15 +4839,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 +@@ -2740,7 +2740,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), +@@ -2767,6 +2767,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/331-mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch b/package/kernel/mac80211/patches/subsys/331-mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch deleted file mode 100644 index a799d96250..0000000000 --- a/package/kernel/mac80211/patches/subsys/331-mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Felix Fietkau -Date: Thu, 17 Sep 2020 12:07:19 +0200 -Subject: [PATCH] mac80211: do not allow bigger VHT MPDUs than the hardware - supports - -Limit maximum VHT MPDU size by local capability - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/vht.c -+++ b/net/mac80211/vht.c -@@ -168,10 +168,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(stru - /* take some capabilities as-is */ - cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info); - vht_cap->cap = cap_info; -- vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | -- IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | -- IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | -- IEEE80211_VHT_CAP_RXLDPC | -+ vht_cap->cap &= IEEE80211_VHT_CAP_RXLDPC | - IEEE80211_VHT_CAP_VHT_TXOP_PS | - IEEE80211_VHT_CAP_HTC_VHT | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | -@@ -180,6 +177,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(stru - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; - -+ vht_cap->cap |= min_t(u32, cap_info & IEEE80211_VHT_CAP_MAX_MPDU_MASK, -+ own_cap.cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK); -+ - /* and some based on our own capabilities */ - switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { - case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: diff --git a/package/kernel/mac80211/patches/subsys/336-mac80211-do-not-drop-tx-nulldata-packets-on-encrypte.patch b/package/kernel/mac80211/patches/subsys/336-mac80211-do-not-drop-tx-nulldata-packets-on-encrypte.patch deleted file mode 100644 index 378c37455d..0000000000 --- a/package/kernel/mac80211/patches/subsys/336-mac80211-do-not-drop-tx-nulldata-packets-on-encrypte.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Felix Fietkau -Date: Fri, 18 Dec 2020 20:08:06 +0100 -Subject: [PATCH] mac80211: do not drop tx nulldata packets on encrypted links - -ieee80211_tx_h_select_key drops any non-mgmt packets without a key when -encryption is used. This is wrong for nulldata packets that can't be -encrypted and are sent out for probing clients and indicating 4-address -mode. - -Reported-by: Sebastian Gottschall -Fixes: a0761a301746 ("mac80211: drop data frames without key on encrypted links") -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -657,7 +657,7 @@ ieee80211_tx_h_select_key(struct ieee802 - if (!skip_hw && tx->key && - tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) - info->control.hw_key = &tx->key->conf; -- } else if (!ieee80211_is_mgmt(hdr->frame_control) && tx->sta && -+ } else if (ieee80211_is_data_present(hdr->frame_control) && tx->sta && - test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) { - return TX_DROP; - } 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 new file mode 100644 index 0000000000..f667d2c94e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/337-mac80211-minstrel_ht-clean-up-CCK-code.patch @@ -0,0 +1,166 @@ +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 new file mode 100644 index 0000000000..abefde7109 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/338-mac80211-minstrel_ht-add-support-for-OFDM-rates-on-n.patch @@ -0,0 +1,762 @@ +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 new file mode 100644 index 0000000000..96ee595ac1 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/339-mac80211-remove-legacy-minstrel-rate-control.patch @@ -0,0 +1,1328 @@ +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 +@@ -55,11 +55,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 new file mode 100644 index 0000000000..9b6a614aa8 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/340-mac80211-minstrel_ht-remove-old-ewma-based-rate-aver.patch @@ -0,0 +1,96 @@ +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 new file mode 100644 index 0000000000..a8e6e89954 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/341-mac80211-minstrel_ht-improve-ampdu-length-estimation.patch @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000000..e084525235 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/342-mac80211-minstrel_ht-improve-sample-rate-selection.patch @@ -0,0 +1,31 @@ +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 new file mode 100644 index 0000000000..0dbfa9d4fb --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/343-mac80211-minstrel_ht-fix-max-probability-rate-select.patch @@ -0,0 +1,124 @@ +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 new file mode 100644 index 0000000000..9972a9414e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/344-mac80211-minstrel_ht-increase-stats-update-interval.patch @@ -0,0 +1,20 @@ +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 new file mode 100644 index 0000000000..1df5dec039 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/345-mac80211-minstrel_ht-fix-rounding-error-in-throughpu.patch @@ -0,0 +1,34 @@ +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 new file mode 100644 index 0000000000..6aa6f0ed93 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/346-mac80211-minstrel_ht-use-bitfields-to-encode-rate-in.patch @@ -0,0 +1,412 @@ +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 new file mode 100644 index 0000000000..dce8104934 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/347-mac80211-minstrel_ht-update-total-packets-counter-in.patch @@ -0,0 +1,54 @@ +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 new file mode 100644 index 0000000000..dc6f11e4b9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/348-mac80211-minstrel_ht-reduce-the-need-to-sample-slowe.patch @@ -0,0 +1,102 @@ +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 new file mode 100644 index 0000000000..09f6fd2214 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/349-mac80211-minstrel_ht-significantly-redesign-the-rate.patch @@ -0,0 +1,767 @@ +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 new file mode 100644 index 0000000000..041ba31a37 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/350-mac80211-minstrel_ht-show-sampling-rates-in-debugfs.patch @@ -0,0 +1,58 @@ +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 new file mode 100644 index 0000000000..8170ff85f8 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/351-mac80211-minstrel_ht-remove-sample-rate-switching-co.patch @@ -0,0 +1,279 @@ +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 new file mode 100644 index 0000000000..a366a921d4 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/352-mac80211-minstrel_ht-fix-regression-in-the-max_prob_.patch @@ -0,0 +1,23 @@ +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/353-mac80211-use-more-bits-for-ack_frame_id.patch b/package/kernel/mac80211/patches/subsys/353-mac80211-use-more-bits-for-ack_frame_id.patch deleted file mode 100644 index ee88996276..0000000000 --- a/package/kernel/mac80211/patches/subsys/353-mac80211-use-more-bits-for-ack_frame_id.patch +++ /dev/null @@ -1,70 +0,0 @@ -From: Johannes Berg -Date: Wed, 15 Jan 2020 12:25:50 +0100 -Subject: [PATCH] mac80211: use more bits for ack_frame_id -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It turns out that this wasn't a good idea, I hit a test failure in -hwsim due to this. That particular failure was easily worked around, -but it raised questions: if an AP needs to, for example, send action -frames to each connected station, the current limit is nowhere near -enough (especially if those stations are sleeping and the frames are -queued for a while.) - -Shuffle around some bits to make more room for ack_frame_id to allow -up to 8192 queued up frames, that's enough for queueing 4 frames to -each connected station, even at the maximum of 2007 stations on a -single AP. - -We take the bits from band (which currently only 2 but I leave 3 in -case we add another band) and from the hw_queue, which can only need -4 since it has a limit of 16 queues. - -Fixes: 6912daed05e1 ("mac80211: Shrink the size of ack_frame_id to make room for tx_time_est") -Signed-off-by: Johannes Berg -Acked-by: Toke Høiland-Jørgensen ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1004,12 +1004,11 @@ ieee80211_rate_get_vht_nss(const struct - struct ieee80211_tx_info { - /* common information */ - u32 flags; -- u8 band; -- -- u8 hw_queue; -- -- u16 ack_frame_id:6; -- u16 tx_time_est:10; -+ u32 band:3, -+ ack_frame_id:13, -+ hw_queue:4, -+ tx_time_est:10; -+ /* 2 free bits */ - - union { - struct { ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -3450,7 +3450,7 @@ int ieee80211_attach_ack_skb(struct ieee - - spin_lock_irqsave(&local->ack_status_lock, spin_flags); - id = idr_alloc(&local->ack_status_frames, ack_skb, -- 1, 0x40, GFP_ATOMIC); -+ 1, 0x2000, GFP_ATOMIC); - spin_unlock_irqrestore(&local->ack_status_lock, spin_flags); - - if (id < 0) { ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -2458,7 +2458,7 @@ static int ieee80211_store_ack_skb(struc - - spin_lock_irqsave(&local->ack_status_lock, flags); - id = idr_alloc(&local->ack_status_frames, ack_skb, -- 1, 0x40, GFP_ATOMIC); -+ 1, 0x2000, GFP_ATOMIC); - spin_unlock_irqrestore(&local->ack_status_lock, flags); - - if (id >= 0) { diff --git a/package/kernel/mac80211/patches/subsys/354-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch b/package/kernel/mac80211/patches/subsys/354-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch new file mode 100644 index 0000000000..16bcbc2ef9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/354-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch @@ -0,0 +1,30 @@ +From: Felix Fietkau +Date: Sat, 6 Feb 2021 16:08:01 +0100 +Subject: [PATCH] mac80211: minstrel_ht: reduce fluctuations in rate + probability stats + +In some scenarios when there is a lot of fluctuation in packet error rates, +rate switching can be amplified when the statistics get skewed by time slots +with very few tries. +Make the input data to the moving average more smooth by adding the +success/attempts count from the last stats window as well. This has the +advantage of smoothing the data without introducing any extra lag to sampling +rates. +This significantly improves rate stability on a strong test link subjected to +periodic noise bursts generated with a SDR + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -700,7 +700,8 @@ minstrel_ht_calc_rate_stats(struct minst + unsigned int cur_prob; + + if (unlikely(mrs->attempts > 0)) { +- cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); ++ cur_prob = MINSTREL_FRAC(mrs->success + mrs->last_success, ++ mrs->attempts + mrs->last_attempts); + minstrel_filter_avg_add(&mrs->prob_avg, + &mrs->prob_avg_1, cur_prob); + mrs->att_hist += mrs->attempts; diff --git a/package/kernel/mac80211/patches/subsys/355-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch b/package/kernel/mac80211/patches/subsys/355-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch new file mode 100644 index 0000000000..aec2e07781 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/355-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch @@ -0,0 +1,151 @@ +From: Felix Fietkau +Date: Sat, 6 Feb 2021 16:33:14 +0100 +Subject: [PATCH] mac80211: minstrel_ht: rework rate downgrade code and + max_prob rate selection + +The current fallback code for fast rate switching on potentially failing rates +is triggering too often if there is some strong noise on the channel. This can +lead to wild fluctuations in the rate selection. +Additionally, switching down to max_prob_rate can create a significant gap down +in throughput, especially when using only 2 spatial streams, because max_prob_rate +is limited to using fewer streams than the max_tp rates. +In order to improve throughput without reducing reliability too much, use the +rate downgrade code for the max_prob_rate only, and allow the non-downgraded +max_prob_rate to use as many spatial streams as the max_tp rates + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -511,6 +511,14 @@ minstrel_ht_set_best_prob_rate(struct mi + int cur_tp_avg, cur_group, cur_idx; + int max_gpr_group, max_gpr_idx; + int max_gpr_tp_avg, max_gpr_prob; ++ int min_dur; ++ ++ min_dur = max(minstrel_get_duration(mi->max_tp_rate[0]), ++ minstrel_get_duration(mi->max_tp_rate[1])); ++ ++ /* make the rate at least 18% slower than max tp rates */ ++ if (minstrel_get_duration(index) <= min_dur * 19 / 16) ++ return; + + cur_group = MI_RATE_GROUP(index); + cur_idx = MI_RATE_IDX(index); +@@ -532,11 +540,6 @@ minstrel_ht_set_best_prob_rate(struct mi + !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 = 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; +@@ -594,40 +597,6 @@ minstrel_ht_assign_best_tp_rates(struct + + } + +-/* +- * Try to increase robustness of max_prob rate by decrease number of +- * streams if possible. +- */ +-static inline void +-minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) +-{ +- struct minstrel_mcs_group_data *mg; +- int tmp_max_streams, group, tmp_idx, tmp_prob; +- int tmp_tp = 0; +- +- if (!mi->sta->ht_cap.ht_supported) +- return; +- +- 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 = 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) && +- (minstrel_mcs_groups[group].streams < tmp_max_streams)) { +- mi->max_prob_rate = mg->max_group_prob_rate; +- tmp_tp = minstrel_ht_get_tp_avg(mi, group, +- tmp_idx, +- tmp_prob); +- } +- } +-} +- + 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 + + mi->max_prob_rate = tmp_max_prob_rate; + +- /* Try to increase robustness of max_prob_rate*/ +- minstrel_ht_prob_rate_reduce_streams(mi); + minstrel_ht_refill_sample_rates(mi); + + #ifdef CPTCFG_MAC80211_DEBUGFS +@@ -1157,7 +1124,7 @@ minstrel_ht_txstat_valid(struct minstrel + } + + static void +-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary) ++minstrel_downgrade_prob_rate(struct minstrel_ht_sta *mi, u16 *idx) + { + int group, orig_group; + +@@ -1172,11 +1139,7 @@ minstrel_downgrade_rate(struct minstrel_ + minstrel_mcs_groups[orig_group].streams) + continue; + +- if (primary) +- *idx = mi->groups[group].max_group_tp_rate[0]; +- else +- *idx = mi->groups[group].max_group_tp_rate[1]; +- break; ++ *idx = mi->groups[group].max_group_prob_rate; + } + } + +@@ -1210,7 +1173,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; +- struct minstrel_rate_stats *rate, *rate2; ++ struct minstrel_rate_stats *rate; + 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 + /* + * check for sudden death of spatial multiplexing, + * downgrade to a lower number of streams if necessary. ++ * only do this for the max_prob_rate to prevent spurious ++ * rate fluctuations when the link changes suddenly + */ +- rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); ++ rate = minstrel_get_ratestats(mi, mi->max_prob_rate); + if (rate->attempts > 30 && + rate->success < rate->attempts / 4) { +- minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); +- update = true; +- } +- +- rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); +- if (rate2->attempts > 30 && +- rate2->success < rate2->attempts / 4) { +- minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); ++ minstrel_downgrade_prob_rate(mi, &mi->max_prob_rate); + update = true; + } + } diff --git a/package/kernel/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch b/package/kernel/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch deleted file mode 100644 index 38144013f0..0000000000 --- a/package/kernel/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 5981fe5b0529ba25d95f37d7faa434183ad618c5 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Mon, 3 Aug 2020 11:02:10 +0200 -Subject: [PATCH] mac80211: fix misplaced while instead of if - -This never was intended to be a 'while' loop, it should've -just been an 'if' instead of 'while'. Fix this. - -I noticed this while applying another patch from Ben that -intended to fix a busy loop at this spot. - -Cc: stable@vger.kernel.org -Fixes: b16798f5b907 ("mac80211: mark station unauthorized before key removal") -Reported-by: Ben Greear -Link: https://lore.kernel.org/r/20200803110209.253009ae41ff.I3522aad099392b31d5cf2dcca34cbac7e5832dde@changeid -Signed-off-by: Johannes Berg ---- - net/mac80211/sta_info.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -1051,7 +1051,7 @@ static void __sta_info_destroy_part2(str - might_sleep(); - lockdep_assert_held(&local->sta_mtx); - -- while (sta->sta_state == IEEE80211_STA_AUTHORIZED) { -+ if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { - ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); - WARN_ON_ONCE(ret); - } 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 52200b6ecc..f9c4caa51c 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 -@@ -613,21 +613,6 @@ static int wiphy_verify_combinations(str +@@ -614,21 +614,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 fe20785871..7cd0417363 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,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -3454,6 +3454,7 @@ struct cfg80211_update_owe_info { +@@ -3736,6 +3736,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 @@ -8,7 +8,7 @@ * * @set_wds_peer: set the WDS peer for a WDS interface * -@@ -3769,6 +3770,7 @@ struct cfg80211_ops { +@@ -4058,6 +4059,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); @@ -18,7 +18,7 @@ const u8 *addr); --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1501,6 +1501,7 @@ enum ieee80211_smps_mode { +@@ -1561,6 +1561,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 -@@ -1521,6 +1522,7 @@ enum ieee80211_smps_mode { +@@ -1581,6 +1582,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 -@@ -2373,6 +2373,9 @@ enum nl80211_commands { - * the allowed channel bandwidth configurations. (u8 attribute) - * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. +@@ -2527,6 +2527,9 @@ enum nl80211_commands { + * override mask. Used with NL80211_ATTR_S1G_CAPABILITY in + * NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT. * + * @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 -@@ -2835,6 +2838,8 @@ enum nl80211_attrs { - NL80211_ATTR_WIPHY_EDMG_CHANNELS, - NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, +@@ -3016,6 +3019,8 @@ enum nl80211_attrs { + NL80211_ATTR_S1G_CAPABILITY, + NL80211_ATTR_S1G_CAPABILITY_MASK, + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2583,6 +2583,19 @@ static int ieee80211_get_tx_power(struct +@@ -2707,6 +2707,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -4018,6 +4031,7 @@ const struct cfg80211_ops mac80211_confi +@@ -4137,6 +4150,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, @@ -87,7 +87,7 @@ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1376,6 +1376,7 @@ struct ieee80211_local { +@@ -1401,6 +1401,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */ @@ -97,7 +97,7 @@ --- a/net/mac80211/main.c +++ b/net/mac80211/main.c -@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct +@@ -96,7 +96,7 @@ static u32 ieee80211_hw_conf_chan(struct struct ieee80211_sub_if_data *sdata; struct cfg80211_chan_def chandef = {}; u32 changed = 0; @@ -106,7 +106,7 @@ u32 offchannel_flag; offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; -@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct +@@ -157,6 +157,12 @@ static u32 ieee80211_hw_conf_chan(struct } rcu_read_unlock(); @@ -119,7 +119,7 @@ if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; -@@ -639,6 +645,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ +@@ -665,6 +671,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,15 +129,15 @@ local->hw.max_mtu = IEEE80211_MAX_DATA_LEN; --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -628,6 +628,7 @@ const struct nla_policy nl80211_policy[N - .len = SAE_PASSWORD_MAX_LEN }, - [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG }, - [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy), +@@ -732,6 +732,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_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, }; /* policy for the key attributes */ -@@ -2992,6 +2993,20 @@ static int nl80211_set_wiphy(struct sk_b +@@ -3240,6 +3241,20 @@ static int nl80211_set_wiphy(struct sk_b if (result) return result; } diff --git a/package/kernel/mac80211/ralink.mk b/package/kernel/mac80211/ralink.mk index 6aca170773..7bbdc1c22c 100644 --- a/package/kernel/mac80211/ralink.mk +++ b/package/kernel/mac80211/ralink.mk @@ -90,7 +90,7 @@ endef define KernelPackage/rt2800-lib $(call KernelPackage/rt2x00/Default) - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT HIDDEN:=1 TITLE+= (rt2800 LIB) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800lib.ko diff --git a/package/kernel/mac80211/realtek.mk b/package/kernel/mac80211/realtek.mk index 19b54e07d7..75cb94d7b6 100644 --- a/package/kernel/mac80211/realtek.mk +++ b/package/kernel/mac80211/realtek.mk @@ -26,7 +26,7 @@ config-$(call config_package,rtl8723bs) += RTL8723BS config-y += STAGING config-$(call config_package,rtw88) += RTW88 RTW88_CORE RTW88_PCI -config-y += RTW88_8822BE RTW88_8822CE +config-y += RTW88_8822BE RTW88_8822CE RTW88_8723DE define KernelPackage/rtl818x/Default $(call KernelPackage/mac80211/Default) @@ -63,7 +63,7 @@ endef define KernelPackage/rtlwifi $(call KernelPackage/mac80211/Default) TITLE:=Realtek common driver part - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtlwifi.ko HIDDEN:=1 endef @@ -177,11 +177,18 @@ endef define KernelPackage/rtw88 $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822BE/RTL8822CE - DEPENDS+= @(PCI_SUPPORT) +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88.ko \ - $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtwpci.ko - AUTOLOAD:=$(call AutoProbe,rtwpci) + TITLE:=Realtek RTL8822BE/RTL8822CE/RTL8723DE + DEPENDS+= @(PCI_SUPPORT) +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT + FILES:=\ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822be.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822b.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822ce.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822c.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723de.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723d.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_core.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822be rtw88_8822ce rtw88_8723de) endef define KernelPackage/rtl8723bs diff --git a/package/kernel/mac80211/scripts/import-backports.sh b/package/kernel/mac80211/scripts/import-backports.sh index d056eb6d04..35aa411e6c 100755 --- a/package/kernel/mac80211/scripts/import-backports.sh +++ b/package/kernel/mac80211/scripts/import-backports.sh @@ -70,7 +70,7 @@ get_next() { done | tail -n1 } -CUR=`get_next` +CUR=$(get_next) CUR="${CUR:-$BASE}" while [ -n "$1" ]; do