diff options
4 files changed, 259 insertions, 114 deletions
diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.c index 773225b3c4..b31b1ae6ba 100644 --- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.c @@ -12,10 +12,10 @@ void rtl838x_print_matrix(void) ptr8 = RTL838X_SW_BASE + RTL838X_PORT_ISO_CTRL(0); for (i = 0; i < 28; i += 8) - pr_info("> %8x %8x %8x %8x %8x %8x %8x %8x\n", + pr_debug("> %8x %8x %8x %8x %8x %8x %8x %8x\n", ptr8[i + 0], ptr8[i + 1], ptr8[i + 2], ptr8[i + 3], ptr8[i + 4], ptr8[i + 5], ptr8[i + 6], ptr8[i + 7]); - pr_info("CPU_PORT> %8x\n", ptr8[28]); + pr_debug("CPU_PORT> %8x\n", ptr8[28]); } static inline int rtl838x_port_iso_ctrl(int p) @@ -42,56 +42,54 @@ static inline int rtl838x_tbl_access_data_0(int i) static void rtl838x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) { - u32 cmd, v; + u32 v; + // Read VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 0); + + rtl_table_read(r, vlan); + info->tagged_ports = sw_r32(rtl_table_data(r, 0)); + v = sw_r32(rtl_table_data(r, 1)); + pr_debug("VLAN_READ %d: %016llx %08x\n", vlan, info->tagged_ports, v); + rtl_table_release(r); - cmd = BIT(15) /* Execute cmd */ - | BIT(14) /* Read */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); - rtl838x_exec_tbl0_cmd(cmd); - info->tagged_ports = sw_r32(RTL838X_TBL_ACCESS_DATA_0(0)); - v = sw_r32(RTL838X_TBL_ACCESS_DATA_0(1)); info->profile_id = v & 0x7; info->hash_mc_fid = !!(v & 0x8); info->hash_uc_fid = !!(v & 0x10); info->fid = (v >> 5) & 0x3f; - - cmd = BIT(15) /* Execute cmd */ - | BIT(14) /* Read */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); - rtl838x_exec_tbl1_cmd(cmd); - info->untagged_ports = sw_r32(RTL838X_TBL_ACCESS_DATA_1(0)); + // Read UNTAG table (0) via table register 1 + r = rtl_table_get(RTL8380_TBL_1, 0); + rtl_table_read(r, vlan); + info->untagged_ports = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); } static void rtl838x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) { - u32 cmd = BIT(15) /* Execute cmd */ - | 0 << 14 /* Write */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); u32 v; + // Access VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 0); - sw_w32(info->tagged_ports, RTL838X_TBL_ACCESS_DATA_0(0)); + sw_w32(info->tagged_ports, rtl_table_data(r, 0)); v = info->profile_id; v |= info->hash_mc_fid ? 0x8 : 0; v |= info->hash_uc_fid ? 0x10 : 0; v |= ((u32)info->fid) << 5; + sw_w32(v, rtl_table_data(r, 1)); - sw_w32(v, RTL838X_TBL_ACCESS_DATA_0(1)); - rtl838x_exec_tbl0_cmd(cmd); + rtl_table_write(r, vlan); + rtl_table_release(r); } static void rtl838x_vlan_set_untagged(u32 vlan, u64 portmask) { - u32 cmd = BIT(15) /* Execute cmd */ - | 0 << 14 /* Write */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); - sw_w32(portmask & 0x1fffffff, RTL838X_TBL_ACCESS_DATA_1(0)); - rtl838x_exec_tbl1_cmd(cmd); + // Access UNTAG table (0) via register 1 + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 0); + + sw_w32(portmask & 0x1fffffff, rtl_table_data(r, 0)); + rtl_table_write(r, vlan); + rtl_table_release(r); } static inline int rtl838x_mac_force_mode_ctrl(int p) @@ -202,9 +200,43 @@ static u64 rtl838x_read_cam(int idx, struct rtl838x_l2_entry *e) return entry; } -static inline int rtl838x_vlan_profile(int profile) +static u64 rtl838x_read_mcast_pmask(int idx) { - return RTL838X_VLAN_PROFILE(profile); + u32 portmask; + // Read MC_PMSK (2) via register RTL8380_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 2); + + rtl_table_read(q, idx); + portmask = sw_r32(rtl_table_data(q, 0)); + rtl_table_release(q); + + return portmask; +} + +static void rtl838x_write_mcast_pmask(int idx, u64 portmask) +{ + // Access MC_PMSK (2) via register RTL8380_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 2); + + sw_w32(((u32)portmask) & 0x1fffffff, rtl_table_data(q, 0)); + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static void rtl838x_vlan_profile_setup(int profile) +{ + u32 pmask_id = UNKNOWN_MC_PMASK; + // Enable L2 Learning BIT 0, portmask UNKNOWN_MC_PMASK for unknown MC traffic flooding + u32 p = 1 | pmask_id << 1 | pmask_id << 10 | pmask_id << 19; + + sw_w32(p, RTL838X_VLAN_PROFILE(profile)); + + /* RTL8380 and RTL8390 use an index into the portmask table to set the + * unknown multicast portmask, setup a default at a safe location + * On RTL93XX, the portmask is directly set in the profile, + * see e.g. rtl9300_vlan_profile_setup + */ + rtl838x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0xfffffff); } static inline int rtl838x_vlan_port_egr_filter(int port) @@ -373,6 +405,7 @@ const struct rtl838x_reg rtl838x_reg = { .vlan_set_untagged = rtl838x_vlan_set_untagged, .mac_force_mode_ctrl = rtl838x_mac_force_mode_ctrl, .vlan_profile_dump = rtl838x_vlan_profile_dump, + .vlan_profile_setup = rtl838x_vlan_profile_setup, .stp_get = rtl838x_stp_get, .stp_set = rtl838x_stp_set, .mac_port_ctrl = rtl838x_mac_port_ctrl, @@ -398,6 +431,8 @@ const struct rtl838x_reg rtl838x_reg = { .init_eee = rtl838x_init_eee, .port_eee_set = rtl838x_port_eee_set, .eee_port_ability = rtl838x_eee_port_ability, + .read_mcast_pmask = rtl838x_read_mcast_pmask, + .write_mcast_pmask = rtl838x_write_mcast_pmask, }; irqreturn_t rtl838x_switch_irq(int irq, void *dev_id) @@ -641,19 +676,18 @@ u32 rtl838x_hash(struct rtl838x_switch_priv *priv, u64 seed) return h; } -void rtl838x_vlan_profile_dump(int index) +void rtl838x_vlan_profile_dump(int profile) { - u32 profile; + u32 p; - if (index < 0 || index > 7) + if (profile < 0 || profile > 7) return; - profile = sw_r32(RTL838X_VLAN_PROFILE(index)); + p = sw_r32(RTL838X_VLAN_PROFILE(profile)); - pr_info("VLAN %d: L2 learning: %d, L2 Unknown MultiCast Field %x, \ - IPv4 Unknown MultiCast Field %x, IPv6 Unknown MultiCast Field: %x", - index, profile & 1, (profile >> 1) & 0x1ff, (profile >> 10) & 0x1ff, - (profile >> 19) & 0x1ff); + pr_info("VLAN profile %d: L2 learning: %d, UNKN L2MC FLD PMSK %d, \ + UNKN IPMC FLD PMSK %d, UNKN IPv6MC FLD PMSK: %d", + profile, p & 1, (p >> 1) & 0x1ff, (p >> 10) & 0x1ff, (p >> 19) & 0x1ff); } void rtl8380_sds_rst(int mac) diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.h index 928a23af77..35d5b1702a 100644 --- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.h @@ -332,8 +332,11 @@ /* Debug features */ #define RTL930X_STAT_PRVTE_DROP_COUNTER0 (0xB5B8) +#define MAX_VLANS 4096 #define MAX_LAGS 16 #define MAX_PRIOS 8 +#define MAX_MC_GROUPS 512 +#define UNKNOWN_MC_PMASK (MAX_MC_GROUPS - 1) enum phy_type { PHY_NONE = 0, @@ -426,6 +429,7 @@ struct rtl838x_reg { void (*vlan_set_tagged)(u32 vlan, struct rtl838x_vlan_info *info); void (*vlan_set_untagged)(u32 vlan, u64 portmask); void (*vlan_profile_dump)(int index); + void (*vlan_profile_setup)(int profile); void (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]); void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]); int (*mac_force_mode_ctrl)(int port); @@ -454,6 +458,8 @@ struct rtl838x_reg { void (*port_eee_set)(struct rtl838x_switch_priv *priv, int port, bool enable); int (*eee_port_ability)(struct rtl838x_switch_priv *priv, struct ethtool_eee *e, int port); + u64 (*read_mcast_pmask)(int idx); + void (*write_mcast_pmask)(int idx, u64 portmask); }; struct rtl838x_switch_priv { diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c index b2846deb11..825655cd54 100644 --- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c @@ -48,68 +48,71 @@ static inline int rtl839x_tbl_access_data_0(int i) static void rtl839x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) { - u32 cmd; - u64 v; - u32 u, w; - - cmd = 1 << 16 /* Execute cmd */ - | 0 << 15 /* Read */ - | 0 << 12 /* Table type 0b000 */ - | (vlan & 0xfff); - rtl839x_exec_tbl0_cmd(cmd); - - v = sw_r32(RTL839X_TBL_ACCESS_DATA_0(0)); - v <<= 32; - u = sw_r32(RTL839X_TBL_ACCESS_DATA_0(1)); - v |= u; - info->tagged_ports = v >> 11; - - w = sw_r32(RTL839X_TBL_ACCESS_DATA_0(2)); - - info->profile_id = w >> 30 | ((u & 1) << 2); - info->hash_mc_fid = !!(u & 2); - info->hash_uc_fid = !!(u & 4); - info->fid = (u >> 3) & 0xff; - - cmd = 1 << 15 /* Execute cmd */ - | 0 << 14 /* Read */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); - rtl839x_exec_tbl1_cmd(cmd); - v = sw_r32(RTL839X_TBL_ACCESS_DATA_1(0)); - v <<= 32; - v |= sw_r32(RTL839X_TBL_ACCESS_DATA_1(1)); - info->untagged_ports = v >> 11; + u32 u, v, w; + // Read VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 0); + + rtl_table_read(r, vlan); + u = sw_r32(rtl_table_data(r, 0)); + v = sw_r32(rtl_table_data(r, 1)); + w = sw_r32(rtl_table_data(r, 2)); + rtl_table_release(r); + + info->tagged_ports = u; + info->tagged_ports = (info->tagged_ports << 21) | ((v >> 11) & 0x1fffff); + info->profile_id = w >> 30 | ((v & 1) << 2); + info->hash_mc_fid = !!(w & BIT(2)); + info->hash_uc_fid = !!(w & BIT(3)); + info->fid = (v >> 3) & 0xff; + + // Read UNTAG table (0) via table register 1 + r = rtl_table_get(RTL8390_TBL_1, 0); + rtl_table_read(r, vlan); + u = sw_r32(rtl_table_data(r, 0)); + v = sw_r32(rtl_table_data(r, 1)); + rtl_table_release(r); + + info->untagged_ports = u; + info->untagged_ports = (info->untagged_ports << 21) | ((v >> 11) & 0x1fffff); } static void rtl839x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) { - u32 cmd = BIT(16) /* Execute cmd */ - | BIT(15) /* Write */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); - u32 w; - u64 v = info->tagged_ports << 11; + u32 u, v, w; + // Access VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 0); - v |= info->profile_id >> 2; - v |= info->hash_mc_fid ? 2 : 0; - v |= info->hash_uc_fid ? 4 : 0; + u = info->tagged_ports >> 21; + v = info->tagged_ports << 11; v |= ((u32)info->fid) << 3; - rtl839x_set_port_reg_be(v, RTL838X_TBL_ACCESS_DATA_0(0)); + v |= info->hash_uc_fid ? BIT(2) : 0; + v |= info->hash_mc_fid ? BIT(1) : 0; + v |= (info->profile_id & 0x4) ? 1 : 0; + w = ((u32)(info->profile_id & 3)) << 30; + + sw_w32(u, rtl_table_data(r, 0)); + sw_w32(v, rtl_table_data(r, 1)); + sw_w32(w, rtl_table_data(r, 2)); - w = info->profile_id; - sw_w32(w << 30, RTL838X_TBL_ACCESS_DATA_0(2)); - rtl839x_exec_tbl0_cmd(cmd); + rtl_table_write(r, vlan); + rtl_table_release(r); } static void rtl839x_vlan_set_untagged(u32 vlan, u64 portmask) { - u32 cmd = BIT(16) /* Execute cmd */ - | BIT(15) /* Write */ - | 0 << 12 /* Table type 0b00 */ - | (vlan & 0xfff); - rtl839x_set_port_reg_be(portmask << 11, RTL838X_TBL_ACCESS_DATA_1(0)); - rtl839x_exec_tbl1_cmd(cmd); + u32 u, v; + + // Access UNTAG table (0) via table register 1 + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 0); + + u = portmask >> 21; + v = portmask << 11; + + sw_w32(u, rtl_table_data(r, 0)); + sw_w32(v, rtl_table_data(r, 1)); + rtl_table_write(r, vlan); + + rtl_table_release(r); } static inline int rtl839x_mac_force_mode_ctrl(int p) @@ -243,9 +246,47 @@ static u64 rtl839x_read_cam(int idx, struct rtl838x_l2_entry *e) return entry; } -static inline int rtl839x_vlan_profile(int profile) +static u64 rtl839x_read_mcast_pmask(int idx) { - return RTL839X_VLAN_PROFILE(profile); + u64 portmask; + // Read MC_PMSK (2) via register RTL8390_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 2); + + rtl_table_read(q, idx); + portmask = sw_r32(rtl_table_data(q, 0)); + portmask <<= 32; + portmask |= sw_r32(rtl_table_data(q, 1)); + portmask >>= 11; // LSB is bit 11 in data registers + rtl_table_release(q); + + return portmask; +} + +static void rtl839x_write_mcast_pmask(int idx, u64 portmask) +{ + // Access MC_PMSK (2) via register RTL8380_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 2); + + portmask <<= 11; // LSB is bit 11 in data registers + sw_w32((u32)(portmask >> 32), rtl_table_data(q, 0)); + sw_w32((u32)((portmask & 0xfffff800)), rtl_table_data(q, 1)); + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static void rtl839x_vlan_profile_setup(int profile) +{ + u32 p[2]; + u32 pmask_id = UNKNOWN_MC_PMASK; + + p[0] = pmask_id; // Use portmaks 0xfff for unknown IPv6 MC flooding + // Enable L2 Learning BIT 0, portmask UNKNOWN_MC_PMASK for IP/L2-MC traffic flooding + p[1] = 1 | pmask_id << 1 | pmask_id << 13; + + sw_w32(p[0], RTL839X_VLAN_PROFILE(profile)); + sw_w32(p[1], RTL839X_VLAN_PROFILE(profile) + 4); + + rtl839x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0x000fffffffffffff); } static inline int rtl839x_vlan_port_egr_filter(int port) @@ -477,20 +518,21 @@ u32 rtl839x_hash(struct rtl838x_switch_priv *priv, u64 seed) return h; } -void rtl839x_vlan_profile_dump(int index) +void rtl839x_vlan_profile_dump(int profile) { - u32 profile, profile1; + u32 p[2]; - if (index < 0 || index > 7) + if (profile < 0 || profile > 7) return; - profile1 = sw_r32(RTL839X_VLAN_PROFILE(index) + 4); - profile = sw_r32(RTL839X_VLAN_PROFILE(index)); + p[0] = sw_r32(RTL839X_VLAN_PROFILE(profile)); + p[1] = sw_r32(RTL839X_VLAN_PROFILE(profile) + 4); - pr_debug("VLAN %d: L2 learning: %d, L2 Unknown MultiCast Field %x, \ - IPv4 Unknown MultiCast Field %x, IPv6 Unknown MultiCast Field: %x", - index, profile & 1, (profile >> 1) & 0xfff, (profile >> 13) & 0xfff, - (profile1) & 0xfff); + pr_info("VLAN profile %d: L2 learning: %d, UNKN L2MC FLD PMSK %d, \ + UNKN IPMC FLD PMSK %d, UNKN IPv6MC FLD PMSK: %d", + profile, p[1] & 1, (p[1] >> 1) & 0xfff, (p[1] >> 13) & 0xfff, + (p[0]) & 0xfff); + pr_info("VLAN profile %d: raw %08x, %08x\n", profile, p[0], p[1]); } static void rtl839x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) @@ -626,6 +668,7 @@ const struct rtl838x_reg rtl839x_reg = { .vlan_set_tagged = rtl839x_vlan_set_tagged, .vlan_set_untagged = rtl839x_vlan_set_untagged, .vlan_profile_dump = rtl839x_vlan_profile_dump, + .vlan_profile_setup = rtl839x_vlan_profile_setup, .stp_get = rtl839x_stp_get, .stp_set = rtl839x_stp_set, .mac_force_mode_ctrl = rtl839x_mac_force_mode_ctrl, @@ -652,4 +695,6 @@ const struct rtl838x_reg rtl839x_reg = { .init_eee = rtl839x_init_eee, .port_eee_set = rtl839x_port_eee_set, .eee_port_ability = rtl839x_eee_port_ability, + .read_mcast_pmask = rtl839x_read_mcast_pmask, + .write_mcast_pmask = rtl839x_write_mcast_pmask, }; diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl930x.c index 4214c7694d..a6e5cb763f 100644 --- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl930x.c @@ -54,7 +54,7 @@ inline static int rtl930x_trk_mbr_ctr(int group) static void rtl930x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) { u32 v, w; - // Read VLAN table (0) via register 0 + // Read VLAN table (1) via register 0 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 1); rtl_table_read(r, vlan); @@ -99,22 +99,28 @@ static void rtl930x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) rtl_table_release(r); } -void rtl930x_vlan_profile_dump(int index) +void rtl930x_vlan_profile_dump(int profile) { - u32 profile[5]; + u32 p[5]; - if (index < 0 || index > 7) + if (profile < 0 || profile > 7) return; - profile[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(index)); - profile[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(index) + 4); - profile[2] = sw_r32(RTL930X_VLAN_PROFILE_SET(index) + 8) & 0x1FFFFFFF; - profile[3] = sw_r32(RTL930X_VLAN_PROFILE_SET(index) + 12) & 0x1FFFFFFF; - profile[4] = sw_r32(RTL930X_VLAN_PROFILE_SET(index) + 16) & 0x1FFFFFFF; + p[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile)); + p[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 4); + p[2] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 8) & 0x1FFFFFFF; + p[3] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 12) & 0x1FFFFFFF; + p[4] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 16) & 0x1FFFFFFF; - pr_debug("VLAN %d: L2 learning: %d, L2 Unknown MultiCast Field %x, \ - IPv4 Unknown MultiCast Field %x, IPv6 Unknown MultiCast Field: %x", - index, profile[0] & (3 << 21), profile[2], profile[3], profile[4]); + pr_info("VLAN %d: L2 learn: %d; Unknown MC PMasks: L2 %0x, IPv4 %0x, IPv6: %0x", + profile, p[0] & (3 << 21), p[2], p[3], p[4]); + pr_info(" Routing enabled: IPv4 UC %c, IPv6 UC %c, IPv4 MC %c, IPv6 MC %c\n", + p[0] & BIT(17) ? 'y' : 'n', p[0] & BIT(16) ? 'y' : 'n', + p[0] & BIT(13) ? 'y' : 'n', p[0] & BIT(12) ? 'y' : 'n'); + pr_info(" Bridge enabled: IPv4 MC %c, IPv6 MC %c,\n", + p[0] & BIT(15) ? 'y' : 'n', p[0] & BIT(14) ? 'y' : 'n'); + pr_info("VLAN profile %d: raw %08x %08x %08x %08x %08x\n", + profile, p[0], p[1], p[2], p[3], p[4]); } static void rtl930x_vlan_set_untagged(u32 vlan, u64 portmask) @@ -126,6 +132,28 @@ static void rtl930x_vlan_set_untagged(u32 vlan, u64 portmask) rtl_table_release(r); } +static void rtl930x_vlan_profile_setup(int profile) +{ + u32 p[5]; + + pr_info("In %s\n", __func__); + p[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile)); + p[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 4); + + // Enable routing of Ipv4/6 Unicast and IPv4/6 Multicast traffic + p[0] |= BIT(17) | BIT(16) | BIT(13) | BIT(12); + p[2] = 0x0fffffff; // L2 unknwon MC flooding portmask: all but the CPU-port + p[3] = 0x0fffffff; // IPv4 unknwon MC flooding portmask + p[4] = 0x0fffffff; // IPv6 unknwon MC flooding portmask + + sw_w32(p[0], RTL930X_VLAN_PROFILE_SET(profile)); + sw_w32(p[1], RTL930X_VLAN_PROFILE_SET(profile) + 4); + 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_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) { int i; @@ -256,6 +284,35 @@ static u64 rtl930x_read_cam(int idx, struct rtl838x_l2_entry *e) return entry; } +static u64 rtl930x_read_mcast_pmask(int idx) +{ + u32 portmask; + // Read MC_PORTMASK (2) via register RTL9300_TBL_L2 + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 2); + + rtl_table_read(q, idx); + portmask = sw_r32(rtl_table_data(q, 0)); + portmask >>= 3; + rtl_table_release(q); + + pr_debug("%s: Index idx %d has portmask %08x\n", __func__, idx, portmask); + return portmask; +} + +static void rtl930x_write_mcast_pmask(int idx, u64 portmask) +{ + u32 pm = portmask; + + // Access MC_PORTMASK (2) via register RTL9300_TBL_L2 + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 2); + + pr_debug("%s: Index idx %d has portmask %08x\n", __func__, idx, pm); + pm <<= 3; + sw_w32(pm, rtl_table_data(q, 0)); + rtl_table_write(q, idx); + rtl_table_release(q); +} + u64 rtl930x_traffic_get(int source) { u32 v; @@ -669,6 +726,7 @@ const struct rtl838x_reg rtl930x_reg = { .vlan_set_tagged = rtl930x_vlan_set_tagged, .vlan_set_untagged = rtl930x_vlan_set_untagged, .vlan_profile_dump = rtl930x_vlan_profile_dump, + .vlan_profile_setup = rtl930x_vlan_profile_setup, .stp_get = rtl930x_stp_get, .stp_set = rtl930x_stp_set, .mac_force_mode_ctrl = rtl930x_mac_force_mode_ctrl, @@ -694,4 +752,6 @@ const struct rtl838x_reg rtl930x_reg = { .init_eee = rtl930x_init_eee, .port_eee_set = rtl930x_port_eee_set, .eee_port_ability = rtl930x_eee_port_ability, + .read_mcast_pmask = rtl930x_read_mcast_pmask, + .write_mcast_pmask = rtl930x_write_mcast_pmask, }; |