On Sat, May 25, 2002 at 01:18:06PM -0700, William Jhun wrote:
> When preparing a buffer for a DMA transfer, we've found it's more
> optimal to only do a wback_inv if the direction is not known
> (PCIDMA_BIDIRECTIONAL), only a wback if transfer is to the device
> (PCIDMA_TO_DEVICE), and only an invalidate if from the device
> (PCIDMA_FROM_DEVICE). Such a modification has made a small (yet
> significant) improvement for one of our network drivers during a packet
> forwarding rate test.
*sigh*. On the platform we were testing on, we used our own cache code
(rm7k with tertiary cache support) which has been well-tested for over a
year now. In these routines, we implement dma_cache_wback and only do
invalidates (no flush) for dma_cache_wback_inv. Now that I'm looking
around in cache support for other MIPS CPUs, I see that all the _wback
calls are not implemented and that many (or all?) of the _inv calls also
flush the caches.
The patch below leaves the existing funtions alone and just adds the two
pci_dma_prep_{sg,single}() calls.
My question is: why are these dma_cache_wback calls not implemented? And
how come dma_cache_inv is treated the same as dma_cache_wback_inv? Are
we doing something wrong by implementing these calls in our cache code
as they are described?
Thanks,
Will
---
Index: include/asm-mips/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-mips/pci.h 2002/02/26 06:00:25 1.24.2.1
+++ include/asm-mips/pci.h 2002/05/25 22:01:53
@@ -250,6 +250,49 @@
#endif
}
+/*
+ * Prepare buffer for a DMA transfer after driver temporarily
+ * re-claimed it with pci_dma_sync_*().
+ *
+ * In essence, this "returns" the buffer to the PCI device.
+ */
+static inline void pci_dma_prep_single(struct pci_dev *hwdev,
+ dma_addr_t dma_handle,
+ size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+#ifdef CONFIG_NONCOHERENT_IO
+ dma_cache_wback_inv((unsigned long)bus_to_virt(dma_handle), size);
+#endif
+}
+
+/*
+ * Prepare buffer for a DMA transfer after driver temporarily
+ * re-claimed it with pci_dma_sync_*().
+ *
+ * The same as pci_dma_prep_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+static inline void pci_dma_prep_sg(struct pci_dev *hwdev,
+ struct scatterlist *sg,
+ int nelems, int direction)
+{
+#ifdef CONFIG_NONCOHERENT_IO
+ int i;
+#endif
+
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ /* 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);
+#endif
+}
+
/* Return whether the given PCI device DMA address mask can
* be supported properly. For example, if your device can
* only drive the low 24-bits during PCI bus mastering, then
|