Commit d930655d authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by David S. Miller

ftgmac100: Work around HW bug in runt frame detection

The HW incorrectly calculates the frame size without the vlan
tag and compares that against 64. It will thus flag 64-bytes
frames with a vlan tag as 60-bytes frames "runt" packets
which we'll then drop. Thus we end up dropping ARP packets
on vlan's ...

It does that whether vlan tag stripping is enabled or not.

This works around it by ignoring the "runt" error bit of the
frame has been vlan tagged and is at least 60 bytes.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4ca24152
...@@ -350,7 +350,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) ...@@ -350,7 +350,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
struct ftgmac100_rxdes *rxdes; struct ftgmac100_rxdes *rxdes;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int pointer, size; unsigned int pointer, size;
u32 status; u32 status, csum_vlan;
dma_addr_t map; dma_addr_t map;
/* Grab next RX descriptor */ /* Grab next RX descriptor */
...@@ -372,11 +372,28 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) ...@@ -372,11 +372,28 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
!(status & FTGMAC100_RXDES0_LRS))) !(status & FTGMAC100_RXDES0_LRS)))
goto drop; 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 ? */ /* Any error (other than csum offload) flagged ? */
if (unlikely(status & RXDES0_ANY_ERROR)) { if (unlikely(status & RXDES0_ANY_ERROR)) {
/* 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); ftgmac100_rx_packet_error(priv, status);
goto drop; goto drop;
} }
}
/* If the packet had no skb (failed to allocate earlier) /* If the packet had no skb (failed to allocate earlier)
* then try to allocate one and skip * then try to allocate one and skip
...@@ -397,19 +414,17 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) ...@@ -397,19 +414,17 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
* we accept the HW test results. * we accept the HW test results.
*/ */
if (netdev->features & NETIF_F_RXCSUM) { if (netdev->features & NETIF_F_RXCSUM) {
__le32 csum_vlan = rxdes->rxdes1; u32 err_bits = FTGMAC100_RXDES1_TCP_CHKSUM_ERR |
__le32 err_bits = cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR |
FTGMAC100_RXDES1_UDP_CHKSUM_ERR | FTGMAC100_RXDES1_UDP_CHKSUM_ERR |
FTGMAC100_RXDES1_IP_CHKSUM_ERR); FTGMAC100_RXDES1_IP_CHKSUM_ERR;
if ((csum_vlan & err_bits) || 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; skb->ip_summed = CHECKSUM_NONE;
else else
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} }
/* Grab received size annd transfer to skb */ /* Transfer received size to skb */
size = status & FTGMAC100_RXDES0_VDBC;
skb_put(skb, size); skb_put(skb, size);
/* Tear down DMA mapping, do necessary cache management */ /* Tear down DMA mapping, do necessary cache management */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment