diff options
author | Ian Abbott <abbotti@mev.co.uk> | 2019-02-01 12:59:48 +0000 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-02-05 12:44:39 +0100 |
commit | 90e9bfa36ea4deef2f1f322dc2503297420c2d20 (patch) | |
tree | 3290fb528480b8594b297c818994ac98699e02f8 /drivers/net | |
parent | 7172ee90b728375ee53f7a5186031ba3168ca0eb (diff) | |
download | barebox-90e9bfa36ea4deef2f1f322dc2503297420c2d20.tar.gz barebox-90e9bfa36ea4deef2f1f322dc2503297420c2d20.tar.xz |
net: designware: drop bad RX frames
In dwc_ether_rx(), check the RX descriptor status for various error
conditions. On error, issue a warning with the error status bits and
drop the received frame.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/designware.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ad70967e8c..21134cd5ab 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -326,24 +326,48 @@ static int dwc_ether_rx(struct eth_device *dev) u32 status = desc_p->txrx_status; int length = 0; + int ret = 0; /* Check if the owner is the CPU */ if (status & DESC_RXSTS_OWNBYDMA) return 0; - length = (status & DESC_RXSTS_FRMLENMSK) >> - DESC_RXSTS_FRMLENSHFT; + if ((status & (DESC_RXSTS_ERROR | DESC_RXSTS_DAFILTERFAIL | + DESC_RXSTS_SAFILTERFAIL)) || + (status & (DESC_RXSTS_RXIPC_GIANTFRAME | + DESC_RXSTS_RXFRAMEETHER)) == + DESC_RXSTS_RXIPC_GIANTFRAME) { + /* Error in packet - discard it */ + dev_warn(&dev->dev, "Rx error status (%x)\n", + status & (DESC_RXSTS_DAFILTERFAIL | + DESC_RXSTS_ERROR | + DESC_RXSTS_RXTRUNCATED | + DESC_RXSTS_SAFILTERFAIL | + DESC_RXSTS_RXIPC_GIANTFRAME | + DESC_RXSTS_RXDAMAGED | + DESC_RXSTS_RXIPC_GIANT | + DESC_RXSTS_RXCOLLISION | + DESC_RXSTS_RXFRAMEETHER | + DESC_RXSTS_RXWATCHDOG | + DESC_RXSTS_RXMIIERROR | + DESC_RXSTS_RXCRC)); + ret = -EIO; + } else { + length = (status & DESC_RXSTS_FRMLENMSK) >> + DESC_RXSTS_FRMLENSHFT; + + dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, + length, DMA_FROM_DEVICE); + net_receive(dev, desc_p->dmamac_addr, length); + dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr, + length, DMA_FROM_DEVICE); + ret = length; + } /* * Make the current descriptor valid again and go to * the next one */ - dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, length, - DMA_FROM_DEVICE); - net_receive(dev, desc_p->dmamac_addr, length); - dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr, length, - DMA_FROM_DEVICE); - desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; /* Test the wrap-around condition. */ @@ -352,7 +376,7 @@ static int dwc_ether_rx(struct eth_device *dev) priv->rx_currdescnum = desc_num; - return length; + return ret; } static void dwc_ether_halt (struct eth_device *dev) |