Hi,
This is a patch to ensure DMA coherency on the SGI O2, by adding
the appropriate cache flushes before and after DMA, and setting the
default page attribute to cacheable non-coherent.
It also fixes the flushed address for the ip27 (offset was missing).
Vivien.
================================================================================
diff -Naur linux/arch/mips64/sgi-ip27/ip27-pci-dma.c
linux.patch/arch/mips64/sgi-ip27/ip27-pci-dma.c
--- linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Thu Jan 3 21:24:54 2002
+++ linux.patch/arch/mips64/sgi-ip27/ip27-pci-dma.c Sun Jul 14 22:29:34 2002
@@ -98,7 +98,8 @@
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nents; i++, sg++) {
- sg->address = (char *)(bus_to_baddr[hwdev->bus->number] |
__pa(sg->address));
+ address = page_address(sg->page) + sg->offset;
+ sg->dvma_address = (char *)(bus_to_baddr[hwdev->bus->number] |
__pa(address));
}
return nents;
diff -Naur linux/arch/mips64/sgi-ip32/ip32-pci-dma.c
linux.patch/arch/mips64/sgi-ip32/ip32-pci-dma.c
--- linux/arch/mips64/sgi-ip32/ip32-pci-dma.c Thu Jan 3 21:24:55 2002
+++ linux.patch/arch/mips64/sgi-ip32/ip32-pci-dma.c Sun Jul 14 22:29:34 2002
@@ -44,7 +44,7 @@
dma_cache_wback_inv((unsigned long) ret, size);
*dma_handle = ( __pa (ret));
DPRINTK("pci_alloc_consistent: addr=%016lx;
dma_handle=%08x\n",(u64)KSEG1ADDR(ret),*dma_handle);
- return KSEG1ADDR(ret);
+ return((void *)KSEG1ADDR(ret));
}
DPRINTK("pci_alloc_consistent2: addr=%016lx;
dma_handle=%08x\n",(u64)KSEG1ADDR(ret),*dma_handle);
return NULL;
@@ -85,7 +85,10 @@
if (direction == PCI_DMA_NONE)
BUG();
DPRINTK("pci_unmap_single\n");
- /* Nothing to do */
+ if (direction != PCI_DMA_TODEVICE) {
+ mips_wbflush();
+ dma_cache_wback_inv((unsigned long)__va(dma_addr), size);
+ }
}
/*
@@ -108,6 +111,7 @@
int nents, int direction)
{
int i;
+ unsigned long address;
if (direction == PCI_DMA_NONE)
BUG();
@@ -117,9 +121,10 @@
DPRINTK("pci_map_sg\n");
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nents; i++, sg++) {
+ address = page_address(sg->page) + sg->offset;
mips_wbflush();
- dma_cache_wback_inv((unsigned long)sg->address, sg->length);
- sg->address = (char *)(__pa(sg->address));
+ dma_cache_wback_inv(address, sg->length);
+ sg->dvma_address = __pa(address);
}
return nents;
@@ -133,10 +138,19 @@
void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nents, int direction)
{
+ int i;
+ unsigned long address;
+
if (direction == PCI_DMA_NONE)
BUG();
DPRINTK("pci_unmap_sg\n");
- /* Nothing to do */
+ for (i = 0; i < nents; i++, sg++) {
+ if (direction != PCI_DMA_TODEVICE) {
+ address = page_address(sg->page) + sg->offset;
+ mips_wbflush();
+ dma_cache_wback_inv(address, sg->length);
+ }
+ }
}
/*
@@ -174,13 +188,16 @@
int nelems, int direction)
{
int i;
+ unsigned long address;
+
if (direction == PCI_DMA_NONE)
BUG();
DPRINTK("pci_dma_sync_sg\n");
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nelems; i++, sg++){
+ address = page_address(sg->page) + sg->offset;
mips_wbflush();
- dma_cache_wback_inv((unsigned long)__va(sg->address),
sg->length);
+ dma_cache_wback_inv(address, sg->length);
}
/* if(direction==PCI_DMA_TODEVICE)
mace_inv_read_buffers();*/
diff -Naur linux/include/asm-mips64/pci.h linux.patch/include/asm-mips64/pci.h
--- linux/include/asm-mips64/pci.h Tue Jul 9 22:03:12 2002
+++ linux.patch/include/asm-mips64/pci.h Sun Jul 14 22:29:34 2002
@@ -343,7 +343,7 @@
* returns, or alternatively stop on the first sg_dma_len(sg) which
* is 0.
*/
-#define sg_dma_address(sg) ((unsigned long)((sg)->address))
+#define sg_dma_address(sg) ((sg)->dvma_address)
#define sg_dma_len(sg) ((sg)->length)
#endif /* __KERNEL__ */
diff -Naur linux/include/asm-mips64/pgtable.h
linux.patch/include/asm-mips64/pgtable.h
--- linux/include/asm-mips64/pgtable.h Mon Jul 8 22:28:12 2002
+++ linux.patch/include/asm-mips64/pgtable.h Sun Jul 14 22:29:34 2002
@@ -188,11 +188,11 @@
#ifdef CONFIG_MIPS_UNCACHED
#define PAGE_CACHABLE_DEFAULT _CACHE_UNCACHED
#else /* ! UNCACHED */
-#ifdef CONFIG_SGI_IP22
+#if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP32)
#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_NONCOHERENT
-#else /* ! IP22 */
+#else /* ! (IP22 || IP32)*/
#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_COW
-#endif /* IP22 */
+#endif /* (IP22 || IP32) */
#endif /* UNCACHED */
#define PAGE_NONE __pgprot(_PAGE_PRESENT | PAGE_CACHABLE_DEFAULT)
|