diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-05-02 13:22:38 +0200 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-05-03 10:00:03 +0200 |
commit | 04fcb5d38bc90779cd9a710d60702075986f0e29 (patch) | |
tree | aa2d1367248f7ed77d4a1e2c1fc1a7bca96d831c /drivers/macb.c | |
parent | 37837828d89084879bee2f2b8c7c68d4695940df (diff) | |
download | u-boot-imx-04fcb5d38bc90779cd9a710d60702075986f0e29.zip u-boot-imx-04fcb5d38bc90779cd9a710d60702075986f0e29.tar.gz u-boot-imx-04fcb5d38bc90779cd9a710d60702075986f0e29.tar.bz2 |
macb: Introduce a few barriers when dealing with DMA descriptors
There were a few theoretical possibilities that the compiler might
optimize away DMA descriptor reads and/or writes and thus cause
synchronization problems with the hardware. Insert barriers where
we depend on reads/writes actually hitting memory.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'drivers/macb.c')
-rw-r--r-- | drivers/macb.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/macb.c b/drivers/macb.c index 186ab19..43bb878 100644 --- a/drivers/macb.c +++ b/drivers/macb.c @@ -51,6 +51,8 @@ #include "macb.h" +#define barrier() asm volatile("" ::: "memory") + #define CFG_MACB_RX_BUFFER_SIZE 4096 #define CFG_MACB_RX_RING_SIZE (CFG_MACB_RX_BUFFER_SIZE / 128) #define CFG_MACB_TX_RING_SIZE 16 @@ -185,31 +187,31 @@ static int macb_send(struct eth_device *netdev, volatile void *packet, macb->tx_ring[tx_head].ctrl = ctrl; macb->tx_ring[tx_head].addr = paddr; + barrier(); macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); /* * I guess this is necessary because the networking core may * re-use the transmit buffer as soon as we return... */ - i = 0; - while (!(macb->tx_ring[tx_head].ctrl & TXBUF_USED)) { - if (i > CFG_MACB_TX_TIMEOUT) { - printf("%s: TX timeout\n", netdev->name); + for (i = 0; i <= CFG_MACB_TX_TIMEOUT; i++) { + barrier(); + ctrl = macb->tx_ring[tx_head].ctrl; + if (ctrl & TXBUF_USED) break; - } udelay(1); - i++; } dma_unmap_single(packet, length, paddr); if (i <= CFG_MACB_TX_TIMEOUT) { - ctrl = macb->tx_ring[tx_head].ctrl; if (ctrl & TXBUF_UNDERRUN) printf("%s: TX underrun\n", netdev->name); if (ctrl & TXBUF_EXHAUSTED) printf("%s: TX buffers exhausted in mid frame\n", netdev->name); + } else { + printf("%s: TX timeout\n", netdev->name); } /* No one cares anyway */ @@ -234,6 +236,7 @@ static void reclaim_rx_buffers(struct macb_device *macb, i++; } + barrier(); macb->rx_tail = new_tail; } @@ -283,6 +286,7 @@ static int macb_recv(struct eth_device *netdev) rx_tail = 0; } } + barrier(); } return 0; |