diff --git a/drivers/net/dsa/b53/Kconfig b/drivers/net/dsa/b53/Kconfig index 27f32a50df5783652ee3273d26897d0913ff0536..b413d100c6b311642c47412939cc2464a95e480f 100644 --- a/drivers/net/dsa/b53/Kconfig +++ b/drivers/net/dsa/b53/Kconfig @@ -1,6 +1,7 @@ menuconfig B53 tristate "Broadcom BCM53xx managed switch support" depends on NET_DSA + select NET_DSA_TAG_BRCM help This driver adds support for Broadcom managed switch chips. It supports BCM5325E, BCM5365, BCM539x, BCM53115 and BCM53125 as well as BCM63XX diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index a7ca62ba27b71060cfa1f0d48151f1753f5dd0de..44a9a03bff550ea9fdcaf9ed998daa7eb39f400b 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -325,7 +325,6 @@ static void b53_get_vlan_entry(struct b53_device *dev, u16 vid, static void b53_set_forwarding(struct b53_device *dev, int enable) { - struct dsa_switch *ds = dev->ds; u8 mgmt; b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); @@ -337,14 +336,11 @@ static void b53_set_forwarding(struct b53_device *dev, int enable) b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); - /* Include IMP port in dumb forwarding mode when no tagging protocol is - * set + /* Include IMP port in dumb forwarding mode */ - if (ds->ops->get_tag_protocol(ds) == DSA_TAG_PROTO_NONE) { - b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt); - mgmt |= B53_MII_DUMB_FWDG_EN; - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); - } + b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt); + mgmt |= B53_MII_DUMB_FWDG_EN; + b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); } static void b53_enable_vlan(struct b53_device *dev, bool enable) @@ -505,7 +501,7 @@ EXPORT_SYMBOL(b53_imp_vlan_setup); int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) { struct b53_device *dev = ds->priv; - unsigned int cpu_port = dev->cpu_port; + unsigned int cpu_port = ds->ports[port].cpu_dp->index; u16 pvlan; /* Clear the Rx and Tx disable bits and set to no spanning tree */ @@ -612,6 +608,8 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port) PORT_CTRL_RX_MCST_EN | PORT_CTRL_RX_UCST_EN; b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl); + + b53_brcm_hdr_setup(dev->ds, port); } static void b53_enable_mib(struct b53_device *dev) @@ -1054,7 +1052,6 @@ void b53_vlan_add(struct dsa_switch *ds, int port, struct b53_device *dev = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; - unsigned int cpu_port = dev->cpu_port; struct b53_vlan *vl; u16 vid; @@ -1063,12 +1060,11 @@ void b53_vlan_add(struct dsa_switch *ds, int port, b53_get_vlan_entry(dev, vid, vl); - vl->members |= BIT(port) | BIT(cpu_port); + vl->members |= BIT(port); if (untagged) vl->untag |= BIT(port); else vl->untag &= ~BIT(port); - vl->untag &= ~BIT(cpu_port); b53_set_vlan_entry(dev, vid, vl); b53_fast_age_vlan(dev, vid); @@ -1432,8 +1428,8 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br) b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg); } else { b53_get_vlan_entry(dev, pvid, vl); - vl->members |= BIT(port) | BIT(dev->cpu_port); - vl->untag |= BIT(port) | BIT(dev->cpu_port); + vl->members |= BIT(port) | BIT(cpu_port); + vl->untag |= BIT(port) | BIT(cpu_port); b53_set_vlan_entry(dev, pvid, vl); } } @@ -1482,9 +1478,41 @@ void b53_br_fast_age(struct dsa_switch *ds, int port) } EXPORT_SYMBOL(b53_br_fast_age); +static bool b53_can_enable_brcm_tags(struct dsa_switch *ds) +{ + unsigned int brcm_tag_mask; + unsigned int i; + + /* Broadcom switches will accept enabling Broadcom tags on the + * following ports: 5, 7 and 8, any other port is not supported + */ + brcm_tag_mask = BIT(B53_CPU_PORT_25) | BIT(7) | BIT(B53_CPU_PORT); + + for (i = 0; i < ds->num_ports; i++) { + if (dsa_is_cpu_port(ds, i)) { + if (!(BIT(i) & brcm_tag_mask)) { + dev_warn(ds->dev, + "Port %d is not Broadcom tag capable\n", + i); + return false; + } + } + } + + return true; +} + static enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds) { - return DSA_TAG_PROTO_NONE; + struct b53_device *dev = ds->priv; + + /* Older models support a different tag format that we do not + * support in net/dsa/tag_brcm.c yet. + */ + if (is5325(dev) || is5365(dev) || !b53_can_enable_brcm_tags(ds)) + return DSA_TAG_PROTO_NONE; + else + return DSA_TAG_PROTO_BRCM; } int b53_mirror_add(struct dsa_switch *ds, int port, diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 48d672b204a4847bc113635ed9534d8a3fd53066..1d96cd594adea6ca63ee71c6e521224fcec2cdde 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "bgmac.h" static bool bgmac_wait_value(struct bgmac *bgmac, u16 reg, u32 mask, @@ -127,6 +128,8 @@ bgmac_dma_tx_add_buf(struct bgmac *bgmac, struct bgmac_dma_ring *ring, dma_desc->ctl1 = cpu_to_le32(ctl1); } +#define ENET_BRCM_TAG_LEN 4 + static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac, struct bgmac_dma_ring *ring, struct sk_buff *skb) @@ -139,6 +142,18 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac, u32 flags; int i; + /* The Ethernet switch we are interfaced with needs packets to be at + * least 64 bytes (including FCS) otherwise they will be discarded when + * they enter the switch port logic. When Broadcom tags are enabled, we + * need to make sure that packets are at least 68 bytes + * (including FCS and tag) because the length verification is done after + * the Broadcom tag is stripped off the ingress packet. + */ + if (netdev_uses_dsa(net_dev)) { + if (skb_put_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) + goto err_stats; + } + if (skb->len > BGMAC_DESC_CTL1_LEN) { netdev_err(bgmac->net_dev, "Too long skb (%d)\n", skb->len); goto err_drop; @@ -225,6 +240,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac, err_drop: dev_kfree_skb(skb); +err_stats: net_dev->stats.tx_dropped++; net_dev->stats.tx_errors++; return NETDEV_TX_OK;