[PATCH] Re: RFC: IOMMU bypass

Stephen Rothwell sfr at canb.auug.org.au
Wed Jul 20 01:33:08 EST 2005


Hi again,

On Fri, 15 Jul 2005 13:09:33 +1000 Stephen Rothwell <sfr at canb.auug.org.au> wrote:
>
> We (Anton Blanchard and others) have been trying to figure out the best
> (or any) way to allow for IOMMU bypass when setting up DMA mappings on
> particular devices.  Our current idea is to hang a structure of pointers
> to DMA mapping operations off the struct device and inherit it from the
> device's parent.  This would allow for per-bus (rather than per-bus_type)
> mapping operations and also allow a driver to override the bus's
> operations for a particular device.
> 
> Does this make sense?  Comments (hopefully consructive) please.
> 
> Is there a better/simpler/more sensible way to do this?

Just to give you all something concrete to attack^Wcomment on, here is a
preliminary patch with the generic work and PPC64 converted.  It actually
helps ppc64 more than some others because we already have two different
"busses": pci and vio.

This has been built on both pSeries and iSeries ppc64 but not tested, yet.
-- 
Cheers,
Stephen Rothwell                    sfr at canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

diff -ruN linus/arch/ppc64/kernel/Makefile linus-dma_bypass.3/arch/ppc64/kernel/Makefile
--- linus/arch/ppc64/kernel/Makefile	2005-06-27 16:08:00.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/Makefile	2005-06-27 17:41:10.000000000 +1000
@@ -5,7 +5,7 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 extra-y		:= head.o vmlinux.lds
 
-obj-y               :=	setup.o entry.o traps.o irq.o idle.o dma.o \
+obj-y               :=	setup.o entry.o traps.o irq.o idle.o \
 			time.o process.o signal.o syscalls.o misc.o ptrace.o \
 			align.o semaphore.o bitops.o pacaData.o \
 			udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
diff -ruN linus/arch/ppc64/kernel/bpa_iommu.c linus-dma_bypass.3/arch/ppc64/kernel/bpa_iommu.c
--- linus/arch/ppc64/kernel/bpa_iommu.c	2005-06-27 16:08:00.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/bpa_iommu.c	2005-07-19 14:25:11.000000000 +1000
@@ -359,6 +359,11 @@
 	return mask < 0x100000000ull;
 }
 
+static int bpa_direct_set_dma_mask(struct device *dev, u64 mask)
+{
+	return pci_set_dma_mask(to_pci_dev(dev), mask);
+}
+
 void bpa_init_iommu(void)
 {
 	bpa_map_iommu();
@@ -374,4 +379,5 @@
 	pci_dma_ops.map_sg = bpa_map_sg;
 	pci_dma_ops.unmap_sg = bpa_unmap_sg;
 	pci_dma_ops.dma_supported = bpa_dma_supported;
+	pci_dma_ops.set_dma_mask = bpa_set_dma_mask;
 }
diff -ruN linus/arch/ppc64/kernel/dma.c linus-dma_bypass.3/arch/ppc64/kernel/dma.c
--- linus/arch/ppc64/kernel/dma.c	2005-06-27 16:08:00.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/dma.c	1970-01-01 10:00:00.000000000 +1000
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2004 IBM Corporation
- *
- * Implements the generic device dma API for ppc64. Handles
- * the pci and vio busses
- */
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-/* Include the busses we support */
-#include <linux/pci.h>
-#include <asm/vio.h>
-#include <asm/scatterlist.h>
-#include <asm/bug.h>
-
-static struct dma_mapping_ops *get_dma_ops(struct device *dev)
-{
-#ifdef CONFIG_PCI
-	if (dev->bus == &pci_bus_type)
-		return &pci_dma_ops;
-#endif
-#ifdef CONFIG_IBMVIO
-	if (dev->bus == &vio_bus_type)
-		return &vio_dma_ops;
-#endif
-	return NULL;
-}
-
-int dma_supported(struct device *dev, u64 mask)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		return dma_ops->dma_supported(dev, mask);
-	BUG();
-	return 0;
-}
-EXPORT_SYMBOL(dma_supported);
-
-int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-#ifdef CONFIG_PCI
-	if (dev->bus == &pci_bus_type)
-		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
-#endif
-#ifdef CONFIG_IBMVIO
-	if (dev->bus == &vio_bus_type)
-		return -EIO;
-#endif /* CONFIG_IBMVIO */
-	BUG();
-	return 0;
-}
-EXPORT_SYMBOL(dma_set_mask);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-		dma_addr_t *dma_handle, unsigned int __nocast flag)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
-	BUG();
-	return NULL;
-}
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-		dma_addr_t dma_handle)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
-	else
-		BUG();
-}
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
-		enum dma_data_direction direction)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		return dma_ops->map_single(dev, cpu_addr, size, direction);
-	BUG();
-	return (dma_addr_t)0;
-}
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		enum dma_data_direction direction)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		dma_ops->unmap_single(dev, dma_addr, size, direction);
-	else
-		BUG();
-}
-EXPORT_SYMBOL(dma_unmap_single);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-		unsigned long offset, size_t size,
-		enum dma_data_direction direction)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		return dma_ops->map_single(dev,
-				(page_address(page) + offset), size, direction);
-	BUG();
-	return (dma_addr_t)0;
-}
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-		enum dma_data_direction direction)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		dma_ops->unmap_single(dev, dma_address, size, direction);
-	else
-		BUG();
-}
-EXPORT_SYMBOL(dma_unmap_page);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction direction)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		return dma_ops->map_sg(dev, sg, nents, direction);
-	BUG();
-	return 0;
-}
-EXPORT_SYMBOL(dma_map_sg);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-		enum dma_data_direction direction)
-{
-	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
-	if (dma_ops)
-		dma_ops->unmap_sg(dev, sg, nhwentries, direction);
-	else
-		BUG();
-}
-EXPORT_SYMBOL(dma_unmap_sg);
diff -ruN linus/arch/ppc64/kernel/pci.c linus-dma_bypass.3/arch/ppc64/kernel/pci.c
--- linus/arch/ppc64/kernel/pci.c	2005-06-29 11:08:36.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/pci.c	2005-07-19 15:28:32.000000000 +1000
@@ -71,9 +71,6 @@
 
 LIST_HEAD(hose_list);
 
-struct dma_mapping_ops pci_dma_ops;
-EXPORT_SYMBOL(pci_dma_ops);
-
 int global_phb_number;		/* Global phb counter */
 
 /* Cached ISA bridge dev. */
diff -ruN linus/arch/ppc64/kernel/pci_direct_iommu.c linus-dma_bypass.3/arch/ppc64/kernel/pci_direct_iommu.c
--- linus/arch/ppc64/kernel/pci_direct_iommu.c	2005-06-27 16:08:00.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/pci_direct_iommu.c	2005-07-19 15:35:04.000000000 +1000
@@ -83,6 +83,11 @@
 	return mask < 0x100000000ull;
 }
 
+static int pci_direct_set_dma_mask(struct device *dev, u64 mask)
+{
+	return pci_set_dma_mask(to_pci_dev(dev), mask);
+}
+
 void __init pci_direct_iommu_init(void)
 {
 	pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent;
@@ -92,4 +97,5 @@
 	pci_dma_ops.map_sg = pci_direct_map_sg;
 	pci_dma_ops.unmap_sg = pci_direct_unmap_sg;
 	pci_dma_ops.dma_supported = pci_direct_dma_supported;
+	pci_dma_ops.set_dma_mask = pci_direct_set_dma_mask;
 }
diff -ruN linus/arch/ppc64/kernel/pci_iommu.c linus-dma_bypass.3/arch/ppc64/kernel/pci_iommu.c
--- linus/arch/ppc64/kernel/pci_iommu.c	2005-06-27 16:08:00.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/pci_iommu.c	2005-07-19 15:35:26.000000000 +1000
@@ -127,6 +127,11 @@
 	return 1;
 }
 
+static int pci_iommu_set_dma_mask(struct device *dev, u64 mask)
+{
+	return pci_set_dma_mask(to_pci_dev(dev), mask);
+}
+
 void pci_iommu_init(void)
 {
 	pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
@@ -136,4 +141,5 @@
 	pci_dma_ops.map_sg = pci_iommu_map_sg;
 	pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
 	pci_dma_ops.dma_supported = pci_iommu_dma_supported;
+	pci_dma_ops.set_dma_mask = pci_iommu_set_dma_mask;
 }
diff -ruN linus/arch/ppc64/kernel/vio.c linus-dma_bypass.3/arch/ppc64/kernel/vio.c
--- linus/arch/ppc64/kernel/vio.c	2005-06-27 16:08:00.000000000 +1000
+++ linus-dma_bypass.3/arch/ppc64/kernel/vio.c	2005-07-19 15:45:05.000000000 +1000
@@ -45,6 +45,8 @@
 static struct iommu_table veth_iommu_table;
 static struct iommu_table vio_iommu_table;
 #endif
+static struct bus_type vio_bus_type;
+static struct dma_mapping_ops vio_dma_mapping_ops;
 static struct vio_dev vio_bus_device  = { /* fake "parent" device */
 	.name = vio_bus_device.dev.bus_id,
 	.type = "",
@@ -53,6 +55,7 @@
 #endif
 	.dev.bus_id = "vio",
 	.dev.bus = &vio_bus_type,
+	.dev.dma_mapping_ops = &vio_dma_mapping_ops,
 };
 
 #ifdef CONFIG_PPC_ISERIES
@@ -600,7 +603,12 @@
 	return 1;
 }
 
-struct dma_mapping_ops vio_dma_ops = {
+static int vio_set_dma_mask(struct device *dev, u64 mask)
+{
+	return -EIO;
+}
+
+static struct dma_mapping_ops vio_dma_mapping_ops = {
 	.alloc_coherent = vio_alloc_coherent,
 	.free_coherent = vio_free_coherent,
 	.map_single = vio_map_single,
@@ -608,6 +616,7 @@
 	.map_sg = vio_map_sg,
 	.unmap_sg = vio_unmap_sg,
 	.dma_supported = vio_dma_supported,
+	.set_dma_mask = vio_set_dma_mask,
 };
 
 static int vio_bus_match(struct device *dev, struct device_driver *drv)
@@ -629,7 +638,7 @@
 	return 0;
 }
 
-struct bus_type vio_bus_type = {
+static struct bus_type vio_bus_type = {
 	.name = "vio",
 	.match = vio_bus_match,
 };
diff -ruN linus/drivers/base/core.c linus-dma_bypass.3/drivers/base/core.c
--- linus/drivers/base/core.c	2005-07-01 09:58:50.000000000 +1000
+++ linus-dma_bypass.3/drivers/base/core.c	2005-07-19 15:18:22.000000000 +1000
@@ -251,6 +251,9 @@
 	if (parent)
 		klist_add_tail(&parent->klist_children, &dev->knode_parent);
 
+	if (parent && (dev->dma_mapping_ops == NULL))
+		dev->dma_mapping_ops = parent->dma_mapping_ops;
+
 	/* notify platform of device entry */
 	if (platform_notify)
 		platform_notify(dev);
diff -ruN linus/drivers/pci/probe.c linus-dma_bypass.3/drivers/pci/probe.c
--- linus/drivers/pci/probe.c	2005-07-06 21:18:22.000000000 +1000
+++ linus-dma_bypass.3/drivers/pci/probe.c	2005-07-19 15:43:37.000000000 +1000
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
+#include <linux/dma-mapping.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
@@ -22,6 +23,8 @@
 
 LIST_HEAD(pci_devices);
 
+struct dma_mapping_ops pci_dma_ops;
+
 #ifdef HAVE_PCI_LEGACY
 /**
  * pci_create_legacy_files - create legacy I/O port and memory files
@@ -915,6 +918,8 @@
 	dev->parent = parent;
 	dev->release = pci_release_bus_bridge_dev;
 	sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);
+	if (parent == NULL)
+		dev->dma_mapping_ops = &pci_dma_ops;
 	error = device_register(dev);
 	if (error)
 		goto dev_reg_err;
diff -ruN linus/include/asm-ppc64/dma-mapping.h linus-dma_bypass.3/include/asm-ppc64/dma-mapping.h
--- linus/include/asm-ppc64/dma-mapping.h	2005-06-27 16:08:08.000000000 +1000
+++ linus-dma_bypass.3/include/asm-ppc64/dma-mapping.h	2005-07-19 13:47:08.000000000 +1000
@@ -16,25 +16,72 @@
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
-extern int dma_supported(struct device *dev, u64 mask);
-extern int dma_set_mask(struct device *dev, u64 dma_mask);
-extern void *dma_alloc_coherent(struct device *dev, size_t size,
-		dma_addr_t *dma_handle, unsigned int __nocast flag);
-extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-		dma_addr_t dma_handle);
-extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-		size_t size, enum dma_data_direction direction);
-extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-		size_t size, enum dma_data_direction direction);
-extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
+static inline struct dma_mapping_ops *__get_dma_ops(struct device *dev)
+{
+	BUG_ON(dev->dma_mapping_ops == NULL);
+	return dev->dma_mapping_ops;
+}
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+	return dev->dma_mapping_ops &&
+		__get_dma_ops(dev)->dma_supported(dev, mask);
+}
+
+static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	return __get_dma_ops(dev)->set_dma_mask(dev, dma_mask);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+		dma_addr_t *dma_handle, unsigned int __nocast flag)
+{
+	return __get_dma_ops(dev)->alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+		void *cpu_addr, dma_addr_t dma_handle)
+{
+	__get_dma_ops(dev)->free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
+		size_t size, enum dma_data_direction direction)
+{
+	return __get_dma_ops(dev)->map_single(dev, cpu_addr, size, direction);
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+		size_t size, enum dma_data_direction direction)
+{
+	__get_dma_ops(dev)->unmap_single(dev, dma_addr, size, direction);
+}
+
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 		unsigned long offset, size_t size,
-		enum dma_data_direction direction);
-extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-		size_t size, enum dma_data_direction direction);
-extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction direction);
-extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-		int nhwentries, enum dma_data_direction direction);
+		enum dma_data_direction direction)
+{
+	return __get_dma_ops(dev)->map_single(dev,
+			(page_address(page) + offset), size, direction);
+}
+
+static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+		size_t size, enum dma_data_direction direction)
+{
+	__get_dma_ops(dev)->unmap_single(dev, dma_address, size, direction);
+}
+
+static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction direction)
+{
+	return __get_dma_ops(dev)->map_sg(dev, sg, nents, direction);
+}
+
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+		int nhwentries, enum dma_data_direction direction)
+{
+	__get_dma_ops(dev)->unmap_sg(dev, sg, nhwentries, direction);
+}
 
 static inline void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
@@ -113,24 +160,4 @@
 	/* nothing to do */
 }
 
-/*
- * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO
- */
-struct dma_mapping_ops {
-	void *		(*alloc_coherent)(struct device *dev, size_t size,
-				dma_addr_t *dma_handle, unsigned int __nocast flag);
-	void		(*free_coherent)(struct device *dev, size_t size,
-				void *vaddr, dma_addr_t dma_handle);
-	dma_addr_t	(*map_single)(struct device *dev, void *ptr,
-				size_t size, enum dma_data_direction direction);
-	void		(*unmap_single)(struct device *dev, dma_addr_t dma_addr,
-				size_t size, enum dma_data_direction direction);
-	int		(*map_sg)(struct device *dev, struct scatterlist *sg,
-				int nents, enum dma_data_direction direction);
-	void		(*unmap_sg)(struct device *dev, struct scatterlist *sg,
-				int nents, enum dma_data_direction direction);
-	int		(*dma_supported)(struct device *dev, u64 mask);
-	int		(*dac_dma_supported)(struct device *dev, u64 mask);
-};
-
 #endif	/* _ASM_DMA_MAPPING_H */
diff -ruN linus/include/asm-ppc64/pci.h linus-dma_bypass.3/include/asm-ppc64/pci.h
--- linus/include/asm-ppc64/pci.h	2005-07-13 11:38:01.000000000 +1000
+++ linus-dma_bypass.3/include/asm-ppc64/pci.h	2005-07-19 15:55:23.000000000 +1000
@@ -66,15 +66,15 @@
 
 extern unsigned int pcibios_assign_all_busses(void);
 
-extern struct dma_mapping_ops pci_dma_ops;
-
 /* For DAC DMA, we currently don't support it by default, but
  * we let the platform override this
  */
 static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
 {
+#if 0
 	if (pci_dma_ops.dac_dma_supported)
 		return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask);
+#endif
 	return 0;
 }
 
diff -ruN linus/include/asm-ppc64/vio.h linus-dma_bypass.3/include/asm-ppc64/vio.h
--- linus/include/asm-ppc64/vio.h	2005-06-27 16:08:08.000000000 +1000
+++ linus-dma_bypass.3/include/asm-ppc64/vio.h	2005-06-27 17:40:50.000000000 +1000
@@ -57,10 +57,6 @@
 int vio_enable_interrupts(struct vio_dev *dev);
 int vio_disable_interrupts(struct vio_dev *dev);
 
-extern struct dma_mapping_ops vio_dma_ops;
-
-extern struct bus_type vio_bus_type;
-
 struct vio_device_id {
 	char *type;
 	char *compat;
diff -ruN linus/include/linux/device.h linus-dma_bypass.3/include/linux/device.h
--- linus/include/linux/device.h	2005-07-13 11:38:01.000000000 +1000
+++ linus-dma_bypass.3/include/linux/device.h	2005-07-19 13:44:49.000000000 +1000
@@ -45,6 +45,7 @@
 struct device_driver;
 struct class;
 struct class_device;
+struct dma_mapping_ops;
 
 struct bus_type {
 	const char		* name;
@@ -301,6 +302,7 @@
 
 	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
 					     override */
+	struct dma_mapping_ops	*dma_mapping_ops;
 
 	void	(*release)(struct device * dev);
 };
diff -ruN linus/include/linux/dma-mapping.h linus-dma_bypass.3/include/linux/dma-mapping.h
--- linus/include/linux/dma-mapping.h	2005-06-27 16:08:11.000000000 +1000
+++ linus-dma_bypass.3/include/linux/dma-mapping.h	2005-07-19 15:54:50.000000000 +1000
@@ -21,6 +21,28 @@
 #define DMA_30BIT_MASK	0x000000003fffffffULL
 #define DMA_29BIT_MASK	0x000000001fffffffULL
 
+struct scatterlist;
+
+/*
+ * DMA operations may be defined per bus or per device.
+ */
+struct dma_mapping_ops {
+	void *		(*alloc_coherent)(struct device *dev, size_t size,
+				dma_addr_t *dma_handle, unsigned int __nocast flag);
+	void		(*free_coherent)(struct device *dev, size_t size,
+				void *vaddr, dma_addr_t dma_handle);
+	dma_addr_t	(*map_single)(struct device *dev, void *ptr,
+				size_t size, enum dma_data_direction direction);
+	void		(*unmap_single)(struct device *dev, dma_addr_t dma_addr,
+				size_t size, enum dma_data_direction direction);
+	int		(*map_sg)(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction);
+	void		(*unmap_sg)(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction);
+	int		(*dma_supported)(struct device *dev, u64 mask);
+	int		(*set_dma_mask)(struct device *dev, u64 mask);
+};
+
 #include <asm/dma-mapping.h>
 
 /* Backwards compat, remove in 2.7.x */
diff -ruN linus/include/linux/pci.h linus-dma_bypass.3/include/linux/pci.h
--- linus/include/linux/pci.h	2005-07-06 21:18:22.000000000 +1000
+++ linus-dma_bypass.3/include/linux/pci.h	2005-07-19 15:42:03.000000000 +1000
@@ -18,6 +18,7 @@
 #define LINUX_PCI_H
 
 #include <linux/mod_devicetable.h>
+#include <linux/dma-mapping.h>
 
 /*
  * Under PCI, each device has 256 bytes of configuration address space,
@@ -722,6 +723,12 @@
 extern struct list_head pci_root_buses;	/* list of all known PCI buses */
 extern struct list_head pci_devices;	/* list of all devices */
 
+/*
+ * These DMA mapping ops will be applied to all discovered
+ * pci busses and inherited, by default, by all pci devices.
+ */
+extern struct dma_mapping_ops pci_dma_ops;
+
 void pcibios_fixup_bus(struct pci_bus *);
 int pcibios_enable_device(struct pci_dev *, int mask);
 char *pcibios_setup (char *str);



More information about the Linuxppc64-dev mailing list