The Broadcom SYSTEMPORT Ethernet controller is capable of extracting a switch tag (4-bytes Broadcom tag) and put it in the second 32-bits word of its pre-pended Receive Status Block. When this feature is requested, make sure that we can satisfy it by turning on receive checksum offload, and copy the 32-bits words with the tag into skb->cb[] using the appropriate helper function: dsa_copy_brcm_tag().
Signed-off-by: Florian Fainelli <f.faine...@gmail.com> --- drivers/net/ethernet/broadcom/bcmsysport.c | 40 +++++++++++++++++++++++++++++- drivers/net/ethernet/broadcom/bcmsysport.h | 1 + 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 4566cdf0bc39..a3db2d9f1c36 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -173,6 +173,23 @@ static int bcm_sysport_set_tx_csum(struct net_device *dev, return 0; } +static int bcm_sysport_set_rx_sw_tag(struct net_device *dev, + netdev_features_t wanted) +{ + struct bcm_sysport_priv *priv = netdev_priv(dev); + u32 reg; + + priv->rx_tag_extract = !!(wanted & NETIF_F_HW_SWITCH_TAG_RX); + reg = rbuf_readl(priv, RBUF_CONTROL); + if (priv->rx_tag_extract) + reg |= RBUF_BRCM_TAG_STRIP; + else + reg &= ~RBUF_BRCM_TAG_STRIP; + rbuf_writel(priv, reg, RBUF_CONTROL); + + return 0; +} + static int bcm_sysport_set_features(struct net_device *dev, netdev_features_t features) { @@ -184,10 +201,25 @@ static int bcm_sysport_set_features(struct net_device *dev, ret = bcm_sysport_set_rx_csum(dev, wanted); if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) ret = bcm_sysport_set_tx_csum(dev, wanted); + if (changed & NETIF_F_HW_SWITCH_TAG_RX) + ret = bcm_sysport_set_rx_sw_tag(dev, wanted); return ret; } +static netdev_features_t bcm_sysport_fix_features(struct net_device *dev, + netdev_features_t features) +{ + /* In order for the switch tag extraction to work, we need to turn on + * the RXCHK block and enable receive checksum offload, do this here to + * satisfy the feature request. + */ + if (features & NETIF_F_HW_SWITCH_TAG_RX) + features |= NETIF_F_RXCSUM; + + return features; +} + /* Hardware counters must be kept in sync because the order/offset * is important here (order in structure declaration = order in hardware) */ @@ -670,6 +702,10 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, if (likely(status & DESC_L4_CSUM)) skb->ip_summed = CHECKSUM_UNNECESSARY; + /* Extract the switch egress tag */ + if (likely(priv->rx_tag_extract)) + dsa_copy_brcm_tag(skb, &rsb->brcm_egress_tag); + /* Hardware pre-pends packets with 2bytes before Ethernet * header plus we have the Receive Status Block, strip off all * of this from the SKB. @@ -1721,6 +1757,7 @@ static const struct net_device_ops bcm_sysport_netdev_ops = { .ndo_open = bcm_sysport_open, .ndo_stop = bcm_sysport_stop, .ndo_set_features = bcm_sysport_set_features, + .ndo_fix_features = bcm_sysport_fix_features, .ndo_set_rx_mode = bcm_sysport_set_rx_mode, .ndo_set_mac_address = bcm_sysport_change_mac, }; @@ -1806,7 +1843,8 @@ static int bcm_sysport_probe(struct platform_device *pdev) /* HW supported features, none enabled by default */ dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_HW_SWITCH_TAG_RX; /* Request the WOL interrupt and advertise suspend if available */ priv->wol_irq_disabled = 1; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index f28bf545d7f4..6d925401d706 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h @@ -680,6 +680,7 @@ struct bcm_sysport_priv { unsigned int rx_chk_en:1; unsigned int tsb_en:1; unsigned int crc_fwd:1; + unsigned int rx_tag_extract:1; u16 rev; u32 wolopts; unsigned int wol_irq_disabled:1; -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html