aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bcmsysport.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-05-14 22:32:14 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-15 16:48:38 -0400
commitdab531b4305bc2852ce6f934dc283464d46871a5 (patch)
tree9fccae4546ce7df0646a101c2eda002152ffe229 /drivers/net/ethernet/broadcom/bcmsysport.c
parentd5e32cc7c997d1d4f18031f5ff88512bd65118f7 (diff)
net: systemport: pad packets to a minimum of 68 bytes
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>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bcmsysport.c')
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 39503647d8bb..8edc0980cdf5 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -821,6 +821,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
821 struct bcm_sysport_cb *cb; 821 struct bcm_sysport_cb *cb;
822 struct netdev_queue *txq; 822 struct netdev_queue *txq;
823 struct dma_desc *desc; 823 struct dma_desc *desc;
824 unsigned int skb_len;
824 dma_addr_t mapping; 825 dma_addr_t mapping;
825 u32 len_status; 826 u32 len_status;
826 u16 queue; 827 u16 queue;
@@ -848,10 +849,25 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
848 } 849 }
849 } 850 }
850 851
851 mapping = dma_map_single(kdev, skb->data, skb->len, DMA_TO_DEVICE); 852 /* The Ethernet switch we are interfaced with needs packets to be at
853 * least 64 bytes (including FCS) otherwise they will be discarded when
854 * they enter the switch port logic. When Broadcom tags are enabled, we
855 * need to make sure that packets are at least 68 bytes
856 * (including FCS and tag) because the length verification is done after
857 * the Broadcom tag is stripped off the ingress packet.
858 */
859 if (skb_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) {
860 ret = NETDEV_TX_OK;
861 goto out;
862 }
863
864 skb_len = skb->len < ETH_ZLEN + ENET_BRCM_TAG_LEN ?
865 ETH_ZLEN + ENET_BRCM_TAG_LEN : skb->len;
866
867 mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE);
852 if (dma_mapping_error(kdev, mapping)) { 868 if (dma_mapping_error(kdev, mapping)) {
853 netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n", 869 netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n",
854 skb->data, skb->len); 870 skb->data, skb_len);
855 ret = NETDEV_TX_OK; 871 ret = NETDEV_TX_OK;
856 goto out; 872 goto out;
857 } 873 }
@@ -860,14 +876,14 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
860 cb = &ring->cbs[ring->curr_desc]; 876 cb = &ring->cbs[ring->curr_desc];
861 cb->skb = skb; 877 cb->skb = skb;
862 dma_unmap_addr_set(cb, dma_addr, mapping); 878 dma_unmap_addr_set(cb, dma_addr, mapping);
863 dma_unmap_len_set(cb, dma_len, skb->len); 879 dma_unmap_len_set(cb, dma_len, skb_len);
864 880
865 /* Fetch a descriptor entry from our pool */ 881 /* Fetch a descriptor entry from our pool */
866 desc = ring->desc_cpu; 882 desc = ring->desc_cpu;
867 883
868 desc->addr_lo = lower_32_bits(mapping); 884 desc->addr_lo = lower_32_bits(mapping);
869 len_status = upper_32_bits(mapping) & DESC_ADDR_HI_MASK; 885 len_status = upper_32_bits(mapping) & DESC_ADDR_HI_MASK;
870 len_status |= (skb->len << DESC_LEN_SHIFT); 886 len_status |= (skb_len << DESC_LEN_SHIFT);
871 len_status |= (DESC_SOP | DESC_EOP | TX_STATUS_APP_CRC) << 887 len_status |= (DESC_SOP | DESC_EOP | TX_STATUS_APP_CRC) <<
872 DESC_STATUS_SHIFT; 888 DESC_STATUS_SHIFT;
873 if (skb->ip_summed == CHECKSUM_PARTIAL) 889 if (skb->ip_summed == CHECKSUM_PARTIAL)