Merge Official Source

This commit is contained in:
ZiMing Mo
2022-06-20 11:33:10 +08:00
224 changed files with 6590 additions and 1825 deletions

View File

@@ -101,7 +101,7 @@ endif
KERNEL_MAKE = $(MAKE) $(KERNEL_MAKEOPTS)
KERNEL_MAKE_FLAGS = \
KCFLAGS="$(call iremap,$(BUILD_DIR),$(notdir $(BUILD_DIR)))" \
KCFLAGS="$(call iremap,$(BUILD_DIR),$(notdir $(BUILD_DIR))) $(call qstrip,$(CONFIG_EXTRA_OPTIMIZATION))" \
HOSTCFLAGS="$(HOST_CFLAGS) -Wall -Wmissing-prototypes -Wstrict-prototypes" \
CROSS_COMPILE="$(KERNEL_CROSS)" \
ARCH="$(LINUX_KARCH)" \

View File

@@ -361,6 +361,8 @@ $(eval $(if $(NF_KMOD),$(call nf_add,NFT_TPROXY,CONFIG_NFT_TPROXY, $(P_XT)nft_tp
$(eval $(if $(NF_KMOD),$(call nf_add,NFT_COMPAT,CONFIG_NFT_COMPAT, $(P_XT)nft_compat),))
$(eval $(if $(NF_KMOD),$(call nf_add,NFT_XFRM,CONFIG_NFT_XFRM, $(P_XT)nft_xfrm),))
# userland only
IPT_BUILTIN += $(NF_IPT-y) $(NF_IPT-m)
IPT_BUILTIN += $(IPT_CORE-y) $(IPT_CORE-m)

View File

@@ -40,35 +40,39 @@ fs_wait_for_key () {
rm -f $keypress_wait
} &
[ "$pi_preinit_no_failsafe" != "y" ] && echo "Press the [$1] key and hit [enter] $2"
echo "Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level"
# if we're on the console we wait for input
{
while [ -r $keypress_wait ]; do
timer="$(cat $keypress_sec)"
local consoles="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | sed -e 's/^console=//' -e 's/,.*//')"
[ -n "$consoles" ] || consoles=console
for console in $consoles; do
[ -c "/dev/$console" ] || continue
[ "$pi_preinit_no_failsafe" != "y" ] && echo "Press the [$1] key and hit [enter] $2" > "/dev/$console"
echo "Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level" > "/dev/$console"
{
while [ -r $keypress_wait ]; do
timer="$(cat $keypress_sec)"
[ -n "$timer" ] || timer=1
timer="${timer%%\ *}"
[ $timer -ge 1 ] || timer=1
do_keypress=""
{
read -t "$timer" do_keypress
case "$do_keypress" in
$1)
echo "true" >$keypress_true
;;
1 | 2 | 3 | 4)
echo "$do_keypress" >/tmp/debug_level
;;
*)
continue;
;;
esac
lock -u $keypress_wait
rm -f $keypress_wait
}
done
}
[ -n "$timer" ] || timer=1
timer="${timer%%\ *}"
[ $timer -ge 1 ] || timer=1
do_keypress=""
{
read -t "$timer" do_keypress < "/dev/$console"
case "$do_keypress" in
$1)
echo "true" >$keypress_true
;;
1 | 2 | 3 | 4)
echo "$do_keypress" >/tmp/debug_level
;;
*)
continue;
;;
esac
lock -u $keypress_wait
rm -f $keypress_wait
}
done
} &
done
lock -w $keypress_wait
keypressed=1

View File

@@ -2,13 +2,14 @@
# Copyright (C) 2010 Vertical Communications
failsafe_shell() {
local console="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | head -1 | sed -e 's/^console=//' -e 's/,.*//')"
[ -n "$console" ] || console=console
[ -c "/dev/$console" ] || return 0
while true; do
ash --login <"/dev/$console" >"/dev/$console" 2>"/dev/$console"
sleep 1
done &
local consoles="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | sed -e 's/^console=//' -e 's/,.*//')"
[ -n "$consoles" ] || consoles=console
for console in $consoles; do
[ -c "/dev/$console" ] && while true; do
ash --login <"/dev/$console" >"/dev/$console" 2>"/dev/$console"
sleep 1
done &
done
}
boot_hook_add failsafe failsafe_shell

View File

@@ -71,6 +71,7 @@ fwtool_check_image() {
# minor compat version -> sysupgrade with -n required
if [ "${devicecompat#.*}" != "${imagecompat#.*}" ] && [ "$SAVE_CONFIG" = "1" ]; then
[ "$IGNORE_MINOR_COMPAT" = 1 ] && return 0
v "The device is supported, but the config is incompatible to the new image ($devicecompat->$imagecompat). Please upgrade without keeping config (sysupgrade -n)."
[ -n "$compatmessage" ] && v "$compatmessage"
return 1

View File

@@ -19,6 +19,7 @@ export CONF_IMAGE=
export CONF_BACKUP_LIST=0
export CONF_BACKUP=
export CONF_RESTORE=
export IGNORE_MINOR_COMPAT=0
export NEED_IMAGE=
export HELP=0
export FORCE=0
@@ -44,6 +45,7 @@ while [ -n "$1" ]; do
-F|--force) export FORCE=1;;
-T|--test) export TEST=1;;
-h|--help) export HELP=1; break;;
--ignore-minor-compat-version) export IGNORE_MINOR_COMPAT=1;;
-*)
echo "Invalid option: $1" >&2
exit 1
@@ -80,6 +82,8 @@ upgrade-option:
Verify image and config .tar.gz but do not actually flash.
-F | --force
Flash image even if image checks fail, this is dangerous!
--ignore-minor-compat-version
Flash image even if the minor compat version is incompatible.
-q less verbose
-v more verbose
-h | --help display this help

View File

@@ -19,6 +19,10 @@ netgear,wndap620|\
netgear,wndap660)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x4000" "0x4000" "4"
;;
wd,mybooklive)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x1000" "0x1000" "1"
ubootenv_add_uci_config "/dev/mtd1" "0x1000" "0x1000" "0x1000" "1"
;;
esac
config_load ubootenv

View File

@@ -104,6 +104,7 @@ netgear,wndr3700-v2|\
netgear,wndrmac-v1)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x10000"
;;
netgear,pgzng1|\
netgear,wndr3700-v4|\
netgear,wndr4300|\
netgear,wndr4300tn|\

View File

@@ -9,6 +9,7 @@ board=$(board_name)
case "$board" in
d-link,dgs-1210-16|\
d-link,dgs-1210-20|\
d-link,dgs-1210-28|\
d-link,dgs-1210-10p|\
zyxel,gs1900-8|\

View File

@@ -68,7 +68,7 @@ endef
define U-Boot/mt7622_ubnt_unifi-6-lr
NAME:=Ubiquiti UniFi 6 LR
UBOOT_CONFIG:=mt7622_ubnt_unifi-6-lr
BUILD_DEVICES:=ubnt_unifi-6-lr-ubootmod
BUILD_DEVICES:=ubnt_unifi-6-lr-v1-ubootmod ubnt_unifi-6-lr-v2-ubootmod
BUILD_SUBTARGET:=mt7622
UBOOT_IMAGE:=u-boot.fip
BL2_BOOTDEV:=nor

View File

@@ -133,7 +133,6 @@ ifneq ($(OF_PLATDATA),)
endif
$(SED) 's#CONFIG_MKIMAGE_DTC_PATH=.*#CONFIG_MKIMAGE_DTC_PATH="$(PKG_BUILD_DIR)/scripts/dtc/dtc"#g' $(PKG_BUILD_DIR)/.config
echo 'CONFIG_IDENT_STRING=" OpenWrt"' >> $(PKG_BUILD_DIR)/.config
endef
define Build/InstallDev

View File

@@ -131,6 +131,25 @@ endef
$(eval $(call KernelPackage,leds-apu))
define KernelPackage/leds-pca955x
SUBMENU:=$(LEDS_MENU)
TITLE:=LED driver for PCA955x I2C chips
DEPENDS:=@GPIO_SUPPORT +kmod-i2c-core
KCONFIG:=CONFIG_LEDS_PCA955X \
CONFIG_LEDS_PCA955X_GPIO=y
FILES:=$(LINUX_DIR)/drivers/leds/leds-pca955x.ko
AUTOLOAD:=$(call AutoLoad,60,leds-pca955x,1)
endef
define KernelPackage/leds-pca955x/description
This option enables support for LEDs connected to PCA955x
LED driver chips accessed via the I2C bus. Supported
devices include PCA9550, PCA9551, PCA9552, and PCA9553.
endef
$(eval $(call KernelPackage,leds-pca955x))
define KernelPackage/leds-pca963x
SUBMENU:=$(LEDS_MENU)
TITLE:=PCA963x LED support

View File

@@ -1271,3 +1271,14 @@ define KernelPackage/nft-compat
endef
$(eval $(call KernelPackage,nft-compat))
define KernelPackage/nft-xfrm
SUBMENU:=$(NF_MENU)
TITLE:=Netfilter nf_tables xfrm support (ipsec)
DEPENDS:=+kmod-nft-core
FILES:=$(foreach mod,$(NFT_XFRM-m),$(LINUX_DIR)/net/$(mod).ko)
AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_XFRM-m)))
KCONFIG:=$(KCONFIG_NFT_XFRM)
endef
$(eval $(call KernelPackage,nft-xfrm))

View File

@@ -0,0 +1,69 @@
From 2587d5198aa5adcbd8896aae4a2404dc13d48637 Mon Sep 17 00:00:00 2001
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Date: Wed, 18 May 2022 10:27:26 +0300
Subject: ath10k: improve tx status reporting
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We use ieee80211_tx_status() to report each completed tx frame.
Internally, this function calls sta_info_get_by_addrs(), what has a
couple of drawbacks:
1. additional station lookup causes a performance degradation;
2. mac80211 can not properly account Ethernet encapsulated frames due
to the inability to properly determine the destination (station) MAC
address since ieee80211_tx_status() assumes the frame has a 802.11
header.
The latter is especially destructive if we want to use hardware frames
encapsulation.
To fix both of these issues, replace ieee80211_tx_status() with
ieee80211_tx_status_ext() call and feed it station pointer from the tx
queue associated with the transmitted frame.
Tested-on: QCA9888 hw2.0 PCI 10.4-3.9.0.2-00131
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00157-QCARMSWPZ-1
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Tested-by: Oldřich Jedlička <oldium.pro@gmail.com> # TP-Link Archer C7 v4 & v5 (QCA9563 + QCA9880)
Tested-by: Edward Matijevic <motolav@gmail.com> # TP-Link Archer C2600 (IPQ8064 + QCA9980 10.4.1.00030-1)
Tested-by: Edward Matijevic <motolav@gmail.com> # QCA9377 PCI in Sta mode
Tested-by: Zhijun You <hujy652@gmail.com> # NETGEAR R7800 (QCA9984 10.4-3.9.0.2-00159)
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220516032519.29831-2-ryazanov.s.a@gmail.com
---
drivers/net/wireless/ath/ath10k/txrx.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -43,6 +43,7 @@ out:
int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
const struct htt_tx_done *tx_done)
{
+ struct ieee80211_tx_status status;
struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
struct ieee80211_tx_info *info;
@@ -128,7 +129,19 @@ int ath10k_txrx_tx_unref(struct ath10k_h
info->status.is_valid_ack_signal = true;
}
- ieee80211_tx_status(htt->ar->hw, msdu);
+ memset(&status, 0, sizeof(status));
+ status.skb = msdu;
+ status.info = info;
+
+ rcu_read_lock();
+
+ if (txq)
+ status.sta = txq->sta;
+
+ ieee80211_tx_status_ext(htt->ar->hw, &status);
+
+ rcu_read_unlock();
+
/* we do not own the msdu anymore */
return 0;

View File

@@ -0,0 +1,74 @@
From a09740548275a74b897654b3aca5af589289b57a Mon Sep 17 00:00:00 2001
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Date: Mon, 16 May 2022 13:26:00 +0300
Subject: ath10k: turn rawmode into frame_mode
Turn boolean rawmode module param into integer frame_mode param that
contains value from ath10k_hw_txrx_mode enum. As earlier the default
param value is non-RAW (native Wi-Fi) encapsulation. The param name
is selected to be consistent with the similar ath11k param.
This is a preparation step for upcoming encapsulation offloading
support.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220516032519.29831-4-ryazanov.s.a@gmail.com
---
drivers/net/wireless/ath/ath10k/core.c | 11 +++++++----
drivers/net/wireless/ath/ath10k/core.h | 1 +
2 files changed, 8 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -32,9 +32,11 @@ EXPORT_SYMBOL(ath10k_debug_mask);
static unsigned int ath10k_cryptmode_param;
static bool uart_print;
static bool skip_otp;
-static bool rawmode;
static bool fw_diag_log;
+/* frame mode values are mapped as per enum ath10k_hw_txrx_mode */
+unsigned int ath10k_frame_mode = ATH10K_HW_TXRX_NATIVE_WIFI;
+
unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |
BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);
@@ -43,15 +45,16 @@ module_param_named(debug_mask, ath10k_de
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644);
-module_param(rawmode, bool, 0644);
module_param(fw_diag_log, bool, 0644);
+module_param_named(frame_mode, ath10k_frame_mode, uint, 0644);
module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
-MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
+MODULE_PARM_DESC(frame_mode,
+ "Datapath frame mode (0: raw, 1: native wifi (default))");
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
@@ -2487,7 +2490,7 @@ static int ath10k_core_init_firmware_fea
ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
- if (rawmode) {
+ if (ath10k_frame_mode == ATH10K_HW_TXRX_RAW) {
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
fw_file->fw_features)) {
ath10k_err(ar, "rawmode = 1 requires support from firmware");
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -1311,6 +1311,7 @@ static inline bool ath10k_peer_stats_ena
return false;
}
+extern unsigned int ath10k_frame_mode;
extern unsigned long ath10k_coredump_mask;
void ath10k_core_napi_sync_disable(struct ath10k *ar);

View File

@@ -0,0 +1,163 @@
From 70f119fb82af7f7417dc659faf02c91e1f853739 Mon Sep 17 00:00:00 2001
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Date: Mon, 16 May 2022 13:26:00 +0300
Subject: ath10k: htt_tx: do not interpret Eth frames as WiFi
The xmit path for the Ethernet encapsulated frames become more or less
usable since d740d8fd2439 ("ath10k: unify tx mode and dispatch"). This
change reorganize the xmit path in a manageable way to properly support
various tx modes, but misses that the Ethernet encapsulated frame is a
special case. We do not have an IEEE 802.11 header at the begining of
them. But the HTT Tx handler still interprets first bytes of each frame
as an IEEE 802.11 Frame Control field.
Than this code was copied by e62ee5c381c5 ("ath10k: Add support for
htt_data_tx_desc_64 descriptor") and a2097d6444c3 ("ath10k: htt: High
latency TX support") to another handlers. In fact the issue in the high
latency (HL) handler was introduced by 83ac260151e7 ("ath10k: add mic
bytes for pmf management packet").
Ethernet encapsulated frame tx mode stay unused until 75d85fd9993c
("ath10k: introduce basic tdls functionality") started using it for TDLS
frames to avoid key selection issue in some firmwares.
Trying to interpret the begining of an Ethernet encapsulated frame as an
IEEE 802.11 header was not hurt us noticeably since we need to meet two
conditions: (1) xmit should be performed towards a TDLS peer, and (2)
the TDLS peer should have a specific OUI part of its MAC address. Looks
like that the rareness in TDLS communications of OUIs that can be
interpreted as an 802.11 management frame saves users from facing this
issue earlier.
Improve Ethernet tx mode support in the HTT Tx handler by avoiding
interpreting its first bytes as an IEEE 802.11 header. While at it, make
the ieee80211_hdr variable local to the code block that is guarded by
!is_eth check. In this way, we clarify in which cases a frame can be
interpreted as IEEE 802.11, and saves us from similar issues in the
future.
Credits: this change as part of xmit encapsulation offloading support
was originally made by QCA and then submitted for inclusion by John
Crispin [1]. But the whole work was not accepted due to the lack of a
part for 64-bits descriptors [2]. Zhijun You then pointed this out to me
in a reply to my initial RFC patch series. And I made this slightly
reworked version that covered all the HTT Tx handler variants.
1. https://lore.kernel.org/all/20191216092207.31032-1-john@phrozen.org/
2. https://patchwork.kernel.org/project/linux-wireless/patch/20191216092207.31032-1-john@phrozen.org/
Reported-by: Zhijun You <hujy652@gmail.com>
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220516032519.29831-3-ryazanov.s.a@gmail.com
---
drivers/net/wireless/ath/ath10k/htt_tx.c | 61 ++++++++++++++++++--------------
1 file changed, 35 insertions(+), 26 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1295,7 +1295,6 @@ static int ath10k_htt_tx_hl(struct ath10
struct ath10k *ar = htt->ar;
int res, data_len;
struct htt_cmd_hdr *cmd_hdr;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
struct htt_data_tx_desc *tx_desc;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct sk_buff *tmp_skb;
@@ -1306,11 +1305,15 @@ static int ath10k_htt_tx_hl(struct ath10
u16 flags1 = 0;
u16 msdu_id = 0;
- if ((ieee80211_is_action(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control) ||
- ieee80211_is_disassoc(hdr->frame_control)) &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ if (!is_eth) {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
+
+ if ((ieee80211_is_action(hdr->frame_control) ||
+ ieee80211_is_deauth(hdr->frame_control) ||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ }
}
data_len = msdu->len;
@@ -1407,7 +1410,6 @@ static int ath10k_htt_tx_32(struct ath10
{
struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct ath10k_hif_sg_item sg_items[2];
@@ -1439,15 +1441,19 @@ static int ath10k_htt_tx_32(struct ath10
txbuf_paddr = htt->txbuf.paddr +
(sizeof(struct ath10k_htt_txbuf_32) * msdu_id);
- if ((ieee80211_is_action(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control) ||
- ieee80211_is_disassoc(hdr->frame_control)) &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
- } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
- txmode == ATH10K_HW_TXRX_RAW &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ if (!is_eth) {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
+
+ if ((ieee80211_is_action(hdr->frame_control) ||
+ ieee80211_is_deauth(hdr->frame_control) ||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
+ txmode == ATH10K_HW_TXRX_RAW &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ }
}
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
@@ -1609,7 +1615,6 @@ static int ath10k_htt_tx_64(struct ath10
{
struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct ath10k_hif_sg_item sg_items[2];
@@ -1641,15 +1646,19 @@ static int ath10k_htt_tx_64(struct ath10
txbuf_paddr = htt->txbuf.paddr +
(sizeof(struct ath10k_htt_txbuf_64) * msdu_id);
- if ((ieee80211_is_action(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control) ||
- ieee80211_is_disassoc(hdr->frame_control)) &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
- } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
- txmode == ATH10K_HW_TXRX_RAW &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ if (!is_eth) {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
+
+ if ((ieee80211_is_action(hdr->frame_control) ||
+ ieee80211_is_deauth(hdr->frame_control) ||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
+ txmode == ATH10K_HW_TXRX_RAW &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ }
}
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,

View File

@@ -0,0 +1,194 @@
From af6d8265c47e46881b80c6b073f53c8c4af52d28 Mon Sep 17 00:00:00 2001
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Date: Mon, 16 May 2022 13:26:00 +0300
Subject: ath10k: add encapsulation offloading support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Frame encapsulation from Ethernet into the IEEE 802.11 frame format
takes a considerable host CPU time on the xmit path. The firmware is
able to do this operation for us, so enable encapsulation offloading for
AP and Sta interface types to improve overall system performance.
The driver is almost ready for encapsulation offloading support. There
are only a few places where the driver assumes the frame format is IEEE
802.11 that need to be fixed.
Encapsulation offloading is currently disabled by default and the driver
utilizes mac80211 encapsulation support. To activate offloading, the
frame_mode=2 parameter should be passed during module loading.
On a QCA9563+QCA9888-based access point in bridged mode, encapsulation
offloading increases TCP 16-streams DL throughput from 365 to 396 mbps
(+8%) and UDP DL throughput from 436 to 483 mbps (+11%).
Tested-on: QCA9888 hw2.0 PCI 10.4-3.9.0.2-00131
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00157-QCARMSWPZ-1
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Tested-by: Oldřich Jedlička <oldium.pro@gmail.com> # TP-Link Archer C7 v4 & v5 (QCA9563 + QCA9880)
Tested-by: Edward Matijevic <motolav@gmail.com> # TP-Link Archer C2600 (IPQ8064 + QCA9980 10.4.1.00030-1)
Tested-by: Edward Matijevic <motolav@gmail.com> # QCA9377 PCI in Sta mode
Tested-by: Zhijun You <hujy652@gmail.com> # NETGEAR R7800 (QCA9984 10.4-3.9.0.2-00159)
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220516032519.29831-5-ryazanov.s.a@gmail.com
---
drivers/net/wireless/ath/ath10k/core.c | 2 +-
drivers/net/wireless/ath/ath10k/mac.c | 67 +++++++++++++++++++++++++++-------
2 files changed, 55 insertions(+), 14 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(uart_print, "Uart targe
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
MODULE_PARM_DESC(frame_mode,
- "Datapath frame mode (0: raw, 1: native wifi (default))");
+ "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3710,6 +3710,9 @@ ath10k_mac_tx_h_get_txmode(struct ath10k
const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
__le16 fc = hdr->frame_control;
+ if (IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
+ return ATH10K_HW_TXRX_ETHERNET;
+
if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
return ATH10K_HW_TXRX_RAW;
@@ -3870,6 +3873,12 @@ static void ath10k_mac_tx_h_fill_cb(stru
bool noack = false;
cb->flags = 0;
+
+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
+ cb->flags |= ATH10K_SKB_F_QOS; /* Assume data frames are QoS */
+ goto finish_cb_fill;
+ }
+
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
@@ -3908,6 +3917,7 @@ static void ath10k_mac_tx_h_fill_cb(stru
cb->flags |= ATH10K_SKB_F_RAW_TX;
}
+finish_cb_fill:
cb->vif = vif;
cb->txq = txq;
cb->airtime_est = airtime;
@@ -4031,7 +4041,11 @@ static int ath10k_mac_tx(struct ath10k *
ath10k_tx_h_seq_no(vif, skb);
break;
case ATH10K_HW_TXRX_ETHERNET:
- ath10k_tx_h_8023(skb);
+ /* Convert 802.11->802.3 header only if the frame was erlier
+ * encapsulated to 802.11 by mac80211. Otherwise pass it as is.
+ */
+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
+ ath10k_tx_h_8023(skb);
break;
case ATH10K_HW_TXRX_RAW:
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) &&
@@ -4643,12 +4657,10 @@ static void ath10k_mac_op_tx(struct ieee
struct ieee80211_vif *vif = info->control.vif;
struct ieee80211_sta *sta = control->sta;
struct ieee80211_txq *txq = NULL;
- struct ieee80211_hdr *hdr = (void *)skb->data;
enum ath10k_hw_txrx_mode txmode;
enum ath10k_mac_tx_path txpath;
bool is_htt;
bool is_mgmt;
- bool is_presp;
int ret;
u16 airtime;
@@ -4662,8 +4674,14 @@ static void ath10k_mac_op_tx(struct ieee
is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT);
if (is_htt) {
+ bool is_presp = false;
+
spin_lock_bh(&ar->htt.tx_lock);
- is_presp = ieee80211_is_probe_resp(hdr->frame_control);
+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+
+ is_presp = ieee80211_is_probe_resp(hdr->frame_control);
+ }
ret = ath10k_htt_tx_inc_pending(htt);
if (ret) {
@@ -5447,6 +5465,30 @@ static int ath10k_mac_set_txbf_conf(stru
ar->wmi.vdev_param->txbf, value);
}
+static void ath10k_update_vif_offload(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
+ struct ath10k *ar = hw->priv;
+ u32 vdev_param;
+ int ret;
+
+ if (ath10k_frame_mode != ATH10K_HW_TXRX_ETHERNET ||
+ ar->wmi.vdev_param->tx_encap_type == WMI_VDEV_PARAM_UNSUPPORTED ||
+ (vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_AP))
+ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
+
+ vdev_param = ar->wmi.vdev_param->tx_encap_type;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+ ATH10K_HW_TXRX_NATIVE_WIFI);
+ /* 10.X firmware does not support this VDEV parameter. Do not warn */
+ if (ret && ret != -EOPNOTSUPP) {
+ ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
+ arvif->vdev_id, ret);
+ }
+}
+
/*
* TODO:
* Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -5656,15 +5698,7 @@ static int ath10k_add_interface(struct i
arvif->def_wep_key_idx = -1;
- vdev_param = ar->wmi.vdev_param->tx_encap_type;
- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
- ATH10K_HW_TXRX_NATIVE_WIFI);
- /* 10.X firmware does not support this VDEV parameter. Do not warn */
- if (ret && ret != -EOPNOTSUPP) {
- ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
- arvif->vdev_id, ret);
- goto err_vdev_delete;
- }
+ ath10k_update_vif_offload(hw, vif);
/* Configuring number of spatial stream for monitor interface is causing
* target assert in qca9888 and qca6174.
@@ -9352,6 +9386,7 @@ static const struct ieee80211_ops ath10k
.stop = ath10k_stop,
.config = ath10k_config,
.add_interface = ath10k_add_interface,
+ .update_vif_offload = ath10k_update_vif_offload,
.remove_interface = ath10k_remove_interface,
.configure_filter = ath10k_configure_filter,
.bss_info_changed = ath10k_bss_info_changed,
@@ -10021,6 +10056,12 @@ int ath10k_mac_register(struct ath10k *a
if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
ieee80211_hw_set(ar->hw, SUPPORTS_TDLS_BUFFER_STA);
+ if (ath10k_frame_mode == ATH10K_HW_TXRX_ETHERNET) {
+ if (ar->wmi.vdev_param->tx_encap_type !=
+ WMI_VDEV_PARAM_UNSUPPORTED)
+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
+ }
+
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
ar->hw->wiphy->max_remain_on_channel_duration = 5000;

View File

@@ -34,7 +34,7 @@ Link: https://lore.kernel.org/r/20211009221711.2315352-1-robimarko@gmail.com
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1199,6 +1199,7 @@ success:
@@ -1202,6 +1202,7 @@ success:
static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
{
const struct firmware *fw;
@@ -42,7 +42,7 @@ Link: https://lore.kernel.org/r/20211009221711.2315352-1-robimarko@gmail.com
if (bd_ie_type == ATH10K_BD_IE_BOARD) {
if (!ar->hw_params.fw.board) {
@@ -1206,9 +1207,19 @@ static int ath10k_core_fetch_board_data_
@@ -1209,9 +1210,19 @@ static int ath10k_core_fetch_board_data_
return -EINVAL;
}

View File

@@ -34,7 +34,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
#include <asm/byteorder.h>
#include "core.h"
@@ -952,7 +953,8 @@ static int ath10k_core_get_board_id_from
@@ -955,7 +956,8 @@ static int ath10k_core_get_board_id_from
}
if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
@@ -44,7 +44,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
else
bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
@@ -1754,7 +1756,8 @@ static int ath10k_download_and_run_otp(s
@@ -1757,7 +1759,8 @@ static int ath10k_download_and_run_otp(s
/* As of now pre-cal is valid for 10_4 variants */
if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
@@ -54,7 +54,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
@@ -1881,6 +1884,39 @@ out_free:
@@ -1884,6 +1887,39 @@ out_free:
return ret;
}
@@ -94,7 +94,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
struct ath10k_fw_file *fw_file)
{
@@ -2115,6 +2151,18 @@ static int ath10k_core_pre_cal_download(
@@ -2118,6 +2154,18 @@ static int ath10k_core_pre_cal_download(
{
int ret;
@@ -113,7 +113,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
if (ret == 0) {
ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
@@ -2181,6 +2229,18 @@ static int ath10k_download_cal_data(stru
@@ -2184,6 +2232,18 @@ static int ath10k_download_cal_data(stru
"pre cal download procedure failed, try cal file: %d\n",
ret);

View File

@@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -3440,6 +3440,16 @@ int ath10k_core_register(struct ath10k *
@@ -3443,6 +3443,16 @@ int ath10k_core_register(struct ath10k *
queue_work(ar->workqueue, &ar->register_work);

View File

@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -9843,6 +9843,21 @@ static int ath10k_mac_init_rd(struct ath
@@ -9878,6 +9878,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[] = {
@@ -10195,6 +10210,12 @@ int ath10k_mac_register(struct ath10k *a
@@ -10236,6 +10251,12 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;

View File

@@ -132,7 +132,7 @@ v13:
unsigned int ath10k_debug_mask;
EXPORT_SYMBOL(ath10k_debug_mask);
@@ -62,6 +63,7 @@ static const struct ath10k_hw_params ath
@@ -65,6 +66,7 @@ static const struct ath10k_hw_params ath
.dev_id = QCA988X_2_0_DEVICE_ID,
.bus = ATH10K_BUS_PCI,
.name = "qca988x hw2.0",
@@ -140,7 +140,7 @@ v13:
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
@@ -135,6 +137,7 @@ static const struct ath10k_hw_params ath
@@ -138,6 +140,7 @@ static const struct ath10k_hw_params ath
.dev_id = QCA9887_1_0_DEVICE_ID,
.bus = ATH10K_BUS_PCI,
.name = "qca9887 hw1.0",
@@ -148,7 +148,7 @@ v13:
.patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
@@ -352,6 +355,7 @@ static const struct ath10k_hw_params ath
@@ -355,6 +358,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,
@@ -394,6 +398,7 @@ static const struct ath10k_hw_params ath
@@ -397,6 +401,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,
@@ -443,6 +448,7 @@ static const struct ath10k_hw_params ath
@@ -446,6 +451,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,
@@ -3155,6 +3161,10 @@ int ath10k_core_start(struct ath10k *ar,
@@ -3158,6 +3164,10 @@ int ath10k_core_start(struct ath10k *ar,
goto err_hif_stop;
}
@@ -183,7 +183,7 @@ v13:
return 0;
err_hif_stop:
@@ -3413,9 +3423,18 @@ static void ath10k_core_register_work(st
@@ -3416,9 +3426,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:
@@ -3461,6 +3480,8 @@ void ath10k_core_unregister(struct ath10
@@ -3464,6 +3483,8 @@ void ath10k_core_unregister(struct ath10
if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
return;

View File

@@ -42,7 +42,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
if (ret)
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -10212,7 +10212,7 @@ int ath10k_mac_register(struct ath10k *a
@@ -10253,7 +10253,7 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
#ifdef CPTCFG_MAC80211_LEDS

View File

@@ -26,7 +26,7 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
#include <linux/property.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
@@ -3331,6 +3332,8 @@ static int ath10k_core_probe_fw(struct a
@@ -3334,6 +3335,8 @@ static int ath10k_core_probe_fw(struct a
device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));

View File

@@ -1,132 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 28 May 2022 16:44:53 +0200
Subject: [PATCH] mac80211: fix overflow issues in airtime fairness code
The airtime weight calculation overflows with a default weight value of 256
whenever more than 8ms worth of airtime is reported.
Bigger weight values impose even smaller limits on maximum airtime values.
This can mess up airtime based calculations for drivers that don't report
per-PPDU airtime values, but batch up values instead.
Fix this by reordering multiplications/shifts and by reducing unnecessary
intermediate precision (which was lost in a later stage anyway).
The new shift value limits the maximum weight to 4096, which should be more
than enough. Any values bigger than that will be clamped to the upper limit.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1666,50 +1666,34 @@ static inline struct airtime_info *to_ai
/* To avoid divisions in the fast path, we keep pre-computed reciprocals for
* airtime weight calculations. There are two different weights to keep track
* of: The per-station weight and the sum of weights per phy.
- *
- * For the per-station weights (kept in airtime_info below), we use 32-bit
- * reciprocals with a devisor of 2^19. This lets us keep the multiplications and
- * divisions for the station weights as 32-bit operations at the cost of a bit
- * of rounding error for high weights; but the choice of divisor keeps rounding
- * errors <10% for weights <2^15, assuming no more than 8ms of airtime is
- * reported at a time.
- *
- * For the per-phy sum of weights the values can get higher, so we use 64-bit
- * operations for those with a 32-bit divisor, which should avoid any
- * significant rounding errors.
+ * The per-sta shift value supports weight values of 1-4096
*/
-#define IEEE80211_RECIPROCAL_DIVISOR_64 0x100000000ULL
-#define IEEE80211_RECIPROCAL_SHIFT_64 32
-#define IEEE80211_RECIPROCAL_DIVISOR_32 0x80000U
-#define IEEE80211_RECIPROCAL_SHIFT_32 19
+#define IEEE80211_RECIPROCAL_SHIFT_SUM 24
+#define IEEE80211_RECIPROCAL_SHIFT_STA 12
+#define IEEE80211_WEIGHT_SHIFT 8
-static inline void airtime_weight_set(struct airtime_info *air_info, u16 weight)
+static inline void airtime_weight_set(struct airtime_info *air_info, u32 weight)
{
+ weight = min_t(u32, weight, BIT(IEEE80211_RECIPROCAL_SHIFT_STA));
if (air_info->weight == weight)
return;
air_info->weight = weight;
- if (weight) {
- air_info->weight_reciprocal =
- IEEE80211_RECIPROCAL_DIVISOR_32 / weight;
- } else {
- air_info->weight_reciprocal = 0;
- }
+ if (weight)
+ weight = BIT(IEEE80211_RECIPROCAL_SHIFT_STA) / weight;
+ air_info->weight_reciprocal = weight;
}
static inline void airtime_weight_sum_set(struct airtime_sched_info *air_sched,
- int weight_sum)
+ u32 weight_sum)
{
if (air_sched->weight_sum == weight_sum)
return;
air_sched->weight_sum = weight_sum;
- if (air_sched->weight_sum) {
- air_sched->weight_sum_reciprocal = IEEE80211_RECIPROCAL_DIVISOR_64;
- do_div(air_sched->weight_sum_reciprocal, air_sched->weight_sum);
- } else {
- air_sched->weight_sum_reciprocal = 0;
- }
+ if (weight_sum)
+ weight_sum = BIT(IEEE80211_RECIPROCAL_SHIFT_SUM) / weight_sum;
+ air_sched->weight_sum_reciprocal = weight_sum;
}
/* A problem when trying to enforce airtime fairness is that we want to divide
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1894,9 +1894,9 @@ void ieee80211_register_airtime(struct i
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
struct ieee80211_local *local = sdata->local;
- u64 weight_sum, weight_sum_reciprocal;
struct airtime_sched_info *air_sched;
struct airtime_info *air_info;
+ u64 weight_sum_reciprocal;
u32 airtime = 0;
air_sched = &local->airtime[txq->ac];
@@ -1907,27 +1907,21 @@ void ieee80211_register_airtime(struct i
if (local->airtime_flags & AIRTIME_USE_RX)
airtime += rx_airtime;
- /* Weights scale so the unit weight is 256 */
- airtime <<= 8;
-
spin_lock_bh(&air_sched->lock);
air_info->tx_airtime += tx_airtime;
air_info->rx_airtime += rx_airtime;
- if (air_sched->weight_sum) {
- weight_sum = air_sched->weight_sum;
+ if (air_sched->weight_sum)
weight_sum_reciprocal = air_sched->weight_sum_reciprocal;
- } else {
- weight_sum = air_info->weight;
+ else
weight_sum_reciprocal = air_info->weight_reciprocal;
- }
/* Round the calculation of global vt */
- air_sched->v_t += (u64)((airtime + (weight_sum >> 1)) *
- weight_sum_reciprocal) >> IEEE80211_RECIPROCAL_SHIFT_64;
- air_info->v_t += (u32)((airtime + (air_info->weight >> 1)) *
- air_info->weight_reciprocal) >> IEEE80211_RECIPROCAL_SHIFT_32;
+ air_sched->v_t += ((u64)airtime * weight_sum_reciprocal) >>
+ (IEEE80211_RECIPROCAL_SHIFT_SUM - IEEE80211_WEIGHT_SHIFT);
+ air_info->v_t += (airtime * air_info->weight_reciprocal) >>
+ (IEEE80211_RECIPROCAL_SHIFT_STA - IEEE80211_WEIGHT_SHIFT);
ieee80211_resort_txq(&local->hw, txq);
spin_unlock_bh(&air_sched->lock);

View File

@@ -1,852 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 28 May 2022 16:51:51 +0200
Subject: [PATCH] mac80211: rework the airtime fairness implementation
The current ATF implementation has a number of issues which have shown up
during testing. Since it does not take into account the AQL budget of
pending packets, the implementation might queue up large amounts of packets
for a single txq until airtime gets reported after tx completion.
The same then happens to the next txq afterwards. While the end result could
still be considered fair, the bursty behavior introduces a large amount of
latency.
The current code also tries to avoid frequent re-sorting of txq entries in
order to avoid having to re-balance the rbtree often.
In order to fix these issues, introduce skip lists as a data structure, which
offer similar lookup/insert/delete times as rbtree, but avoids the need for
rebalacing by being probabilistic.
Use this to keep tx entries sorted by virtual time + pending AQL budget and
re-sort after each ieee80211_return_txq call.
Since multiple txqs share a single air_time struct with a virtual time value,
switch the active_txqs list to queue up air_time structs instead of queues.
This helps avoid imbalance between shared txqs by servicing them round robin.
ieee80211_next_txq now only dequeues the first element of active_txqs. To
make that work for non-AQL or non-ATF drivers as well, add estimated tx
airtime directly to air_info virtual time if either AQL or ATF is not
supported.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
create mode 100644 include/linux/skiplist.h
--- /dev/null
+++ b/include/linux/skiplist.h
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * A skip list is a probabilistic alternative to balanced trees. Unlike the
+ * red-black tree, it does not require rebalancing.
+ *
+ * This implementation uses only unidirectional next pointers and is optimized
+ * for use in a priority queue where elements are mostly deleted from the front
+ * of the queue.
+ *
+ * When storing up to 2^n elements in a n-level skiplist. lookup and deletion
+ * for the first element happens in O(1) time, other than that, insertion and
+ * deletion takes O(log n) time, assuming that the number of elements for an
+ * n-level list does not exceed 2^n.
+ *
+ * Usage:
+ * DECLARE_SKIPLIST_TYPE(foo, 5) will define the data types for a 5-level list:
+ * struct foo_list: the list data type
+ * struct foo_node: the node data for an element in the list
+ *
+ * DECLARE_SKIPLIST_IMPL(foo, foo_cmp_fn)
+ *
+ * Adds the skip list implementation. It depends on a provided function:
+ * int foo_cmp_fn(struct foo_list *list, struct foo_node *n1, struct foo_node *n2)
+ * This compares two elements given by their node pointers, returning values <0
+ * if n1 is less than n2, =0 and >0 for equal or bigger than respectively.
+ *
+ * This macro implements the following functions:
+ *
+ * void foo_list_init(struct foo_list *list)
+ * initializes the skip list
+ *
+ * void foo_node_init(struct foo_node *node)
+ * initializes a node. must be called before adding the node to the list
+ *
+ * struct foo_node *foo_node_next(struct foo_node *node)
+ * gets the node directly after the provided node, or NULL if it was the last
+ * element in the list.
+ *
+ * bool foo_is_queued(struct foo_node *node)
+ * returns true if the node is on a list
+ *
+ * struct foo_node *foo_dequeue(struct foo_list *list)
+ * deletes and returns the first element of the list (or returns NULL if empty)
+ *
+ * struct foo_node *foo_peek(struct foo_list *list)
+ * returns the first element of the list
+ *
+ * void foo_insert(struct foo_list *list, struct foo_node *node)
+ * inserts the node into the list. the node must be initialized and not on a
+ * list already.
+ *
+ * void foo_delete(struct foo_list *list, struct foo_node *node)
+ * deletes the node from the list, or does nothing if it's not on the list
+ */
+#ifndef __SKIPLIST_H
+#define __SKIPLIST_H
+
+#include <linux/bits.h>
+#include <linux/minmax.h>
+#include <linux/bug.h>
+#include <linux/prandom.h>
+
+#define SKIPLIST_POISON ((void *)1)
+
+#define DECLARE_SKIPLIST_TYPE(name, levels) \
+struct name##_node { \
+ struct name##_node *next[levels]; \
+}; \
+struct name##_list { \
+ struct name##_node head; \
+ unsigned int max_level; \
+ unsigned int count; \
+};
+
+#define DECLARE_SKIPLIST_IMPL(name, cmp_fn) \
+static inline void \
+name##_list_init(struct name##_list *list) \
+{ \
+ memset(list, 0, sizeof(*list)); \
+} \
+static inline void \
+name##_node_init(struct name##_node *node) \
+{ \
+ node->next[0] = SKIPLIST_POISON; \
+} \
+static inline struct name##_node * \
+name##_node_next(struct name##_node *node) \
+{ \
+ return node->next[0]; \
+} \
+static inline bool \
+name##_is_queued(struct name##_node *node) \
+{ \
+ return node->next[0] != SKIPLIST_POISON; \
+} \
+static inline int \
+__skiplist_##name##_cmp_impl(void *head, void *n1, void *n2) \
+{ \
+ return cmp_fn(head, n1, n2); \
+} \
+static inline void \
+__##name##_delete(struct name##_list *list) \
+{ \
+ list->count--; \
+ while (list->max_level && \
+ !list->head.next[list->max_level]) \
+ list->max_level--; \
+} \
+static inline struct name##_node * \
+name##_dequeue(struct name##_list *list) \
+{ \
+ struct name##_node *ret; \
+ unsigned int max_level = ARRAY_SIZE(list->head.next) - 1; \
+ ret = (void *)__skiplist_dequeue((void **)&list->head, \
+ max_level); \
+ if (!ret) \
+ return NULL; \
+ __##name##_delete(list); \
+ return ret; \
+} \
+static inline struct name##_node * \
+name##_peek(struct name##_list *list) \
+{ \
+ return list->head.next[0]; \
+} \
+static inline void \
+name##_insert(struct name##_list *list, struct name##_node *node) \
+{ \
+ int level = __skiplist_level(ARRAY_SIZE(list->head.next) - 1, \
+ list->count, prandom_u32()); \
+ level = min_t(int, level, list->max_level + 1); \
+ __skiplist_insert((void *)&list->head, (void *)node, level, \
+ __skiplist_##name##_cmp_impl); \
+ if (level > list->max_level) \
+ list->max_level = level; \
+ list->count++; \
+} \
+static inline void \
+name##_delete(struct name##_list *list, struct name##_node *node) \
+{ \
+ if (node->next[0] == SKIPLIST_POISON) \
+ return; \
+ __skiplist_delete((void *)&list->head, (void *)node, \
+ ARRAY_SIZE(list->head.next) - 1, \
+ __skiplist_##name##_cmp_impl); \
+ __##name##_delete(list); \
+}
+
+
+typedef int (*__skiplist_cmp_t)(void *head, void *n1, void *n2);
+
+#define __skiplist_cmp(cmp, head, cur, node) \
+ ({ \
+ int cmp_val = cmp(head, cur, node); \
+ if (!cmp_val) \
+ cmp_val = (unsigned long)(cur) - \
+ (unsigned long)(node); \
+ cmp_val; \
+ })
+
+static inline void *
+__skiplist_dequeue(void **list, int max_level)
+{
+ void **node = list[0];
+ unsigned int i;
+
+ if (!node)
+ return NULL;
+
+ list[0] = node[0];
+ for (i = 1; i <= max_level; i++) {
+ if (list[i] != node)
+ break;
+
+ list[i] = node[i];
+ }
+ node[0] = SKIPLIST_POISON;
+
+ return node;
+}
+
+static inline void
+__skiplist_insert(void **list, void **node, int level, __skiplist_cmp_t cmp)
+{
+ void **head = list;
+
+ if (WARN(node[0] != SKIPLIST_POISON, "Insert on already inserted or uninitialized node"))
+ return;
+ for (; level >= 0; level--) {
+ while (list[level] &&
+ __skiplist_cmp(cmp, head, list[level], node) < 0)
+ list = list[level];
+
+ node[level] = list[level];
+ list[level] = node;
+ }
+}
+
+
+static inline void
+__skiplist_delete(void **list, void **node, int max_level, __skiplist_cmp_t cmp)
+{
+ void *head = list;
+ int i;
+
+ for (i = max_level; i >= 0; i--) {
+ while (list[i] && list[i] != node &&
+ __skiplist_cmp(cmp, head, list[i], node) <= 0)
+ list = list[i];
+
+ if (list[i] != node)
+ continue;
+
+ list[i] = node[i];
+ }
+ node[0] = SKIPLIST_POISON;
+}
+
+static inline unsigned int
+__skiplist_level(unsigned int max_level, unsigned int count, unsigned int seed)
+{
+ unsigned int level = 0;
+
+ if (max_level >= 16 && !(seed & GENMASK(15, 0))) {
+ level += 16;
+ seed >>= 16;
+ }
+
+ if (max_level >= 8 && !(seed & GENMASK(7, 0))) {
+ level += 8;
+ seed >>= 8;
+ }
+
+ if (max_level >= 4 && !(seed & GENMASK(3, 0))) {
+ level += 4;
+ seed >>= 4;
+ }
+
+ if (!(seed & GENMASK(1, 0))) {
+ level += 2;
+ seed >>= 2;
+ }
+
+ if (!(seed & BIT(0)))
+ level++;
+
+ return min(level, max_level);
+}
+
+#endif
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1563,7 +1563,6 @@ static void sta_apply_airtime_params(str
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
struct airtime_sched_info *air_sched = &local->airtime[ac];
struct airtime_info *air_info = &sta->airtime[ac];
- struct txq_info *txqi;
u8 tid;
spin_lock_bh(&air_sched->lock);
@@ -1575,10 +1574,6 @@ static void sta_apply_airtime_params(str
airtime_weight_set(air_info, params->airtime_weight);
- txqi = to_txq_info(sta->sta.txq[tid]);
- if (RB_EMPTY_NODE(&txqi->schedule_order))
- continue;
-
ieee80211_update_airtime_weight(local, air_sched,
0, true);
}
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -25,7 +25,8 @@
#include <linux/leds.h>
#include <linux/idr.h>
#include <linux/rhashtable.h>
-#include <linux/rbtree.h>
+#include <linux/prandom.h>
+#include <linux/skiplist.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
@@ -854,6 +855,7 @@ enum txq_info_flags {
IEEE80211_TXQ_AMPDU,
IEEE80211_TXQ_NO_AMSDU,
IEEE80211_TXQ_STOP_NETIF_TX,
+ IEEE80211_TXQ_FORCE_ACTIVE,
};
/**
@@ -870,7 +872,6 @@ struct txq_info {
struct fq_tin tin;
struct codel_vars def_cvars;
struct codel_stats cstats;
- struct rb_node schedule_order;
struct sk_buff_head frags;
unsigned long flags;
@@ -1185,8 +1186,7 @@ enum mac80211_scan_state {
*
* @lock: spinlock that protects all the fields in this struct
* @active_txqs: rbtree of currently backlogged queues, sorted by virtual time
- * @schedule_pos: the current position maintained while a driver walks the tree
- * with ieee80211_next_txq()
+ * @schedule_pos: last used airtime_info node while a driver walks the tree
* @active_list: list of struct airtime_info structs that were active within
* the last AIRTIME_ACTIVE_DURATION (100 ms), used to compute
* weight_sum
@@ -1207,8 +1207,8 @@ enum mac80211_scan_state {
*/
struct airtime_sched_info {
spinlock_t lock;
- struct rb_root_cached active_txqs;
- struct rb_node *schedule_pos;
+ struct airtime_sched_list active_txqs;
+ struct airtime_sched_node *schedule_pos;
struct list_head active_list;
u64 last_weight_update;
u64 last_schedule_activity;
@@ -1663,6 +1663,20 @@ static inline struct airtime_info *to_ai
return &sdata->airtime[txq->ac];
}
+static inline int
+airtime_sched_cmp(struct airtime_sched_list *list,
+ struct airtime_sched_node *n1, struct airtime_sched_node *n2)
+{
+ struct airtime_info *a1, *a2;
+
+ a1 = container_of(n1, struct airtime_info, schedule_order);
+ a2 = container_of(n2, struct airtime_info, schedule_order);
+
+ return a1->v_t_cur - a2->v_t_cur;
+}
+
+DECLARE_SKIPLIST_IMPL(airtime_sched, airtime_sched_cmp);
+
/* To avoid divisions in the fast path, we keep pre-computed reciprocals for
* airtime weight calculations. There are two different weights to keep track
* of: The per-station weight and the sum of weights per phy.
@@ -1750,6 +1764,7 @@ static inline void init_airtime_info(str
air_info->aql_limit_high = air_sched->aql_txq_limit_high;
airtime_weight_set(air_info, IEEE80211_DEFAULT_AIRTIME_WEIGHT);
INIT_LIST_HEAD(&air_info->list);
+ airtime_sched_node_init(&air_info->schedule_order);
}
static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -709,7 +709,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
struct airtime_sched_info *air_sched = &local->airtime[i];
- air_sched->active_txqs = RB_ROOT_CACHED;
+ airtime_sched_list_init(&air_sched->active_txqs);
INIT_LIST_HEAD(&air_sched->active_list);
spin_lock_init(&air_sched->lock);
air_sched->aql_txq_limit_low = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1902,8 +1902,7 @@ void ieee80211_register_airtime(struct i
air_sched = &local->airtime[txq->ac];
air_info = to_airtime_info(txq);
- if (local->airtime_flags & AIRTIME_USE_TX)
- airtime += tx_airtime;
+ airtime += tx_airtime;
if (local->airtime_flags & AIRTIME_USE_RX)
airtime += rx_airtime;
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -135,11 +135,14 @@ enum ieee80211_agg_stop_reason {
#define AIRTIME_USE_TX BIT(0)
#define AIRTIME_USE_RX BIT(1)
+DECLARE_SKIPLIST_TYPE(airtime_sched, 5);
struct airtime_info {
+ struct airtime_sched_node schedule_order;
+ struct ieee80211_txq *txq[3];
u64 rx_airtime;
u64 tx_airtime;
- u64 v_t;
+ u64 v_t, v_t_cur;
u64 last_scheduled;
struct list_head list;
atomic_t aql_tx_pending; /* Estimated airtime for frames pending */
@@ -147,6 +150,7 @@ struct airtime_info {
u32 aql_limit_high;
u32 weight_reciprocal;
u16 weight;
+ u8 txq_idx;
};
void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -19,6 +19,7 @@
#include <linux/rcupdate.h>
#include <linux/export.h>
#include <linux/timekeeping.h>
+#include <linux/prandom.h>
#include <net/net_namespace.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
@@ -1476,11 +1477,12 @@ void ieee80211_txq_init(struct ieee80211
struct sta_info *sta,
struct txq_info *txqi, int tid)
{
+ struct airtime_info *air_info;
+
fq_tin_init(&txqi->tin);
codel_vars_init(&txqi->def_cvars);
codel_stats_init(&txqi->cstats);
__skb_queue_head_init(&txqi->frags);
- RB_CLEAR_NODE(&txqi->schedule_order);
txqi->txq.vif = &sdata->vif;
@@ -1489,7 +1491,7 @@ void ieee80211_txq_init(struct ieee80211
txqi->txq.tid = 0;
txqi->txq.ac = IEEE80211_AC_BE;
- return;
+ goto out;
}
if (tid == IEEE80211_NUM_TIDS) {
@@ -1511,6 +1513,12 @@ void ieee80211_txq_init(struct ieee80211
txqi->txq.sta = &sta->sta;
txqi->txq.tid = tid;
sta->sta.txq[tid] = &txqi->txq;
+
+out:
+ air_info = to_airtime_info(&txqi->txq);
+ air_info->txq[air_info->txq_idx++] = &txqi->txq;
+ if (air_info->txq_idx == ARRAY_SIZE(air_info->txq))
+ air_info->txq_idx--;
}
void ieee80211_txq_purge(struct ieee80211_local *local,
@@ -3633,6 +3641,8 @@ struct sk_buff *ieee80211_tx_dequeue(str
struct ieee80211_tx_data tx;
ieee80211_tx_result r;
struct ieee80211_vif *vif = txq->vif;
+ u32 airtime;
+ bool ampdu;
WARN_ON_ONCE(softirq_count() == 0);
@@ -3791,21 +3801,26 @@ begin:
encap_out:
IEEE80211_SKB_CB(skb)->control.vif = vif;
- if (vif &&
- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
- bool ampdu = txq->ac != IEEE80211_AC_VO;
- u32 airtime;
-
- airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
- skb->len, ampdu);
- if (airtime) {
- airtime = ieee80211_info_set_tx_time_est(info, airtime);
- ieee80211_sta_update_pending_airtime(local, tx.sta,
- txq->ac,
- airtime,
- false);
- }
- }
+ if (!vif)
+ return skb;
+
+ ampdu = txq->ac != IEEE80211_AC_VO;
+ airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
+ skb->len, ampdu);
+ if (!airtime)
+ return skb;
+
+ if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL) ||
+ !wiphy_ext_feature_isset(local->hw.wiphy,
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
+ ieee80211_register_airtime(txq, airtime, 0);
+
+ if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
+ return skb;
+
+ airtime = ieee80211_info_set_tx_time_est(info, airtime);
+ ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac,
+ airtime, false);
return skb;
@@ -3816,85 +3831,95 @@ out:
}
EXPORT_SYMBOL(ieee80211_tx_dequeue);
+static void
+airtime_info_next_txq_idx(struct airtime_info *air_info)
+{
+ air_info->txq_idx++;
+ if (air_info->txq_idx >= ARRAY_SIZE(air_info->txq) ||
+ !air_info->txq[air_info->txq_idx])
+ air_info->txq_idx = 0;
+}
+
struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
{
struct ieee80211_local *local = hw_to_local(hw);
struct airtime_sched_info *air_sched;
u64 now = ktime_get_coarse_boottime_ns();
- struct ieee80211_txq *ret = NULL;
+ struct airtime_sched_node *node = NULL;
+ struct ieee80211_txq *txq;
struct airtime_info *air_info;
struct txq_info *txqi = NULL;
- struct rb_node *node;
- bool first = false;
+ u8 txq_idx;
air_sched = &local->airtime[ac];
spin_lock_bh(&air_sched->lock);
- node = air_sched->schedule_pos;
-
begin:
- if (!node) {
- node = rb_first_cached(&air_sched->active_txqs);
- first = true;
- } else {
- node = rb_next(node);
- }
+ txq = NULL;
+ if (airtime_sched_peek(&air_sched->active_txqs) ==
+ air_sched->schedule_pos)
+ goto out;
+ node = airtime_sched_dequeue(&air_sched->active_txqs);
if (!node)
goto out;
- txqi = container_of(node, struct txq_info, schedule_order);
- air_info = to_airtime_info(&txqi->txq);
+ air_info = container_of(node, struct airtime_info, schedule_order);
- if (air_info->v_t > air_sched->v_t &&
- (!first || !airtime_catchup_v_t(air_sched, air_info->v_t, now)))
- goto out;
-
- if (!ieee80211_txq_airtime_check(hw, &txqi->txq)) {
- first = false;
+ airtime_info_next_txq_idx(air_info);
+ txq_idx = air_info->txq_idx;
+ txq = air_info->txq[txq_idx];
+ if (!txq || !ieee80211_txq_airtime_check(hw, txq))
goto begin;
+
+ while (1) {
+ txqi = to_txq_info(txq);
+ if (test_and_clear_bit(IEEE80211_TXQ_FORCE_ACTIVE, &txqi->flags))
+ break;
+
+ if (txq_has_queue(txq))
+ break;
+
+ airtime_info_next_txq_idx(air_info);
+ txq = air_info->txq[air_info->txq_idx];
+ if (txq_idx == air_info->txq_idx)
+ goto begin;
+ }
+
+ if (air_info->v_t_cur > air_sched->v_t) {
+ if (node == airtime_sched_peek(&air_sched->active_txqs))
+ airtime_catchup_v_t(air_sched, air_info->v_t_cur, now);
}
air_sched->schedule_pos = node;
air_sched->last_schedule_activity = now;
- ret = &txqi->txq;
out:
spin_unlock_bh(&air_sched->lock);
- return ret;
+ return txq;
}
EXPORT_SYMBOL(ieee80211_next_txq);
-static void __ieee80211_insert_txq(struct rb_root_cached *root,
+static void __ieee80211_insert_txq(struct ieee80211_local *local,
+ struct airtime_sched_info *air_sched,
struct txq_info *txqi)
{
- struct rb_node **new = &root->rb_root.rb_node;
- struct airtime_info *old_air, *new_air;
- struct rb_node *parent = NULL;
- struct txq_info *__txqi;
- bool leftmost = true;
-
- while (*new) {
- parent = *new;
- __txqi = rb_entry(parent, struct txq_info, schedule_order);
- old_air = to_airtime_info(&__txqi->txq);
- new_air = to_airtime_info(&txqi->txq);
+ struct airtime_info *air_info = to_airtime_info(&txqi->txq);
+ u32 aql_time = 0;
- if (new_air->v_t <= old_air->v_t) {
- new = &parent->rb_left;
- } else {
- new = &parent->rb_right;
- leftmost = false;
- }
+ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
+ aql_time = atomic_read(&air_info->aql_tx_pending);
+ aql_time *= air_info->weight_reciprocal;
+ aql_time >>= IEEE80211_RECIPROCAL_SHIFT_STA - IEEE80211_WEIGHT_SHIFT;
}
- rb_link_node(&txqi->schedule_order, parent, new);
- rb_insert_color_cached(&txqi->schedule_order, root, leftmost);
+ airtime_sched_delete(&air_sched->active_txqs, &air_info->schedule_order);
+ air_info->v_t_cur = air_info->v_t + aql_time;
+ airtime_sched_insert(&air_sched->active_txqs, &air_info->schedule_order);
}
void ieee80211_resort_txq(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
- struct airtime_info *air_info = to_airtime_info(txq);
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = to_txq_info(txq);
struct airtime_sched_info *air_sched;
@@ -3902,41 +3927,7 @@ void ieee80211_resort_txq(struct ieee802
air_sched = &local->airtime[txq->ac];
lockdep_assert_held(&air_sched->lock);
-
- if (!RB_EMPTY_NODE(&txqi->schedule_order)) {
- struct airtime_info *a_prev = NULL, *a_next = NULL;
- struct txq_info *t_prev, *t_next;
- struct rb_node *n_prev, *n_next;
-
- /* Erasing a node can cause an expensive rebalancing operation,
- * so we check the previous and next nodes first and only remove
- * and re-insert if the current node is not already in the
- * correct position.
- */
- if ((n_prev = rb_prev(&txqi->schedule_order)) != NULL) {
- t_prev = container_of(n_prev, struct txq_info,
- schedule_order);
- a_prev = to_airtime_info(&t_prev->txq);
- }
-
- if ((n_next = rb_next(&txqi->schedule_order)) != NULL) {
- t_next = container_of(n_next, struct txq_info,
- schedule_order);
- a_next = to_airtime_info(&t_next->txq);
- }
-
- if ((!a_prev || a_prev->v_t <= air_info->v_t) &&
- (!a_next || a_next->v_t > air_info->v_t))
- return;
-
- if (air_sched->schedule_pos == &txqi->schedule_order)
- air_sched->schedule_pos = n_prev;
-
- rb_erase_cached(&txqi->schedule_order,
- &air_sched->active_txqs);
- RB_CLEAR_NODE(&txqi->schedule_order);
- __ieee80211_insert_txq(&air_sched->active_txqs, txqi);
- }
+ __ieee80211_insert_txq(local, air_sched, txqi);
}
void ieee80211_update_airtime_weight(struct ieee80211_local *local,
@@ -3985,7 +3976,7 @@ void ieee80211_schedule_txq(struct ieee8
was_active = airtime_is_active(air_info, now);
airtime_set_active(air_sched, air_info, now);
- if (!RB_EMPTY_NODE(&txqi->schedule_order))
+ if (airtime_sched_is_queued(&air_info->schedule_order))
goto out;
/* If the station has been inactive for a while, catch up its v_t so it
@@ -3997,7 +3988,7 @@ void ieee80211_schedule_txq(struct ieee8
air_info->v_t = air_sched->v_t;
ieee80211_update_airtime_weight(local, air_sched, now, !was_active);
- __ieee80211_insert_txq(&air_sched->active_txqs, txqi);
+ __ieee80211_insert_txq(local, air_sched, txqi);
out:
spin_unlock_bh(&air_sched->lock);
@@ -4023,19 +4014,10 @@ static void __ieee80211_unschedule_txq(s
ieee80211_update_airtime_weight(local, air_sched, 0, true);
}
- if (RB_EMPTY_NODE(&txqi->schedule_order))
- return;
-
- if (air_sched->schedule_pos == &txqi->schedule_order)
- air_sched->schedule_pos = rb_prev(&txqi->schedule_order);
-
+ airtime_sched_delete(&air_sched->active_txqs, &air_info->schedule_order);
if (!purge)
airtime_set_active(air_sched, air_info,
ktime_get_coarse_boottime_ns());
-
- rb_erase_cached(&txqi->schedule_order,
- &air_sched->active_txqs);
- RB_CLEAR_NODE(&txqi->schedule_order);
}
void ieee80211_unschedule_txq(struct ieee80211_hw *hw,
@@ -4055,14 +4037,24 @@ void ieee80211_return_txq(struct ieee802
{
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = to_txq_info(txq);
+ struct airtime_sched_info *air_sched;
+ struct airtime_info *air_info;
- spin_lock_bh(&local->airtime[txq->ac].lock);
+ air_sched = &local->airtime[txq->ac];
+ air_info = to_airtime_info(&txqi->txq);
- if (!RB_EMPTY_NODE(&txqi->schedule_order) && !force &&
- !txq_has_queue(txq))
- __ieee80211_unschedule_txq(hw, txq, false);
+ if (force)
+ set_bit(IEEE80211_TXQ_FORCE_ACTIVE, &txqi->flags);
- spin_unlock_bh(&local->airtime[txq->ac].lock);
+ spin_lock_bh(&air_sched->lock);
+ if (!ieee80211_txq_airtime_check(hw, &txqi->txq))
+ airtime_sched_delete(&air_sched->active_txqs,
+ &air_info->schedule_order);
+ else if (txq_has_queue(txq) || force)
+ __ieee80211_insert_txq(local, air_sched, txqi);
+ else
+ __ieee80211_unschedule_txq(hw, txq, false);
+ spin_unlock_bh(&air_sched->lock);
}
EXPORT_SYMBOL(ieee80211_return_txq);
@@ -4101,46 +4093,48 @@ EXPORT_SYMBOL(ieee80211_txq_airtime_chec
bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
- struct txq_info *first_txqi = NULL, *txqi = to_txq_info(txq);
+ struct txq_info *txqi = to_txq_info(txq);
struct ieee80211_local *local = hw_to_local(hw);
struct airtime_sched_info *air_sched;
+ struct airtime_sched_node *node = NULL;
struct airtime_info *air_info;
- struct rb_node *node = NULL;
bool ret = false;
+ u32 aql_slack;
u64 now;
-
if (!ieee80211_txq_airtime_check(hw, txq))
return false;
air_sched = &local->airtime[txq->ac];
spin_lock_bh(&air_sched->lock);
- if (RB_EMPTY_NODE(&txqi->schedule_order))
- goto out;
-
now = ktime_get_coarse_boottime_ns();
/* Like in ieee80211_next_txq(), make sure the first station in the
* scheduling order is eligible for transmission to avoid starvation.
*/
- node = rb_first_cached(&air_sched->active_txqs);
+ node = airtime_sched_peek(&air_sched->active_txqs);
if (node) {
- first_txqi = container_of(node, struct txq_info,
- schedule_order);
- air_info = to_airtime_info(&first_txqi->txq);
+ air_info = container_of(node, struct airtime_info,
+ schedule_order);
if (air_sched->v_t < air_info->v_t)
airtime_catchup_v_t(air_sched, air_info->v_t, now);
}
air_info = to_airtime_info(&txqi->txq);
- if (air_info->v_t <= air_sched->v_t) {
+ aql_slack = air_info->aql_limit_low;
+ aql_slack *= air_info->weight_reciprocal;
+ aql_slack >>= IEEE80211_RECIPROCAL_SHIFT_STA - IEEE80211_WEIGHT_SHIFT;
+ /*
+ * add extra slack of aql_limit_low in order to avoid queue
+ * starvation when bypassing normal scheduling order
+ */
+ if (air_info->v_t <= air_sched->v_t + aql_slack) {
air_sched->last_schedule_activity = now;
ret = true;
}
-out:
spin_unlock_bh(&air_sched->lock);
return ret;
}
@@ -4151,9 +4145,7 @@ void ieee80211_txq_schedule_start(struct
struct ieee80211_local *local = hw_to_local(hw);
struct airtime_sched_info *air_sched = &local->airtime[ac];
- spin_lock_bh(&air_sched->lock);
air_sched->schedule_pos = NULL;
- spin_unlock_bh(&air_sched->lock);
}
EXPORT_SYMBOL(ieee80211_txq_schedule_start);

View File

@@ -57,7 +57,7 @@
__NL80211_ATTR_AFTER_LAST,
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2840,6 +2840,19 @@ static int ieee80211_get_tx_power(struct
@@ -2845,6 +2845,19 @@ static int ieee80211_get_tx_power(struct
return 0;
}
@@ -77,7 +77,7 @@
static void ieee80211_rfkill_poll(struct wiphy *wiphy)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -4544,6 +4557,7 @@ const struct cfg80211_ops mac80211_confi
@@ -4549,6 +4562,7 @@ const struct cfg80211_ops mac80211_confi
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,

View File

@@ -56,7 +56,7 @@ endef
define Package/libusb-1.0/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libusb-1.0.so.* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libusb-1.0.so* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,libusb-1.0))

View File

@@ -9,9 +9,9 @@ PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall4.git
PKG_SOURCE_DATE:=2022-05-31
PKG_SOURCE_VERSION:=210991df51587bdb736b4fc74b1200ec6cf6ecc7
PKG_MIRROR_HASH:=486c3fdf7201db8ae51dee7ffac1e80e7b652b27eca9a8174e0fc6f286a457fa
PKG_SOURCE_DATE:=2022-06-17
PKG_SOURCE_VERSION:=15c38317eff2bdef963cc3032512ce6cf191dadb
PKG_MIRROR_HASH:=cff2beca5ef6c337ce8f0e93466509071dc8c614216b974c4adf4848d67f52e0
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC

View File

@@ -164,32 +164,7 @@ found:
struct uci_element *os;
s = uci_to_section(e);
if (!strcmp(s->type, "switch_port")) {
char *devn = NULL, *port = NULL, *port_err = NULL;
int port_n;
uci_foreach_element(&s->options, os) {
o = uci_to_option(os);
if (o->type != UCI_TYPE_STRING)
continue;
if (!strcmp(os->name, "device")) {
devn = o->v.string;
if (!swlib_match_name(dev, devn))
devn = NULL;
} else if (!strcmp(os->name, "port")) {
port = o->v.string;
}
}
if (!devn || !port || !port[0])
continue;
port_n = strtoul(port, &port_err, 0);
if (port_err && port_err[0])
continue;
swlib_map_settings(dev, SWLIB_ATTR_GROUP_PORT, port_n, s);
} else if (!strcmp(s->type, "switch_vlan")) {
if (!strcmp(s->type, "switch_vlan")) {
char *devn = NULL, *vlan = NULL, *vlan_err = NULL;
int vlan_n;
@@ -216,6 +191,38 @@ found:
swlib_map_settings(dev, SWLIB_ATTR_GROUP_VLAN, vlan_n, s);
}
}
uci_foreach_element(&p->sections, e) {
struct uci_element *os;
char *devn = NULL, *port = NULL, *port_err = NULL;
int port_n;
s = uci_to_section(e);
if (strcmp(s->type, "switch_port"))
continue;
uci_foreach_element(&s->options, os) {
o = uci_to_option(os);
if (o->type != UCI_TYPE_STRING)
continue;
if (!strcmp(os->name, "device")) {
devn = o->v.string;
if (!swlib_match_name(dev, devn))
devn = NULL;
} else if (!strcmp(os->name, "port")) {
port = o->v.string;
}
}
if (!devn || !port || !port[0])
continue;
port_n = strtoul(port, &port_err, 0);
if (port_err && port_err[0])
continue;
swlib_map_settings(dev, SWLIB_ATTR_GROUP_PORT, port_n, s);
}
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
struct swlib_setting *st = &early_settings[i];

View File

@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=464xlat
PKG_RELEASE:=12
PKG_RELEASE:=13
PKG_SOURCE_DATE:=2018-01-16
PKG_MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>

View File

@@ -98,6 +98,9 @@ proto_464xlat_teardown() {
ip -6 rule del from all lookup local
ip -6 rule add from all lookup local pref 0
fi
# Kill conntracks SNATed to 192.0.0.1
echo 192.0.0.1 > /proc/net/nf_conntrack
}
proto_464xlat_init_config() {

View File

@@ -9,9 +9,9 @@ PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE_URL:=http://w1.fi/hostap.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2022-05-08
PKG_SOURCE_VERSION:=b859b9bceadccd882252ff0aa2fdba0d3b91764e
PKG_MIRROR_HASH:=4655a747c197d7622b41865203d6601a080b9750fcd68073688cbb6076d13894
PKG_SOURCE_DATE:=2022-06-02
PKG_SOURCE_VERSION:=4383528e01955d995d3b3db201e4c0f9840e8236
PKG_MIRROR_HASH:=1b533287661d4877d56aca8a5b2a53d84d2a90eebe246d8d9b3adf943da7f0a1
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -338,6 +338,7 @@ hostapd_common_add_bss_config() {
config_add_int sae_pwe
config_add_string 'owe_transition_bssid:macaddr' 'owe_transition_ssid:string'
config_add_string owe_transition_ifname
config_add_boolean iw_enabled iw_internet iw_asra iw_esr iw_uesa
config_add_int iw_access_network_type iw_venue_group iw_venue_type
@@ -638,10 +639,11 @@ hostapd_set_bss_options() {
case "$auth_type" in
none|owe)
json_get_vars owe_transition_bssid owe_transition_ssid
json_get_vars owe_transition_bssid owe_transition_ssid owe_transition_ifname
[ -n "$owe_transition_ssid" ] && append bss_conf "owe_transition_ssid=\"$owe_transition_ssid\"" "$N"
[ -n "$owe_transition_bssid" ] && append bss_conf "owe_transition_bssid=$owe_transition_bssid" "$N"
[ -n "$owe_transition_ifname" ] && append bss_conf "owe_transition_ifname=$owe_transition_ifname" "$N"
wps_possible=1
# Here we make the assumption that if we're in open mode

View File

@@ -0,0 +1,19 @@
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -8104,6 +8104,7 @@ int wpas_network_disabled(struct wpa_sup
!ssid->mem_only_psk)
return 1;
+#ifdef CONFIG_IEEE8021X_EAPOL
#ifdef CRYPTO_RSA_OAEP_SHA256
if (ssid->eap.imsi_privacy_cert) {
struct crypto_rsa_key *key;
@@ -8121,7 +8122,7 @@ int wpas_network_disabled(struct wpa_sup
}
}
#endif /* CRYPTO_RSA_OAEP_SHA256 */
-
+#endif /* CONFIG_IEEE8021X_EAPOL */
return 0;
}

View File

@@ -21,6 +21,6 @@ include $(INCLUDE_DIR)/target.mk
KERNELNAME:=uImage
DEFAULT_PACKAGES += \
kmod-leds-gpio kmod-i2c-core kmod-gpio-button-hotplug
kmod-leds-gpio kmod-i2c-core kmod-gpio-button-hotplug uboot-envtools
$(eval $(call BuildTarget))

View File

@@ -180,7 +180,7 @@
keys {
compatible = "gpio-keys";
reset {
button-restart {
/* Label as per Meraki's "MR24 Installation Guide" */
label = "Factory Reset Button";
linux,code = <KEY_RESTART>;

View File

@@ -175,7 +175,7 @@
keys {
compatible = "gpio-keys";
reset {
button-restart {
label = "Reset button";
linux,code = <KEY_RESTART>;
gpios = <&GPIO0 16 GPIO_ACTIVE_LOW>;

View File

@@ -130,7 +130,7 @@
keys {
compatible = "gpio-keys";
reset {
button-restart {
label = "Reset Button";
gpios = <&GPIO0 16 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;

View File

@@ -355,7 +355,7 @@
keys {
compatible = "gpio-keys";
reset {
button-restart {
label = "Reset button";
gpios = <&GPIO0 15 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
@@ -364,7 +364,7 @@
debounce-interval = <60>;
};
backup_hd {
button-backup_hd {
label = "Backup HD button";
gpios = <&GPIO0 19 GPIO_ACTIVE_LOW>;
linux,code = <BTN_0>;
@@ -373,7 +373,7 @@
debounce-interval = <60>;
};
rfkill {
button-rfkill {
label = "RFKILL button";
gpios = <&GPIO0 20 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RFKILL>;
@@ -382,7 +382,7 @@
debounce-interval = <60>;
};
wps {
button-wps {
label = "WPS button";
gpios = <&GPIO0 23 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;

View File

@@ -22,7 +22,7 @@
ebc {
nor_flash@0,0 {
status = "okay";
compatible = "amd,s29gl512n", "jedec-probe", "cfi-flash", "mtd-rom";
compatible = "microchip,sst39vf040", "jedec-flash";
bank-width = <1>;
reg = <0x00000000 0x00000000 0x00080000>;
#address-cells = <1>;
@@ -32,16 +32,19 @@
/* Part of bootrom - Don't use it without a jump */
label = "free";
reg = <0x00000000 0x0001e000>;
read-only;
};
partition@1e000 {
label = "env";
reg = <0x0001e000 0x00002000>;
read-only;
};
partition@20000 {
label = "uboot";
reg = <0x00020000 0x00050000>;
read-only;
};
};
};
@@ -113,7 +116,7 @@
poll-interval = <60>; /* 3 * 20 = 60ms */
autorepeat;
reset-button {
button-restart {
label = "Reset button";
linux,code = <KEY_RESTART>;
gpios = <&GPIO2 2 GPIO_ACTIVE_LOW>;

View File

@@ -35,6 +35,8 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
# CONFIG_MD_RAID10 is not set
# CONFIG_MD_RAID456 is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_PM=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_CLK=y

View File

@@ -58,8 +58,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
};

View File

@@ -125,8 +125,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
};

View File

@@ -103,8 +103,6 @@
#size-cells = <0>;
status = "okay";
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;
phy-mode = "rgmii";

View File

@@ -73,8 +73,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -107,8 +107,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
};

View File

@@ -62,7 +62,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x0f>;
phy1: ethernet-phy@1 {
reg = <0x1>;
};

View File

@@ -110,8 +110,6 @@
#size-cells = <0>;
status = "okay";
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;
phy-mode = "rgmii";

View File

@@ -123,8 +123,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -179,8 +179,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -110,8 +110,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x10>;
ethernet-switch@1e {
compatible = "brcm,bcm53128";
reg = <0x1e>;

View File

@@ -191,7 +191,6 @@
#address-cells = <1>;
#size-cells = <0>;
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;

View File

@@ -200,8 +200,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};

View File

@@ -78,7 +78,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy0: ethernet-phy@0 {
phy-mode = "rgmii";
reg = <0>;

View File

@@ -10,7 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy4: ethernet-phy@4 {
phy-mode = "rgmii";
reg = <4>;

View File

@@ -10,8 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy1: ethernet-phy@1 {
reg = <1>;
phy-mode = "mii";

View File

@@ -10,8 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy1: ethernet-phy@1 {
reg = <1>;
phy-mode = "mii";

View File

@@ -11,7 +11,6 @@
status = "okay";
phy4-mii-enable;
phy-mask = <0x23>;
phy0: ethernet-phy@0 {
reg = <0>;

View File

@@ -10,8 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy1: ethernet-phy@1 {
reg = <1>;
};

View File

@@ -10,8 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy4: ethernet-phy@4 {
reg = <4>;
};

View File

@@ -5,8 +5,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy4: ethernet-phy@4 {
reg = <4>;
};

View File

@@ -5,8 +5,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy0: ethernet-phy@0 {
phy-mode = "rgmii";
reg = <0>;

View File

@@ -159,8 +159,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;

View File

@@ -116,8 +116,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -36,8 +36,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
qca,ar8327-initvals = <

View File

@@ -0,0 +1,333 @@
// SPDX-License-Identifier: GPL-2.0-only
#include "ar9344.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/leds/leds-pca955x.h>
/ {
model = "Netgear PGZNG1";
compatible = "netgear,pgzng1", "qca,ar9344";
aliases {
led-boot = &led_power_green;
led-failsafe = &led_power_red;
led-running = &led_power_green;
led-upgrade = &led_power_green;
label-mac-device = &eth0;
};
chosen {
bootargs = "console=ttyS0,115200";
};
keys {
compatible = "gpio-keys";
reset {
label = "Reset button";
linux,code = <KEY_RESTART>;
gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
debounce-interval = <60>;
};
};
i2c {
compatible = "i2c-gpio";
sda-gpios = <&gpio 14 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
scl-gpios = <&gpio 13 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
#address-cells = <1>;
#size-cells = <0>;
expander0: pca9551@60 {
compatible = "nxp,pca9551";
reg = <0x60>;
#address-cells = <1>;
#size-cells = <0>;
led_power_green: led@0 {
reg = <0>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_BOOT;
type = <PCA955X_TYPE_LED>;
chan-name = "green:boot";
};
led_power_red: led@1 {
reg = <1>;
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_BOOT;
type = <PCA955X_TYPE_LED>;
chan-name = "red:boot";
};
led@2 {
reg = <2>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WAN;
function-enumerator = <1>;
type = <PCA955X_TYPE_LED>;
};
led@3 {
reg = <3>;
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_WAN;
type = <PCA955X_TYPE_LED>;
};
led@4 {
reg = <4>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WLAN;
type = <PCA955X_TYPE_LED>;
};
led@5 {
reg = <5>;
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_WLAN;
type = <PCA955X_TYPE_LED>;
};
led@6 {
reg = <6>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_INDICATOR;
type = <PCA955X_TYPE_LED>;
};
led@7 {
reg = <7>;
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_INDICATOR;
type = <PCA955X_TYPE_LED>;
};
};
expander1: pca9551@61 {
compatible = "nxp,pca9551";
reg = <0x61>;
#address-cells = <1>;
#size-cells = <0>;
gpio-controller;
#gpio-cells = <2>;
/* zwave_rst - Resets ZWave */
gpio@4 {
reg = <4>;
type = <PCA955X_TYPE_GPIO>;
};
/* em_rst - Unknown */
gpio@5 {
reg = <5>;
type = <PCA955X_TYPE_GPIO>;
};
/* tp34 - Test point on PCB? */
gpio@6 {
reg = <6>;
type = <PCA955X_TYPE_GPIO>;
};
/* sw_rst - resets SoC */
gpio@7 {
reg = <7>;
type = <PCA955X_TYPE_GPIO>;
};
};
rtc@6f {
compatible = "isil,isl1208";
reg = <0x6f>;
};
};
leds {
compatible = "gpio-leds";
eth1_link {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_LAN;
gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
};
eth1_act {
color = <LED_COLOR_ID_AMBER>;
function = LED_FUNCTION_LAN;
gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};
eth0_link {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WAN;
function-enumerator = <0>;
gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
};
eth0_act {
color = <LED_COLOR_ID_AMBER>;
function = LED_FUNCTION_WAN;
gpios = <&gpio 3 GPIO_ACTIVE_LOW>;
};
};
};
&eth0 {
status = "okay";
phy-handle = <&swphy0>;
nvmem-cells = <&macaddr_caldata_6>;
nvmem-cell-names = "mac-address";
};
&eth1 {
status = "okay";
phy-handle = <&swphy4>;
nvmem-cells = <&macaddr_caldata_0>;
nvmem-cell-names = "mac-address";
gmac-config {
device = <&gmac>;
switch-phy-swap = <1>;
switch-only-mode = <1>;
};
};
&gpio {
gpio_ext_lna0 {
gpio-hog;
line-name = "ext:lna0";
gpios = <18 GPIO_ACTIVE_HIGH>;
output-high;
};
gpio_ext_lna1 {
gpio-hog;
line-name = "ext:lna1";
gpios = <19 GPIO_ACTIVE_HIGH>;
output-high;
};
gpio_enable_rs422 {
gpio-hog;
line-name = "power:rs422";
gpios = <20 GPIO_ACTIVE_HIGH>;
output-high;
};
};
&nand {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "u-boot";
reg = <0x0 0x40000>;
read-only;
};
partition@40000 {
label = "u-boot-env";
reg = <0x40000 0x40000>;
read-only;
};
/* factory kernel used to be reg = <0x80000 0x200000> */
partition@80000 {
label = "kernel";
reg = <0x80000 0x500000>;
};
/* factory rootfs used to be reg = <0x280000 0x5000000> */
partition@580000 {
label = "ubi";
reg = <0x580000 0x4d00000>;
};
partition@5280000 {
label = "uImage2";
reg = <0x5280000 0x200000>;
read-only;
};
partition@5480000 {
label = "rootfs_bak";
reg = <0x5480000 0x5000000>;
read-only;
};
partition@a480000 {
label = "config";
reg = <0xa480000 0x1400000>;
read-only;
};
partition@b880000 {
label = "storage";
reg = <0xb880000 0x4700000>;
read-only;
};
partition@ff80000 {
label = "dummy";
reg = <0xff80000 0x60000>;
read-only;
};
caldata: partition@ffe0000 {
label = "caldata";
reg = <0xffe0000 0x20000>;
read-only;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
macaddr_caldata_0: macaddr@0 {
reg = <0x0 0x6>;
};
macaddr_caldata_6: macaddr@6 {
reg = <0x6 0x6>;
};
cal_caldata_1000: cal@1000 {
reg = <0x1000 0x440>;
};
};
};
};
&ref {
clock-frequency = <40000000>;
};
/* zWave is wired up via SPI and UART1 (no idea on pins sadly) */
&spi {
status = "okay";
};
&wmac {
status = "okay";
nvmem-cells = <&cal_caldata_1000>;
nvmem-cell-names = "calibration";
};
&usb {
status = "okay";
};
&usb_phy {
status = "okay";
};

View File

@@ -192,8 +192,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -148,8 +148,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
eee-broken-100tx;

View File

@@ -82,8 +82,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x1>;
phy0: ethernet-phy@0 {
reg = <0>;
eee-broken-100tx;

View File

@@ -160,8 +160,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x80>;
phy7: ethernet-phy@7 {
reg = <7>;
eee-broken-100tx;

View File

@@ -142,8 +142,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -135,8 +135,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -10,8 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -10,8 +10,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -93,8 +93,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";

View File

@@ -94,8 +94,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
switch0@1f {
compatible = "qca,ar8327";
reg = <0x1f>;

View File

@@ -134,8 +134,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;
};

View File

@@ -187,8 +187,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;
};

View File

@@ -46,10 +46,4 @@
reg = <0xf50000 0xa0000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};

View File

@@ -46,10 +46,4 @@
reg = <0xf60000 0x90000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};

View File

@@ -41,6 +41,20 @@
reg = <0x60000 0x10000>;
read-only;
};
partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
cal_ath9k: calibration@1000 {
reg = <0x1000 0x440>;
};
};
};
};
};
@@ -48,5 +62,6 @@
&wmac {
status = "okay";
mtd-cal-data = <&art 0x1000>;
nvmem-cells = <&cal_ath9k>;
nvmem-cell-names = "calibration";
};

View File

@@ -51,12 +51,6 @@
reg = <0xf50000 0xa0000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};
&mdio0 {
@@ -85,4 +79,18 @@
&pcie0 {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
nvmem-cells = <&cal_ath10k>;
nvmem-cell-names = "calibration";
};
};
&art {
cal_ath10k: calibration@5000 {
reg = <0x5000 0x844>;
};
};

View File

@@ -51,12 +51,6 @@
reg = <0xf50000 0xa0000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};
&mdio0 {
@@ -85,4 +79,18 @@
&pcie0 {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
nvmem-cells = <&precal_ath10k>;
nvmem-cell-names = "pre-calibration";
};
};
&art {
precal_ath10k: pre-calibration@5000 {
reg = <0x5000 0x2f20>;
};
};

View File

@@ -63,12 +63,6 @@
reg = <0xfe0000 0x010000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x010000>;
read-only;
};
};
&mdio0 {
@@ -101,7 +95,6 @@
&eth1 {
status = "okay";
phy-mask = <0>;
pll-data = <0x03000101 0x00000101 0x00001616>;
fixed-link {
@@ -112,4 +105,18 @@
&pcie0 {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
nvmem-cells = <&cal_ath10k>;
nvmem-cell-names = "calibration";
};
};
&art {
cal_ath10k: calibration@5000 {
reg = <0x5000 0x844>;
};
};

View File

@@ -51,12 +51,6 @@
reg = <0xf60000 0x90000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};
&mdio0 {
@@ -99,4 +93,18 @@
&pcie0 {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
nvmem-cells = <&cal_ath10k>;
nvmem-cell-names = "calibration";
};
};
&art {
cal_ath10k: calibration@5000 {
reg = <0x5000 0x844>;
};
};

View File

@@ -119,8 +119,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x6>;
phy1: ethernet-phy@1 {
reg = <1>;
eee-broken-100tx;

View File

@@ -127,8 +127,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x20>;
phy5: ethernet-phy@5 {
reg = <5>;
eee-broken-100tx;

View File

@@ -138,8 +138,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x6>;
phy1: ethernet-phy@1 {
reg = <1>;
eee-broken-100tx;

View File

@@ -168,8 +168,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;
eee-broken-100tx;
@@ -180,8 +178,6 @@
&mdio1 {
status = "okay";
phy-mask = <0x2>;
phy1: ethernet-phy@1 {
reg = <1>;
eee-broken-100tx;

View File

@@ -121,8 +121,6 @@
&mdio0 {
status = "okay";
phy-mask = <0x10>;
phy4: ethernet-phy@4 {
reg = <4>;
eee-broken-100tx;

View File

@@ -81,7 +81,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy4: ethernet-phy@4 {
phy-mode = "sgmii";
reg = <4>;

View File

@@ -21,7 +21,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy4: ethernet-phy@4 {
phy-mode = "sgmii";
reg = <4>;

View File

@@ -21,7 +21,6 @@
&mdio0 {
status = "okay";
phy-mask = <4>;
phy4: ethernet-phy@4 {
phy-mode = "sgmii";
reg = <4>;

View File

@@ -41,6 +41,20 @@
reg = <0x60000 0x10000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
cal_ath9k: calibration@1000 {
reg = <0x1000 0x440>;
};
};
};
};
};
@@ -48,5 +62,6 @@
&wmac {
status = "okay";
mtd-cal-data = <&art 0x1000>;
nvmem-cells = <&cal_ath9k>;
nvmem-cell-names = "calibration";
};

View File

@@ -58,6 +58,16 @@
&pcie {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
mac-address-increment = <1>;
nvmem-cells = <&macaddr_info_8>, <&precalibration_ath10k>;
nvmem-cell-names = "mac-address", "pre-calibration";
};
};
&spi {
@@ -121,6 +131,18 @@
label = "art";
reg = <0xff0000 0x010000>;
read-only;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
calibration_ath9k: calibration@1000 {
reg = <0x1000 0x440>;
};
precalibration_ath10k: pre-calibration@5000 {
reg = <0x5000 0x2f20>;
};
};
};
};
@@ -136,9 +158,8 @@
&wmac {
status = "okay";
mtd-cal-data = <&art 0x1000>;
nvmem-cells = <&macaddr_info_8>;
nvmem-cell-names = "mac-address";
nvmem-cells = <&macaddr_info_8>, <&calibration_ath9k>;
nvmem-cell-names = "mac-address", "calibration";
};
&info {

View File

@@ -134,8 +134,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@3 {
reg = <0x3>;
phy-mode = "sgmii";

View File

@@ -104,8 +104,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "sgmii";

View File

@@ -99,8 +99,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "sgmii";

View File

@@ -121,8 +121,6 @@
&mdio0 {
status = "okay";
phy-mask = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
qca,mib-poll-interval = <500>;

Some files were not shown because too many files have changed in this diff Show More