[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 |