summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2007-05-02 13:22:38 +0200
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-05-03 10:00:03 +0200
commit04fcb5d38bc90779cd9a710d60702075986f0e29 (patch)
treeaa2d1367248f7ed77d4a1e2c1fc1a7bca96d831c
parent37837828d89084879bee2f2b8c7c68d4695940df (diff)
downloadu-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>
-rw-r--r--drivers/macb.c18
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;