Hello,
Here there is a series of 20 patches that lays the foundations for
using dma_ops in i386 in the very same way x86_64, as well as many other
architectures already do.
The functions themselves for i386 are placed in a pci-base_32.c, but just
a few among them are actually implemented. Most were no-ops anyway.
Also, as I said, this is by no means a complete coverage of dma_ops.
there are still some call sites to be patches in pci-dma_32.c (although I don't
really plan to change them, but to integrate them in a single pci-dma.c).
I intend to have it done progressively.
The granularity is per-operation, meaning each patch moves one specific function
to the common header. This is compiled-tested in both i386 and x86_64 in
~5 randconfigs each, and boot-tested in my hardware with my default configs
The motivation for that is the ongoing work for pci-passthrough in KVM.
So ingo, avi, what do you think it's the best way to handle these patches through?
Thanks
take it off the x86_64 specific header
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping.h | 54 ++++++++++++++++++++++++++++++++++++++
include/asm-x86/dma-mapping_64.h | 49 ----------------------------------
2 files changed, 54 insertions(+), 49 deletions(-)
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 58f790f..aebd178 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -1,5 +1,59 @@
+#ifndef _ASM_DMA_MAPPING_H_
+#define _ASM_DMA_MAPPING_H_
+
+/*
+ * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
+ * documentation.
+ */
+
+#include <linux/scatterlist.h>
+#include <asm/io.h>
+#include <asm/swiotlb.h>
+
+struct dma_mapping_ops {
+ int (*mapping_error)(dma_addr_t dma_addr);
+ void* (*alloc_coherent)(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp);
+ void (*free_coherent)(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+ dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
+ size_t size, int direction);
+ /* like map_single, but doesn't check the device mask */
+ dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
+ size_t size, int direction);
+ void (*unmap_single)(struct device *dev, dma_addr_t addr,
+ size_t size, int direction);
+ void (*sync_single_for_cpu)(struct device *hwdev,
+ dma_addr_t dma_handle, size_t size,
+ int direction);
+ void (*sync_single_for_device)(struct device *hwdev,
+ dma_addr_t dma_handle, size_t size,
+ int direction);
+ void (*sync_single_range_for_cpu)(struct device *hwdev,
+ dma_addr_t dma_handle, unsigned long offset,
+ size_t size, int direction);
+ void (*sync_single_range_for_device)(struct device *hwdev,
+ dma_addr_t dma_handle, unsigned long offset,
+ size_t size, int direction);
+ void (*sync_sg_for_cpu)(struct device *hwdev,
+ struct scatterlist *sg, int nelems,
+ int direction);
+ void (*sync_sg_for_device)(struct device *hwdev,
+ struct scatterlist *sg, int nelems,
+ int direction);
+ int (*map_sg)(struct device *hwdev, struct scatterlist *sg,
+ int nents, int direction);
+ void (*unmap_sg)(struct device *hwdev,
+ struct scatterlist *sg, int nents,
+ int direction);
+ int (*dma_supported)(struct device *hwdev, u64 mask);
+ int is_phys;
+};
+
#ifdef CONFIG_X86_32
# include "dma-mapping_32.h"
#else
# include "dma-mapping_64.h"
#endif
+
+#endif
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index ecd0f61..369188a 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -1,55 +1,6 @@
#ifndef _X8664_DMA_MAPPING_H
#define _X8664_DMA_MAPPING_H 1
-/*
- * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
- * documentation.
- */
-
-#include <linux/scatterlist.h>
-#include <asm/io.h>
-#include <asm/swiotlb.h>
-
-struct dma_mapping_ops {
- int (*mapping_error)(dma_addr_t dma_addr);
- void* (*alloc_coherent)(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp);
- void (*free_coherent)(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
- dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
- size_t size, int direction);
- /* like map_single, but doesn't check the device mask */
- dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
- size_t size, int direction);
- void (*unmap_single)(struct device *dev, dma_addr_t addr,
- size_t size, int direction);
- void (*sync_single_for_cpu)(struct device *hwdev,
- dma_addr_t dma_handle, size_t size,
- int direction);
- void (*sync_single_for_device)(struct device *hwdev,
- dma_addr_t dma_handle, size_t size,
- int direction);
- void (*sync_single_range_for_cpu)(struct device *hwdev,
- dma_addr_t dma_handle, unsigned long offset,
- size_t size, int direction);
- void (*sync_single_range_for_device)(struct device *hwdev,
- dma_addr_t dma_handle, unsigned long offset,
- size_t size, int direction);
- void (*sync_sg_for_cpu)(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- int direction);
- void (*sync_sg_for_device)(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- int direction);
- int (*map_sg)(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
- void (*unmap_sg)(struct device *hwdev,
- struct scatterlist *sg, int nents,
- int direction);
- int (*dma_supported)(struct device *hwdev, u64 mask);
- int is_phys;
-};
-
extern dma_addr_t bad_dma_address;
extern const struct dma_mapping_ops* dma_ops;
extern int iommu_merge;
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 9 +++++++++
include/asm-x86/dma-mapping_32.h | 6 ------
include/asm-x86/dma-mapping_64.h | 11 -----------
4 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index 4512c30..d876600 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -39,6 +39,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.sync_single_for_device = NULL,
.sync_single_range_for_cpu = NULL,
.sync_single_range_for_device = NULL,
+ .sync_sg_for_cpu = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 260538b..1a301d7 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -139,4 +139,13 @@ dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
flush_write_buffers();
}
+static inline void
+dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
+ int nelems, int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->sync_sg_for_cpu)
+ dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
+ flush_write_buffers();
+}
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index 60d5371..e7c82e3 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -33,12 +33,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
}
static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
-}
-
-static inline void
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index dfa66cc..804b154 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -27,17 +27,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_map_single((dev), page_address(page)+(offset), (size), (dir))
#define dma_unmap_page dma_unmap_single
-
-static inline void
-dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
- int nelems, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- if (dma_ops->sync_sg_for_cpu)
- dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
- flush_write_buffers();
-}
-
static inline void
dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
int nelems, int direction)
--
1.5.0.6
the old i386 implementation is moved to pci-base_32.c
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 19 +++++++++++++++++++
include/asm-x86/dma-mapping.h | 8 +++++++-
include/asm-x86/dma-mapping_32.h | 20 --------------------
include/asm-x86/dma-mapping_64.h | 7 -------
4 files changed, 26 insertions(+), 28 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index a8a7c7f..2474152 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -12,9 +12,28 @@ static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
return virt_to_phys(ptr);
}
+static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
+ int nents, int direction)
+{
+ struct scatterlist *sg;
+ int i;
+
+ WARN_ON(nents == 0 || sglist[0].length == 0);
+
+ for_each_sg(sglist, sg, nents, i) {
+ BUG_ON(!sg_page(sg));
+
+ sg->dma_address = sg_phys(sg);
+ }
+
+ flush_write_buffers();
+ return nents;
+}
+
static const struct dma_mapping_ops pci32_dma_ops = {
.map_single = pci32_map_single,
.unmap_single = NULL,
+ .map_sg = pci32_dma_map_sg,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index bb0378f..0901154 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -75,5 +75,11 @@ dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
dma_ops->unmap_single(dev, addr, size, direction);
}
-
+static inline int
+dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+ int nents, int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ return dma_ops->map_sg(hwdev, sg, nents, direction);
+}
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index 0b27cb0..cdcdeff 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -17,26 +17,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
- enum dma_data_direction direction)
-{
- struct scatterlist *sg;
- int i;
-
- BUG_ON(!valid_dma_direction(direction));
- WARN_ON(nents == 0 || sglist[0].length == 0);
-
- for_each_sg(sglist, sg, nents, i) {
- BUG_ON(!sg_page(sg));
-
- sg->dma_address = sg_phys(sg);
- }
-
- flush_write_buffers();
- return nents;
-}
-
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)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 5d349db..b27527a 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -96,13 +96,6 @@ dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
flush_write_buffers();
}
-static inline int
-dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- return dma_ops->map_sg(hwdev, sg, nents, direction);
-}
-
static inline void
dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
int direction)
--
1.5.0.6
i386 base does not need it, so it gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 10 ++++++++++
include/asm-x86/dma-mapping_32.h | 7 -------
include/asm-x86/dma-mapping_64.h | 8 --------
4 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index b613d73..a8a7c7f 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -14,6 +14,7 @@ static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
static const struct dma_mapping_ops pci32_dma_ops = {
.map_single = pci32_map_single,
+ .unmap_single = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index d320244..bb0378f 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -66,4 +66,14 @@ dma_map_single(struct device *hwdev, void *ptr, size_t size,
return dma_ops->map_single(hwdev, ptr, size, direction);
}
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
+ int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->unmap_single)
+ dma_ops->unmap_single(dev, addr, size, direction);
+}
+
+
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index b496306..0b27cb0 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -17,13 +17,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(!valid_dma_direction(direction));
-}
-
static inline int
dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
enum dma_data_direction direction)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 969a7da..5d349db 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -23,14 +23,6 @@ extern void *dma_alloc_coherent(struct device *dev, size_t size,
extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
- int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- dma_ops->unmap_single(dev, addr, size, direction);
-}
-
#define dma_map_page(dev,page,offset,size,dir) \
dma_map_single((dev), page_address(page)+(offset), (size), (dir))
--
1.5.0.6
That's already the name of the game for x86_64. For i386,
we add a pci-base_32.c, that will hold the default operations.
The function call itself goes through dma-mapping.h , the common
header
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/pci-base_32.c | 20 ++++++++++++++++++++
include/asm-x86/dma-mapping.h | 10 ++++++++++
include/asm-x86/dma-mapping_32.h | 10 ----------
include/asm-x86/dma-mapping_64.h | 9 ---------
5 files changed, 31 insertions(+), 19 deletions(-)
create mode 100644 arch/x86/kernel/pci-base_32.c
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 340221f..95fbf57 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -27,6 +27,7 @@ obj-y += pci-dma_$(BITS).o bootflag.o e820_$(BITS).o
obj-y += quirks.o i8237.o topology.o kdebugfs.o
obj-y += alternative.o i8253.o
obj-$(CONFIG_X86_64) += pci-nommu_64.o bugs_64.o
+obj-$(CONFIG_X86_32) += pci-base_32.o
obj-y += tsc_$(BITS).o io_delay.o rtc.o
obj-y += process.o
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
new file mode 100644
index 0000000..b613d73
--- /dev/null
+++ b/arch/x86/kernel/pci-base_32.c
@@ -0,0 +1,20 @@
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <asm/dma-mapping.h>
+
+static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
+ size_t size, int direction)
+{
+ WARN_ON(size == 0);
+ flush_write_buffers();
+ return virt_to_phys(ptr);
+}
+
+static const struct dma_mapping_ops pci32_dma_ops = {
+ .map_single = pci32_map_single,
+};
+
+const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
+EXPORT_SYMBOL(dma_ops);
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index aebd178..d320244 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -50,10 +50,20 @@ struct dma_mapping_ops {
int is_phys;
};
+extern const struct dma_mapping_ops *dma_ops;
+
#ifdef CONFIG_X86_32
# include "dma-mapping_32.h"
#else
# include "dma-mapping_64.h"
#endif
+static inline dma_addr_t
+dma_map_single(struct device *hwdev, void *ptr, size_t size,
+ int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ return dma_ops->map_single(hwdev, ptr, size, direction);
+}
+
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index 55f01bd..b496306 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -17,16 +17,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- WARN_ON(size == 0);
- flush_write_buffers();
- return virt_to_phys(ptr);
-}
-
static inline void
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 369188a..969a7da 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -2,7 +2,6 @@
#define _X8664_DMA_MAPPING_H 1
extern dma_addr_t bad_dma_address;
-extern const struct dma_mapping_ops* dma_ops;
extern int iommu_merge;
static inline int dma_mapping_error(dma_addr_t dma_addr)
@@ -24,14 +23,6 @@ extern void *dma_alloc_coherent(struct device *dev, size_t size,
extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
-static inline dma_addr_t
-dma_map_single(struct device *hwdev, void *ptr, size_t size,
- int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- return dma_ops->map_single(hwdev, ptr, size, direction);
-}
-
static inline void
dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
int direction)
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 12 ++++++++++++
include/asm-x86/dma-mapping_32.h | 6 ------
include/asm-x86/dma-mapping_64.h | 11 -----------
4 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index 9205304..dce03c8 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -35,6 +35,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.unmap_single = NULL,
.map_sg = pci32_dma_map_sg,
.unmap_sg = NULL,
+ .sync_single_for_cpu = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 6e7747a..507069d 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -91,4 +91,16 @@ dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
if (dma_ops->unmap_sg)
dma_ops->unmap_sg(hwdev, sg, nents, direction);
}
+
+static inline void
+dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+ size_t size, int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->sync_single_for_cpu)
+ dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
+ direction);
+ flush_write_buffers();
+}
+
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index 55445e3..a05b2fc 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -33,12 +33,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
}
static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
-}
-
-static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index ce37efb..b055964 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -29,17 +29,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
#define dma_unmap_page dma_unmap_single
static inline void
-dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
- size_t size, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- if (dma_ops->sync_single_for_cpu)
- dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
- direction);
- flush_write_buffers();
-}
-
-static inline void
dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
size_t size, int direction)
{
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 9 +++++++++
include/asm-x86/dma-mapping_32.h | 8 --------
include/asm-x86/dma-mapping_64.h | 8 --------
4 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index 2474152..9205304 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -34,6 +34,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.map_single = pci32_map_single,
.unmap_single = NULL,
.map_sg = pci32_dma_map_sg,
+ .unmap_sg = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 0901154..6e7747a 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -82,4 +82,13 @@ dma_map_sg(struct device *hwdev, struct scatterlist *sg,
BUG_ON(!valid_dma_direction(direction));
return dma_ops->map_sg(hwdev, sg, nents, direction);
}
+
+static inline void
+dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+ int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->unmap_sg)
+ dma_ops->unmap_sg(hwdev, sg, nents, direction);
+}
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index cdcdeff..55445e3 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -32,14 +32,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
BUG_ON(!valid_dma_direction(direction));
}
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-{
- BUG_ON(!valid_dma_direction(direction));
-}
-
static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index b27527a..ce37efb 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -96,14 +96,6 @@ dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
flush_write_buffers();
}
-static inline void
-dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
- int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- dma_ops->unmap_sg(hwdev, sg, nents, direction);
-}
-
extern int dma_supported(struct device *hwdev, u64 mask);
/* same for gart, swiotlb, and nommu */
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 11 +++++++++++
include/asm-x86/dma-mapping_32.h | 7 -------
include/asm-x86/dma-mapping_64.h | 11 -----------
4 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index dce03c8..3648824 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -36,6 +36,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.map_sg = pci32_dma_map_sg,
.unmap_sg = NULL,
.sync_single_for_cpu = NULL,
+ .sync_single_for_device = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 507069d..8ad582c 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -103,4 +103,15 @@ dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
flush_write_buffers();
}
+static inline void
+dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
+ size_t size, int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->sync_single_for_device)
+ dma_ops->sync_single_for_device(hwdev, dma_handle, size,
+ direction);
+ flush_write_buffers();
+}
+
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index a05b2fc..b91771a 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -33,13 +33,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
}
static inline void
-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- flush_write_buffers();
-}
-
-static inline void
dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
unsigned long offset, size_t size,
enum dma_data_direction direction)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index b055964..b539f61 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -29,17 +29,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
#define dma_unmap_page dma_unmap_single
static inline void
-dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
- size_t size, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- if (dma_ops->sync_single_for_device)
- dma_ops->sync_single_for_device(hwdev, dma_handle, size,
- direction);
- flush_write_buffers();
-}
-
-static inline void
dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
unsigned long offset, size_t size, int direction)
{
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 14 ++++++++++++++
include/asm-x86/dma-mapping_32.h | 8 --------
include/asm-x86/dma-mapping_64.h | 12 ------------
4 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index c501599..4512c30 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -38,6 +38,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.sync_single_for_cpu = NULL,
.sync_single_for_device = NULL,
.sync_single_range_for_cpu = NULL,
+ .sync_single_range_for_device = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index a466470..260538b 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -125,4 +125,18 @@ dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
flush_write_buffers();
}
+
+static inline void
+dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->sync_single_range_for_device)
+ dma_ops->sync_single_range_for_device(hwdev, dma_handle,
+ offset, size, direction);
+
+ flush_write_buffers();
+}
+
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index e24c59d..60d5371 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -33,14 +33,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
}
static inline void
-dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- flush_write_buffers();
-}
-
-static inline void
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 6ecafad..dfa66cc 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -29,18 +29,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
#define dma_unmap_page dma_unmap_single
static inline void
-dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
- unsigned long offset, size_t size, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- if (dma_ops->sync_single_range_for_device)
- dma_ops->sync_single_range_for_device(hwdev, dma_handle,
- offset, size, direction);
-
- flush_write_buffers();
-}
-
-static inline void
dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
int nelems, int direction)
{
--
1.5.0.6
they are the same between architectures (except for the fact
that x86_64 has duplicate code)
move them to dma-mapping.h
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping.h | 10 ++++++++++
include/asm-x86/dma-mapping_32.h | 9 ---------
include/asm-x86/dma-mapping_64.h | 11 -----------
3 files changed, 10 insertions(+), 20 deletions(-)
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 53a404b..3ea3802 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -52,6 +52,16 @@ struct dma_mapping_ops {
extern const struct dma_mapping_ops *dma_ops;
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag);
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+
+
#ifdef CONFIG_X86_32
# include "dma-mapping_32.h"
#else
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index eff42f4..d8f6420 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -8,15 +8,6 @@
#include <asm/io.h>
#include <asm/bug.h>
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
-
-void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
-
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)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 707dbbe..ce881d9 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -12,17 +12,6 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
return (dma_addr == bad_dma_address);
}
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-extern void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp);
-extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle);
-
#define dma_map_page(dev,page,offset,size,dir) \
dma_map_single((dev), page_address(page)+(offset), (size), (dir))
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 11 +++++++++++
include/asm-x86/dma-mapping_32.h | 7 -------
include/asm-x86/dma-mapping_64.h | 12 ------------
4 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index d876600..033d94e 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -40,6 +40,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.sync_single_range_for_cpu = NULL,
.sync_single_range_for_device = NULL,
.sync_sg_for_cpu = NULL,
+ .sync_sg_for_device = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 1a301d7..53a404b 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -148,4 +148,15 @@ dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
flush_write_buffers();
}
+
+static inline void
+dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
+ int nelems, int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->sync_sg_for_device)
+ dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
+
+ flush_write_buffers();
+}
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index e7c82e3..eff42f4 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -32,13 +32,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
BUG_ON(!valid_dma_direction(direction));
}
-static inline void
-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- flush_write_buffers();
-}
-
static inline int
dma_mapping_error(dma_addr_t dma_addr)
{
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 804b154..707dbbe 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -27,18 +27,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_map_single((dev), page_address(page)+(offset), (size), (dir))
#define dma_unmap_page dma_unmap_single
-static inline void
-dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
- int nelems, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- if (dma_ops->sync_sg_for_device) {
- dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
- }
-
- flush_write_buffers();
-}
-
extern int dma_supported(struct device *hwdev, u64 mask);
/* same for gart, swiotlb, and nommu */
--
1.5.0.6
i386 gets an empty function
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 1 +
include/asm-x86/dma-mapping.h | 11 +++++++++++
include/asm-x86/dma-mapping_32.h | 7 -------
include/asm-x86/dma-mapping_64.h | 12 ------------
4 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index 3648824..c501599 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -37,6 +37,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.unmap_sg = NULL,
.sync_single_for_cpu = NULL,
.sync_single_for_device = NULL,
+ .sync_single_range_for_cpu = NULL,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 8ad582c..a466470 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -114,4 +114,15 @@ dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
flush_write_buffers();
}
+static inline void
+dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, int direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ if (dma_ops->sync_single_range_for_cpu)
+ dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset,
+ size, direction);
+
+ flush_write_buffers();
+}
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index b91771a..e24c59d 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -33,13 +33,6 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
}
static inline void
-dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
-}
-
-static inline void
dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
unsigned long offset, size_t size,
enum dma_data_direction direction)
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index b539f61..6ecafad 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -29,18 +29,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
#define dma_unmap_page dma_unmap_single
static inline void
-dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
- unsigned long offset, size_t size, int direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- if (dma_ops->sync_single_range_for_cpu) {
- dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset, size, direction);
- }
-
- flush_write_buffers();
-}
-
-static inline void
dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
unsigned long offset, size_t size, int direction)
{
--
1.5.0.6
Do it instead of using the conservative approach we're currently
doing. This is the way x86_64 does, and this patch makes this piece
of code the same between them, ready to be integrated
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping_32.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index fd7246d..d0512c9 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -21,7 +21,7 @@ dma_get_cache_alignment(void)
{
/* no easy way to get cache size on all x86, so return the
* maximum possible, to be safe */
- return (1 << INTERNODE_CACHE_SHIFT);
+ return boot_cpu_data.x86_clflush_size;
}
#define dma_is_consistent(d, h) (1)
--
1.5.0.6
all the code that is left is ready to be merged as-is
in dma-mapping.h
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping.h | 19 +++++++++++++------
include/asm-x86/dma-mapping_32.h | 23 -----------------------
include/asm-x86/dma-mapping_64.h | 17 -----------------
3 files changed, 13 insertions(+), 46 deletions(-)
delete mode 100644 include/asm-x86/dma-mapping_32.h
delete mode 100644 include/asm-x86/dma-mapping_64.h
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 9548b19..3809b35 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -11,6 +11,9 @@
#include <asm/swiotlb.h>
extern dma_addr_t bad_dma_address;
+extern int iommu_merge;
+extern struct device fallback_dev;
+extern int panic_on_overflow;
struct dma_mapping_ops {
int (*mapping_error)(dma_addr_t dma_addr);
@@ -75,12 +78,6 @@ void dma_free_coherent(struct device *dev, size_t size,
extern int dma_supported(struct device *hwdev, u64 mask);
extern int dma_set_mask(struct device *dev, u64 mask);
-#ifdef CONFIG_X86_32
-# include "dma-mapping_32.h"
-#else
-# include "dma-mapping_64.h"
-#endif
-
static inline dma_addr_t
dma_map_single(struct device *hwdev, void *ptr, size_t size,
int direction)
@@ -203,6 +200,15 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
flush_write_buffers();
}
+static inline int dma_get_cache_alignment(void)
+{
+ /* no easy way to get cache size on all x86, so return the
+ * maximum possible, to be safe */
+ return boot_cpu_data.x86_clflush_size;
+}
+
+#define dma_is_consistent(d, h) (1)
+
#ifdef CONFIG_X86_32
# define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
extern int
@@ -215,5 +221,6 @@ dma_release_declared_memory(struct device *dev);
extern void *
dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size);
+extern int forbid_dac;
#endif /* CONFIG_X86_32 */
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
deleted file mode 100644
index 4ec4f45..0000000
--- a/include/asm-x86/dma-mapping_32.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _ASM_I386_DMA_MAPPING_H
-#define _ASM_I386_DMA_MAPPING_H
-
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/bug.h>
-
-extern int forbid_dac;
-
-static inline int
-dma_get_cache_alignment(void)
-{
- /* no easy way to get cache size on all x86, so return the
- * maximum possible, to be safe */
- return boot_cpu_data.x86_clflush_size;
-}
-
-#define dma_is_consistent(d, h) (1)
-
-#endif
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
deleted file mode 100644
index 8353025..0000000
--- a/include/asm-x86/dma-mapping_64.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _X8664_DMA_MAPPING_H
-#define _X8664_DMA_MAPPING_H 1
-
-extern int iommu_merge;
-
-/* same for gart, swiotlb, and nommu */
-static inline int dma_get_cache_alignment(void)
-{
- return boot_cpu_data.x86_clflush_size;
-}
-
-#define dma_is_consistent(d, h) 1
-
-extern struct device fallback_dev;
-extern int panic_on_overflow;
-
-#endif /* _X8664_DMA_MAPPING_H */
--
1.5.0.6
they are the same in both architectures.
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping.h | 6 ++++++
include/asm-x86/dma-mapping_32.h | 7 -------
include/asm-x86/dma-mapping_64.h | 7 -------
3 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index b5a413a..70a5ede 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -183,4 +183,10 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
dma_unmap_single(dev, addr, size, direction);
}
+static inline void
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction dir)
+{
+ flush_write_buffers();
+}
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index c61ae7f..e60c30a 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -55,13 +55,6 @@ dma_get_cache_alignment(void)
#define dma_is_consistent(d, h) (1)
-static inline void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
-{
- flush_write_buffers();
-}
-
#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
extern int
dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 2b4a430..b1bc6ca 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -24,13 +24,6 @@ static inline int dma_get_cache_alignment(void)
extern int dma_set_mask(struct device *dev, u64 mask);
-static inline void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction dir)
-{
- flush_write_buffers();
-}
-
extern struct device fallback_dev;
extern int panic_on_overflow;
--
1.5.0.6
They are similar enough to do this move.
the macro version is ugly, and we use inline functions instead
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping.h | 14 ++++++++++++++
include/asm-x86/dma-mapping_32.h | 15 ---------------
include/asm-x86/dma-mapping_64.h | 4 ----
3 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 3ea3802..b5a413a 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -169,4 +169,18 @@ dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
flush_write_buffers();
}
+
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ size_t offset, size_t size,
+ int direction)
+{
+ return dma_map_single(dev, page_address(page)+offset, size, direction);
+}
+
+static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
+ size_t size, int direction)
+{
+ dma_unmap_single(dev, addr, size, direction);
+}
+
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index d8f6420..c61ae7f 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -8,21 +8,6 @@
#include <asm/io.h>
#include <asm/bug.h>
-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)
-{
- BUG_ON(!valid_dma_direction(direction));
- return page_to_phys(page) + offset;
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(!valid_dma_direction(direction));
-}
-
static inline int
dma_mapping_error(dma_addr_t dma_addr)
{
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index ce881d9..2b4a430 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -12,10 +12,6 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
return (dma_addr == bad_dma_address);
}
-#define dma_map_page(dev,page,offset,size,dir) \
- dma_map_single((dev), page_address(page)+(offset), (size), (dir))
-
-#define dma_unmap_page dma_unmap_single
extern int dma_supported(struct device *hwdev, u64 mask);
/* same for gart, swiotlb, and nommu */
--
1.5.0.6
This is the way x86_64 does, so this make them equal. They have
to be extern now in the header, and the extern definition is moved to
the common dma-mapping.h header
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-dma_32.c | 33 +++++++++++++++++++++++++++++++++
include/asm-x86/dma-mapping.h | 3 +++
include/asm-x86/dma-mapping_32.h | 29 -----------------------------
include/asm-x86/dma-mapping_64.h | 4 ----
4 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
index 5133032..453b4bd 100644
--- a/arch/x86/kernel/pci-dma_32.c
+++ b/arch/x86/kernel/pci-dma_32.c
@@ -156,6 +156,39 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
int forbid_dac;
EXPORT_SYMBOL(forbid_dac);
+int
+dma_supported(struct device *dev, u64 mask)
+{
+ /*
+ * we fall back to GFP_DMA when the mask isn't all 1s,
+ * so we can't guarantee allocations that must be
+ * within a tighter range than GFP_DMA..
+ */
+ if (mask < 0x00ffffff)
+ return 0;
+
+ /* Work around chipset bugs */
+ if (forbid_dac > 0 && mask > 0xffffffffULL)
+ return 0;
+
+ if (dma_ops->dma_supported)
+ return dma_ops->dma_supported(dev, mask);
+
+ return 1;
+}
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+
+ *dev->dma_mask = mask;
+
+ return 0;
+}
+
+
static __devinit void via_no_dac(struct pci_dev *dev)
{
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 70a5ede..06eb448 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -62,6 +62,9 @@ void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
+extern int dma_supported(struct device *hwdev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 mask);
+
#ifdef CONFIG_X86_32
# include "dma-mapping_32.h"
#else
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index e60c30a..fd7246d 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -17,35 +17,6 @@ dma_mapping_error(dma_addr_t dma_addr)
extern int forbid_dac;
static inline int
-dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
- if(mask < 0x00ffffff)
- return 0;
-
- /* Work around chipset bugs */
- if (forbid_dac > 0 && mask > 0xffffffffULL)
- return 0;
-
- return 1;
-}
-
-static inline int
-dma_set_mask(struct device *dev, u64 mask)
-{
- if(!dev->dma_mask || !dma_supported(dev, mask))
- return -EIO;
-
- *dev->dma_mask = mask;
-
- return 0;
-}
-
-static inline int
dma_get_cache_alignment(void)
{
/* no easy way to get cache size on all x86, so return the
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index b1bc6ca..9674dac 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -12,8 +12,6 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
return (dma_addr == bad_dma_address);
}
-extern int dma_supported(struct device *hwdev, u64 mask);
-
/* same for gart, swiotlb, and nommu */
static inline int dma_get_cache_alignment(void)
{
@@ -22,8 +20,6 @@ static inline int dma_get_cache_alignment(void)
#define dma_is_consistent(d, h) 1
-extern int dma_set_mask(struct device *dev, u64 mask);
-
extern struct device fallback_dev;
extern int panic_on_overflow;
--
1.5.0.6
We provide a map_error function in pci-base_32.c to make
sure i386 keeps with the same behaviour it used to.
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 7 +++++++
include/asm-x86/dma-mapping.h | 8 ++++++++
include/asm-x86/dma-mapping_32.h | 6 ------
include/asm-x86/dma-mapping_64.h | 8 --------
4 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/pci-base_32.c b/arch/x86/kernel/pci-base_32.c
index 033d94e..89d3587 100644
--- a/arch/x86/kernel/pci-base_32.c
+++ b/arch/x86/kernel/pci-base_32.c
@@ -30,6 +30,12 @@ static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
return nents;
}
+/* Make sure we keep the same behaviour */
+static int pci32_map_error(dma_addr_t dma_addr)
+{
+ return 0;
+}
+
static const struct dma_mapping_ops pci32_dma_ops = {
.map_single = pci32_map_single,
.unmap_single = NULL,
@@ -41,6 +47,7 @@ static const struct dma_mapping_ops pci32_dma_ops = {
.sync_single_range_for_device = NULL,
.sync_sg_for_cpu = NULL,
.sync_sg_for_device = NULL,
+ .mapping_error = pci32_map_error,
};
const struct dma_mapping_ops *dma_ops = &pci32_dma_ops;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 908fcaa..352433b 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -54,6 +54,14 @@ struct dma_mapping_ops {
extern const struct dma_mapping_ops *dma_ops;
+static inline int dma_mapping_error(dma_addr_t dma_addr)
+{
+ if (dma_ops->mapping_error)
+ return dma_ops->mapping_error(dma_addr);
+
+ return (dma_addr == bad_dma_address);
+}
+
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index d0512c9..03a75f8 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -8,12 +8,6 @@
#include <asm/io.h>
#include <asm/bug.h>
-static inline int
-dma_mapping_error(dma_addr_t dma_addr)
-{
- return 0;
-}
-
extern int forbid_dac;
static inline int
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 352bf41..8353025 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -3,14 +3,6 @@
extern int iommu_merge;
-static inline int dma_mapping_error(dma_addr_t dma_addr)
-{
- if (dma_ops->mapping_error)
- return dma_ops->mapping_error(dma_addr);
-
- return (dma_addr == bad_dma_address);
-}
-
/* same for gart, swiotlb, and nommu */
static inline int dma_get_cache_alignment(void)
{
--
1.5.0.6
It's initially 0, since we don't expect any DMA there.
Signed-off-by: Glauber Costa <[email protected]>
---
arch/x86/kernel/pci-dma_32.c | 4 ++++
include/asm-x86/dma-mapping.h | 2 ++
include/asm-x86/dma-mapping_64.h | 1 -
3 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
index 453b4bd..55ab3c8 100644
--- a/arch/x86/kernel/pci-dma_32.c
+++ b/arch/x86/kernel/pci-dma_32.c
@@ -14,6 +14,10 @@
#include <linux/module.h>
#include <asm/io.h>
+/* For i386, we make it point to the NULL address */
+dma_addr_t bad_dma_address __read_mostly = 0x0;
+EXPORT_SYMBOL(bad_dma_address);
+
struct dma_coherent_mem {
void *virt_base;
u32 device_base;
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 06eb448..908fcaa 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -10,6 +10,8 @@
#include <asm/io.h>
#include <asm/swiotlb.h>
+extern dma_addr_t bad_dma_address;
+
struct dma_mapping_ops {
int (*mapping_error)(dma_addr_t dma_addr);
void* (*alloc_coherent)(struct device *dev, size_t size,
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 9674dac..352bf41 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -1,7 +1,6 @@
#ifndef _X8664_DMA_MAPPING_H
#define _X8664_DMA_MAPPING_H 1
-extern dma_addr_t bad_dma_address;
extern int iommu_merge;
static inline int dma_mapping_error(dma_addr_t dma_addr)
--
1.5.0.6
define it conditionally to i386
Signed-off-by: Glauber Costa <[email protected]>
---
include/asm-x86/dma-mapping.h | 14 ++++++++++++++
include/asm-x86/dma-mapping_32.h | 12 ------------
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 352433b..9548b19 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -202,4 +202,18 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
{
flush_write_buffers();
}
+
+#ifdef CONFIG_X86_32
+# define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+extern int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+ dma_addr_t device_addr, size_t size, int flags);
+
+extern void
+dma_release_declared_memory(struct device *dev);
+
+extern void *
+dma_mark_declared_memory_occupied(struct device *dev,
+ dma_addr_t device_addr, size_t size);
+#endif /* CONFIG_X86_32 */
#endif
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index 03a75f8..4ec4f45 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -20,16 +20,4 @@ dma_get_cache_alignment(void)
#define dma_is_consistent(d, h) (1)
-#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
-extern int
-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
- dma_addr_t device_addr, size_t size, int flags);
-
-extern void
-dma_release_declared_memory(struct device *dev);
-
-extern void *
-dma_mark_declared_memory_occupied(struct device *dev,
- dma_addr_t device_addr, size_t size);
-
#endif
--
1.5.0.6
* Glauber Costa <[email protected]> wrote:
> Hello,
>
> Here there is a series of 20 patches that lays the foundations for
> using dma_ops in i386 in the very same way x86_64, as well as many
> other architectures already do.
>
> The functions themselves for i386 are placed in a pci-base_32.c, but
> just a few among them are actually implemented. Most were no-ops
> anyway.
>
> Also, as I said, this is by no means a complete coverage of dma_ops.
> there are still some call sites to be patches in pci-dma_32.c
> (although I don't really plan to change them, but to integrate them in
> a single pci-dma.c). I intend to have it done progressively.
>
> The granularity is per-operation, meaning each patch moves one
> specific function to the common header. This is compiled-tested in
> both i386 and x86_64 in ~5 randconfigs each, and boot-tested in my
> hardware with my default configs
>
> The motivation for that is the ongoing work for pci-passthrough in
> KVM. So ingo, avi, what do you think it's the best way to handle these
> patches through?
looks very nice to me! I've applied it to x86.git, lets see what
happens.
Ingo
* Glauber Costa <[email protected]> wrote:
> /* no easy way to get cache size on all x86, so return the
> * maximum possible, to be safe */
> - return (1 << INTERNODE_CACHE_SHIFT);
> + return boot_cpu_data.x86_clflush_size;
please update the comment too. (just add a delta patch to your next
series)
Ingo
Glauber Costa wrote:
> Hello,
>
> Here there is a series of 20 patches that lays the foundations for
> using dma_ops in i386 in the very same way x86_64, as well as many other
> architectures already do.
>
> The functions themselves for i386 are placed in a pci-base_32.c, but just
> a few among them are actually implemented. Most were no-ops anyway.
>
>
I see the headers are unified, but the .c files are duplicated. I
presume unifying the implementation is deferred to later patches?
> The motivation for that is the ongoing work for pci-passthrough in KVM.
> So ingo, avi, what do you think it's the best way to handle these patches through?
>
x86.git.
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
Avi Kivity wrote:
> Glauber Costa wrote:
>> Hello,
>>
>> Here there is a series of 20 patches that lays the foundations for
>> using dma_ops in i386 in the very same way x86_64, as well as many other
>> architectures already do.
>>
>> The functions themselves for i386 are placed in a pci-base_32.c, but just
>> a few among them are actually implemented. Most were no-ops anyway.
>>
>>
>
> I see the headers are unified, but the .c files are duplicated. I
> presume unifying the implementation is deferred to later patches?
presume correctly.
* Ingo Molnar <[email protected]> wrote:
> > The motivation for that is the ongoing work for pci-passthrough in
> > KVM. So ingo, avi, what do you think it's the best way to handle
> > these patches through?
>
> looks very nice to me! I've applied it to x86.git, lets see what
> happens.
Houston, we've got a problem! :-/
randconfig testing found that this patchset broke sendfile on certain
.config's - DMA started returning all 0xfffffffff data, corrupting
files. (config attached)
After some bisection fun it turns out that the conversions from struct
page are wrong:
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ size_t offset, size_t size,
+ int direction)
+{
+ return dma_map_single(dev, page_address(page)+offset, size, direction);
because page_address() is not defined for highmem pages in general. (and
even if it's defined, it will corrupt data)
changing it to page_to_phys() is not good because it goes via a 32-bit
bottleneck that trims things on PAE:
dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
the 'ptr' is 32-bit albeit it's a DMA target.
what i came up is the prototype 32-bit fix below - this works on 32-bit
but breaks 64-bit because we pass in physical addresses instead of
virtual direct addresses.
i'll fix the 64-bit side but that means materially touching all the
dma_mapping_ops instantiations materially on the 64-bit side - not
really something we wanted to do :-/
Ingo
---------------->
Subject: x86: dma-ops on highmem fix
From: Ingo Molnar <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 4 ++--
include/asm-x86/dma-mapping.h | 10 ++++++----
2 files changed, 8 insertions(+), 6 deletions(-)
Index: linux-x86.q/arch/x86/kernel/pci-base_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-base_32.c
+++ linux-x86.q/arch/x86/kernel/pci-base_32.c
@@ -4,12 +4,12 @@
#include <linux/dma-mapping.h>
#include <asm/dma-mapping.h>
-static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
+static dma_addr_t pci32_map_single(struct device *dev, u64 ptr,
size_t size, int direction)
{
WARN_ON(size == 0);
flush_write_buffers();
- return virt_to_phys(ptr);
+ return ptr;
}
static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
Index: linux-x86.q/include/asm-x86/dma-mapping.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/dma-mapping.h
+++ linux-x86.q/include/asm-x86/dma-mapping.h
@@ -16,10 +16,10 @@ struct dma_mapping_ops {
dma_addr_t *dma_handle, gfp_t gfp);
void (*free_coherent)(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
- dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
+ dma_addr_t (*map_single)(struct device *hwdev, u64 ptr,
size_t size, int direction);
/* like map_single, but doesn't check the device mask */
- dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
+ dma_addr_t (*map_simple)(struct device *hwdev, u64 ptr,
size_t size, int direction);
void (*unmap_single)(struct device *dev, dma_addr_t addr,
size_t size, int direction);
@@ -73,7 +73,7 @@ dma_map_single(struct device *hwdev, voi
int direction)
{
BUG_ON(!valid_dma_direction(direction));
- return dma_ops->map_single(hwdev, ptr, size, direction);
+ return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
}
static inline void
@@ -174,7 +174,9 @@ static inline dma_addr_t dma_map_page(st
size_t offset, size_t size,
int direction)
{
- return dma_map_single(dev, page_address(page)+offset, size, direction);
+ BUG_ON(!valid_dma_direction(direction));
+ return dma_ops->map_single(dev, page_to_phys(page)+offset,
+ size, direction);
}
static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
* Ingo Molnar <[email protected]> wrote:
> what i came up is the prototype 32-bit fix below - this works on
> 32-bit but breaks 64-bit because we pass in physical addresses instead
> of virtual direct addresses.
>
> i'll fix the 64-bit side but that means materially touching all the
> dma_mapping_ops instantiations materially on the 64-bit side - not
> really something we wanted to do :-/
the full fix ended up being the one below. It's not that bad - and
gart_64.c looks even a bit cleaner. Still, it needs careful review.
Ingo
--------------->
Subject: x86: dma-ops on highmem fix
From: Ingo Molnar <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/pci-base_32.c | 4 ++--
arch/x86/kernel/pci-calgary_64.c | 3 ++-
arch/x86/kernel/pci-dma_64.c | 2 +-
arch/x86/kernel/pci-gart_64.c | 15 +++++++--------
arch/x86/kernel/pci-nommu_64.c | 4 ++--
arch/x86/kernel/pci-swiotlb_64.c | 9 ++++++++-
include/asm-x86/dma-mapping.h | 10 ++++++----
7 files changed, 28 insertions(+), 19 deletions(-)
Index: linux-x86.q/arch/x86/kernel/pci-base_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-base_32.c
+++ linux-x86.q/arch/x86/kernel/pci-base_32.c
@@ -4,12 +4,12 @@
#include <linux/dma-mapping.h>
#include <asm/dma-mapping.h>
-static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
+static dma_addr_t pci32_map_single(struct device *dev, phys_addr_t ptr,
size_t size, int direction)
{
WARN_ON(size == 0);
flush_write_buffers();
- return virt_to_phys(ptr);
+ return ptr;
}
static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
Index: linux-x86.q/arch/x86/kernel/pci-calgary_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-calgary_64.c
+++ linux-x86.q/arch/x86/kernel/pci-calgary_64.c
@@ -470,10 +470,11 @@ error:
return 0;
}
-static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
+static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
size_t size, int direction)
{
dma_addr_t dma_handle = bad_dma_address;
+ void *vaddr = phys_to_virt(paddr);
unsigned long uaddr;
unsigned int npages;
struct iommu_table *tbl = find_iommu_table(dev);
Index: linux-x86.q/arch/x86/kernel/pci-dma_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-dma_64.c
+++ linux-x86.q/arch/x86/kernel/pci-dma_64.c
@@ -141,7 +141,7 @@ dma_alloc_coherent(struct device *dev, s
}
if (dma_ops->map_simple) {
- *dma_handle = dma_ops->map_simple(dev, memory,
+ *dma_handle = dma_ops->map_simple(dev, virt_to_phys(memory),
size,
PCI_DMA_BIDIRECTIONAL);
if (*dma_handle != bad_dma_address)
Index: linux-x86.q/arch/x86/kernel/pci-gart_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-gart_64.c
+++ linux-x86.q/arch/x86/kernel/pci-gart_64.c
@@ -264,9 +264,9 @@ static dma_addr_t dma_map_area(struct de
}
static dma_addr_t
-gart_map_simple(struct device *dev, char *buf, size_t size, int dir)
+gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir)
{
- dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
+ dma_addr_t map = dma_map_area(dev, paddr, size, dir);
flush_gart();
@@ -275,18 +275,17 @@ gart_map_simple(struct device *dev, char
/* Map a single area into the IOMMU */
static dma_addr_t
-gart_map_single(struct device *dev, void *addr, size_t size, int dir)
+gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir)
{
- unsigned long phys_mem, bus;
+ unsigned long bus;
if (!dev)
dev = &fallback_dev;
- phys_mem = virt_to_phys(addr);
- if (!need_iommu(dev, phys_mem, size))
- return phys_mem;
+ if (!need_iommu(dev, paddr, size))
+ return paddr;
- bus = gart_map_simple(dev, addr, size, dir);
+ bus = gart_map_simple(dev, paddr, size, dir);
return bus;
}
Index: linux-x86.q/arch/x86/kernel/pci-nommu_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-nommu_64.c
+++ linux-x86.q/arch/x86/kernel/pci-nommu_64.c
@@ -26,10 +26,10 @@ check_addr(char *name, struct device *hw
}
static dma_addr_t
-nommu_map_single(struct device *hwdev, void *ptr, size_t size,
+nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
int direction)
{
- dma_addr_t bus = virt_to_bus(ptr);
+ dma_addr_t bus = paddr;
if (!check_addr("map_single", hwdev, bus, size))
return bad_dma_address;
return bus;
Index: linux-x86.q/arch/x86/kernel/pci-swiotlb_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-swiotlb_64.c
+++ linux-x86.q/arch/x86/kernel/pci-swiotlb_64.c
@@ -11,11 +11,18 @@
int swiotlb __read_mostly;
+static dma_addr_t
+swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size,
+ int direction)
+{
+ return swiotlb_map_single(hwdev, phys_to_virt(paddr), size, direction);
+}
+
const struct dma_mapping_ops swiotlb_dma_ops = {
.mapping_error = swiotlb_dma_mapping_error,
.alloc_coherent = swiotlb_alloc_coherent,
.free_coherent = swiotlb_free_coherent,
- .map_single = swiotlb_map_single,
+ .map_single = swiotlb_map_single_phys,
.unmap_single = swiotlb_unmap_single,
.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
.sync_single_for_device = swiotlb_sync_single_for_device,
Index: linux-x86.q/include/asm-x86/dma-mapping.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/dma-mapping.h
+++ linux-x86.q/include/asm-x86/dma-mapping.h
@@ -16,10 +16,10 @@ struct dma_mapping_ops {
dma_addr_t *dma_handle, gfp_t gfp);
void (*free_coherent)(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
- dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
+ dma_addr_t (*map_single)(struct device *hwdev, phys_addr_t ptr,
size_t size, int direction);
/* like map_single, but doesn't check the device mask */
- dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
+ dma_addr_t (*map_simple)(struct device *hwdev, phys_addr_t ptr,
size_t size, int direction);
void (*unmap_single)(struct device *dev, dma_addr_t addr,
size_t size, int direction);
@@ -73,7 +73,7 @@ dma_map_single(struct device *hwdev, voi
int direction)
{
BUG_ON(!valid_dma_direction(direction));
- return dma_ops->map_single(hwdev, ptr, size, direction);
+ return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
}
static inline void
@@ -174,7 +174,9 @@ static inline dma_addr_t dma_map_page(st
size_t offset, size_t size,
int direction)
{
- return dma_map_single(dev, page_address(page)+offset, size, direction);
+ BUG_ON(!valid_dma_direction(direction));
+ return dma_ops->map_single(dev, page_to_phys(page)+offset,
+ size, direction);
}
static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
Ingo Molnar wrote:
> * Ingo Molnar <[email protected]> wrote:
>
>> what i came up is the prototype 32-bit fix below - this works on
>> 32-bit but breaks 64-bit because we pass in physical addresses instead
>> of virtual direct addresses.
>>
>> i'll fix the 64-bit side but that means materially touching all the
>> dma_mapping_ops instantiations materially on the 64-bit side - not
>> really something we wanted to do :-/
>
> the full fix ended up being the one below. It's not that bad - and
> gart_64.c looks even a bit cleaner. Still, it needs careful review.
>
> Ingo
>
> --------------->
> Subject: x86: dma-ops on highmem fix
> From: Ingo Molnar <[email protected]>
>
> Signed-off-by: Ingo Molnar <[email protected]>
> ---
> arch/x86/kernel/pci-base_32.c | 4 ++--
> arch/x86/kernel/pci-calgary_64.c | 3 ++-
> arch/x86/kernel/pci-dma_64.c | 2 +-
> arch/x86/kernel/pci-gart_64.c | 15 +++++++--------
> arch/x86/kernel/pci-nommu_64.c | 4 ++--
> arch/x86/kernel/pci-swiotlb_64.c | 9 ++++++++-
> include/asm-x86/dma-mapping.h | 10 ++++++----
> 7 files changed, 28 insertions(+), 19 deletions(-)
>
> Index: linux-x86.q/arch/x86/kernel/pci-base_32.c
> ===================================================================
> --- linux-x86.q.orig/arch/x86/kernel/pci-base_32.c
> +++ linux-x86.q/arch/x86/kernel/pci-base_32.c
> @@ -4,12 +4,12 @@
> #include <linux/dma-mapping.h>
> #include <asm/dma-mapping.h>
>
> -static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
> +static dma_addr_t pci32_map_single(struct device *dev, phys_addr_t ptr,
> size_t size, int direction)
> {
> WARN_ON(size == 0);
> flush_write_buffers();
> - return virt_to_phys(ptr);
> + return ptr;
> }
>
> static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
> Index: linux-x86.q/arch/x86/kernel/pci-calgary_64.c
> ===================================================================
> --- linux-x86.q.orig/arch/x86/kernel/pci-calgary_64.c
> +++ linux-x86.q/arch/x86/kernel/pci-calgary_64.c
> @@ -470,10 +470,11 @@ error:
> return 0;
> }
>
> -static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
> +static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
> size_t size, int direction)
> {
> dma_addr_t dma_handle = bad_dma_address;
> + void *vaddr = phys_to_virt(paddr);
> unsigned long uaddr;
> unsigned int npages;
> struct iommu_table *tbl = find_iommu_table(dev);
> Index: linux-x86.q/arch/x86/kernel/pci-dma_64.c
> ===================================================================
> --- linux-x86.q.orig/arch/x86/kernel/pci-dma_64.c
> +++ linux-x86.q/arch/x86/kernel/pci-dma_64.c
> @@ -141,7 +141,7 @@ dma_alloc_coherent(struct device *dev, s
> }
>
> if (dma_ops->map_simple) {
> - *dma_handle = dma_ops->map_simple(dev, memory,
> + *dma_handle = dma_ops->map_simple(dev, virt_to_phys(memory),
> size,
> PCI_DMA_BIDIRECTIONAL);
> if (*dma_handle != bad_dma_address)
> Index: linux-x86.q/arch/x86/kernel/pci-gart_64.c
> ===================================================================
> --- linux-x86.q.orig/arch/x86/kernel/pci-gart_64.c
> +++ linux-x86.q/arch/x86/kernel/pci-gart_64.c
> @@ -264,9 +264,9 @@ static dma_addr_t dma_map_area(struct de
> }
>
> static dma_addr_t
> -gart_map_simple(struct device *dev, char *buf, size_t size, int dir)
> +gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir)
> {
> - dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
> + dma_addr_t map = dma_map_area(dev, paddr, size, dir);
>
> flush_gart();
>
> @@ -275,18 +275,17 @@ gart_map_simple(struct device *dev, char
>
> /* Map a single area into the IOMMU */
> static dma_addr_t
> -gart_map_single(struct device *dev, void *addr, size_t size, int dir)
> +gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir)
> {
> - unsigned long phys_mem, bus;
> + unsigned long bus;
>
> if (!dev)
> dev = &fallback_dev;
>
> - phys_mem = virt_to_phys(addr);
> - if (!need_iommu(dev, phys_mem, size))
> - return phys_mem;
> + if (!need_iommu(dev, paddr, size))
> + return paddr;
>
> - bus = gart_map_simple(dev, addr, size, dir);
> + bus = gart_map_simple(dev, paddr, size, dir);
>
> return bus;
> }
> Index: linux-x86.q/arch/x86/kernel/pci-nommu_64.c
> ===================================================================
> --- linux-x86.q.orig/arch/x86/kernel/pci-nommu_64.c
> +++ linux-x86.q/arch/x86/kernel/pci-nommu_64.c
> @@ -26,10 +26,10 @@ check_addr(char *name, struct device *hw
> }
>
> static dma_addr_t
> -nommu_map_single(struct device *hwdev, void *ptr, size_t size,
> +nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
> int direction)
> {
> - dma_addr_t bus = virt_to_bus(ptr);
> + dma_addr_t bus = paddr;
> if (!check_addr("map_single", hwdev, bus, size))
> return bad_dma_address;
> return bus;
> Index: linux-x86.q/arch/x86/kernel/pci-swiotlb_64.c
> ===================================================================
> --- linux-x86.q.orig/arch/x86/kernel/pci-swiotlb_64.c
> +++ linux-x86.q/arch/x86/kernel/pci-swiotlb_64.c
> @@ -11,11 +11,18 @@
>
> int swiotlb __read_mostly;
>
> +static dma_addr_t
> +swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size,
> + int direction)
> +{
> + return swiotlb_map_single(hwdev, phys_to_virt(paddr), size, direction);
> +}
> +
> const struct dma_mapping_ops swiotlb_dma_ops = {
> .mapping_error = swiotlb_dma_mapping_error,
> .alloc_coherent = swiotlb_alloc_coherent,
> .free_coherent = swiotlb_free_coherent,
> - .map_single = swiotlb_map_single,
> + .map_single = swiotlb_map_single_phys,
> .unmap_single = swiotlb_unmap_single,
> .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
> .sync_single_for_device = swiotlb_sync_single_for_device,
> Index: linux-x86.q/include/asm-x86/dma-mapping.h
> ===================================================================
> --- linux-x86.q.orig/include/asm-x86/dma-mapping.h
> +++ linux-x86.q/include/asm-x86/dma-mapping.h
> @@ -16,10 +16,10 @@ struct dma_mapping_ops {
> dma_addr_t *dma_handle, gfp_t gfp);
> void (*free_coherent)(struct device *dev, size_t size,
> void *vaddr, dma_addr_t dma_handle);
> - dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
> + dma_addr_t (*map_single)(struct device *hwdev, phys_addr_t ptr,
> size_t size, int direction);
> /* like map_single, but doesn't check the device mask */
> - dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
> + dma_addr_t (*map_simple)(struct device *hwdev, phys_addr_t ptr,
> size_t size, int direction);
> void (*unmap_single)(struct device *dev, dma_addr_t addr,
> size_t size, int direction);
> @@ -73,7 +73,7 @@ dma_map_single(struct device *hwdev, voi
> int direction)
> {
> BUG_ON(!valid_dma_direction(direction));
> - return dma_ops->map_single(hwdev, ptr, size, direction);
> + return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
> }
>
> static inline void
> @@ -174,7 +174,9 @@ static inline dma_addr_t dma_map_page(st
> size_t offset, size_t size,
> int direction)
> {
> - return dma_map_single(dev, page_address(page)+offset, size, direction);
> + BUG_ON(!valid_dma_direction(direction));
> + return dma_ops->map_single(dev, page_to_phys(page)+offset,
> + size, direction);
> }
>
> static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
It looks all good to me.
I'll give a shot in my systems to see if it goes okay.
* On Wednesday 26 March 2008 03:06:19 Glauber Costa wrote:
> Hello,
>
> Here there is a series of 20 patches that lays the foundations for
> using dma_ops in i386 in the very same way x86_64, as well as many other
> architectures already do.
Thanks; Please also see Stephen Tweedie's tree at
http://git.et.redhat.com/?p=linux-2.6-dom0-pvops.git;a=summary
I guess your work would be overlapped anyway, but just to make sure there's no
double work.
On Tue, 2008-03-25 at 18:36 -0300, Glauber Costa wrote:
> This is the way x86_64 does, so this make them equal. They have
> to be extern now in the header, and the extern definition is moved to
> the common dma-mapping.h header
>
> Signed-off-by: Glauber Costa <[email protected]>
...
> diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
> index 5133032..453b4bd 100644
> --- a/arch/x86/kernel/pci-dma_32.c
> +++ b/arch/x86/kernel/pci-dma_32.c
> @@ -156,6 +156,39 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
> int forbid_dac;
> EXPORT_SYMBOL(forbid_dac);
>
> +int
> +dma_supported(struct device *dev, u64 mask)
> +{
...
> +}
> +
> +int
> +dma_set_mask(struct device *dev, u64 mask)
> +{
...
> +}
...
> diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
> index e60c30a..fd7246d 100644
> --- a/include/asm-x86/dma-mapping_32.h
> +++ b/include/asm-x86/dma-mapping_32.h
> @@ -17,35 +17,6 @@ dma_mapping_error(dma_addr_t dma_addr)
> extern int forbid_dac;
>
> static inline int
> -dma_supported(struct device *dev, u64 mask)
> -{
...
> -}
> -
> -static inline int
> -dma_set_mask(struct device *dev, u64 mask)
> -{
...
> -}
This breaks for me with:
ERROR: "dma_supported" [drivers/ssb/ssb.ko] undefined!
ERROR: "dma_set_mask" [drivers/scsi/qla2xxx/qla2xxx.ko] undefined!
ERROR: "dma_set_mask" [drivers/scsi/aic7xxx/aic7xxx.ko] undefined!
ERROR: "dma_set_mask" [drivers/scsi/aic7xxx/aic79xx.ko] undefined!
ERROR: "dma_supported" [drivers/net/pcnet32.ko] undefined!
ERROR: "dma_supported" [drivers/media/video/saa7134/saa7134.ko] undefined!
ERROR: "dma_set_mask" [drivers/media/video/meye.ko] undefined!
ERROR: "dma_supported" [drivers/media/video/cx88/cx8802.ko] undefined!
ERROR: "dma_supported" [drivers/media/video/cx88/cx8800.ko] undefined!
ERROR: "dma_supported" [drivers/media/video/cx88/cx88-alsa.ko] undefined!
ERROR: "dma_supported" [drivers/media/video/cx23885/cx23885.ko] undefined!
They just need to be exported like on x86_64.
Cheers,
Mark.
Subject: [PATCH] x86: export dma_supported() and dma_set_mask() on i386
dma_supported() and dma_set_mask() were previously inlined,
but are now moved to pci-dma_32.c.
Since they're used by various drivers, they need to be
exported.
Signed-off-by: Mark McLoughlin <[email protected]>
---
arch/x86/kernel/pci-dma_32.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
index 55ab3c8..be6b1f6 100644
--- a/arch/x86/kernel/pci-dma_32.c
+++ b/arch/x86/kernel/pci-dma_32.c
@@ -180,6 +180,7 @@ dma_supported(struct device *dev, u64 mask)
return 1;
}
+EXPORT_SYMBOL(dma_supported);
int
dma_set_mask(struct device *dev, u64 mask)
@@ -191,6 +192,7 @@ dma_set_mask(struct device *dev, u64 mask)
return 0;
}
+EXPORT_SYMBOL(dma_set_mask);
static __devinit void via_no_dac(struct pci_dev *dev)
* Mark McLoughlin <[email protected]> wrote:
> This breaks for me with:
>
> ERROR: "dma_supported" [drivers/ssb/ssb.ko] undefined!
> ERROR: "dma_set_mask" [drivers/scsi/qla2xxx/qla2xxx.ko] undefined!
> ERROR: "dma_set_mask" [drivers/scsi/aic7xxx/aic7xxx.ko] undefined!
> ERROR: "dma_set_mask" [drivers/scsi/aic7xxx/aic79xx.ko] undefined!
> ERROR: "dma_supported" [drivers/net/pcnet32.ko] undefined!
> ERROR: "dma_supported" [drivers/media/video/saa7134/saa7134.ko] undefined!
> ERROR: "dma_set_mask" [drivers/media/video/meye.ko] undefined!
> ERROR: "dma_supported" [drivers/media/video/cx88/cx8802.ko] undefined!
> ERROR: "dma_supported" [drivers/media/video/cx88/cx8800.ko] undefined!
> ERROR: "dma_supported" [drivers/media/video/cx88/cx88-alsa.ko] undefined!
> ERROR: "dma_supported" [drivers/media/video/cx23885/cx23885.ko] undefined!
>
> They just need to be exported like on x86_64.
thanks Mark, applied.
Ingo