提交 012c79ba 编写于 作者: D David Howells 提交者: Linus Torvalds

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: NDavid Howells <dhowells@redhat.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 112b4a0b
...@@ -16,12 +16,24 @@ ...@@ -16,12 +16,24 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/io.h> #include <asm/io.h>
static unsigned long pci_sram_allocated = 0xbc000000;
void *dma_alloc_coherent(struct device *dev, size_t size, void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int gfp) dma_addr_t *dma_handle, int gfp)
{ {
unsigned long addr; unsigned long addr;
void *ret; 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 */ /* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
...@@ -41,7 +53,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size, ...@@ -41,7 +53,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
/* write back and evict all cache lines covering this region */ /* write back and evict all cache lines covering this region */
mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE); mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE);
done:
*dma_handle = virt_to_bus((void *) addr); *dma_handle = virt_to_bus((void *) addr);
printk("dma_alloc_coherent() = %p [%x]\n", ret, *dma_handle);
return ret; return ret;
} }
EXPORT_SYMBOL(dma_alloc_coherent); EXPORT_SYMBOL(dma_alloc_coherent);
...@@ -51,6 +65,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr, ...@@ -51,6 +65,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{ {
unsigned long addr = (unsigned long) vaddr & ~0x20000000; unsigned long addr = (unsigned long) vaddr & ~0x20000000;
if (addr >= 0x9c000000)
return;
free_pages(addr, get_order(size)); free_pages(addr, get_order(size));
} }
EXPORT_SYMBOL(dma_free_coherent); EXPORT_SYMBOL(dma_free_coherent);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册