|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] x86: use custom dma_get_required_mask()
# HG changeset patch
# User David Vrabel <david.vrabel@xxxxxxxxxx>
# Date 1415886941 -3600
# Node ID 78e400792c76811445c6a80dfebdbded116f1aad
# Parent 6d727f2dcc8386e9658d84082f45633c08d992d1
x86: use custom dma_get_required_mask()
On a Xen PV guest the DMA addresses and physical addresses are not 1:1
(such as Xen PV guests) and the generic dma_get_required_mask() does
not return the correct mask (since it uses max_pfn).
Some device drivers (such as mptsas, mpt2sas) use
dma_get_required_mask() to set the device's DMA mask to allow them to
use only 32-bit DMA addresses in hardware structures. This results in
unnecessary use of the SWIOTLB if DMA addresses are more than 32-bits,
impacting performance significantly.
Provide a get_required_mask op that uses the maximum MFN to calculate
the DMA mask.
Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Committed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
diff -r 6d727f2dcc83 -r 78e400792c76 arch/i386/kernel/pci-dma-xen.c
--- a/arch/i386/kernel/pci-dma-xen.c Thu Nov 13 14:51:07 2014 +0100
+++ b/arch/i386/kernel/pci-dma-xen.c Thu Nov 13 14:55:41 2014 +0100
@@ -22,6 +22,8 @@
#include <asm-i386/mach-xen/asm/gnttab_dma.h>
#include <asm/bug.h>
+#include <xen/interface/memory.h>
+
#ifdef __x86_64__
#include <asm/proto.h>
@@ -208,6 +210,16 @@ dma_supported(struct device *dev, u64 ma
}
EXPORT_SYMBOL(dma_supported);
+u64 dma_get_required_mask(struct device *dev)
+{
+ unsigned long max_mfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page,
+ NULL);
+
+ return (((u64)1 << (__fls(max_mfn - 1) + 1 + PAGE_SHIFT)) - 1)
+ & *dev->dma_mask;
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
diff -r 6d727f2dcc83 -r 78e400792c76 include/asm-i386/bitops.h
--- a/include/asm-i386/bitops.h Thu Nov 13 14:51:07 2014 +0100
+++ b/include/asm-i386/bitops.h Thu Nov 13 14:55:41 2014 +0100
@@ -318,6 +318,20 @@ static inline unsigned long __ffs(unsign
return word;
}
+/*
+ * __fls: find last bit set.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+ __asm__("bsrl %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+}
+
/**
* find_first_bit - find the first set bit in a memory region
* @addr: The address to start the search at
diff -r 6d727f2dcc83 -r 78e400792c76 include/asm-i386/mach-xen/asm/dma-mapping.h
--- a/include/asm-i386/mach-xen/asm/dma-mapping.h Thu Nov 13 14:51:07
2014 +0100
+++ b/include/asm-i386/mach-xen/asm/dma-mapping.h Thu Nov 13 14:55:41
2014 +0100
@@ -12,6 +12,8 @@
#include <asm/scatterlist.h>
#include <asm/swiotlb.h>
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
static inline int
address_needs_mapping(struct device *hwdev, dma_addr_t addr)
{
diff -r 6d727f2dcc83 -r 78e400792c76
include/asm-x86_64/mach-xen/asm/dma-mapping.h
--- a/include/asm-x86_64/mach-xen/asm/dma-mapping.h Thu Nov 13 14:51:07
2014 +0100
+++ b/include/asm-x86_64/mach-xen/asm/dma-mapping.h Thu Nov 13 14:55:41
2014 +0100
@@ -11,6 +11,8 @@
#include <asm/io.h>
#include <asm/swiotlb.h>
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
struct dma_mapping_ops {
int (*mapping_error)(dma_addr_t dma_addr);
void* (*alloc_coherent)(struct device *dev, size_t size,
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |