Now that we have all the necessary plumbing in place to get notified when a multicast MAC address must be programmed, configure the switch to oeprate in managed mode and let the network stack learn about management traffic.
Signed-off-by: Florian Fainelli <f.faine...@gmail.com> --- drivers/net/dsa/b53/b53_common.c | 39 ++++++++++++++++++++-- drivers/net/dsa/b53/b53_priv.h | 1 + drivers/net/dsa/bcm_sf2.c | 56 +++++++++++++++++++++++--------- drivers/net/dsa/bcm_sf2_regs.h | 5 +++ 4 files changed, 84 insertions(+), 17 deletions(-) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index c0c064a544b9..10e115a43975 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -364,8 +364,6 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable, b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, &vc5); } - mgmt &= ~SM_SW_FWD_MODE; - if (enable) { vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID; vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN; @@ -490,6 +488,43 @@ static int b53_fast_age_vlan(struct b53_device *dev, u16 vid) return b53_flush_arl(dev, FAST_AGE_VLAN); } +void b53_port_learn_setup(struct dsa_switch *ds, int port) +{ + struct b53_device *dev = ds->priv; + u16 reg; + + /* Enable learning */ + b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARN, ®); + reg &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_DIS_LEARN, reg); + + /* Software learning control disabled */ + b53_read16(dev, B53_CTRL_PAGE, B53_SFT_LRN_CTRL, ®); + reg &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_SFT_LRN_CTRL, reg); + + /* Configure IP multicast, allow Unicast ARL misses to be forwarded */ + b53_read16(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, ®); + reg |= B53_IPMC_FWD_EN | B53_UC_FWD_EN; + b53_write16(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, reg); + + /* Set port in Unicast lookup forward map */ + b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, ®); + reg |= BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, reg); + + /* Do not set port in Multicast lookup forward map, learn */ + b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, ®); + reg &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, reg); + + /* Do not set port in IP multicast lookup formward map, learn */ + b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, ®); + reg &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, reg); +} +EXPORT_SYMBOL(b53_port_learn_setup); + void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port) { struct b53_device *dev = ds->priv; diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index cd259fb8b00e..1806304c38cc 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -309,6 +309,7 @@ static inline int b53_switch_get_reset_gpio(struct b53_device *dev) #endif /* Exported functions towards other drivers */ +void b53_port_learn_setup(struct dsa_switch *ds, int port); void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port); int b53_configure_vlan(struct dsa_switch *ds); void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset, diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 361fbde76654..c9e6ffb737a4 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -51,19 +51,19 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) reg &= ~P_TXQ_PSM_VDD(port); core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL); - /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */ - reg = core_readl(priv, CORE_IMP_CTL); - reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN); - reg &= ~(RX_DIS | TX_DIS); - core_writel(priv, reg, CORE_IMP_CTL); + /* Enable forwarding and managed mode */ + core_writel(priv, SW_FWDG_EN | SW_FWDG_MODE, CORE_SWMODE); - /* Enable forwarding */ - core_writel(priv, SW_FWDG_EN, CORE_SWMODE); + /* Configure port for learning */ + b53_port_learn_setup(ds, port); - /* Enable IMP port in dumb mode */ - reg = core_readl(priv, CORE_SWITCH_CTRL); - reg |= MII_DUMB_FWDG_EN; - core_writel(priv, reg, CORE_SWITCH_CTRL); + /* Enable IGMP and MLD high-level protocol snooping support */ + reg = HL_PRTC_IGMP_RPTLVE_EN | HL_PRTC_IGMP_RPTVLE_FWD_MODE | + HL_PRTC_IGMP_QRY_EN | HL_PRTC_IGMP_QRY_FWD_MODE | + HL_PRTC_IGMP_UKN_EN | HL_PRTC_IGMP_UKN_FWD_MODE | + HL_PRTC_MLD_RPTDONE_EN | HL_PRTC_MLD_RPTDONE_FWD_MODE | + HL_PRTC_MLD_QRY_EN | HL_PRTC_MLD_QRY_FWD_MODE; + b53_write32(priv->dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, reg); /* Configure Traffic Class to QoS mapping, allow each priority to map * to a different queue number @@ -75,10 +75,26 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) b53_brcm_hdr_setup(ds, port); + /* Set IMP0 or IMP1 port to be managed port, enable BPDU */ + reg = core_readl(priv, CORE_GMNCFGCFG); + reg &= ~(FRM_MGNP_MASK << FRM_MGNP_SHIFT); + if (port == core_readl(priv, CORE_IMP0_PRT_ID)) + reg |= FRM_MNGP_IMP0 << FRM_MGNP_SHIFT; + if (port == core_readl(priv, CORE_IMP1_PRT_ID)) + reg |= FRM_MGNP_IMP_DUAL << FRM_MGNP_SHIFT; + reg |= RXBPDU_EN; + core_writel(priv, reg, CORE_GMNCFGCFG); + /* Force link status for IMP port */ reg = core_readl(priv, offset); reg |= (MII_SW_OR | LINK_STS); core_writel(priv, reg, offset); + + /* Enable Broadcast, Unicast forwarding to IMP port */ + reg = core_readl(priv, CORE_IMP_CTL); + reg |= (RX_BCST_EN | RX_UCST_EN); + reg &= ~(RX_DIS | TX_DIS); + core_writel(priv, reg, CORE_IMP_CTL); } static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable) @@ -166,10 +182,8 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, reg &= ~P_TXQ_PSM_VDD(port); core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL); - /* Enable learning */ - reg = core_readl(priv, CORE_DIS_LEARN); - reg &= ~BIT(port); - core_writel(priv, reg, CORE_DIS_LEARN); + /* Configure port for learning */ + b53_port_learn_setup(ds, port); /* Enable Broadcom tags for that port if requested */ if (priv->brcm_tag_mask & BIT(port)) @@ -683,6 +697,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) { struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); unsigned int port; + u32 reg; bcm_sf2_intr_disable(priv); @@ -695,6 +710,13 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) bcm_sf2_port_disable(ds, port, NULL); } + /* Disable management mode since we won't be able to + * perform any tasks while being suspended. + */ + reg = core_readl(priv, CORE_SWMODE); + reg &= ~SW_FWDG_MODE; + core_writel(priv, reg, CORE_SWMODE); + return 0; } @@ -930,6 +952,10 @@ static const struct dsa_switch_ops bcm_sf2_ops = { .set_rxnfc = bcm_sf2_set_rxnfc, .port_mirror_add = b53_mirror_add, .port_mirror_del = b53_mirror_del, + .port_multicast_toggle = b53_multicast_toggle, + .port_mdb_prepare = b53_mdb_prepare, + .port_mdb_add = b53_mdb_add, + .port_mdb_del = b53_mdb_del, }; struct bcm_sf2_of_data { diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h index 0a1e530d52b7..211db9a2e9e9 100644 --- a/drivers/net/dsa/bcm_sf2_regs.h +++ b/drivers/net/dsa/bcm_sf2_regs.h @@ -222,8 +222,13 @@ enum bcm_sf2_reg_offs { #define CORE_GMNCFGCFG 0x0800 #define RST_MIB_CNT (1 << 0) #define RXBPDU_EN (1 << 1) +#define FRM_MGNP_SHIFT 6 +#define FRM_MGNP_MASK 0x3 +#define FRM_MNGP_IMP0 2 +#define FRM_MGNP_IMP_DUAL 3 #define CORE_IMP0_PRT_ID 0x0804 +#define CORE_IMP1_PRT_ID 0x0808 #define CORE_RST_MIB_CNT_EN 0x0950 -- 2.17.1