From 012c79bad50469d964fda126102080d4b93a5946 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 8 Jan 2010 14:43:21 -0800 Subject: mn10300: make the ASB2305's PCnet32 NIC work by using the PCI bridge'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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mn10300/mm/dma-alloc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch/mn10300') diff --git a/arch/mn10300/mm/dma-alloc.c b/arch/mn10300/mm/dma-alloc.c index f3649d8f50e..ee82d624b3c 100644 --- a/arch/mn10300/mm/dma-alloc.c +++ b/arch/mn10300/mm/dma-alloc.c @@ -16,12 +16,24 @@ #include #include +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); @@ -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); @@ -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); -- cgit v1.2.3