From 28e972b2ea2f55a593defcbd2dc21710cce648c7 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Wed, 8 Sep 2021 20:00:31 +0200 Subject: [PATCH] realtek: Configure initial L2 learning setup Configure a sane L2 learning configuration upon DSA driver load so that the switch can start learning L2 addresses. Also configure the correct flood masks for broadcast and unknown unicast traffice. Signed-off-by: Birger Koblitz --- .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 4 ++++ .../drivers/net/dsa/rtl83xx/rtl838x.c | 19 +++++++++++++++++++ .../drivers/net/dsa/rtl83xx/rtl838x.h | 12 ++++++++++++ .../drivers/net/dsa/rtl83xx/rtl839x.c | 15 +++++++++++++++ .../drivers/net/dsa/rtl83xx/rtl930x.c | 14 +++++++++++++- 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index 3a0806e70a..8ed0e45bb9 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -184,6 +184,8 @@ static int rtl83xx_setup(struct dsa_switch *ds) ds->configure_vlan_while_not_filtering = true; + priv->r->l2_learning_setup(); + /* Enable MAC Polling PHY again */ rtl83xx_enable_phy_polling(priv); pr_debug("Please wait until PHY is settled\n"); @@ -228,6 +230,8 @@ static int rtl930x_setup(struct dsa_switch *ds) ds->configure_vlan_while_not_filtering = true; + priv->r->l2_learning_setup(); + rtl83xx_enable_phy_polling(priv); priv->r->pie_init(priv); diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c index 2d24eaa337..15a486d724 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c @@ -491,6 +491,24 @@ static void rtl838x_vlan_profile_setup(int profile) rtl838x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0x1fffffff); } +static void rtl838x_l2_learning_setup(void) +{ + /* Set portmask for broadcast traffic and unknown unicast address flooding + * to the reserved entry in the portmask table used also for + * multicast flooding */ + sw_w32(UNKNOWN_MC_PMASK << 12 | UNKNOWN_MC_PMASK, RTL838X_L2_FLD_PMSK); + + /* Enable learning constraint system-wide (bit 0), per-port (bit 1) + * and per vlan (bit 2) */ + sw_w32(0x7, RTL838X_L2_LRN_CONSTRT_EN); + + // Limit learning to maximum: 16k entries, after that just flood (bits 0-1) + sw_w32((0x3fff << 2) | 0, RTL838X_L2_LRN_CONSTRT); + + // Do not trap ARP packets to CPU_PORT + sw_w32(0, RTL838X_SPCL_TRAP_ARP_CTRL); +} + static inline int rtl838x_vlan_port_egr_filter(int port) { return RTL838X_VLAN_PORT_EGR_FLTR; @@ -1605,6 +1623,7 @@ const struct rtl838x_reg rtl838x_reg = { .pie_rule_write = rtl838x_pie_rule_write, .pie_rule_add = rtl838x_pie_rule_add, .pie_rule_rm = rtl838x_pie_rule_rm, + .l2_learning_setup = rtl838x_l2_learning_setup, .packet_cntr_read = rtl838x_packet_cntr_read, .packet_cntr_clear = rtl838x_packet_cntr_clear, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h index e695879da1..6ff59c4348 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -198,6 +198,15 @@ #define RTL930X_L2_TBL_FLUSH_CTRL (0x9404) #define RTL931X_L2_TBL_FLUSH_CTRL (0xCD9C) +#define RTL838X_L2_LRN_CONSTRT (0x329C) +#define RTL839X_L2_LRN_CONSTRT (0x3910) +#define RTL930X_L2_LRN_CONSTRT_CTRL (0x909c) +#define RTL838X_L2_FLD_PMSK (0x3288) +#define RTL839X_L2_FLD_PMSK (0x38EC) +#define RTL930X_L2_BC_FLD_PMSK (0x9068) +#define RTL930X_L2_UNKN_UC_FLD_PMSK (0x9064) +#define RTL838X_L2_LRN_CONSTRT_EN (0x3368) + #define RTL838X_L2_PORT_NEW_SALRN(p) (0x328c + (((p >> 4) << 2))) #define RTL839X_L2_PORT_NEW_SALRN(p) (0x38F0 + (((p >> 4) << 2))) #define RTL930X_L2_PORT_SALRN(p) (0x8FEC + (((p >> 4) << 2))) @@ -303,6 +312,8 @@ /* 802.1X */ #define RTL838X_SPCL_TRAP_EAPOL_CTRL (0x6988) #define RTL839X_SPCL_TRAP_EAPOL_CTRL (0x105C) +#define RTL838X_SPCL_TRAP_ARP_CTRL (0x698C) +#define RTL839X_SPCL_TRAP_ARP_CTRL (0x1060) /* QoS */ #define RTL838X_QM_INTPRI2QID_CTRL (0x5F00) @@ -699,6 +710,7 @@ struct rtl838x_reg { int (*pie_rule_write)(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr); int (*pie_rule_add)(struct rtl838x_switch_priv *priv, struct pie_rule *rule); void (*pie_rule_rm)(struct rtl838x_switch_priv *priv, struct pie_rule *rule); + void (*l2_learning_setup)(void); u32 (*packet_cntr_read)(int counter); void (*packet_cntr_clear)(int counter); }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c index 8faf6c07e9..4ed2184efa 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c @@ -542,6 +542,20 @@ void rtl839x_traffic_disable(int source, int dest) rtl839x_mask_port_reg_be(BIT_ULL(dest), 0, rtl839x_port_iso_ctrl(source)); } +static void rtl839x_l2_learning_setup(void) +{ + /* Set portmask for broadcast (offset bit 12) and unknown unicast (offset 0) + * address flooding to the reserved entry in the portmask table used + * also for multicast flooding */ + sw_w32(UNKNOWN_MC_PMASK << 12 | UNKNOWN_MC_PMASK, RTL839X_L2_FLD_PMSK); + + // Limit learning to maximum: 32k entries, after that just flood (bits 0-1) + sw_w32((0x7fff << 2) | 0, RTL839X_L2_LRN_CONSTRT); + + // Do not trap ARP packets to CPU_PORT + sw_w32(0, RTL839X_SPCL_TRAP_ARP_CTRL); +} + irqreturn_t rtl839x_switch_irq(int irq, void *dev_id) { struct dsa_switch *ds = dev_id; @@ -1677,6 +1691,7 @@ const struct rtl838x_reg rtl839x_reg = { .pie_rule_write = rtl839x_pie_rule_write, .pie_rule_add = rtl839x_pie_rule_add, .pie_rule_rm = rtl839x_pie_rule_rm, + .l2_learning_setup = rtl839x_l2_learning_setup, .packet_cntr_read = rtl839x_packet_cntr_read, .packet_cntr_clear = rtl839x_packet_cntr_clear, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c index 4291954234..aa6306c1c6 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c @@ -254,7 +254,18 @@ static void rtl930x_vlan_profile_setup(int profile) sw_w32(p[2], RTL930X_VLAN_PROFILE_SET(profile) + 8); sw_w32(p[3], RTL930X_VLAN_PROFILE_SET(profile) + 12); sw_w32(p[4], RTL930X_VLAN_PROFILE_SET(profile) + 16); - pr_info("Leaving %s\n", __func__); +} + +static void rtl930x_l2_learning_setup(void) +{ + // Portmask for flooding broadcast traffic + sw_w32(0x1fffffff, RTL930X_L2_BC_FLD_PMSK); + + // Portmask for flooding unicast traffic with unknown destination + sw_w32(0x1fffffff, RTL930X_L2_UNKN_UC_FLD_PMSK); + + // Limit learning to maximum: 32k entries, after that just flood (bits 0-1) + sw_w32((0x7fff << 2) | 0, RTL930X_L2_LRN_CONSTRT_CTRL); } static void rtl930x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) @@ -1712,6 +1723,7 @@ const struct rtl838x_reg rtl930x_reg = { .pie_rule_write = rtl930x_pie_rule_write, .pie_rule_add = rtl930x_pie_rule_add, .pie_rule_rm = rtl930x_pie_rule_rm, + .l2_learning_setup = rtl930x_l2_learning_setup, .packet_cntr_read = rtl930x_packet_cntr_read, .packet_cntr_clear = rtl930x_packet_cntr_clear, }; -- 2.30.2