net: systemport: pad packets to a minimum of 68 bytes
authorFlorian Fainelli <f.fainelli@gmail.com>
Thu, 15 May 2014 02:32:14 +0000 (19:32 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 15 May 2014 20:48:38 +0000 (16:48 -0400)
Packets need to be at least 64 bytes to enter the switch port logic,
including the FCS, otherwise they will be discarded as RUNT packets.

With packets having Broadcom tags, the 4-bytes tag is first stripped
off the packet, and the packet length is then checked, so we need to
make sure that the packet length with FCS is at least 64 bytes.

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

index 39503647d8bb5a9df5a7e747783ab0590a301fb4..8edc0980cdf56634d2dc96d8af6e780720145694 100644 (file)
@@ -821,6 +821,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
        struct bcm_sysport_cb *cb;
        struct netdev_queue *txq;
        struct dma_desc *desc;
+       unsigned int skb_len;
        dma_addr_t mapping;
        u32 len_status;
        u16 queue;
@@ -848,10 +849,25 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
                }
        }
 
-       mapping = dma_map_single(kdev, skb->data, skb->len, DMA_TO_DEVICE);
+       /* 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 (skb_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) {
+               ret = NETDEV_TX_OK;
+               goto out;
+       }
+
+       skb_len = skb->len < ETH_ZLEN + ENET_BRCM_TAG_LEN ?
+                       ETH_ZLEN + ENET_BRCM_TAG_LEN : skb->len;
+
+       mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE);
        if (dma_mapping_error(kdev, mapping)) {
                netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n",
-                               skb->data, skb->len);
+                               skb->data, skb_len);
                ret = NETDEV_TX_OK;
                goto out;
        }
@@ -860,14 +876,14 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
        cb = &ring->cbs[ring->curr_desc];
        cb->skb = skb;
        dma_unmap_addr_set(cb, dma_addr, mapping);
-       dma_unmap_len_set(cb, dma_len, skb->len);
+       dma_unmap_len_set(cb, dma_len, skb_len);
 
        /* Fetch a descriptor entry from our pool */
        desc = ring->desc_cpu;
 
        desc->addr_lo = lower_32_bits(mapping);
        len_status = upper_32_bits(mapping) & DESC_ADDR_HI_MASK;
-       len_status |= (skb->len << DESC_LEN_SHIFT);
+       len_status |= (skb_len << DESC_LEN_SHIFT);
        len_status |= (DESC_SOP | DESC_EOP | TX_STATUS_APP_CRC) <<
                        DESC_STATUS_SHIFT;
        if (skb->ip_summed == CHECKSUM_PARTIAL)
index a0441e7c83cd8406e59d8cb3ad8fece9633b13c4..abdeb62616dff7c521f0fbad93d76c1a4efad40e 100644 (file)
 /* Default RX buffer allocation size */
 #define RX_BUF_LENGTH          2048
 
-/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
+/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(4) + FCS(4) = 1526.
  * 1536 is multiple of 256 bytes
  */
-#define ENET_BRCM_TAG_LEN      6
-#define ENET_PAD               8
+#define ENET_BRCM_TAG_LEN      4
+#define ENET_PAD               10
 #define UMAC_MAX_MTU_SIZE      (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
                                 ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)