From 80e4e2285fdf4a7b19c84532deafe2d1e690ed30 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Jan 2024 14:36:42 +0100 Subject: [PATCH 01/18] mac80211: do not emit VHT160 capabilities if channel width is less than 160 MHz Fixes compatibility issues with VHT160 capable clients Signed-off-by: Felix Fietkau --- .../kernel/mac80211/files/lib/netifd/wireless/mac80211.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index b5378e556e..6ff627b038 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -327,6 +327,11 @@ mac80211_hostapd_setup_base() { [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))" + [ "$vht_oper_chwidth" -lt 2 ] && { + vht160=0 + short_gi_160=0 + } + mac80211_add_capabilities vht_capab $vht_cap \ RXLDPC:0x10::$rxldpc \ SHORT-GI-80:0x20::$short_gi_80 \ From 38bec08e87b69212daf34eac7b26d643a92d9353 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Jan 2024 15:15:08 +0100 Subject: [PATCH 02/18] mediatek: fix BPI-R3 wifi mac address Setting/clearing bits on the first byte of the mac address causes collisions when using multiple SSIDs on both PHYs. Change the allocation to alter the last byte instead. Signed-off-by: Felix Fietkau --- .../base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index 7f013732d3..d9e0335b67 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -37,9 +37,9 @@ case "$board" in [ "$PHYNBR" = "1" ] && echo "$addr" > /sys${DEVPATH}/macaddress ;; bananapi,bpi-r3) - addr=$(macaddr_add $(cat /sys/class/net/eth0/address) 2) - [ "$PHYNBR" = "0" ] && macaddr_unsetbit $addr 6 > /sys${DEVPATH}/macaddress - [ "$PHYNBR" = "1" ] && macaddr_setbit $addr 6 > /sys${DEVPATH}/macaddress + addr=$(cat /sys/class/net/eth0/address) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress ;; cetron,ct3003) addr=$(mtd_get_mac_binary "art" 0) From 3e753c45cd19199ef61aad805b0e29ed261577bd Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Mon, 27 Nov 2023 17:08:04 +0100 Subject: [PATCH 03/18] rtl838x: Enable jumbo frames by default Increase DEFAULT_MTU and max-mtu size Increase truncate length on rx of jumbo frame Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../files-5.15/drivers/net/ethernet/rtl838x_eth.c | 15 +++++++++------ .../files-5.15/drivers/net/ethernet/rtl838x_eth.h | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c index 9dcb7a3b78..54e592aeaa 100644 --- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c @@ -43,6 +43,9 @@ extern struct rtl83xx_soc_info soc_info; #define RX_EN 0x4 #define TX_EN_93XX 0x20 #define RX_EN_93XX 0x10 +#define RX_TRUNCATE_EN_93XX BIT(6) +#define RX_TRUNCATE_EN_83XX BIT(4) +#define TX_PAD_EN_838X BIT(5) #define TX_DO 0x2 #define WRAP 0x2 #define MAX_PORTS 57 @@ -727,8 +730,8 @@ static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) /* Disable Head of Line features for all RX rings */ sw_w32(0xffffffff, priv->r->dma_if_rx_ring_size(0)); - /* Truncate RX buffer to 0x640 (1600) bytes, pad TX */ - sw_w32(0x06400020, priv->r->dma_if_ctrl); + /* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */ + sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X, priv->r->dma_if_ctrl); /* Enable RX done, RX overflow and TX done interrupts */ sw_w32(0xfffff, priv->r->dma_if_intr_msk); @@ -752,7 +755,7 @@ static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) { /* Setup CPU-Port: RX Buffer */ - sw_w32(0x0000c808, priv->r->dma_if_ctrl); + sw_w32((DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX, priv->r->dma_if_ctrl); /* Enable Notify, RX done, RX overflow and TX done interrupts */ sw_w32(0x007fffff, priv->r->dma_if_intr_msk); /* Notify IRQ! */ @@ -775,8 +778,8 @@ static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) static void rtl93xx_hw_en_rxtx(struct rtl838x_eth_priv *priv) { - /* Setup CPU-Port: RX Buffer truncated at 1600 Bytes */ - sw_w32(0x06400040, priv->r->dma_if_ctrl); + /* Setup CPU-Port: RX Buffer truncated at DEFAULT_MTU Bytes */ + sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_93XX, priv->r->dma_if_ctrl); for (int i = 0; i < priv->rxrings; i++) { int pos = (i % 3) * 10; @@ -2415,7 +2418,7 @@ static int __init rtl838x_eth_probe(struct platform_device *pdev) dev->ethtool_ops = &rtl838x_ethtool_ops; dev->min_mtu = ETH_ZLEN; - dev->max_mtu = 1536; + dev->max_mtu = DEFAULT_MTU; dev->features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM; dev->hw_features = NETIF_F_RXCSUM; diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h index 7a5ff678a4..47ed286aa4 100644 --- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h @@ -216,6 +216,9 @@ /* Registers of the internal Serdes of the 8380 */ #define RTL838X_SDS4_FIB_REG0 (0xF800) +/* Default MTU with jumbo frames support */ +#define DEFAULT_MTU 9000 + inline int rtl838x_mac_port_ctrl(int p) { return RTL838X_MAC_PORT_CTRL + (p << 7); From e0c0137eed81e365156270d20a3ba73b14e142f1 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Mon, 27 Nov 2023 17:09:27 +0100 Subject: [PATCH 04/18] rtl83xx: dsa: disable VLAN filtering on CPU port Before driver code - enabled egress filter for cpu and non-cpu ports - enabled ingress filter for non-cpu ports This patch explicitly enables ingress and egress filtering for non-cpu ports and disables ingress and egress filtering for cpu port. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 9f608950c0..75f9ceb557 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -1357,10 +1357,15 @@ static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port, * 2: Trap packet to CPU port * The Egress filter used 1 bit per state (0: DISABLED, 1: ENABLED) */ - if (port != priv->cpu_port) + if (port != priv->cpu_port) { priv->r->set_vlan_igr_filter(port, IGR_DROP); + priv->r->set_vlan_egr_filter(port, EGR_ENABLE); + } + else { + priv->r->set_vlan_igr_filter(port, IGR_TRAP); + priv->r->set_vlan_egr_filter(port, EGR_DISABLE); + } - priv->r->set_vlan_egr_filter(port, EGR_ENABLE); } else { /* Disable ingress and egress filtering */ if (port != priv->cpu_port) From a376508216440178184fb3ab71faf87eea637109 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Mon, 27 Nov 2023 17:09:55 +0100 Subject: [PATCH 05/18] rtl83xx: dsa: Do nothing when vid 0 Following other dsa drivers, vid 0 is no-op Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 75f9ceb557..3b5af72dd6 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -1430,6 +1430,8 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port, pr_debug("%s port %d, vid %d, flags %x\n", __func__, port, vlan->vid, vlan->flags); + if(!vlan->vid) return 0; + if (vlan->vid > 4095) { dev_err(priv->dev, "VLAN out of range: %d", vlan->vid); return -ENOTSUPP; From 2cfb1ecf103558a23c19ac55721dd4bfb0f7d4c1 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Tue, 12 Dec 2023 15:48:56 +0100 Subject: [PATCH 06/18] rtl930x: Rework per port LED configuration Use led_setX to determine number of LEDs per port. Introduce macros to calculate register value and shift for particular LED in a particular set. Problem with previous implementation is that it uses is10G status to determine leds per port. However with usxgmii, driver sets 10g, 5g and 2.5g so even though there are only 2 leds per port it selects 4 leds per port This implementation relies on configured led_set node. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../dts-5.15/rtl9302_zyxel_xgs1250-12.dts | 4 +- .../drivers/net/dsa/rtl83xx/common.c | 20 ++++-- .../drivers/net/dsa/rtl83xx/rtl838x.h | 1 + .../drivers/net/dsa/rtl83xx/rtl930x.c | 69 ++++++++++++------- 4 files changed, 65 insertions(+), 29 deletions(-) diff --git a/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts b/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts index 0fe8f1997e..98ac08b26a 100644 --- a/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts +++ b/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts @@ -66,10 +66,10 @@ compatible = "realtek,rtl9300-leds"; active-low; - led_set0 = <0x0000 0xffff 0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps + led_set0 = <0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps led_set1 = <0x0a0b 0x0a28 0x0a82 0x0a0b>; // LED set 1: (10G, 5G, 2.5G) (2.5G, 1G) // (5G, 10/100) (10G, 5G, 2.5G) - led_set2 = <0x0000 0xffff 0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit + led_set2 = <0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit }; }; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c index 0434312afc..221428cc77 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c @@ -271,7 +271,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val) static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) { struct device *dev = priv->dev; - struct device_node *dn, *phy_node, *mii_np = dev->of_node; + struct device_node *dn, *phy_node, *led_node, *mii_np = dev->of_node; struct mii_bus *bus; int ret; u32 pn; @@ -325,9 +325,12 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) return -ENODEV; } + led_node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); + for_each_node_by_name(dn, "port") { phy_interface_t interface; u32 led_set; + char led_set_str[16] = {0}; if (!of_device_is_available(dn)) continue; @@ -355,9 +358,18 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) if (interface == PHY_INTERFACE_MODE_10GBASER) priv->ports[pn].is10G = true; - if (of_property_read_u32(dn, "led-set", &led_set)) - led_set = 0; - priv->ports[pn].led_set = led_set; + priv->ports[pn].leds_on_this_port = 0; + if (led_node) { + if (of_property_read_u32(dn, "led-set", &led_set)) + led_set = 0; + priv->ports[pn].led_set = led_set; + sprintf(led_set_str, "led_set%d", led_set); + priv->ports[pn].leds_on_this_port = of_property_count_u32_elems(led_node, led_set_str); + if (priv->ports[pn].leds_on_this_port > 4) { + dev_err(priv->dev, "led_set %d for port %d configuration is invalid\n", led_set, pn); + return -ENODEV; + } + } /* Check for the integrated SerDes of the RTL8380M first */ if (of_property_read_bool(phy_node, "phy-is-integrated") diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h index 24d18d61fa..a642c74775 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h @@ -635,6 +635,7 @@ struct rtl838x_port { bool is2G5; int sds_num; int led_set; + int leds_on_this_port; const struct dsa_port *dp; }; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c index c4f200bc0e..4a4a926bb2 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c @@ -24,6 +24,15 @@ #define RTL930X_LED_GLB_ACTIVE_LOW BIT(22) +#define RTL930X_LED_SETX_0_CTRL(x) (RTL930X_LED_SET0_0_CTRL - (x * 8)) +#define RTL930X_LED_SETX_1_CTRL(x) (RTL930X_LED_SETX_0_CTRL(x) - 4) + +/* get register for given set and led in the set */ +#define RTL930X_LED_SETX_LEDY(x,y) (RTL930X_LED_SETX_0_CTRL(x) - 4 * (y / 2)) + +/* get shift for given led in any set */ +#define RTL930X_LED_SET_LEDX_SHIFT(x) (16 * (x % 2)) + extern struct mutex smi_lock; extern struct rtl83xx_soc_info soc_info; @@ -2396,10 +2405,44 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) return; } + for (int set = 0; set < 4; set++) { + char set_name[16] = {0}; + u32 set_config[4]; + int leds_in_this_set = 0; + + /* Reset LED set configuration */ + sw_w32(0, RTL930X_LED_SETX_0_CTRL(set)); + sw_w32(0, RTL930X_LED_SETX_1_CTRL(set)); + + /** + * Each led set has 4 number of leds, and each LED is configured with 16 bits + * So each 32bit register holds configuration for 2 leds + * And therefore each set requires 2 registers for configuring 4 LEDs + * + */ + sprintf(set_name, "led_set%d", set); + leds_in_this_set = of_property_count_u32_elems(node, set_name); + + if (leds_in_this_set == 0 || leds_in_this_set > sizeof(set_config)) { + pr_err("%s led_set configuration invalid skipping over this set\n", __func__); + continue; + } + + if (of_property_read_u32_array(node, set_name, set_config, leds_in_this_set)) { + break; + } + + /* Write configuration as per number of LEDs */ + for (int i=0, led = leds_in_this_set-1; led >= 0; led--,i++) { + sw_w32_mask(0xffff << RTL930X_LED_SET_LEDX_SHIFT(led), + (0xffff & set_config[i]) << RTL930X_LED_SET_LEDX_SHIFT(led), + RTL930X_LED_SETX_LEDY(set, led)); + } + } + for (int i = 0; i < priv->cpu_port; i++) { int pos = (i << 1) % 32; u32 set; - u32 v; sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i)); @@ -2407,12 +2450,8 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) if (!priv->ports[i].phy) continue; - v = 0x1; - if (priv->ports[i].is10G) - v = 0x3; - if (priv->ports[i].phy_is_integrated) - v = 0x1; - sw_w32_mask(0x3 << pos, v << pos, RTL930X_LED_PORT_NUM_CTRL(i)); + /* 0x0 = 1 led, 0x1 = 2 leds, 0x2 = 3 leds, 0x3 = 4 leds per port */ + sw_w32_mask(0x3 << pos, (priv->ports[i].leds_on_this_port -1) << pos, RTL930X_LED_PORT_NUM_CTRL(i)); pm |= BIT(i); @@ -2421,22 +2460,6 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) sw_w32_mask(0, set << pos, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); } - for (int i = 0; i < 4; i++) { - const __be32 *led_set; - char set_name[9]; - u32 setlen; - u32 v; - - sprintf(set_name, "led_set%d", i); - led_set = of_get_property(node, set_name, &setlen); - if (!led_set || setlen != 16) - break; - v = be32_to_cpup(led_set) << 16 | be32_to_cpup(led_set + 1); - sw_w32(v, RTL930X_LED_SET0_0_CTRL - 4 - i * 8); - v = be32_to_cpup(led_set + 2) << 16 | be32_to_cpup(led_set + 3); - sw_w32(v, RTL930X_LED_SET0_0_CTRL - i * 8); - } - /* Set LED mode to serial (0x1) */ sw_w32_mask(0x3, 0x1, RTL930X_LED_GLB_CTRL); From fe01435b6933756f4a916e4bccc409a88e3fcc56 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Wed, 13 Dec 2023 08:29:36 +0100 Subject: [PATCH 07/18] rtl83xx: dsa: Clear duplex bit correctly Without this, luci shows 10M full duplex when there is no link. So explicitly set half duplex and unknown speed. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 3b5af72dd6..0e1d64ae69 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -870,6 +870,8 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port, if (state->duplex == DUPLEX_FULL) reg |= RTL930X_DUPLEX_MODE; + else + reg &= ~RTL930X_DUPLEX_MODE; /* Clear duplex bit otherwise */ if (priv->ports[port].phy_is_integrated) reg &= ~RTL930X_FORCE_EN; /* Clear MAC_FORCE_EN to allow SDS-MAC link */ From da495c477d9018d59b1f6deb128cc8372d16df16 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Wed, 3 Jan 2024 15:53:47 +0100 Subject: [PATCH 08/18] rtl93xx: dsa: Fix 802.1QinQ for trunk ports Fix incorrect register value being set for VLAN_PORT_FWD Before, the 0b1111 would be set for the register which means outgoing packets would receive an extra tag, corresponding to the PVID of the port. On untagged ports, this meant outgoing packets with a single tag. On tagged ports, this meant outgoing QinQ packets, where the inner tag was either the PVID of the untagged ingress port, or the already assigned original (single) tag. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c | 4 ++-- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c index 4a4a926bb2..793d762489 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c @@ -258,9 +258,9 @@ static void rtl930x_vlan_fwd_on_inner(int port, bool is_set) { /* Always set all tag modes to fwd based on either inner or outer tag */ if (is_set) - sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); - else sw_w32_mask(0xf, 0, RTL930X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); } static void rtl930x_vlan_profile_setup(int profile) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c index 3221109c18..0e82d79d4c 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c @@ -827,9 +827,9 @@ static void rtl931x_vlan_fwd_on_inner(int port, bool is_set) { /* Always set all tag modes to fwd based on either inner or outer tag */ if (is_set) - sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2)); - else sw_w32_mask(0xf, 0, RTL931X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2)); } static void rtl931x_vlan_profile_setup(int profile) From e691e2b302d98d4239ffbfced0759384592ea995 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Wed, 3 Jan 2024 16:15:12 +0100 Subject: [PATCH 09/18] rtl83xx: dsa: reset PVID to 1 instead of 0 Before, PVID is reset for all ports and goes out of bounds. Also, PVID is later changed by dsa configuration by `ip link` and `bridge vlan` commands, this does not change the CPU port PVID and CPU PVID stays 0. It does not allow sending packets from OpenWrt to any connected devices unless default configuration is changed This change iterates up to and including cpu_port and sets default PVID to 1. For lan* ports PVID can be configured with `ip link` and `bridge vlan` commands Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 0e1d64ae69..a5b8ccea1c 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -137,9 +137,9 @@ static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv) priv->r->vlan_set_tagged(i, &info); /* reset PVIDs; defaults to 1 on reset */ - for (int i = 0; i <= priv->ds->num_ports; i++) { - priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 0); - priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 0); + for (int i = 0; i <= priv->cpu_port; i++) { + priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 1); + priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 1); priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_INNER, PBVLAN_MODE_UNTAG_AND_PRITAG); priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_OUTER, PBVLAN_MODE_UNTAG_AND_PRITAG); } From 1f11a4e28336c07aca61dd3b4fef01ef872a362d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 27 Dec 2023 16:20:45 +0100 Subject: [PATCH 10/18] uhttpd: handle reload after uhttpd-mod-ubus installation using postinst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use postinst script to reload service instead of uci-defaults hack. It's possible thanks to recent base-files change that executes postinst after uci-defaults. This fixes support for uhttpd customizations. It's possible (again) to adjust uhttpd config with custom uci-defaults before it gets started. Cc: Hauke Mehrtens Fixes: d25d281fd668 ("uhttpd: Reload config after uhttpd-mod-ubus was added") Ref: b799dd3c705d ("base-files: execute package's "postinst" after executing uci-defaults") Signed-off-by: Rafał Miłecki --- package/network/services/uhttpd/Makefile | 9 ++++++++- package/network/services/uhttpd/files/ubus.default | 6 ------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package/network/services/uhttpd/Makefile b/package/network/services/uhttpd/Makefile index 02a02405fd..37117bf911 100644 --- a/package/network/services/uhttpd/Makefile +++ b/package/network/services/uhttpd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uhttpd -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git @@ -107,6 +107,13 @@ define Package/uhttpd-mod-ubus/install $(INSTALL_DATA) ./files/ubus.default $(1)/etc/uci-defaults/00_uhttpd_ubus endef +define Package/uhttpd-mod-ubus/postinst +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + /etc/init.d/uhttpd reload +fi +endef + define Package/uhttpd-mod-ucode/install $(INSTALL_DIR) $(1)/usr/lib $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_ucode.so $(1)/usr/lib/ diff --git a/package/network/services/uhttpd/files/ubus.default b/package/network/services/uhttpd/files/ubus.default index 474016c1c5..d0a218a0ad 100644 --- a/package/network/services/uhttpd/files/ubus.default +++ b/package/network/services/uhttpd/files/ubus.default @@ -1,17 +1,11 @@ #!/bin/sh -commit=0 - if [ -z "$(uci -q get uhttpd.main.ubus_prefix)" ]; then uci set uhttpd.main.ubus_prefix=/ubus - commit=1 fi [ "$(uci -q get uhttpd.main.ubus_socket)" = "/var/run/ubus.sock" ] && { uci set uhttpd.main.ubus_socket='/var/run/ubus/ubus.sock' - commit=1 } -[ "$commit" = 1 ] && uci commit uhttpd && /etc/init.d/uhttpd reload - exit 0 From 0709bd87ba8a8c4b11389c4dea764d35ceabab85 Mon Sep 17 00:00:00 2001 From: Tomasz Maciej Nowak Date: Wed, 10 Jan 2024 16:39:57 +0100 Subject: [PATCH 11/18] ramips: mt76x8: add support for TP-Link RE365 v1 TP-Link RE365 is a wireless range extender, hardware-wise resembles RE305 with slight changes regarding buttons and LEDs. Specification SoC: MediaTek MT7628AN RAM: 64 MiB DDR2 Flash: 8 MiB SPI NOR WiFi: 2.4 GHz 2T2R integrated 5 GHz 2T2R MediaTek MT7612EN conncted to PCIe lanes Ethernet: 1x 10/100 Mbps integrated LEDs: 6x GPIO controlled Buttons: 4x GPIO controlled UART: row of 4 holes marked on PCB as J1, starting count from white triangle 1. VCC (3.3V), 2. GND, 3. RX, 4. TX baud: 57600, parity: none, flow control: none Installation 1. Open web management interface. 2. Go to Settings > System Tools > Firmware upgrade. 3. Select "Browse" and select the OpenWrt image with factory.bin suffix. 4. After selecting "Upgrade" firmware writing process will start. 5. Wait till device reboots, power LED should stay solid when it's fully booted, then it's ready for configuration through LAN port. Additional information With how device manufacturer patrtitioned the flash memory, it's possible that with default packages set, initial factory.bin image won't be created. In such case, try to reduce packages amount or use older release for initial conversion to OpenWrt. Later You can use sysupgrade.bin image with full set of packages because OpenWrt uses unpartitioned flash memory space unused by vendor firmware. Reverting to vendor firmware involves converting firmware using tplink-safeloader with -z option (can be found in ImageBuilder or SDK) and forcibly applying converted firmware as sysupgrade. Known issues WARNING: after removing casing of the device one is exposed to high voltage and is in a risk of being electrocuted. Caution when interfacing whith bootloader, saving its environment either by issuing "saveenv" or selecting option "1: Load system code to SDRAM via TFTP." in boot menu, any of those will lead to overwriting part of kernel. This will lead to need of firmware recovery. The cause of this issue is bootloader having environment offset on flash at 0x40000, while kernel starts from 0x20000. Signed-off-by: Tomasz Maciej Nowak [Wrap long line in DTS] Signed-off-by: Sander Vanheule --- .../ramips/dts/mt7628an_tplink_re365-v1.dts | 214 ++++++++++++++++++ target/linux/ramips/image/mt76x8.mk | 12 + .../mt76x8/base-files/etc/board.d/01_leds | 3 + .../mt76x8/base-files/etc/board.d/02_network | 1 + 4 files changed, 230 insertions(+) create mode 100644 target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts diff --git a/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts b/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts new file mode 100644 index 0000000000..17fa9c0b5a --- /dev/null +++ b/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7628an.dtsi" + +#include +#include +#include + +/ { + model = "TP-Link RE365 v1"; + compatible = "tplink,re365-v1", "mediatek,mt7628an-soc"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = ðernet; + }; + + keys { + compatible = "gpio-keys"; + + button-led { + label = "led"; + gpios = <&gpio 44 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-power { + label = "power"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-reset { + label = "reset"; + gpios = <&gpio 37 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-wps { + label = "wps"; + gpios = <&gpio 38 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + + led_power: led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 39 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + + led-rssi-bad { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + }; + + led-rssi-good { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; + }; + + led-wlan2g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <2>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-wlan5g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <5>; + gpios = <&gpio 40 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; + + virtual_flash { + compatible = "mtd-concat"; + devices = <&fwconcat0>, <&fwconcat1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "tplink,firmware"; + label = "firmware"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +ðernet { + nvmem-cells = <&macaddr_config_10008 0>; + nvmem-cell-names = "mac-address"; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + mt76@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + nvmem-cells = <&eeprom_radio_8000>, <&macaddr_config_10008 2>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + fwconcat0: partition@20000 { + label = "fwconcat0"; + reg = <0x20000 0x5e0000>; + }; + + partition@600000 { + label = "config"; + reg = <0x600000 0x50000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_config_10008: macaddr@10008 { + compatible = "mac-base"; + reg = <0x10008 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + fwconcat1: partition@650000 { + label = "fwconcat1"; + reg = <0x650000 0x1a0000>; + }; + + partition@7f0000 { + label = "radio"; + reg = <0x7f0000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_radio_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + }; + }; + }; + }; +}; + +&state_default { + gpio { + groups = "refclk", "wdt", "p0led_an", "p1led_an", "p2led_an", "p3led_an", + "p4led_an"; + function = "gpio"; + }; +}; + +&wmac { + status = "okay"; + + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_10008 1>; + nvmem-cell-names = "eeprom", "mac-address"; +}; diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk index 8a6bccfba6..9a458d38f3 100644 --- a/target/linux/ramips/image/mt76x8.mk +++ b/target/linux/ramips/image/mt76x8.mk @@ -666,6 +666,18 @@ define Device/tplink_re305-v3 endef TARGET_DEVICES += tplink_re305-v3 +define Device/tplink_re365-v1 + $(Device/tplink-safeloader) + DEVICE_MODEL := RE365 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-mt76x2 + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata + IMAGE_SIZE := 7680k + KERNEL_SIZE := 6016k + TPLINK_BOARD_ID := RE365 +endef +TARGET_DEVICES += tplink_re365-v1 + define Device/tplink_tl-mr3020-v3 $(Device/tplink-v2) IMAGE_SIZE := 7808k diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds index c4301737b2..5a0e0ab214 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds @@ -91,6 +91,9 @@ tplink,tl-mr3020-v3|\ tplink,tl-wa801nd-v5) ucidef_set_led_netdev "lan" "lan" "green:lan" "eth0" ;; +tplink,re365-v1) + ucidef_set_led_netdev "lan" "lan" "blue:lan" "eth0" + ;; tplink,tl-mr3420-v5|\ tplink,tl-wr840n-v4|\ tplink,tl-wr842n-v5) diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network index fe3ac9193f..63abb14d13 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network @@ -27,6 +27,7 @@ ramips_setup_interfaces() tplink,re220-v2|\ tplink,re305-v1|\ tplink,re305-v3|\ + tplink,re365-v1|\ tplink,tl-wr802n-v4|\ tplink,tl-wa801nd-v5|\ tplink,tl-wr902ac-v4|\ From 6b0db8592a3e4342c32111491948f32d5bc0087f Mon Sep 17 00:00:00 2001 From: Uwe Niethammer Date: Fri, 10 Nov 2023 02:06:15 +0100 Subject: [PATCH 12/18] uqmi: added timeouts in qmi.sh Modems which are using qmi do not reply on the 1st sync but they do on subsequent. Sometimes uqmi is hanging - even when using an early dummy access to unlock the modem. To always guarantee a proper initialisation, running or hanging uqmi processes must be stopped before. All uqmi calls have now a timeout option -t to avoid hanging. Signed-off-by: Uwe Niethammer --- .../utils/uqmi/files/lib/netifd/proto/qmi.sh | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh index f8e655455a..49fd87ff9d 100755 --- a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh +++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh @@ -85,8 +85,8 @@ proto_qmi_setup() { echo "Waiting for SIM initialization" local uninitialized_timeout=0 # timeout 3s for first call to avoid hanging uqmi - uqmi -d "$device" --get-pin-status -t 3000 > /dev/null 2>&1 - while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do + uqmi -d "$device" -t 3000 --get-pin-status > /dev/null 2>&1 + while uqmi -s -d "$device" -t 1000 --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do [ -e "$device" ] || return 1 if [ "$uninitialized_timeout" -lt "$timeout" -o "$timeout" = "0" ]; then let uninitialized_timeout++ @@ -102,7 +102,7 @@ proto_qmi_setup() { # Check if UIM application is stuck in illegal state local uim_state_timeout=0 while true; do - json_load "$(uqmi -s -d "$device" --uim-get-sim-state)" + json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)" json_get_var card_application_state card_application_state # SIM card is either completely absent or state is labeled as illegal @@ -111,9 +111,9 @@ proto_qmi_setup() { echo "SIM in illegal state - Power-cycling SIM" # Try to reset SIM application - uqmi -d "$device" --uim-power-off --uim-slot 1 + uqmi -d "$device" -t 1000 --uim-power-off --uim-slot 1 sleep 3 - uqmi -d "$device" --uim-power-on --uim-slot 1 + uqmi -d "$device" -t 1000 --uim-power-on --uim-slot 1 if [ "$uim_state_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then let uim_state_timeout++ @@ -130,10 +130,10 @@ proto_qmi_setup() { fi done - if uqmi -s -d "$device" --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' && - uqmi -s -d "$device" --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then + if uqmi -s -d "$device" -t 1000 --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' && + uqmi -s -d "$device" -t 1000 --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then [ -n "$pincode" ] && { - uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null || { + uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null || { echo "Unable to verify PIN" proto_notify_error "$interface" PIN_FAILED proto_block_restart "$interface" @@ -141,10 +141,10 @@ proto_qmi_setup() { } } else - json_load "$(uqmi -s -d "$device" --get-pin-status)" + json_load "$(uqmi -s -d "$device" -t 1000 --get-pin-status)" json_get_var pin1_status pin1_status if [ -z "$pin1_status" ]; then - json_load "$(uqmi -s -d "$device" --uim-get-sim-state)" + json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)" json_get_var pin1_status pin1_status fi json_get_var pin1_verify_tries pin1_verify_tries @@ -167,7 +167,7 @@ proto_qmi_setup() { return 1 } if [ -n "$pincode" ]; then - uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || { + uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || { echo "Unable to verify PIN" proto_notify_error "$interface" PIN_FAILED proto_block_restart "$interface" @@ -194,7 +194,7 @@ proto_qmi_setup() { fi if [ -n "$plmn" ]; then - json_load "$(uqmi -s -d "$device" --get-plmn)" + json_load "$(uqmi -s -d "$device" -t 1000 --get-plmn)" json_get_var plmn_mode mode json_get_vars mcc mnc || { mcc=0 @@ -218,16 +218,16 @@ proto_qmi_setup() { fi # Cleanup current state if any - uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 - uqmi -s -d "$device" --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 # Go online - uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-device-operating-mode online > /dev/null 2>&1 # Set IP format - uqmi -s -d "$device" --set-data-format 802.3 > /dev/null 2>&1 - uqmi -s -d "$device" --wda-set-data-format 802.3 > /dev/null 2>&1 - dataformat="$(uqmi -s -d "$device" --wda-get-data-format)" + uqmi -s -d "$device" -t 1000 --set-data-format 802.3 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --wda-set-data-format 802.3 > /dev/null 2>&1 + dataformat="$(uqmi -s -d "$device" -t 1000 --wda-get-data-format)" if [ "$dataformat" = '"raw-ip"' ]; then @@ -240,13 +240,13 @@ proto_qmi_setup() { echo "Y" > /sys/class/net/$ifname/qmi/raw_ip fi - uqmi -s -d "$device" --sync > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --sync > /dev/null 2>&1 - uqmi -s -d "$device" --network-register > /dev/null 2>&1 + uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1 # PLMN selection must happen after the call to network-register if [ -n "$mcc" -a -n "$mnc" ]; then - uqmi -s -d "$device" --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || { + uqmi -s -d "$device" -t 1000 --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || { echo "Unable to set PLMN" proto_notify_error "$interface" PLMN_FAILED proto_block_restart "$interface" @@ -255,10 +255,10 @@ proto_qmi_setup() { fi [ -n "$modes" ] && { - uqmi -s -d "$device" --set-network-modes "$modes" > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-network-modes "$modes" > /dev/null 2>&1 sleep 3 # Scan network to not rely on registration-timeout after RAT change - uqmi -s -d "$device" --network-scan > /dev/null 2>&1 + uqmi -s -d "$device" -t 30000 --network-scan > /dev/null 2>&1 } echo "Waiting for network registration" @@ -266,7 +266,7 @@ proto_qmi_setup() { local registration_timeout=0 local registration_state="" while true; do - registration_state=$(uqmi -s -d "$device" --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null) + registration_state=$(uqmi -s -d "$device" -t 1000 --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null) [ "$registration_state" = "registered" ] && break @@ -274,7 +274,7 @@ proto_qmi_setup() { if [ "$registration_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then [ "$registration_state" = "searching" ] || { echo "Device stopped network registration. Restart network registration" - uqmi -s -d "$device" --network-register > /dev/null 2>&1 + uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1 } let registration_timeout++ sleep 1 @@ -302,7 +302,7 @@ proto_qmi_setup() { # establish a non-LTE data session. profile_pdptype="$pdptype" [ "$profile_pdptype" = "ip" ] && profile_pdptype="ipv4" - uqmi -s -d "$device" --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1 if [ "$pdptype" = "ip" ]; then [ -z "$autoconnect" ] && autoconnect=1 @@ -312,16 +312,16 @@ proto_qmi_setup() { fi [ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && { - cid_4=$(uqmi -s -d "$device" --get-client-id wds) + cid_4=$(uqmi -s -d "$device" -t 1000 --get-client-id wds) if ! [ "$cid_4" -eq "$cid_4" ] 2> /dev/null; then echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 fi - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1 - pdh_4=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" \ + pdh_4=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_4" \ --start-network \ ${apn:+--apn $apn} \ ${profile:+--profile $profile} \ @@ -333,35 +333,35 @@ proto_qmi_setup() { # pdh_4 is a numeric value on success if ! [ "$pdh_4" -eq "$pdh_4" ] 2> /dev/null; then echo "Unable to connect IPv4" - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 fi # Check data connection state - connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" --get-data-status) + connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --get-data-status) [ "$connstat" == '"connected"' ] || { echo "No data link!" - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 } } [ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && { - cid_6=$(uqmi -s -d "$device" --get-client-id wds) + cid_6=$(uqmi -s -d "$device" -t 1000 --get-client-id wds) if ! [ "$cid_6" -eq "$cid_6" ] 2> /dev/null; then echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 fi - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1 : "${v6apn:=${apn}}" : "${v6profile:=${profile}}" - pdh_6=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" \ + pdh_6=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_6" \ --start-network \ ${v6apn:+--apn $v6apn} \ ${v6profile:+--profile $v6profile} \ @@ -373,16 +373,16 @@ proto_qmi_setup() { # pdh_6 is a numeric value on success if ! [ "$pdh_6" -eq "$pdh_6" ] 2> /dev/null; then echo "Unable to connect IPv6" - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 fi # Check data connection state - connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status) + connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status) [ "$connstat" == '"connected"' ] || { echo "No data link!" - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 } @@ -407,7 +407,7 @@ proto_qmi_setup() { [ -n "$pdh_6" ] && { if [ -z "$dhcpv6" -o "$dhcpv6" = 0 ]; then - json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)" + json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_6 --get-current-settings)" json_select ipv6 json_get_var ip_6 ip json_get_var gateway_6 gateway @@ -449,7 +449,7 @@ proto_qmi_setup() { [ -n "$pdh_4" ] && { if [ "$dhcp" = 0 ]; then - json_load "$(uqmi -s -d $device --set-client-id wds,$cid_4 --get-current-settings)" + json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_4 --get-current-settings)" json_select ipv4 json_get_var ip_4 ip json_get_var gateway_4 gateway @@ -492,16 +492,16 @@ qmi_wds_stop() { [ -n "$cid" ] || return - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --stop-network 0xffffffff \ --autoconnect > /dev/null 2>&1 [ -n "$pdh" ] && { - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --stop-network "$pdh" > /dev/null 2>&1 } - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --release-client-id wds > /dev/null 2>&1 } From 2fe8ecd880396b5ae25fe9583aaa1d71be0b8468 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Tue, 9 Jan 2024 20:52:56 +0100 Subject: [PATCH 13/18] ath79: read back reset register Read back the reset register in order to flush the cache. This fixes spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel DRAM chips. This issue was fixed in the past, but switching to the reset-driver specific implementation removed the cache barrier which was previously implicitly added by reading back the register in question. Link: https://github.com/freifunk-gluon/gluon/issues/2904 Link: https://github.com/openwrt/openwrt/issues/13043 Link: https://dev.archive.openwrt.org/ticket/17839 Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") Signed-off-by: David Bauer --- ...reset-ath79-read-back-reset-register.patch | 33 +++++++++++++++++++ ...reset-ath79-read-back-reset-register.patch | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch create mode 100644 target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch diff --git a/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; diff --git a/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; From 3df9322771cc932e5b82438634337fcca6cc97bc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 11 Jan 2024 09:14:59 +0100 Subject: [PATCH 14/18] hostapd: make ubus calls to wpa_supplicant asynchronous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a deadlock issue where depending on the setup order, hostapd and wpa_supplicant could end up waiting for each other Reported-by: Michael-cy Lee (李峻宇) Signed-off-by: Felix Fietkau --- .../network/services/hostapd/files/hostapd.uc | 131 ++++++++++++++---- 1 file changed, 105 insertions(+), 26 deletions(-) diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc index b85f523b35..0c89cd71cc 100644 --- a/package/network/services/hostapd/files/hostapd.uc +++ b/package/network/services/hostapd/files/hostapd.uc @@ -2,9 +2,10 @@ let libubus = require("ubus"); import { open, readfile } from "fs"; import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common"; -let ubus = libubus.connect(); +let ubus = libubus.connect(null, 60); hostapd.data.config = {}; +hostapd.data.pending_config = {}; hostapd.data.file_fields = { vlan_file: true, @@ -122,17 +123,111 @@ function iface_config_macaddr_list(config) return macaddr_list; } -function iface_update_supplicant_macaddr(phy, config) +function __iface_pending_next(pending, state, ret, data) { - let macaddr_list = []; - for (let i = 0; i < length(config.bss); i++) - push(macaddr_list, config.bss[i].bssid); - ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); + let config = pending.config; + let phydev = pending.phydev; + let phy = pending.phy; + + if (pending.defer) + pending.defer.abort(); + delete pending.defer; + switch (state) { + case "init": + let macaddr_list = []; + for (let i = 0; i < length(config.bss); i++) + push(macaddr_list, config.bss[i].bssid); + pending.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); + return "create_bss"; + case "create_bss": + let bss = config.bss[0]; + let err = wdev_create(phy, bss.ifname, { mode: "ap" }); + if (err) { + hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); + return null; + } + + pending.call("wpa_supplicant", "phy_status", { phy: phy }); + return "check_phy"; + case "check_phy": + let phy_status = data; + if (phy_status && phy_status.state == "COMPLETED") { + if (iface_add(phy, config, phy_status)) + return "done"; + + hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); + } + pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); + return "wpas_stopped"; + case "wpas_stopped": + if (!iface_add(phy, config)) + hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); + pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); + return null; + case "done": + default: + delete hostapd.data.pending_config[phy]; + break; + } +} + +function iface_pending_next(ret, data) +{ + let pending = true; + let cfg = this; + + while (pending) { + this.next_state = __iface_pending_next(cfg, this.next_state, ret, data); + if (!this.next_state) { + __iface_pending_next(cfg, "done"); + return; + } + pending = !this.defer; + } +} + +function iface_pending_abort() +{ + this.next_state = "done"; + this.next(); +} + +function iface_pending_ubus_call(obj, method, arg) +{ + let ubus = hostapd.data.ubus; + let pending = this; + this.defer = ubus.defer(obj, method, arg, (ret, data) => { delete pending.defer; pending.next(ret, data) }); +} + +const iface_pending_proto = { + next: iface_pending_next, + call: iface_pending_ubus_call, + abort: iface_pending_abort, +}; + +function iface_pending_init(phydev, config) +{ + let phy = phydev.name; + + let pending = proto({ + next_state: "init", + phydev: phydev, + phy: phy, + config: config, + next: iface_pending_next, + }, iface_pending_proto); + + hostapd.data.pending_config[phy] = pending; + pending.next(); } function iface_restart(phydev, config, old_config) { let phy = phydev.name; + let pending = hostapd.data.pending_config[phy]; + + if (pending) + pending.abort(); hostapd.remove_iface(phy); iface_remove(old_config); @@ -150,26 +245,7 @@ function iface_restart(phydev, config, old_config) bss.bssid = phydev.macaddr_next(); } - iface_update_supplicant_macaddr(phy, config); - - let bss = config.bss[0]; - let err = wdev_create(phy, bss.ifname, { mode: "ap" }); - if (err) - hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); - - let ubus = hostapd.data.ubus; - let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy }); - if (phy_status && phy_status.state == "COMPLETED") { - if (iface_add(phy, config, phy_status)) - return; - - hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); - } - - ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); - if (!iface_add(phy, config)) - hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); - ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); + iface_pending_init(phydev, config); } function array_to_obj(arr, key, start) @@ -274,6 +350,9 @@ function iface_reload_config(phydev, config, old_config) if (is_equal(old_config.bss, config.bss)) return true; + if (hostapd.data.pending_config[phy]) + return false; + if (!old_config.bss || !old_config.bss[0]) return false; From 2d4552a96c7e5d44f9caaf1367e2be9d3775afae Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 10 Jan 2024 17:21:01 +0100 Subject: [PATCH 15/18] ci: no longer require real name This goes in accordance with the Linux Kernel: > using a known identity (sorry, no anonymous contributions.) https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?id=HEAD#n442 Signed-off-by: Paul Spooren --- .github/workflows/formal.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml index 8083c5832c..1532591dfc 100644 --- a/.github/workflows/formal.yml +++ b/.github/workflows/formal.yml @@ -37,14 +37,6 @@ jobs: RET=1 fi - author="$(git show -s --format=%aN $commit)" - if echo $author | grep -q '\S\+\s\+\S\+'; then - success "Author name ($author) seems ok" - else - err "Author name ($author) need to be your real name 'firstname lastname'" - RET=1 - fi - subject="$(git show -s --format=%s $commit)" if echo "$subject" | grep -q -e '^[0-9A-Za-z,+/_\.-]\+: ' -e '^Revert '; then success "Commit subject line seems ok ($subject)" From d5a1de17ade34abfa276b074e82f40a6a7b908de Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 22 Oct 2023 18:00:08 +0200 Subject: [PATCH 16/18] mac80211.sh: fix deadlock on configuring multiple PHYs simultaneously When hitting a timing window where ubus configuration calls are hitting hostapd and wpa_supplicant simultaneously, they can deadlock waiting for each other. Fix this by using a lock around the ubus calls. Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 6ff627b038..6572999fbc 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -19,6 +19,10 @@ wdev_tool() { ucode /usr/share/hostap/wdev.uc "$@" } +ubus_call() { + flock /var/run/hostapd.lock ubus call "$@" +} + drv_mac80211_init_device_config() { hostapd_common_add_device_config @@ -903,7 +907,7 @@ wpa_supplicant_set_config() { ubus wait_for wpa_supplicant } - local supplicant_res="$(ubus call wpa_supplicant config_set "$data")" + local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")" ret="$?" [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED @@ -913,12 +917,12 @@ wpa_supplicant_set_config() { hostapd_set_config() { [ -n "$hostapd_ctrl" ] || { - ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null + ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null return 0; } ubus wait_for hostapd - local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" + local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" ret="$?" [ "$ret" != 0 -o -z "$hostapd_res" ] && { wireless_setup_failed HOSTAPD_START_FAILED @@ -933,7 +937,7 @@ wpa_supplicant_start() { [ -n "$wpa_supp_init" ] || return 0 - ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null + ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null } mac80211_setup_supplicant() { @@ -1041,8 +1045,8 @@ mac80211_reset_config() { local phy="$1" hostapd_conf_file="/var/run/hostapd-$phy.conf" - ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null - ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null + ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null + ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null wdev_tool "$phy" set_config '{}' } From b7f9742da82fa9b122e8d63e48a9a5c0dec298f2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 14 Nov 2023 13:00:27 +0100 Subject: [PATCH 17/18] mac80211: rework interface setup, fix race condition Only tell netifd about vifs when the setup is complete and hostapd + wpa_supplicant have been notified Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 159 ++++++++---------- .../network/services/hostapd/files/hostapd.sh | 7 +- 2 files changed, 74 insertions(+), 92 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 6572999fbc..cc7e143030 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -635,71 +635,6 @@ mac80211_set_ifname() { eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))" } -mac80211_prepare_vif() { - json_select config - - json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file - - [ -n "$ifname" ] || { - local prefix; - - case "$mode" in - ap|sta|mesh) prefix=$mode;; - adhoc) prefix=ibss;; - monitor) prefix=mon;; - esac - - mac80211_set_ifname "$phy" "$prefix" - } - - append active_ifnames "$ifname" - set_default wds 0 - set_default powersave 0 - json_add_string _ifname "$ifname" - - default_macaddr= - if [ -z "$macaddr" ]; then - macaddr="$(mac80211_generate_mac $phy)" - macidx="$(($macidx + 1))" - default_macaddr=1 - elif [ "$macaddr" = 'random' ]; then - macaddr="$(macaddr_random)" - fi - json_add_string _macaddr "$macaddr" - json_add_string _default_macaddr "$default_macaddr" - json_select .. - - - [ "$mode" == "ap" ] && { - [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" - [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname" - } - - json_select config - - # It is far easier to delete and create the desired interface - case "$mode" in - ap) - # Hostapd will handle recreating the interface and - # subsequent virtual APs belonging to the same PHY - if [ -n "$hostapd_ctrl" ]; then - type=bss - else - type=interface - fi - - mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return - - [ -n "$hostapd_ctrl" ] || { - ap_ifname="${ifname}" - hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" - } - ;; - esac - - json_select .. -} - mac80211_prepare_iw_htmode() { case "$htmode" in VHT20|HT20|HE20) iw_htmode=HT20;; @@ -842,17 +777,6 @@ mac80211_setup_monitor() { json_set_namespace "$prev" } -mac80211_set_vif_txpower() { - local name="$1" - - json_select config - json_get_var ifname _ifname - json_get_vars vif_txpower - json_select .. - - [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" -} - wpa_supplicant_init_config() { json_set_namespace wpa_supp prev @@ -957,19 +881,41 @@ mac80211_setup_supplicant() { return 0 } -mac80211_setup_vif() { - local name="$1" - local failed - +mac80211_prepare_vif() { json_select config - json_get_var ifname _ifname - json_get_var macaddr _macaddr - json_get_var default_macaddr _default_macaddr - json_get_vars mode wds powersave - set_default powersave 0 + json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file + local config_wpa_psk_file="$wpa_psk_file" + local config_vlan_file="$vlan_file" + + [ -n "$ifname" ] || { + local prefix; + + case "$mode" in + ap|sta|mesh) prefix=$mode;; + adhoc) prefix=ibss;; + monitor) prefix=mon;; + esac + + mac80211_set_ifname "$phy" "$prefix" + } + + append active_ifnames "$ifname" + + default_macaddr= + if [ -z "$macaddr" ]; then + macaddr="$(mac80211_generate_mac $phy)" + macidx="$(($macidx + 1))" + default_macaddr=1 + elif [ "$macaddr" = 'random' ]; then + macaddr="$(macaddr_random)" + fi + + local failed= set_default wds 0 + set_default powersave 0 + # It is far easier to delete and create the desired interface case "$mode" in mesh) json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING @@ -995,10 +941,48 @@ mac80211_setup_vif() { monitor) mac80211_setup_monitor ;; + ap) + # Hostapd will handle recreating the interface and + # subsequent virtual APs belonging to the same PHY + if [ -n "$hostapd_ctrl" ]; then + type=bss + else + type=interface + fi + + mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return + + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; esac + [ -n "$failed" ] || { + json_add_string _ifname "$ifname" + json_add_string _macaddr "$macaddr" + json_add_string _default_macaddr "$default_macaddr" + } + json_select .. - [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" + + [ "$mode" == "ap" ] && { + [ -z "$config_wpa_psk_file" ] && hostapd_set_psk "$ifname" + [ -z "$config_vlan_file" ] && hostapd_set_vlan "$ifname" + } +} + +mac80211_setup_vif() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower + json_select .. + + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" + [ -n "$ifname" ] && wireless_add_vif "$name" "$ifname" } get_freq() { @@ -1144,7 +1128,6 @@ drv_mac80211_setup() { mac80211_prepare_iw_htmode active_ifnames= for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif - for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" @@ -1155,7 +1138,7 @@ drv_mac80211_setup() { wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames json_set_namespace "$prev" - for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif wireless_set_up } diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 271c1f7bec..c0c39a9399 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -398,6 +398,7 @@ hostapd_set_vlan() { rm -f /var/run/hostapd-${ifname}.vlan for_each_vlan hostapd_set_vlan_file ${ifname} + touch /var/run/hostapd-${ifname}.vlan } hostapd_set_psk_file() { @@ -416,6 +417,7 @@ hostapd_set_psk() { rm -f /var/run/hostapd-${ifname}.psk for_each_station hostapd_set_psk_file ${ifname} + touch /var/run/hostapd-${ifname}.psk } append_iw_roaming_consortium() { @@ -688,10 +690,7 @@ hostapd_set_bss_options() { return 1 fi [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk - [ -n "$wpa_psk_file" ] && { - [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file" - append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" - } + [ -n "$wpa_psk_file" ] && append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" set_default dynamic_vlan 0 From 5b8f188c0f0a18eecc7a5f4078b96338c3c282f2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Jan 2024 11:19:07 +0100 Subject: [PATCH 18/18] Revert "mac80211: rework interface setup, fix race condition" This reverts commit b7f9742da82fa9b122e8d63e48a9a5c0dec298f2. There are several reports of regressions with this commit. Will be added back once I've figured out and fixed the cause Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 159 ++++++++++-------- .../network/services/hostapd/files/hostapd.sh | 7 +- 2 files changed, 92 insertions(+), 74 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index cc7e143030..6572999fbc 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -635,6 +635,71 @@ mac80211_set_ifname() { eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))" } +mac80211_prepare_vif() { + json_select config + + json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file + + [ -n "$ifname" ] || { + local prefix; + + case "$mode" in + ap|sta|mesh) prefix=$mode;; + adhoc) prefix=ibss;; + monitor) prefix=mon;; + esac + + mac80211_set_ifname "$phy" "$prefix" + } + + append active_ifnames "$ifname" + set_default wds 0 + set_default powersave 0 + json_add_string _ifname "$ifname" + + default_macaddr= + if [ -z "$macaddr" ]; then + macaddr="$(mac80211_generate_mac $phy)" + macidx="$(($macidx + 1))" + default_macaddr=1 + elif [ "$macaddr" = 'random' ]; then + macaddr="$(macaddr_random)" + fi + json_add_string _macaddr "$macaddr" + json_add_string _default_macaddr "$default_macaddr" + json_select .. + + + [ "$mode" == "ap" ] && { + [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" + [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname" + } + + json_select config + + # It is far easier to delete and create the desired interface + case "$mode" in + ap) + # Hostapd will handle recreating the interface and + # subsequent virtual APs belonging to the same PHY + if [ -n "$hostapd_ctrl" ]; then + type=bss + else + type=interface + fi + + mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return + + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; + esac + + json_select .. +} + mac80211_prepare_iw_htmode() { case "$htmode" in VHT20|HT20|HE20) iw_htmode=HT20;; @@ -777,6 +842,17 @@ mac80211_setup_monitor() { json_set_namespace "$prev" } +mac80211_set_vif_txpower() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower + json_select .. + + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" +} + wpa_supplicant_init_config() { json_set_namespace wpa_supp prev @@ -881,41 +957,19 @@ mac80211_setup_supplicant() { return 0 } -mac80211_prepare_vif() { +mac80211_setup_vif() { + local name="$1" + local failed + json_select config + json_get_var ifname _ifname + json_get_var macaddr _macaddr + json_get_var default_macaddr _default_macaddr + json_get_vars mode wds powersave - json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file - local config_wpa_psk_file="$wpa_psk_file" - local config_vlan_file="$vlan_file" - - [ -n "$ifname" ] || { - local prefix; - - case "$mode" in - ap|sta|mesh) prefix=$mode;; - adhoc) prefix=ibss;; - monitor) prefix=mon;; - esac - - mac80211_set_ifname "$phy" "$prefix" - } - - append active_ifnames "$ifname" - - default_macaddr= - if [ -z "$macaddr" ]; then - macaddr="$(mac80211_generate_mac $phy)" - macidx="$(($macidx + 1))" - default_macaddr=1 - elif [ "$macaddr" = 'random' ]; then - macaddr="$(macaddr_random)" - fi - - local failed= - set_default wds 0 set_default powersave 0 + set_default wds 0 - # It is far easier to delete and create the desired interface case "$mode" in mesh) json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING @@ -941,48 +995,10 @@ mac80211_prepare_vif() { monitor) mac80211_setup_monitor ;; - ap) - # Hostapd will handle recreating the interface and - # subsequent virtual APs belonging to the same PHY - if [ -n "$hostapd_ctrl" ]; then - type=bss - else - type=interface - fi - - mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return - - [ -n "$hostapd_ctrl" ] || { - ap_ifname="${ifname}" - hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" - } - ;; esac - [ -n "$failed" ] || { - json_add_string _ifname "$ifname" - json_add_string _macaddr "$macaddr" - json_add_string _default_macaddr "$default_macaddr" - } - json_select .. - - [ "$mode" == "ap" ] && { - [ -z "$config_wpa_psk_file" ] && hostapd_set_psk "$ifname" - [ -z "$config_vlan_file" ] && hostapd_set_vlan "$ifname" - } -} - -mac80211_setup_vif() { - local name="$1" - - json_select config - json_get_var ifname _ifname - json_get_vars vif_txpower - json_select .. - - [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" - [ -n "$ifname" ] && wireless_add_vif "$name" "$ifname" + [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" } get_freq() { @@ -1128,6 +1144,7 @@ drv_mac80211_setup() { mac80211_prepare_iw_htmode active_ifnames= for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" @@ -1138,7 +1155,7 @@ drv_mac80211_setup() { wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames json_set_namespace "$prev" - for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif + for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower wireless_set_up } diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index c0c39a9399..271c1f7bec 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -398,7 +398,6 @@ hostapd_set_vlan() { rm -f /var/run/hostapd-${ifname}.vlan for_each_vlan hostapd_set_vlan_file ${ifname} - touch /var/run/hostapd-${ifname}.vlan } hostapd_set_psk_file() { @@ -417,7 +416,6 @@ hostapd_set_psk() { rm -f /var/run/hostapd-${ifname}.psk for_each_station hostapd_set_psk_file ${ifname} - touch /var/run/hostapd-${ifname}.psk } append_iw_roaming_consortium() { @@ -690,7 +688,10 @@ hostapd_set_bss_options() { return 1 fi [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk - [ -n "$wpa_psk_file" ] && append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" + [ -n "$wpa_psk_file" ] && { + [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file" + append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" + } [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" set_default dynamic_vlan 0