pcnet: align rx buffers for cache invalidation

The RX buffers are invalidated when a packet is received, however they
were not suitably cache-line aligned. Allocate them seperately to the
pcnet_priv structure and align to ARCH_DMA_MINALIGN in order to ensure
suitable alignment for the cache invalidation, preventing anything else
being placed in the same lines & lost.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
This commit is contained in:
Paul Burton 2014-04-07 16:41:47 +01:00 committed by Tom Rini
parent f1ae382dfd
commit a354ddc3d7

View file

@ -80,7 +80,7 @@ struct pcnet_uncached_priv {
typedef struct pcnet_priv { typedef struct pcnet_priv {
struct pcnet_uncached_priv *uc; struct pcnet_uncached_priv *uc;
/* Receive Buffer space */ /* Receive Buffer space */
unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4];
int cur_rx; int cur_rx;
int cur_tx; int cur_tx;
} pcnet_priv_t; } pcnet_priv_t;
@ -335,6 +335,10 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis)
flush_dcache_range(addr, addr + sizeof(*lp->uc)); flush_dcache_range(addr, addr + sizeof(*lp->uc));
addr = UNCACHED_SDRAM(addr); addr = UNCACHED_SDRAM(addr);
lp->uc = (struct pcnet_uncached_priv *)addr; lp->uc = (struct pcnet_uncached_priv *)addr;
addr = (u32)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->rx_buf));
flush_dcache_range(addr, addr + sizeof(*lp->rx_buf));
lp->rx_buf = (void *)addr;
} }
uc = lp->uc; uc = lp->uc;
@ -348,7 +352,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis)
*/ */
lp->cur_rx = 0; lp->cur_rx = 0;
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
uc->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]); uc->rx_ring[i].base = PCI_TO_MEM_LE(dev, (*lp->rx_buf)[i]);
uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);
uc->rx_ring[i].status = cpu_to_le16(0x8000); uc->rx_ring[i].status = cpu_to_le16(0x8000);
PCNET_DEBUG1 PCNET_DEBUG1
@ -467,6 +471,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len)
static int pcnet_recv (struct eth_device *dev) static int pcnet_recv (struct eth_device *dev)
{ {
struct pcnet_rx_head *entry; struct pcnet_rx_head *entry;
unsigned char *buf;
int pkt_len = 0; int pkt_len = 0;
u16 status; u16 status;
@ -500,14 +505,12 @@ static int pcnet_recv (struct eth_device *dev)
printf("%s: Rx%d: invalid packet length %d\n", printf("%s: Rx%d: invalid packet length %d\n",
dev->name, lp->cur_rx, pkt_len); dev->name, lp->cur_rx, pkt_len);
} else { } else {
invalidate_dcache_range( buf = (*lp->rx_buf)[lp->cur_rx];
(unsigned long)lp->rx_buf[lp->cur_rx], invalidate_dcache_range((unsigned long)buf,
(unsigned long)lp->rx_buf[lp->cur_rx] + (unsigned long)buf + pkt_len);
pkt_len); NetReceive(buf, pkt_len);
NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n",
lp->cur_rx, pkt_len, lp->cur_rx, pkt_len, buf);
lp->rx_buf[lp->cur_rx]);
} }
} }
entry->status |= cpu_to_le16(0x8000); entry->status |= cpu_to_le16(0x8000);