What fixes? Ping @Ansuel
VLAN Question on RTL8367D (chip_id 0x6642)
Hi!
Current status: VLAN is disabled by skipping rtl8365mb_vlan_setup() for 0x6642.
The following errors were thrown during initialization:
[ 23.910493] ipq5018-gmac-dwmac 39d00000.ethernet eth0: entered allmulticast mode
[ 23.928190] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 23.978547] rtl8365mb-mdio 90000.mdio-1:1d lan4: failed to initialize vlan filtering on this port
[ 23.983843] rtl8365mb-mdio 90000.mdio-1:1d lan4: left allmulticast mode
[ 23.986414] ipq5018-gmac-dwmac 39d00000.ethernet eth0: left allmulticast mode
[ 23.993321] br-lan: port 1(lan4) entered blocking state
[ 24.000198] br-lan: port 1(lan4) entered disabled state
[ 24.005204] rtl8365mb-mdio 90000.mdio-1:1d lan4: entered allmulticast mode
[ 24.010439] ipq5018-gmac-dwmac 39d00000.ethernet eth0: entered allmulticast mode
[ 24.087762] rtl8365mb-mdio 90000.mdio-1:1d wan: configuring for phy/gmii link mode
[ 24.099566] rtl8365mb-mdio 90000.mdio-1:1d lan1: configuring for phy/gmii link mode
[ 24.132037] br-lan: port 2(lan1) entered blocking state
[ 24.132114] br-lan: port 2(lan1) entered disabled state
[ 24.136179] rtl8365mb-mdio 90000.mdio-1:1d lan1: entered allmulticast mode
[ 24.168313] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.218771] rtl8365mb-mdio 90000.mdio-1:1d lan1: failed to initialize vlan filtering on this port
[ 24.221495] rtl8365mb-mdio 90000.mdio-1:1d lan1: left allmulticast mode
[ 24.227090] br-lan: port 2(lan1) entered blocking state
[ 24.233245] br-lan: port 2(lan1) entered disabled state
[ 24.238336] rtl8365mb-mdio 90000.mdio-1:1d lan1: entered allmulticast mode
[ 24.275297] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.308951] rtl8365mb-mdio 90000.mdio-1:1d lan1: failed to initialize vlan filtering on this port
[ 24.312248] rtl8365mb-mdio 90000.mdio-1:1d lan1: left allmulticast mode
[ 24.317283] br-lan: port 2(lan1) entered blocking state
[ 24.323468] br-lan: port 2(lan1) entered disabled state
[ 24.328683] rtl8365mb-mdio 90000.mdio-1:1d lan1: entered allmulticast mode
[ 24.345702] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.388589] rtl8365mb-mdio 90000.mdio-1:1d lan1: failed to initialize vlan filtering on this port
[ 24.391102] rtl8365mb-mdio 90000.mdio-1:1d lan1: left allmulticast mode
[ 24.416190] rtl8365mb-mdio 90000.mdio-1:1d lan2: configuring for phy/gmii link mode
[ 24.435762] br-lan: port 2(lan2) entered blocking state
[ 24.435833] br-lan: port 2(lan2) entered disabled state
[ 24.440013] rtl8365mb-mdio 90000.mdio-1:1d lan2: entered allmulticast mode
[ 24.454125] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.498535] rtl8365mb-mdio 90000.mdio-1:1d lan2: failed to initialize vlan filtering on this port
[ 24.500489] rtl8365mb-mdio 90000.mdio-1:1d lan2: left allmulticast mode
[ 24.506715] br-lan: port 2(lan2) entered blocking state
[ 24.512921] br-lan: port 2(lan2) entered disabled state
[ 24.518069] rtl8365mb-mdio 90000.mdio-1:1d lan2: entered allmulticast mode
[ 24.530408] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.568538] rtl8365mb-mdio 90000.mdio-1:1d lan2: failed to initialize vlan filtering on this port
[ 24.570437] rtl8365mb-mdio 90000.mdio-1:1d lan2: left allmulticast mode
[ 24.576718] br-lan: port 2(lan2) entered blocking state
[ 24.582937] br-lan: port 2(lan2) entered disabled state
[ 24.588082] rtl8365mb-mdio 90000.mdio-1:1d lan2: entered allmulticast mode
[ 24.600377] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.638536] rtl8365mb-mdio 90000.mdio-1:1d lan2: failed to initialize vlan filtering on this port
[ 24.640443] rtl8365mb-mdio 90000.mdio-1:1d lan2: left allmulticast mode
[ 24.652280] rtl8365mb-mdio 90000.mdio-1:1d lan3: configuring for phy/gmii link mode
[ 24.662297] br-lan: port 2(lan3) entered blocking state
[ 24.662349] br-lan: port 2(lan3) entered disabled state
[ 24.666393] rtl8365mb-mdio 90000.mdio-1:1d lan3: entered allmulticast mode
[ 24.678899] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.718531] rtl8365mb-mdio 90000.mdio-1:1d lan3: failed to initialize vlan filtering on this port
[ 24.720451] rtl8365mb-mdio 90000.mdio-1:1d lan3: left allmulticast mode
[ 24.726702] br-lan: port 2(lan3) entered blocking state
[ 24.732918] br-lan: port 2(lan3) entered disabled state
[ 24.738068] rtl8365mb-mdio 90000.mdio-1:1d lan3: entered allmulticast mode
[ 24.750451] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.788537] rtl8365mb-mdio 90000.mdio-1:1d lan3: failed to initialize vlan filtering on this port
[ 24.790448] rtl8365mb-mdio 90000.mdio-1:1d lan3: left allmulticast mode
[ 24.796700] br-lan: port 2(lan3) entered blocking state
[ 24.802928] br-lan: port 2(lan3) entered disabled state
[ 24.808077] rtl8365mb-mdio 90000.mdio-1:1d lan3: entered allmulticast mode
[ 24.820451] rtl8365mb-mdio 90000.mdio-1:1d: VLAN should already exist in VLAN MC
[ 24.858549] rtl8365mb-mdio 90000.mdio-1:1d lan3: failed to initialize vlan filtering on this port
[ 24.860460] rtl8365mb-mdio 90000.mdio-1:1d lan3: left allmulticast mode
[ 25.459019] br-lan: port 2(phy0-ap0) entered blocking state
[ 25.459087] br-lan: port 2(phy0-ap0) entered disabled state
[ 25.463481] ath11k c000000.wifi phy0-ap0: entered allmulticast mode
[ 25.469663] ath11k c000000.wifi phy0-ap0: entered promiscuous mode
[ 26.465184] br-lan: port 3(phy1-ap0) entered blocking state
[ 26.465256] br-lan: port 3(phy1-ap0) entered disabled state
[ 26.469779] ath11k b00a040.wifi phy1-ap0: entered allmulticast mode
[ 26.475554] ath11k b00a040.wifi phy1-ap0: entered promiscuous mode
[ 27.285128] br-lan: port 3(phy1-ap0) entered blocking state
[ 27.285206] br-lan: port 3(phy1-ap0) entered forwarding state
[ 30.750462] br-lan: port 2(phy0-ap0) entered blocking state
[ 30.750538] br-lan: port 2(phy0-ap0) entered forwarding state
Observations:
LAN works as an L2 switch β traffic passes between ports without VLAN filtering.
Questions:
-
In your build (chip_id 0x6367), does VLAN work natively or is it disabled?
-
On the RTL8367D, is the VLAN4K table write-only?
In the GPL vendor driver, a software shadow table (Rtl8367dVirtualVlanTable[4096]) is used.
To implement full VLAN support in mainline, the following changes are needed:- Add a shadow table to
struct rtl8365mb. - Intercept VLAN MC reads β read from the shadow table.
- Intercept VLAN MC writes β write to both the shadow table and the hardware.
- During
vlan_init()β populate the default VLAN (vid=1) in the shadow table.
- Add a shadow table to
-
How critical is this for the AX55?
Without VLAN, do LAN/WAN/WiFi still work properly?
Is VLAN only required for isolation (guest network) and 802.1Q trunking?
Both chips use the same register 0x07A8 for VLAN control (bit 0). However:
RTL8367C β hardware VLAN4K table is readable/writable:
setAsicVlan4kEntry writes 3 words via the access table (0x0510-0x0512)
getAsicVlan4kEntry reads back the same 3 words
The driver can verify that the write has been saved
RTL8367D β hardware VLAN4K table is write-only:
setAsicVlan4kEntry writes 2 words via the access table
getAsicVlan4kEntry reads from the software shadow table (Rtl8367dVirtualVlanTable), not from hardware
The vendor driver knows that the hardware cannot be read β hence it uses a shadow table
In mainline rtl8365mb: there is no shadow table β when reading VLAN entries, it returns 0 β the switch sees an empty table β drops frames.
Here is the translation of your message into English with the patch, code, and logs separated into distinct sections.
I added the patch as shown below. Maybe I did something wrong, I followed your recipe. But here are the logs.
The PC sends data to the router and it reaches it, but for some reason, the router doesn't respond.
PATCH CODE:
Index: linux-6.12.94/drivers/net/dsa/realtek/rtl8365mb_main.c
===================================================================
--- linux-6.12.94.orig/drivers/net/dsa/realtek/rtl8365mb_main.c
+++ linux-6.12.94/drivers/net/dsa/realtek/rtl8365mb_main.c
@@ -97,6 +97,7 @@
#include <linux/mutex.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
+#include <linux/firmware.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
@@ -213,23 +214,16 @@
#define RTL8365MB_EXT_PORT_MODE_1000X_100FX 11
#define RTL8365MB_EXT_PORT_MODE_1000X 12
#define RTL8365MB_EXT_PORT_MODE_100FX 13
-/* Registers used to bring up the (H)SGMII extension interface. The
- * RTL8365MB_MAGIC_REG/RTL8365MB_MAGIC_VALUE, RTL8365MB_CHIP_VER_REG and
- * RTL8365MB_CHIP_RESET_REG defines already exist above and are reused here.
- */
+/* RTL8367D SerDes registers */
#define RTL8365MB_OPTION_MAGIC_REG 0x13C0
#define RTL8365MB_OPTION_REG 0x13C1
-
#define RTL8365MB_MISC_CFG0_REG 0x130C
#define RTL8365MB_MISC_CFG0_DW8051_EN_MASK 0x0020
-
#define RTL8365MB_CHIP_RESET_DW8051_MASK 0x0010
-
#define RTL8365MB_DW8051_RDY_REG 0x1336
#define RTL8365MB_DW8051_RDY_ACS_IROM_MASK 0x0002
#define RTL8365MB_DW8051_RDY_IROM_MSB_MASK 0x0004
#define RTL8365MB_DW8051_IRAM_BASE 0xE000
-
#define RTL8365MB_SDS_MISC_REG 0x1D11
#define RTL8365MB_SDS_MISC_MAC8_SGMII_MASK 0x0040
#define RTL8365MB_SDS_MISC_MAC8_HSGMII_MASK 0x0800
@@ -238,13 +232,23 @@
#define RTL8365MB_SDS_MISC_SGMII_FDUP_MASK 0x0400
#define RTL8365MB_SDS_MISC_SGMII_LINK_MASK 0x0200
#define RTL8365MB_SDS_MISC_SGMII_SPD_MASK 0x0180
-
#define RTL8365MB_SDS_INDACS_CMD_REG 0x6600
#define RTL8365MB_SDS_INDACS_CMD_WRITE 0x00C0
-#define RTL8365MB_SDS_INDACS_CMD_READ 0x0080
+#define RTL8365MB_SDS_INDACS_CMD_READ 0x0080
#define RTL8365MB_SDS_INDACS_ADR_REG 0x6601
#define RTL8365MB_SDS_INDACS_DATA_REG 0x6602
-
+#define RTL8365MB_SDS_INDACS_CMD_WRITE_D 0x00CD
+#define RTL8365MB_SDS_INDACS_CMD_READ_D 0x008D
+#define RTL8365MB_D_FORCE_LINK_REG(id) (0x12C5 + (id))
+#define RTL8365MB_D_FORCE_LINK_EN_REG(id) (0x12CD + (id))
+#define RTL8365MB_D_SDS_MODE_MASK 0x001F
+#define RTL8365MB_D_SDS_MODE_DISABLE 0x1F
+#define RTL8365MB_D_SDS_MODE_SGMII 0x02
+#define RTL8365MB_D_SDS_MODE_HSGMII 0x12
+#define RTL8365MB_D_MAC6_SEL_SDS0 BIT(9)
+#define RTL8365MB_D_PA12PC_EN_S0 BIT(10)
+#define RTL8365MB_D_PA33PC_EN_S0 BIT(11)
+#define RTL8365MB_SGMII_FW_NAME "rtl_switch/rtl8367s-sgmii.bin"
/* External interface mode configuration registers 0~1 */
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 0x1305 /* EXT0,EXT1 */
@@ -684,6 +688,18 @@ static const struct rtl8365mb_chip_info
.jam_table = rtl8365mb_init_jam_8365mb_vc,
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
},
+ {
+ .name = "RTL8367D",
+ .chip_id = 0x6642,
+ .chip_ver = 0x0010,
+ .extints = {
+ { 6, 1, PHY_INTF(SGMII) | PHY_INTF(HSGMII) },
+ { 7, 2, PHY_INTF(MII) | PHY_INTF(TMII) |
+ PHY_INTF(RMII) | PHY_INTF(RGMII) },
+ },
+ .jam_table = rtl8365mb_init_jam_8365mb_vc,
+ .jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ },
};
enum rtl8365mb_stp_state {
@@ -1424,6 +1440,119 @@ static int rtl8365mb_ext_config_sgmii(st
return 0;
}
+/* RTL8367D SerDes calibration tables from GPL vendor driver */
+static const u16 rtl8365mb_sds_d_sgmii[][2] = {
+ { 0x1020, 0x0423 }, { 0x5242, 0x0425 }, { 0x4E0C, 0x0427 },
+ { 0xAA00, 0x0428 }, { 0x031B, 0x0484 },
+ { 0x1400, 0x0000 }, { 0x1403, 0x0000 },
+};
+static const u16 rtl8365mb_sds_d_hsgmii[][2] = {
+ { 0x8E11, 0x0421 }, { 0x1020, 0x0423 }, { 0x5242, 0x0425 },
+ { 0x4E0C, 0x0427 }, { 0xAA00, 0x0428 }, { 0x051B, 0x0504 },
+ { 0x1400, 0x0000 }, { 0x1403, 0x0000 },
+};
+static int rtl8365mb_sds_indacs_write_d(struct realtek_priv *priv, u16 data,
+ u16 addr)
+{
+ int ret;
+ ret = regmap_write(priv->map, RTL8365MB_SDS_INDACS_DATA_REG, data);
+ if (ret) return ret;
+ ret = regmap_write(priv->map, RTL8365MB_SDS_INDACS_ADR_REG, addr);
+ if (ret) return ret;
+ return regmap_write(priv->map, RTL8365MB_SDS_INDACS_CMD_REG,
+ RTL8365MB_SDS_INDACS_CMD_WRITE_D);
+}
+static int rtl8365mb_ext_config_sgmii_d(struct realtek_priv *priv, int port,
+ phy_interface_t interface)
+{
+ const struct rtl8365mb_extint *extint =
+ rtl8365mb_get_port_extint(priv, port);
+ bool hsgmii = interface == PHY_INTERFACE_MODE_2500BASEX;
+ const u16 (*red)[2];
+ size_t red_cnt;
+ int ret;
+ size_t i;
+ u32 val;
+ if (!extint) return -ENODEV;
+ if (extint->id != 1) return -EOPNOTSUPP;
+ ret = regmap_update_bits(priv->map, 0x03F7, BIT(extint->id), 0);
+ if (ret) return ret;
+ ret = regmap_update_bits(priv->map,
+ RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(extint->id), 0xF0, 0);
+ if (ret) return ret;
+ ret = regmap_update_bits(priv->map, RTL8365MB_SDS_MISC_REG,
+ RTL8365MB_D_SDS_MODE_MASK,
+ RTL8365MB_D_SDS_MODE_DISABLE);
+ if (ret) return ret;
+ ret = regmap_update_bits(priv->map, RTL8365MB_SDS_MISC_REG,
+ RTL8365MB_D_MAC6_SEL_SDS0 |
+ RTL8365MB_D_PA12PC_EN_S0 |
+ RTL8365MB_D_PA33PC_EN_S0,
+ RTL8365MB_D_MAC6_SEL_SDS0 |
+ RTL8365MB_D_PA12PC_EN_S0 |
+ RTL8365MB_D_PA33PC_EN_S0);
+ if (ret) return ret;
+ ret = regmap_update_bits(priv->map, 0x13E8, 0xC0, 0x40);
+ if (ret) return ret;
+ ret = regmap_update_bits(priv->map, 0x13EB, 0xF000, 0xE000);
+ if (ret) return ret;
+ if (hsgmii) {
+ red = rtl8365mb_sds_d_hsgmii;
+ red_cnt = ARRAY_SIZE(rtl8365mb_sds_d_hsgmii);
+ } else {
+ red = rtl8365mb_sds_d_sgmii;
+ red_cnt = ARRAY_SIZE(rtl8365mb_sds_d_sgmii);
+ }
+ for (i = 0; i < red_cnt; i++) {
+ ret = rtl8365mb_sds_indacs_write_d(priv, red[i][0], red[i][1]);
+ if (ret) return ret;
+ }
+ ret = regmap_update_bits(priv->map, RTL8365MB_SDS_MISC_REG,
+ RTL8365MB_D_SDS_MODE_MASK,
+ hsgmii ? RTL8365MB_D_SDS_MODE_HSGMII :
+ RTL8365MB_D_SDS_MODE_SGMII);
+ if (ret) return ret;
+ ret = rtl8365mb_sds_indacs_read(priv, 0x0002, &val);
+ if (ret) return ret;
+ val &= ~BIT(9);
+ val |= BIT(8);
+ ret = rtl8365mb_sds_indacs_write_d(priv, val, 0x0002);
+ if (ret) return ret;
+ return 0;
+}
+static int rtl8365mb_ext_config_forcemode_d(struct realtek_priv *priv, int port,
+ phy_interface_t interface,
+ bool link, int speed, int duplex,
+ bool tx_pause, bool rx_pause)
+{
+ const struct rtl8365mb_extint *extint =
+ rtl8365mb_get_port_extint(priv, port);
+ u32 val;
+ int ret;
+ if (!extint) return -ENODEV;
+ val = (link ? (1 << 4) : 0) |
+ (tx_pause ? (1 << 6) : 0) |
+ (rx_pause ? (1 << 5) : 0) |
+ (duplex == DUPLEX_FULL ? (1 << 2) : 0);
+ if (speed == SPEED_2500) {
+ val |= (1 << 12) | (1 << 0);
+ val |= (1 << 2);
+ } else if (speed == SPEED_1000) {
+ val |= (1 << 12) | (1 << 0);
+ val |= (1 << 2);
+ } else if (speed == SPEED_100) {
+ val |= (1 << 12) | (1 << 0);
+ }
+ ret = regmap_write(priv->map,
+ RTL8365MB_D_FORCE_LINK_REG(extint->id), val);
+ if (ret) return ret;
+ ret = regmap_write(priv->map,
+ RTL8365MB_D_FORCE_LINK_EN_REG(extint->id),
+ link ? 0xFFFF : 0);
+ if (ret) return ret;
+ return 0;
+}
+
static void rtl8365mb_phylink_get_caps(struct dsa_switch *ds, int port,
struct phylink_config *config)
{
@@ -1490,7 +1619,11 @@ static void rtl8365mb_phylink_mac_config
if (state->interface == PHY_INTERFACE_MODE_SGMII ||
state->interface == PHY_INTERFACE_MODE_2500BASEX) {
- ret = rtl8365mb_ext_config_sgmii(priv, port, state->interface);
+ struct rtl8365mb *mb = priv->chip_data;
+ if (mb->chip_info->chip_id == 0x6642)
+ ret = rtl8365mb_ext_config_sgmii_d(priv, port, state->interface);
+ else
+ ret = rtl8365mb_ext_config_sgmii(priv, port, state->interface);
if (ret)
dev_err(priv->dev,
"failed to configure SGMII mode on port %d: %d\n",
@@ -1520,9 +1653,13 @@ static void rtl8365mb_phylink_mac_link_d
if (phy_interface_mode_is_rgmii(interface) ||
interface == PHY_INTERFACE_MODE_SGMII ||
interface == PHY_INTERFACE_MODE_2500BASEX) {
- ret = rtl8365mb_ext_config_forcemode(priv, port, interface,
- false, 0, 0,
- false, false);
+ struct rtl8365mb *mb = priv->chip_data;
+ if (mb->chip_info->chip_id == 0x6642)
+ ret = rtl8365mb_ext_config_forcemode_d(priv, port, interface,
+ false, 0, 0, false, false);
+ else
+ ret = rtl8365mb_ext_config_forcemode(priv, port, interface,
+ false, 0, 0, false, false);
if (ret)
dev_err(priv->dev,
"failed to reset forced mode on port %d: %pe\n",
@@ -1553,10 +1690,15 @@ static void rtl8365mb_phylink_mac_link_u
if (phy_interface_mode_is_rgmii(interface) ||
interface == PHY_INTERFACE_MODE_SGMII ||
interface == PHY_INTERFACE_MODE_2500BASEX) {
- ret = rtl8365mb_ext_config_forcemode(priv, port, interface,
- true, speed,
- duplex, tx_pause,
- rx_pause);
+ struct rtl8365mb *mb = priv->chip_data;
+ if (mb->chip_info->chip_id == 0x6642)
+ ret = rtl8365mb_ext_config_forcemode_d(priv, port, interface,
+ true, speed, duplex,
+ tx_pause, rx_pause);
+ else
+ ret = rtl8365mb_ext_config_forcemode(priv, port, interface,
+ true, speed, duplex,
+ tx_pause, rx_pause);
if (ret)
dev_err(priv->dev,
"failed to force mode on port %d: %pe\n", port,
@@ -1678,11 +1820,16 @@ static int rtl8365mb_port_vlan_filtering
enum rtl8365mb_frame_ingress accepted_frame, prev_accepted_frame;
enum rtl8365mb_vlan_egress_mode mode;
struct realtek_priv *priv = ds->priv;
+ struct rtl8365mb *mb = priv->chip_data;
u32 configured_ports = 0;
struct dsa_port *dp;
u16 pvid_vid;
int ret;
+ /* RTL8367D: write-only VLAN4K registers, skip VLAN filtering */
+ if (mb->chip_info->chip_id == 0x6642)
+ return 0;
+
dev_dbg(priv->dev, "port %d: %s VLAN filtering\n", port,
vlan_filtering ? "enable" : "disable");
@@ -1789,8 +1936,13 @@ static int rtl8365mb_port_vlan_add(struc
bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
u16 pvid_vid;
struct realtek_priv *priv = ds->priv;
+ struct rtl8365mb *mb = priv->chip_data;
int ret;
+ /* RTL8367D: skip VLAN add - write-only registers */
+ if (mb->chip_info->chip_id == 0x6642)
+ return 0;
+
dev_dbg(priv->dev, "add VLAN %d on port %d, %s, %s\n",
vlan->vid, port, untagged ? "untagged" : "tagged",
pvid ? "PVID" : "no PVID");
@@ -1850,8 +2002,13 @@ static int rtl8365mb_port_vlan_del(struc
bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
struct realtek_priv *priv = ds->priv;
+ struct rtl8365mb *mb = priv->chip_data;
int ret;
+ /* RTL8367D: skip VLAN del - write-only registers */
+ if (mb->chip_info->chip_id == 0x6642)
+ return 0;
+
dev_dbg(priv->dev, "del VLAN %d on port %d, %s, %s\n",
vlan->vid, port, untagged ? "untagged" : "tagged",
pvid ? "PVID" : "no PVID");
@@ -1899,7 +2056,15 @@ static int rtl8365mb_vlan_setup(struct d
}
}
- /* VLAN is always enabled. */
+ /* On RTL8367D (0x6642) VLAN4K registers are write-only. Enabling
+ * global VLAN causes the switch to check membership against an empty
+ * table and drop all frames. Skip VLAN enable on this chip.
+ */
+ {
+ struct rtl8365mb *mb = priv->chip_data;
+ if (mb->chip_info->chip_id == 0x6642)
+ return 0;
+ }
ret = regmap_update_bits(priv->map, RTL8365MB_VLAN_CTRL_REG,
RTL8365MB_VLAN_CTRL_EN_MASK,
FIELD_PREP(RTL8365MB_VLAN_CTRL_EN_MASK, 1));
LOGS:
root@OpenWrt:~# ethtool -S eth0 | grep -E "p06_if"
p06_ifInOctets: 0
p06_ifInUcastPkts: 0
p06_ifInMulticastPkts: 0
p06_ifInBroadcastPkts: 0
p06_ifOutOctets: 2930
p06_ifOutDiscards: 0
p06_ifOutUcastPkts: 0
p06_ifOutMulticastPkts: 7
p06_ifOutBroadcastPkts: 32
root@OpenWrt:~# ethtool -S eth0 | grep -E "p06_if"
p06_ifInOctets: 0
p06_ifInUcastPkts: 0
p06_ifInMulticastPkts: 0
p06_ifInBroadcastPkts: 0
p06_ifOutOctets: 2930
p06_ifOutDiscards: 0
p06_ifOutUcastPkts: 0
p06_ifOutMulticastPkts: 7
p06_ifOutBroadcastPkts: 32
root@OpenWrt:~# ip neigh show
root@OpenWrt:~#
[ 70.571922] rtl8365mb-mdio 90000.mdio-1:1d lan1: Link is Down
[ 70.572121] br-lan: port 1(lan1) entered disabled state
[ 73.693291] rtl8365mb-mdio 90000.mdio-1:1d lan1: Link is Up - 1Gbps/Full - flow control rx/tx
[ 73.693393] br-lan: port 1(lan1) entered blocking state
[ 73.700870] br-lan: port 1(lan1) entered forwarding state
root@OpenWrt:~# ip neigh show
root@OpenWrt:~# ip neigh show
root@OpenWrt:~# brctl show
bridge name bridge id STP enabled interfaces
br-lan 7fff.ac15a2b57580 no phy1-ap0
lan4
lan2
lan3
lan1
phy0-ap0
root@OpenWrt:~# ip link show | grep -E "lan|wan"
3: wan@eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN qlen 1000
4: lan1@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-lan state UP qlen 1000
5: lan2@eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN qlen 1000
6: lan3@eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN qlen 1000
7: lan4@eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN qlen 1000
8: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
9: phy0-ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-lan state UP qlen 1000
10: phy1-ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-lan state UP qlen 1000
root@OpenWrt:~# dmesg | grep -i "vlan\|failed"
[ 0.000000] psci: [Firmware Bug]: failed to set PC mode: -1
[ 1.448615] 8021q: 802.1Q VLAN Support v1.8
root@OpenWrt:~# ping 192.168.1.100
PING 192.168.1.100 (192.168.1.100): 56 data bytes
^C
--- 192.168.1.100 ping statistics ---
6 packets transmitted, 0 packets received, 100% packet loss
root@OpenWrt:~# ethtool -S eth0 | grep -E "p06_if"
p06_ifInOctets: 0
p06_ifInUcastPkts: 0
p06_ifInMulticastPkts: 0
p06_ifInBroadcastPkts: 0
p06_ifOutOctets: 5312
p06_ifOutDiscards: 0
p06_ifOutUcastPkts: 0
p06_ifOutMulticastPkts: 10
p06_ifOutBroadcastPkts: 62
root@OpenWrt:~# ethtool -S eth0 | grep -E "p06_if"
p06_ifInOctets: 0
p06_ifInUcastPkts: 0
p06_ifInMulticastPkts: 0
p06_ifInBroadcastPkts: 0
p06_ifOutOctets: 7511
p06_ifOutDiscards: 0
p06_ifOutUcastPkts: 0
p06_ifOutMulticastPkts: 17
p06_ifOutBroadcastPkts: 72
root@OpenWrt:~# ethtool -S eth0 | grep -E "p06_if"
p06_ifInOctets: 0
p06_ifInUcastPkts: 0
p06_ifInMulticastPkts: 0
p06_ifInBroadcastPkts: 0
p06_ifOutOctets: 7511
p06_ifOutDiscards: 0
p06_ifOutUcastPkts: 0
p06_ifOutMulticastPkts: 17
p06_ifOutBroadcastPkts: 72
root@OpenWrt:~# cat /sys/kernel/debug/regmap/90000.mdio-1\:1d/registers | grep -
E "^(03f7|07a8|12c6|12ce|1305|13e8|13eb|1d11):"
03f7: 0000
07a8: 0000
12c6: 1075
12ce: ffff
1305: c000
13e8: 3040
13eb: e5bb
1d11: 0e12
root@OpenWrt:~# ip neigh show
192.168.1.100 dev br-lan used 0/0/0 probes 6 FAILED
The write-only VLAN4K table is a great find β that explains why the always-on VLAN design of the new driver can't work as-is on the D. Skipping the VLAN ops for 0x6642 is the right interim call; when we fold your chip into the SGMII/HSGMII patch, we can start exactly like that and add a software shadow table later (the vendor DAL proves it's workable). Please share your patch when it's stable.
On the unidirectional traffic β that's the exact symptom class I've now debugged twice on the S, so here's the short checklist:
-
Force-link value: for the 2.5G HSGMII test it must be
0x12c6 = 0x1075(2500M encoding: speed=0x5 packed as bits[13:12]+[1:0]), not the0x0076from my earlier SGMII recipe β plus0x12ce = 0xFFFF. With 1G forced on the MAC against a 2.5G SerDes you get exactly "frames counted out, nothing valid in". -
Use the CPU-port FCS counter as your compass β it distinguishes the two failure modes. Flood from the PC and watch deltas of
dot3StatsFCSErrorsvsifInUcastPktson the CPU port:- FCS rising, ifIn flat β frames DO cross the SerDes but arrive corrupted (misalignment). Pulse the SerDes reset again after everything else is configured (INDACS write SDS reg
0x0000 = 0x1400, then0x1403) and re-check. I hit a state on the S this week where the SDS status register even reported lock while 100% of frames arrived as FCS garbage β the status bit lies, the MIB counters don't. - both flat β frames never leave the port toward the CPU: force-link (see 1), port isolation mask, or the
MAC6_SEL_SDS0/pad-enable bits from the full bring-up list I posted earlier.
- FCS rising, ifIn flat β frames DO cross the SerDes but arrive corrupted (misalignment). Pulse the SerDes reset again after everything else is configured (INDACS write SDS reg
-
Order matters: SDS mode (
0x1d11 bits[4:0] = 0x12) as the last config step, after the jam table; force-link after that.
FWIW I ended up giving the S a runtime "SerDes babysitter" in the driver (poll lock + MIB deltas from the periodic stats work, pulse the SerDes reset on garbage, escalate to a full re-config) because a cold-booted SerDes occasionally comes up broken even with a correct static config. If your D shows the same cold-boot lottery once traffic works, the same medicine should apply.
Maybe even it won't help, because I found out that a full s-like s family has been added to the mb driver, and the d family family has not been added, and now they are doing it, so apparently I'm temporarily in flight, since I'm not very erudite in this(
I asked the developers who are engaged in the mb driver of our real library, so far the answer is unambiguous, what will they do later(
And you're good that you were able to debug the work, s series
Thanks for the update β that explains it. The mainline rtl8365mb driver only covers the RTL8367C register family (RTL8365MB-VC, RTL8367S, RTL8367RB-VB). The D-family chips (RTL8367D/S-VB etc.) have a different register map β in Realtek's vendor SDK they are handled by a separate rtl8367d sub-driver, and nobody has ported that to mainline DSA yet.
So unfortunately your board variant needs real driver work, not just a DTS change. If you post the exact marking printed on your switch chip, it will help whoever picks this up later.
On our S-series variant everything works now (trunk, WAN/NAT, WiFi), including a fix for cold-boot SerDes lock issues β so once a D-family driver exists, the rest of the port should carry over.
@kuncy7 Hello. Thank you for all the hard work. I managed to enable Telnet, but I am unable to log into the root account. It keeps asking me for a password, and I am unable to find it anywhere. I probably missed something, but could you lead me in the right direction? Thank you.
My repack doesn't authenticate at all: I added one line to /etc/rc.local, before exit 0:
telnetd -l /bin/sh &
-l /bin/sh tells busybox telnetd to spawn a shell directly instead of /bin/login, so it drops you straight into a root shell β no password, /etc/passwd and /etc/shadow are never consulted.
What's happening on your side is the stock /etc/init.d/telnet, which starts telnetd -l /bin/login. That path does authenticate, and stock ships root with an invalid hash (root:x:... in /etc/shadow), so no password will ever work β that's why it keeps asking.
Two ways to fix it, both edited into the rootfs before you repack:
- Bypass login (what I do): add
telnetd -l /bin/sh &to/etc/rc.local. Simplest for a throwaway install shell. - Give root a real password: in
/etc/shadowchange therootline's second field fromxto an empty string (root::0:0:99999:7:::) β empty password β or to a known hash. Then stock-l /bin/logintelnet will let you in.
Hi,
To enable telnet login without any password, stop using TP link's login binary from sbin. Instead use login.sh (OpenWrt shell wrapper) which should directly drop you into root shell. Unecessary to mess with passwd and other stuffs.
You can see this patch here for enabling telnet. Can confirm this works perfectly -- at least on ax53. Should work for ax55 too.
Also I notice in recent firmwares from tplink, they've started RSA encrypting the firmware to avoid tampering. I found a way to decrypt that -- see here if you're interested.
Cheers.
The first method worked perfectly. The router seems functional. It was basically a paperweight until now. Now, I can use it as a test device to learn stuff. Thanks for your assistance.
Status update on the AX55 v1 port β and images to try
Quick summary for everyone following this thread: the TP-Link Archer AX55 v1 port is now a fully functional router on mainline OpenWrt β no QSDK, no NSS, no SerDes firmware blob. WAN + NAT + IPv6, 4ΓLAN over DSA, both Wi-Fi radios (2.4 + 5 GHz) with the correct factory calibration, factory MACs, USB2, and the RTL8367S β SoC link running as a 2.5G HSGMII trunk (faster than stock, which caps it at 1G). The whole thing was brought up without ever soldering a serial console.
Sources, ready-to-flash images and full install/recovery notes:
https://github.com/kuncy7/openwrt-ax55-v1 β Release v1.0 (factory.ubi for a first install via mtd write, sysupgrade.bin for updates).
Upstream submission (draft while the switch-driver patches go through netdev):
https://github.com/openwrt/openwrt/pull/24197
Two things worth knowing:
- Check your switch chip first. This targets v1 with the RTL8367S. Some v1 units shipped an RTL8367D instead, which isn't supported yet β on such a board Ethernet would come up dead and Wi-Fi off by default. (v2 is a different SoC entirely.)
- One open issue we're actively chasing: after the router sits powered off for several hours, the 2.5G trunk can come up degraded on the first boot (a reboot recovers it). It's being worked on the netdev list and the "reduce number of drivers for rtl8367s" thread; the current candidate fix is already in the v1.0 build. Warm reboots and short power-cycles are unaffected.
If you flash it, feedback is very welcome β especially anyone who can reproduce (or not reproduce) the cold-boot trunk behaviour on their unit. More units in the wild is exactly what this needs right now. Thanks to everyone who helped get here. ![]()
Good afternoon. My first experience with OpenWRT was with this router. I managed to install your build. Everything seems to be working fine. One bug I encountered is that when I change the Wi-Fi settings, the Wi-Fi stops working until I reboot the router. Also, I canβt install the WireGuard client, but that might be due to the specifics of your build (Iβm still new to OpenWRT). Other than that, I havenβt encountered any critical errors during the 12 hours Iβve been using it. If you need any further feedback, I can provide it to the best of my ability and knowledge. (Again, this is limited by my current understanding of OpenWRT, since Iβve only been using it for literally one day =))
