diff options
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/faraday/ftgmac100.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 41e8467f272a..8447987577bd 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -350,7 +350,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) struct ftgmac100_rxdes *rxdes; struct sk_buff *skb; unsigned int pointer, size; - u32 status; + u32 status, csum_vlan; dma_addr_t map; /* Grab next RX descriptor */ @@ -372,10 +372,27 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) !(status & FTGMAC100_RXDES0_LRS))) goto drop; + /* Grab received size and csum vlan field in the descriptor */ + size = status & FTGMAC100_RXDES0_VDBC; + csum_vlan = le32_to_cpu(rxdes->rxdes1); + /* Any error (other than csum offload) flagged ? */ if (unlikely(status & RXDES0_ANY_ERROR)) { - ftgmac100_rx_packet_error(priv, status); - goto drop; + /* Correct for incorrect flagging of runt packets + * with vlan tags... Just accept a runt packet that + * has been flagged as vlan and whose size is at + * least 60 bytes. + */ + if ((status & FTGMAC100_RXDES0_RUNT) && + (csum_vlan & FTGMAC100_RXDES1_VLANTAG_AVAIL) && + (size >= 60)) + status &= ~FTGMAC100_RXDES0_RUNT; + + /* Any error still in there ? */ + if (status & RXDES0_ANY_ERROR) { + ftgmac100_rx_packet_error(priv, status); + goto drop; + } } /* If the packet had no skb (failed to allocate earlier) @@ -397,19 +414,17 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) * we accept the HW test results. */ if (netdev->features & NETIF_F_RXCSUM) { - __le32 csum_vlan = rxdes->rxdes1; - __le32 err_bits = cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR | - FTGMAC100_RXDES1_UDP_CHKSUM_ERR | - FTGMAC100_RXDES1_IP_CHKSUM_ERR); + u32 err_bits = FTGMAC100_RXDES1_TCP_CHKSUM_ERR | + FTGMAC100_RXDES1_UDP_CHKSUM_ERR | + FTGMAC100_RXDES1_IP_CHKSUM_ERR; if ((csum_vlan & err_bits) || - !(csum_vlan & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK))) + !(csum_vlan & FTGMAC100_RXDES1_PROT_MASK)) skb->ip_summed = CHECKSUM_NONE; else skb->ip_summed = CHECKSUM_UNNECESSARY; } - /* Grab received size annd transfer to skb */ - size = status & FTGMAC100_RXDES0_VDBC; + /* Transfer received size to skb */ skb_put(skb, size); /* Tear down DMA mapping, do necessary cache management */ |