[PATCH] dma_cache_wback, pci DMA cache coherency changes

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

 



This is a re-hash of patches I sent out a while ago which do a more
optimal cache-flushing for pci_map_*() and pci_dma_sync_*(). It
basically does an invalidate for PCI_DMA_FROMDEVICE operations and a
writeback for PCI_DMA_TODEVICE pci_map_* (or writeback/invalidate if
PCI_DMA_BIDIRECTIONAL). This is similar to the ARM implementation.

Additionally, I filled in the _dma_cache_wback calls in the
arch/mips/c-*.c to call *_dma_cache_wback_inv* instead of calling
panic(). Some architectures could probably do a real writeback instead
of just wback_inv, but this will at least allow code that can use
writeback-only if available.

Note: I'm not familiar with a lot of these CPUs, but the change should
be innocuous. Could someone validate/improve these?

Thanks,
William

Index: include/asm/pci.h
===================================================================
RCS file: /cvs/linux/include/asm-mips/pci.h,v
retrieving revision 1.24.2.1
diff -u -r1.24.2.1 pci.h
--- include/asm/pci.h	2002/02/26 06:00:25	1.24.2.1
+++ include/asm/pci.h	2002/06/18 16:51:30
@@ -79,7 +79,40 @@
 extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
 				void *vaddr, dma_addr_t dma_handle);
 
+#ifdef CONFIG_NONCOHERENT_IO
+/*
+ * Prepare buffer for DMA transfer
+ */
+static inline void prep_buffer(void *ptr, size_t size, int direction)
+{
+        switch(direction) {
+        case PCI_DMA_TODEVICE:
+                dma_cache_wback((unsigned long)ptr, size);
+                break;
+        case PCI_DMA_FROMDEVICE:
+                dma_cache_inv((unsigned long)ptr, size);
+                break;
+        case PCI_DMA_BIDIRECTIONAL:
+                dma_cache_wback_inv((unsigned long)ptr, size);
+                break;
+        }
+}
+
 /*
+ * Prepare buffer for CPU access after DMA transfer
+ */
+static inline void sync_buffer(void *ptr, size_t size, int direction)
+{
+        switch(direction) {
+        case PCI_DMA_FROMDEVICE:
+        case PCI_DMA_BIDIRECTIONAL:
+                dma_cache_inv((unsigned long)ptr, size);
+                break;
+        }
+}
+#endif
+
+/*
  * Map a single buffer of the indicated size for DMA in streaming mode.
  * The 32-bit bus address to use is returned.
  *
@@ -93,7 +126,7 @@
 		BUG();
 
 #ifdef CONFIG_NONCOHERENT_IO
-	dma_cache_wback_inv((unsigned long)ptr, size);
+	prep_buffer(ptr, size, direction);
 #endif
 
 	return virt_to_bus(ptr);
@@ -132,7 +165,7 @@
 	addr = (unsigned long) page_address(page);
 	addr += offset;
 #ifdef CONFIG_NONCOHERENT_IO
-	dma_cache_wback_inv(addr, size);
+	prep_buffer((void*)addr, size, direction);
 #endif
 
 	return virt_to_bus((void *)addr);
@@ -183,7 +216,7 @@
 #ifdef CONFIG_NONCOHERENT_IO
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nents; i++, sg++)
-		dma_cache_wback_inv((unsigned long)sg->address, sg->length);
+		prep_buffer(sg->address, sg->length, direction);
 #endif
 
 	return nents;
@@ -221,7 +254,7 @@
 		BUG();
 
 #ifdef CONFIG_NONCOHERENT_IO
-	dma_cache_wback_inv((unsigned long)bus_to_virt(dma_handle), size);
+	sync_buffer(bus_to_virt(dma_handle), size, direction);
 #endif
 }
 
@@ -246,8 +279,9 @@
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 #ifdef CONFIG_NONCOHERENT_IO
 	for (i = 0; i < nelems; i++, sg++)
-		dma_cache_wback_inv((unsigned long)sg->address, sg->length);
+		sync_buffer(sg->address, sg->length, direction);
 #endif
+
 }
 
 /* Return whether the given PCI device DMA address mask can

Index: arch/mips/mm/c-mips32.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-mips32.c,v
retrieving revision 1.3.2.4
diff -u -r1.3.2.4 c-mips32.c
--- arch/mips/mm/c-mips32.c	2002/05/29 03:03:17	1.3.2.4
+++ arch/mips/mm/c-mips32.c	2002/06/18 16:52:21
@@ -393,12 +393,6 @@
 	}
 }
 
-static void
-mips32_dma_cache_wback(unsigned long addr, unsigned long size)
-{
-	panic("mips32_dma_cache called - should not happen.");
-}
-
 /*
  * While we're protected against bad userland addresses we don't care
  * very much about what happens in that case.  Usually a segmentation
@@ -603,7 +597,7 @@
 	_flush_icache_page = mips32_flush_icache_page;
 
 	_dma_cache_wback_inv = mips32_dma_cache_wback_inv_pc;
-	_dma_cache_wback = mips32_dma_cache_wback;
+	_dma_cache_wback = mips32_dma_cache_wback_inv_pc;
 	_dma_cache_inv = mips32_dma_cache_inv_pc;
 }
 
@@ -621,7 +615,7 @@
 	_flush_icache_page = mips32_flush_icache_page_s;
 
 	_dma_cache_wback_inv = mips32_dma_cache_wback_inv_sc;
-	_dma_cache_wback = mips32_dma_cache_wback;
+	_dma_cache_wback = mips32_dma_cache_wback_inv_sc;
 	_dma_cache_inv = mips32_dma_cache_inv_sc;
 }
 
Index: arch/mips/mm/c-r3k.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-r3k.c,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 c-r3k.c
--- arch/mips/mm/c-r3k.c	2002/02/18 15:22:30	1.4.2.1
+++ arch/mips/mm/c-r3k.c	2002/06/18 16:52:21
@@ -337,7 +337,9 @@
 	_flush_icache_page = r3k_flush_icache_page;
 	_flush_icache_range = r3k_flush_icache_range;
 
+	_dma_cache_inv = r3k_dma_cache_wback_inv;
 	_dma_cache_wback_inv = r3k_dma_cache_wback_inv;
+	_dma_cache_wback = r3k_dma_cache_wback_inv;
 
 	printk("Primary instruction cache %dkb, linesize %d bytes\n",
 		(int) (icache_size >> 10), (int) icache_lsize);
Index: arch/mips/mm/c-r4k.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-r4k.c,v
retrieving revision 1.3.2.3
diff -u -r1.3.2.3 c-r4k.c
--- arch/mips/mm/c-r4k.c	2002/05/29 03:03:17	1.3.2.3
+++ arch/mips/mm/c-r4k.c	2002/06/18 16:52:21
@@ -1150,12 +1150,6 @@
 	}
 }
 
-static void
-r4k_dma_cache_wback(unsigned long addr, unsigned long size)
-{
-	panic("r4k_dma_cache called - should not happen.");
-}
-
 /*
  * While we're protected against bad userland addresses we don't care
  * very much about what happens in that case.  Usually a segmentation
@@ -1358,7 +1352,7 @@
 	_flush_icache_page = r4k_flush_icache_page_p;
 
 	_dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
-	_dma_cache_wback = r4k_dma_cache_wback;
+	_dma_cache_wback = r4k_dma_cache_wback_inv_pc;
 	_dma_cache_inv = r4k_dma_cache_inv_pc;
 }
 
@@ -1441,7 +1435,7 @@
 	___flush_cache_all = _flush_cache_all;
 	_flush_icache_page = r4k_flush_icache_page_s;
 	_dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
-	_dma_cache_wback = r4k_dma_cache_wback;
+	_dma_cache_wback = r4k_dma_cache_wback_inv_sc;
 	_dma_cache_inv = r4k_dma_cache_inv_sc;
 }
 
Index: arch/mips/mm/c-r5432.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-r5432.c,v
retrieving revision 1.4
diff -u -r1.4 c-r5432.c
--- arch/mips/mm/c-r5432.c	2001/11/30 13:28:06	1.4
+++ arch/mips/mm/c-r5432.c	2002/06/18 16:52:21
@@ -414,12 +414,6 @@
 	bc_inv(addr, size);
 }
 
-static void
-r5432_dma_cache_wback(unsigned long addr, unsigned long size)
-{
-	panic("r5432_dma_cache called - should not happen.");
-}
-
 /*
  * While we're protected against bad userland addresses we don't care
  * very much about what happens in that case.  Usually a segmentation
@@ -470,7 +464,7 @@
 	_flush_cache_page = r5432_flush_cache_page_d32i32;
 	_flush_icache_page = r5432_flush_icache_page_i32;
 	_dma_cache_wback_inv = r5432_dma_cache_wback_inv_pc;
-	_dma_cache_wback = r5432_dma_cache_wback;
+	_dma_cache_wback = r5432_dma_cache_wback_inv_pc;
 	_dma_cache_inv = r5432_dma_cache_inv_pc;
 
 	_flush_cache_sigtramp = r5432_flush_cache_sigtramp;
Index: arch/mips/mm/c-rm7k.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-rm7k.c,v
retrieving revision 1.4.2.2
diff -u -r1.4.2.2 c-rm7k.c
--- arch/mips/mm/c-rm7k.c	2002/05/29 03:03:17	1.4.2.2
+++ arch/mips/mm/c-rm7k.c	2002/06/18 16:52:21
@@ -177,12 +177,6 @@
 	}
 }
 
-static void
-rm7k_dma_cache_wback(unsigned long addr, unsigned long size)
-{
-	panic("rm7k_dma_cache_wback called - should not happen.");
-}
-
 /*
  * While we're protected against bad userland addresses we don't care
  * very much about what happens in that case.  Usually a segmentation
@@ -342,7 +336,7 @@
 	_flush_icache_page = rm7k_flush_icache_page;
 
 	_dma_cache_wback_inv = rm7k_dma_cache_wback_inv;
-	_dma_cache_wback = rm7k_dma_cache_wback;
+	_dma_cache_wback = rm7k_dma_cache_wback_inv;
 	_dma_cache_inv = rm7k_dma_cache_inv;
 
 	__flush_cache_all_d32i32();
Index: arch/mips/mm/c-tx39.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-tx39.c,v
retrieving revision 1.4
diff -u -r1.4 c-tx39.c
--- arch/mips/mm/c-tx39.c	2001/11/30 13:28:06	1.4
+++ arch/mips/mm/c-tx39.c	2002/06/18 16:52:21
@@ -225,11 +225,6 @@
 	}
 }
 
-static void tx39_dma_cache_wback(unsigned long addr, unsigned long size)
-{
-	panic("tx39_dma_cache called - should not happen.");
-}
-
 static void tx39_flush_cache_sigtramp(unsigned long addr)
 {
 	unsigned long config;
@@ -317,7 +312,7 @@
 		_flush_icache_range = tx39_flush_icache_range;
 
 		_dma_cache_wback_inv = tx39_dma_cache_wback_inv;
-		_dma_cache_wback = tx39_dma_cache_wback;
+		_dma_cache_wback = tx39_dma_cache_wback_inv;
 		_dma_cache_inv = tx39_dma_cache_inv;
 
 		break;
Index: arch/mips/mm/c-tx49.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-tx49.c,v
retrieving revision 1.3.2.1
diff -u -r1.3.2.1 c-tx49.c
--- arch/mips/mm/c-tx49.c	2002/05/29 03:03:17	1.3.2.1
+++ arch/mips/mm/c-tx49.c	2002/06/18 16:52:21
@@ -343,12 +343,6 @@
 	}
 }
 
-static void
-r4k_dma_cache_wback(unsigned long addr, unsigned long size)
-{
-	panic("r4k_dma_cache called - should not happen.");
-}
-
 /*
  * While we're protected against bad userland addresses we don't care
  * very much about what happens in that case.  Usually a segmentation
@@ -429,7 +423,7 @@
 	_flush_icache_page = r4k_flush_icache_page;
 
 	_dma_cache_wback_inv = r4k_dma_cache_wback_inv;
-	_dma_cache_wback = r4k_dma_cache_wback;
+	_dma_cache_wback = r4k_dma_cache_wback_inv;
 	_dma_cache_inv = r4k_dma_cache_inv;
 
 	_flush_cache_sigtramp = r4k_flush_cache_sigtramp;

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

  Powered by Linux