cache coherency on I/O

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

	Here is a patch to fix cache coherency when doing I/O on the
O2. It simply adds writeback and invalidate when unmapping DMA
memory. This fixes coherency when reading from a device. It
also adds support for mapping/unmapping pages for both the IP27 and
the O2.

Vivien Chappelier.
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	Sun Dec  9 15:47:15 2001
+++ linux.patch/arch/mips64/sgi-ip27/ip27-pci-dma.c	Fri Dec 21 11:08:22 2001
@@ -112,7 +112,11 @@
 
 	/* 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));
+	        if(sg->address)
+		  address = sg->address;
+		else
+		  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	Sun Dec  9 15:47:15 2001
+++ linux.patch/arch/mips64/sgi-ip32/ip32-pci-dma.c	Fri Dec 21 11:07:33 2001
@@ -99,7 +99,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);
+	}
 }
 
 /*
@@ -122,6 +125,7 @@
 			     int nents, int direction)
 {
 	int i;
+	unsigned long address;
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
@@ -131,9 +135,13 @@
 	DPRINTK("pci_map_sg\n");
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nents; i++, sg++) {
+	        if(sg->address)
+		  address = sg->address;
+		else
+		  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;
@@ -147,10 +155,22 @@
 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) {
+	        if(sg->address)
+		  address = sg->address;
+		else
+		  address = page_address(sg->page) + sg->offset;
+	        mips_wbflush();
+	        dma_cache_wback_inv(address, sg->length);
+	  }
+	}
 }
 
 /*
@@ -188,13 +208,19 @@
 				   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++){
+	        if(sg->address)
+		  address = sg->address;
+		else
+		  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/mipsregs.h linux.patch/include/asm-mips64/mipsregs.h
--- linux/include/asm-mips64/mipsregs.h	Sun Dec  9 15:52:27 2001
+++ linux.patch/include/asm-mips64/mipsregs.h	Fri Dec 21 11:28:06 2001
@@ -367,6 +367,7 @@
 #define CONF_CM_CMASK			7
 #define CONF_DB				(1 <<  4)
 #define CONF_IB				(1 <<  5)
+#define CONF_SE				(1 << 12)
 #define CONF_SC				(1 << 17)
 #define CONF_AC                         (1 << 23)
 #define CONF_HALT                       (1 << 25)
diff -Naur linux/include/asm-mips64/pci.h linux.patch/include/asm-mips64/pci.h
--- linux/include/asm-mips64/pci.h	Thu Dec 20 18:32:18 2001
+++ linux.patch/include/asm-mips64/pci.h	Fri Dec 21 11:10:08 2001
@@ -319,7 +319,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	Thu Dec 20 18:32:18 2001
+++ linux.patch/include/asm-mips64/pgtable.h	Thu Dec 20 20:03:07 2001
@@ -180,11 +180,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)
diff -Naur linux/include/asm-mips64/scatterlist.h linux.patch/include/asm-mips64/scatterlist.h
--- linux/include/asm-mips64/scatterlist.h	Thu Dec 20 18:32:18 2001
+++ linux.patch/include/asm-mips64/scatterlist.h	Fri Dec 21 11:09:40 2001
@@ -7,7 +7,7 @@
 	unsigned int offset;
 	unsigned int length;
 
-	__u32 dvma_address;
+	dma_addr_t dvma_address;
 };
 
 struct mmu_sglist {

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux