OSDN Git Service

net: systemport: Add support for VLAN transmit acceleration
authorFlorian Fainelli <f.fainelli@gmail.com>
Mon, 6 Jul 2020 21:29:39 +0000 (14:29 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Jul 2020 19:39:53 +0000 (12:39 -0700)
SYSTEMPORT is capable of performing VLAN transmit acceleration, support
that by configuring it appropriately, providing the VLAN ID and PCP/DEI
where necessary.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bcmsysport.c

index b25356e..b470551 100644 (file)
@@ -160,13 +160,26 @@ static void bcm_sysport_set_tx_csum(struct net_device *dev,
        /* Hardware transmit checksum requires us to enable the Transmit status
         * block prepended to the packet contents
         */
-       priv->tsb_en = !!(wanted & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM));
+       priv->tsb_en = !!(wanted & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                                   NETIF_F_HW_VLAN_CTAG_TX));
        reg = tdma_readl(priv, TDMA_CONTROL);
        if (priv->tsb_en)
                reg |= tdma_control_bit(priv, TSB_EN);
        else
                reg &= ~tdma_control_bit(priv, TSB_EN);
+       /* Indicating that software inserts Broadcom tags is needed for the TX
+        * checksum to be computed correctly when using VLAN HW acceleration,
+        * else it has no effect, so it can always be turned on.
+        */
+       if (netdev_uses_dsa(dev))
+               reg |= tdma_control_bit(priv, SW_BRCM_TAG);
+       else
+               reg &= ~tdma_control_bit(priv, SW_BRCM_TAG);
        tdma_writel(priv, reg, TDMA_CONTROL);
+
+       /* Default TPID is ETH_P_8021AD, change to ETH_P_8021Q */
+       if (wanted & NETIF_F_HW_VLAN_CTAG_TX)
+               tdma_writel(priv, ETH_P_8021Q, TDMA_TPID);
 }
 
 static int bcm_sysport_set_features(struct net_device *dev,
@@ -1236,6 +1249,12 @@ static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
        /* Zero-out TSB by default */
        memset(tsb, 0, sizeof(*tsb));
 
+       if (skb_vlan_tag_present(skb)) {
+               tsb->pcp_dei_vid = (skb_vlan_tag_get_prio(skb) >>
+                                   VLAN_PRIO_SHIFT & PCP_DEI_MASK);
+               tsb->pcp_dei_vid |= (u32)skb_vlan_tag_get_id(skb) << VID_SHIFT;
+       }
+
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                ip_ver = skb->protocol;
                switch (ip_ver) {
@@ -1251,6 +1270,9 @@ static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
 
                /* Get the checksum offset and the L4 (transport) offset */
                csum_start = skb_checksum_start_offset(skb) - sizeof(*tsb);
+               /* Account for the HW inserted VLAN tag */
+               if (skb_vlan_tag_present(skb))
+                       csum_start += VLAN_HLEN;
                csum_info = (csum_start + skb->csum_offset) & L4_CSUM_PTR_MASK;
                csum_info |= (csum_start << L4_PTR_SHIFT);
 
@@ -1330,6 +1352,8 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
                       DESC_STATUS_SHIFT;
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                len_status |= (DESC_L4_CSUM << DESC_STATUS_SHIFT);
+       if (skb_vlan_tag_present(skb))
+               len_status |= (TX_STATUS_VLAN_VID_TSB << DESC_STATUS_SHIFT);
 
        ring->curr_desc++;
        if (ring->curr_desc == ring->size)
@@ -1503,7 +1527,13 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
                reg |= RING_IGNORE_STATUS;
        }
        tdma_writel(priv, reg, TDMA_DESC_RING_MAPPING(index));
-       tdma_writel(priv, 0, TDMA_DESC_RING_PCP_DEI_VID(index));
+       reg = 0;
+       /* Adjust the packet size calculations if SYSTEMPORT is responsible
+        * for HW insertion of VLAN tags
+        */
+       if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)
+               reg = VLAN_HLEN << RING_PKT_SIZE_ADJ_SHIFT;
+       tdma_writel(priv, reg, TDMA_DESC_RING_PCP_DEI_VID(index));
 
        /* Enable ACB algorithm 2 */
        reg = tdma_readl(priv, TDMA_CONTROL);
@@ -2523,7 +2553,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
        netif_napi_add(dev, &priv->napi, bcm_sysport_poll, 64);
 
        dev->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_VLAN_CTAG_TX;
        dev->hw_features |= dev->features;
        dev->vlan_features |= dev->features;