Skip to content

Commit

Permalink
mn10300: make the ASB2305's PCnet32 NIC work by using the PCI bridge'…
Browse files Browse the repository at this point in the history
…s SRAM

Access to the ASB2305's PCnet32 NIC doesn't work correctly because when
the NIC attempts to update the ring buffer flags by DMA, the change to RAM
crops up about 17uS after the interrupt line is asserted.  This is almost
certainly due to a bug in the PCI bridge FPGA on that board.

We can get around this by making dma_alloc_coherent() put the ring buffer
in the SRAM attached to the PCI bridge rather than in the SDRAM.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
David Howells authored and Linus Torvalds committed Jan 11, 2010
1 parent 112b4a0 commit 012c79b
Showing 1 changed file with 17 additions and 0 deletions.
17 changes: 17 additions & 0 deletions arch/mn10300/mm/dma-alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,24 @@
#include <linux/pci.h>
#include <asm/io.h>

static unsigned long pci_sram_allocated = 0xbc000000;

void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int gfp)
{
unsigned long addr;
void *ret;

printk("dma_alloc_coherent(%s,%zu,,%x)\n", dev_name(dev), size, gfp);

if (0xbe000000 - pci_sram_allocated >= size) {
size = (size + 255) & ~255;
addr = pci_sram_allocated;
pci_sram_allocated += size;
ret = (void *) addr;
goto done;
}

/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);

Expand All @@ -41,7 +53,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
/* write back and evict all cache lines covering this region */
mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE);

done:
*dma_handle = virt_to_bus((void *) addr);
printk("dma_alloc_coherent() = %p [%x]\n", ret, *dma_handle);
return ret;
}
EXPORT_SYMBOL(dma_alloc_coherent);
Expand All @@ -51,6 +65,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr & ~0x20000000;

if (addr >= 0x9c000000)
return;

free_pages(addr, get_order(size));
}
EXPORT_SYMBOL(dma_free_coherent);

0 comments on commit 012c79b

Please sign in to comment.