integrate dma_ops
Subsystems (4)
cover integrate dma_ops
Hi,
This is the final integration of dma_ops between x86_64 and i386. The final code is closer to x86_64 than to i386, which is obviously expected.
At the end, pci-dma_{32,64}.c are gone, pci-nommu_64.c is gone, and the temporary pci-base_32.c is gone too.
This patchset received the same level of scrutiny as the others from my side:
compiled tested in at least 6 different random configs, boot tested in my hardware.
The final diffstat says:
Documentation/feature-removal-schedule.txt | 7 arch/x86/kernel/Makefile | 9 arch/x86/kernel/pci-base_32.c | 72 --- arch/x86/kernel/pci-dma.c | 524 +++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 503 +++++++-------------------- arch/x86/kernel/pci-dma_64.c | 443 +----------------------- arch/x86/kernel/pci-nommu.c | 100 +++++ arch/x86/kernel/pci-nommu_64.c | 140 ------- arch/x86/mm/init_64.c | 4 include/asm-x86/dma-mapping.h | 14 include/asm-x86/scatterlist.h | 3 11 files changed, 832 insertions(+), 987 deletions(-)
PATCH 1/28 x86: introduce pci-dma.c
This patch introduces pci-dma.c, a common file for pci dma between i386 and x86_64. As a start, dma_set_mask() is the same between architectures, and is placed there.
--- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/pci-dma.c | 14 ++++++++++++++ arch/x86/kernel/pci-dma_32.c | 12 ------------ arch/x86/kernel/pci-dma_64.c | 9 --------- 4 files changed, 15 insertions(+), 22 deletions(-) create mode 100644 arch/x86/kernel/pci-dma.c
arch/x86/kernel/Makefile +1 -1
@@ -24,7 +24,7 @@ obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o obj-y += pci-dma_$(BITS).o bootflag.o e820_$(BITS).o -obj-y += quirks.o i8237.o topology.o kdebugfs.o +obj-y += pci-dma.o 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
arch/x86/kernel/pci-dma.c new file +14 -0
@@ -0,0 +1,14 @@ +#include <linux/dma-mapping.h> + +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 ; +} +EXPORT_SYMBOL (dma_set_mask); + +
arch/x86/kernel/pci-dma_32.c +0 -12
@@ -182,18 +182,6 @@ dma_supported(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_supported); -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 ; -} -EXPORT_SYMBOL (dma_set_mask); -static __devinit void via_no_dac (struct pci_dev *dev) {
arch/x86/kernel/pci-dma_64.c +0 -9
@@ -213,15 +213,6 @@ int dma_supported(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_supported); -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 ; -} -EXPORT_SYMBOL (dma_set_mask); -/* * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter * documentation.
Signature · 1 line
1.5.0.6
PATCH 2/28 x86: delete empty functions from pci-nommu_64.c
In reply to Glauber CostaThis functions are now called conditionally on their existence in the struct. So just delete them, instead of keeping an empty implementation.
--- arch/x86/kernel/pci-nommu_64.c | 15 --------------- 1 files changed, 0 insertions(+), 15 deletions(-)
arch/x86/kernel/pci-nommu_64.c +0 -15
@@ -35,10 +35,6 @@ nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,return bus; } -static void nommu_unmap_single (struct device *dev,dma_addr_t addr,size_t size, -int direction) -{ -}/* Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scatter-gather version of the
@@ -71,20 +67,9 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,return nents; } -/* Unmap a set of streaming mode DMA translations. -* Again, cpu read rules concerning calls here are the same as for -* pci_unmap_single() above. -*/ -static void nommu_unmap_sg (struct device *dev,struct scatterlist *sg, -int nents,int dir) -{ -} -const struct dma_mapping_ops nommu_dma_ops = { .map_single = nommu_map_single, - .unmap_single = nommu_unmap_single, .map_sg = nommu_map_sg, - .unmap_sg = nommu_unmap_sg, .is_phys =1 , };
Signature · 1 line
1.5.0.6
PATCH 3/28 x86: implement mapping_error in pci-nommu_64.c
In reply to Glauber CostaThis patch implements mapping_error for pci-nommu_64.c. It takes care to keep the same compatible behaviour it already had. Although this file is not (yet) used for i386, we introduce the i386 version here. Again, care is taken, even at the expense of an ifdef, to keep the same behaviour inconditionally.
--- arch/x86/kernel/pci-nommu_64.c | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
arch/x86/kernel/pci-nommu_64.c +12 -0
@@ -67,9 +67,21 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,return nents; } +/* Make sure we keep the same behaviour */ +static int nommu_mapping_error (dma_addr_t dma_addr) +{ +#ifdef CONFIG_X86_32 +return 0 ; +#else +return (dma_addr == bad_dma_address); +#endif +} + +const struct dma_mapping_ops nommu_dma_ops = { .map_single = nommu_map_single, .map_sg = nommu_map_sg, + .mapping_error = nommu_mapping_error, .is_phys =1 , };
Signature · 1 line
1.5.0.6
PATCH 4/28 x86: Add flush_write_buffers in nommu functions
In reply to Glauber CostaThis patch adds flush_write_buffers() in some functions of pci-nommu_64.c They are added anywhere i386 would also have it. This is not a problem for x86_64, since flush_rite_buffers() an nop for it.
--- arch/x86/kernel/pci-nommu_64.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86/kernel/pci-nommu_64.c +2 -0
@@ -32,6 +32,7 @@ nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,dma_addr_t bus = paddr;if (!check_addr ("map_single" , hwdev, bus, size))return bad_dma_address; +flush_write_buffers ();return bus; }
@@ -64,6 +65,7 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,return 0 ; s->dma_length = s->length; } +flush_write_buffers ();return nents; }
Signature · 1 line
1.5.0.6
PATCH 5/28 x86: use sg_phys in x86_64
In reply to Glauber CostaTo make the code usable in i386, where we have high memory mappings, we drop te virt_to_bus(sg_virt()) construction in favour of sg_phys.
--- arch/x86/kernel/pci-nommu_64.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kernel/pci-nommu_64.c +1 -1
@@ -60,7 +60,7 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,for_each_sg (sg, s, nents, i) {BUG_ON (!sg_page (s)); - s->dma_address =virt_to_bus (sg_virt (s)); + s->dma_address =sg_phys (s);if (!check_addr ("map_sg" , hwdev, s->dma_address, s->length))return 0 ; s->dma_length = s->length;
Signature · 1 line
1.5.0.6
PATCH 6/28 x86: use dma_length in i386
In reply to Glauber CostaThis is done to get the code closer to x86_64.
--- arch/x86/kernel/pci-base_32.c | 1 + include/asm-x86/scatterlist.h | 2 -- 2 files changed, 1 insertions(+), 2 deletions(-)
arch/x86/kernel/pci-base_32.c +1 -0
@@ -24,6 +24,7 @@ static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,BUG_ON (!sg_page (sg)); sg->dma_address =sg_phys (sg); + sg->dma_length = sg->length; }flush_write_buffers ();
include/asm-x86/scatterlist.h +0 -2
@@ -11,9 +11,7 @@ struct scatterlist {unsigned int offset;unsigned int length;dma_addr_t dma_address; -#ifdef CONFIG_X86_64 unsigned int dma_length; -#endif };#define ARCH_HAS_SG_CHAIN
Signature · 1 line
1.5.0.6
PATCH 7/28 x86: use WARN_ON in mapping functions
In reply to Glauber CostaIn the very same way i386 do, we use WARN_ON functions in map_simple and map_sg.
--- arch/x86/kernel/pci-nommu_64.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/x86/kernel/pci-nommu_64.c +3 -0
@@ -30,6 +30,7 @@ nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int direction) {dma_addr_t bus = paddr; +WARN_ON (size ==0 );if (!check_addr ("map_single" , hwdev, bus, size))return bad_dma_address;flush_write_buffers ();
@@ -58,6 +59,8 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,struct scatterlist *s;int i; +WARN_ON (nents ==0 || sg[0 ].length ==0 ); +for_each_sg (sg, s, nents, i) {BUG_ON (!sg_page (s)); s->dma_address =sg_phys (s);
Signature · 1 line
1.5.0.6
PATCH 8/28 x86: move definition to pci-dma.c
In reply to Glauber CostaMove dma_ops structure definition to pci-dma.c, where it belongs.
--- arch/x86/kernel/pci-base_32.c | 11 ++++++++--- arch/x86/kernel/pci-dma.c | 3 +++ arch/x86/mm/init_64.c | 3 --- 3 files changed, 11 insertions(+), 6 deletions(-)
arch/x86/kernel/pci-base_32.c +8 -3
@@ -37,7 +37,7 @@ static int pci32_map_error(dma_addr_t dma_addr)return 0 ; } -static const struct dma_mapping_ops pci32_dma_ops = { +const struct dma_mapping_ops pci32_dma_ops = { .map_single = pci32_map_single, .unmap_single =NULL , .map_sg = pci32_dma_map_sg,
@@ -51,5 +51,10 @@ static const struct dma_mapping_ops pci32_dma_ops = { .mapping_error = pci32_map_error, }; -const struct dma_mapping_ops *dma_ops = &pci32_dma_ops; -EXPORT_SYMBOL (dma_ops); +/* this is temporary */ +int __init no_iommu_init (void ) +{ + dma_ops = &pci32_dma_ops; +return 0 ; +} +fs_initcall (no_iommu_init);
arch/x86/kernel/pci-dma.c +3 -0
@@ -1,5 +1,8 @@#include <linux/dma-mapping.h> +const struct dma_mapping_ops *dma_ops; +EXPORT_SYMBOL (dma_ops); +int dma_set_mask (struct device *dev,u64 mask) {if (!dev->dma_mask || !dma_supported (dev, mask))
arch/x86/mm/init_64.c +0 -3
@@ -47,9 +47,6 @@#include <asm/numa.h> #include <asm/cacheflush.h> -const struct dma_mapping_ops *dma_ops; -EXPORT_SYMBOL (dma_ops); -static unsigned long dma_reserve__initdata ; DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
Signature · 1 line
1.5.0.6
PATCH 9/28 x86: move initialization functions to pci-dma.c
In reply to Glauber Costainitcalls that triggers the various possibiities for dma subsys are moved to pci-dma.c.
--- arch/x86/kernel/pci-dma.c | 25 +++++++++++++++++++++++++ arch/x86/kernel/pci-dma_64.c | 23 ----------------------- 2 files changed, 25 insertions(+), 23 deletions(-)
arch/x86/kernel/pci-dma.c +25 -0
@@ -1,4 +1,8 @@#include <linux/dma-mapping.h> +#include <linux/dmar.h> + +#include <asm/gart.h> +#include <asm/calgary.h> const struct dma_mapping_ops *dma_ops;EXPORT_SYMBOL (dma_ops);
@@ -14,4 +18,25 @@ int dma_set_mask(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_set_mask); +static int __init pci_iommu_init (void ) +{ +#ifdef CONFIG_CALGARY_IOMMU +calgary_iommu_init (); +#endif + +intel_iommu_init (); +#ifdef CONFIG_GART_IOMMU +gart_iommu_init (); +#endif + +no_iommu_init (); +return 0 ; +} + +void pci_iommu_shutdown (void ) +{ +gart_iommu_shutdown (); +} +/* Must execute after PCI subsystem */ +fs_initcall (pci_iommu_init);
arch/x86/kernel/pci-dma_64.c +0 -23
@@ -347,27 +347,6 @@ void __init pci_iommu_alloc(void)#endif } -static int __init pci_iommu_init (void ) -{ -#ifdef CONFIG_CALGARY_IOMMU -calgary_iommu_init (); -#endif - -intel_iommu_init (); - -#ifdef CONFIG_GART_IOMMU -gart_iommu_init (); -#endif - -no_iommu_init (); -return 0 ; -} - -void pci_iommu_shutdown (void ) -{ -gart_iommu_shutdown (); -} -#ifdef CONFIG_PCI /* Many VIA bridges seem to corrupt data for DAC. Disable it here */
@@ -380,5 +359,3 @@ static __devinit void via_no_dac(struct pci_dev *dev) }DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac);#endif -/* Must execute after PCI subsystem */ -fs_initcall (pci_iommu_init);
Signature · 1 line
1.5.0.6
PATCH 10/28 x86: unify pci-nommu
In reply to Glauber Costamerge pci-base_32.c and pci-nommu_64.c into pci-nommu.c Their code were made the same, so now they can be merged.
--- arch/x86/kernel/Makefile | 5 +- arch/x86/kernel/pci-base_32.c | 60 ------------------------ arch/x86/kernel/pci-dma.c | 8 +++ arch/x86/kernel/pci-dma_64.c | 8 --- arch/x86/kernel/pci-nommu.c | 100 ++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/pci-nommu_64.c | 100 ---------------------------------------- 6 files changed, 110 insertions(+), 171 deletions(-) delete mode 100644 arch/x86/kernel/pci-base_32.c create mode 100644 arch/x86/kernel/pci-nommu.c delete mode 100644 arch/x86/kernel/pci-nommu_64.c
arch/x86/kernel/Makefile +2 -3
@@ -25,9 +25,8 @@ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o obj-y += pci-dma_$(BITS).o bootflag.o e820_$(BITS).o obj-y += pci-dma.o 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 += alternative.o i8253.o pci-nommu.o +obj-$(CONFIG_X86_64) += bugs_64.o obj-y += tsc_$(BITS).o io_delay.o rtc.o obj-y += process.o
arch/x86/kernel/pci-base_32.c deleted +0 -60
60 lines not on this page · raw message
arch/x86/kernel/pci-dma.c +8 -0
@@ -7,6 +7,14 @@const struct dma_mapping_ops *dma_ops;EXPORT_SYMBOL (dma_ops); +#ifdef CONFIG_IOMMU_DEBUG +int panic_on_overflow__read_mostly =1 ; +int force_iommu__read_mostly =1 ; +#else +int panic_on_overflow__read_mostly =0 ; +int force_iommu__read_mostly =0 ; +#endif +int dma_set_mask (struct device *dev,u64 mask) {if (!dev->dma_mask || !dma_supported (dev, mask))
arch/x86/kernel/pci-dma_64.c +0 -8
@@ -27,14 +27,6 @@ EXPORT_SYMBOL(iommu_bio_merge);static int iommu_sac_force__read_mostly =0 ;int no_iommu__read_mostly ; -#ifdef CONFIG_IOMMU_DEBUG -int panic_on_overflow__read_mostly =1 ; -int force_iommu__read_mostly =1 ; -#else -int panic_on_overflow__read_mostly =0 ; -int force_iommu__read_mostly =0 ; -#endif -/* Set this to 1 if there is a HW IOMMU in the system */ int iommu_detected__read_mostly =0 ;
arch/x86/kernel/pci-nommu.c new file +100 -0
100 lines not on this page · raw message
arch/x86/kernel/pci-nommu_64.c deleted +0 -100
100 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 11/28 x86: move pci fixup to pci-dma.c
In reply to Glauber Costavia_no_dac provides a fixup that is the same for both architectures. Move it to pci-dma.c.
--- arch/x86/kernel/pci-dma.c | 18 ++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 13 ------------- arch/x86/kernel/pci-dma_64.c | 15 --------------- include/asm-x86/dma-mapping.h | 2 +- 4 files changed, 19 insertions(+), 29 deletions(-)
arch/x86/kernel/pci-dma.c +18 -0
@@ -1,9 +1,13 @@#include <linux/dma-mapping.h> #include <linux/dmar.h> +#include <linux/pci.h> #include <asm/gart.h> #include <asm/calgary.h> +int forbid_dac__read_mostly ; +EXPORT_SYMBOL (forbid_dac); +const struct dma_mapping_ops *dma_ops;EXPORT_SYMBOL (dma_ops);
@@ -48,3 +52,17 @@ void pci_iommu_shutdown(void) }/* Must execute after PCI subsystem */ fs_initcall (pci_iommu_init); + +#ifdef CONFIG_PCI +/* Many VIA bridges seem to corrupt data for DAC. Disable it here */ + +static __devinit void via_no_dac (struct pci_dev *dev) +{ +if ((dev->class >>8 ) ==PCI_CLASS_BRIDGE_PCI && forbid_dac ==0 ) { +printk (KERN_INFO "PCI: VIA PCI bridge detected." +"Disabling DAC.\n" ); + forbid_dac =1 ; + } +} +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac); +#endif
arch/x86/kernel/pci-dma_32.c +0 -13
@@ -157,9 +157,6 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);#ifdef CONFIG_PCI /* Many VIA bridges seem to corrupt data for DAC. Disable it here */ -int forbid_dac; -EXPORT_SYMBOL (forbid_dac); -int dma_supported (struct device *dev,u64 mask) {
@@ -182,16 +179,6 @@ dma_supported(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_supported); - -static __devinit void via_no_dac (struct pci_dev *dev) -{ -if ((dev->class >>8 ) ==PCI_CLASS_BRIDGE_PCI && forbid_dac ==0 ) { -printk (KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n" ); - forbid_dac =1 ; - } -} -DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac); -static int check_iommu (char *s) {if (!strcmp (s,"usedac" )) {
arch/x86/kernel/pci-dma_64.c +0 -15
@@ -161,8 +161,6 @@ void dma_free_coherent(struct device *dev, size_t size, }EXPORT_SYMBOL (dma_free_coherent); -static int forbid_dac__read_mostly ; -int dma_supported (struct device *dev,u64 mask) {#ifdef CONFIG_PCI
@@ -338,16 +336,3 @@ void __init pci_iommu_alloc(void)pci_swiotlb_init ();#endif } - -#ifdef CONFIG_PCI -/* Many VIA bridges seem to corrupt data for DAC. Disable it here */ - -static __devinit void via_no_dac (struct pci_dev *dev) -{ -if ((dev->class >>8 ) ==PCI_CLASS_BRIDGE_PCI && forbid_dac ==0 ) { -printk (KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n" ); - forbid_dac =1 ; - } -} -DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac); -#endif
include/asm-x86/dma-mapping.h +1 -1
@@ -14,6 +14,7 @@ extern dma_addr_t bad_dma_address;extern int iommu_merge;extern struct device fallback_dev;extern int panic_on_overflow; +extern int forbid_dac;struct dma_mapping_ops {int (*mapping_error)(dma_addr_t dma_addr);
@@ -223,6 +224,5 @@ 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
Signature · 1 line
1.5.0.6
PATCH 12/28 x86: move x86_64-specific to common code.
In reply to Glauber CostaThis patch moves the bootmem functions, that are largely x86_64-specific into pci-dma.c. The code goes inside an ifdef.
--- arch/x86/kernel/pci-dma.c | 73 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_64.c | 68 --------------------------------------- 2 files changed, 73 insertions(+), 68 deletions(-)
arch/x86/kernel/pci-dma.c +73 -0
@@ -1,7 +1,10 @@#include <linux/dma-mapping.h> #include <linux/dmar.h> #include <linux/pci.h> +#include <linux/bootmem.h> +#include <asm/proto.h> +#include <asm/dma.h> #include <asm/gart.h> #include <asm/calgary.h>
@@ -66,3 +69,73 @@ static __devinit void via_no_dac(struct pci_dev *dev) }DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac);#endif + +#ifdef CONFIG_X86_64 +static __initdata void *dma32_bootmem_ptr; +static unsigned long dma32_bootmem_size__initdata = (128ULL <<20 ); + +static int __init parse_dma32_size_opt (char *p) +{ +if (!p) +return -EINVAL ; + dma32_bootmem_size =memparse (p, &p); +return 0 ; +} +early_param ("dma32_size" , parse_dma32_size_opt); + +void __init dma32_reserve_bootmem (void ) +{ +unsigned long size, align; +if (end_pfn <=MAX_DMA32_PFN ) +return ; + + align =64ULL <<20 ; + size =round_up (dma32_bootmem_size, align); + dma32_bootmem_ptr =__alloc_bootmem_nopanic (size, align, +__pa (MAX_DMA_ADDRESS )); +if (dma32_bootmem_ptr) + dma32_bootmem_size = size; +else + dma32_bootmem_size =0 ; +} +static void __init dma32_free_bootmem (void ) +{ +int node; + +if (end_pfn <=MAX_DMA32_PFN ) +return ; + +if (!dma32_bootmem_ptr) +return ; + +for_each_online_node (node) +free_bootmem_node (NODE_DATA (node),__pa (dma32_bootmem_ptr), + dma32_bootmem_size); + + dma32_bootmem_ptr =NULL ; + dma32_bootmem_size =0 ; +} + +void __init pci_iommu_alloc (void ) +{ +/* free the range so iommu could get some range less than 4G */ +dma32_free_bootmem (); +/* +* The order of these functions is important for +* fall-back/fail-over reasons +*/ +#ifdef CONFIG_GART_IOMMU +gart_iommu_hole_init (); +#endif + +#ifdef CONFIG_CALGARY_IOMMU +detect_calgary (); +#endif + +detect_intel_iommu (); + +#ifdef CONFIG_SWIOTLB +pci_swiotlb_init (); +#endif +} +#endif
arch/x86/kernel/pci-dma_64.c +0 -68
71 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 13/28 x86: merge dma_supported
In reply to Glauber CostaThe code for both arches are very similar, so this patch merge them.
--- arch/x86/kernel/pci-dma.c | 44 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 24 ---------------------- arch/x86/kernel/pci-dma_64.c | 44 +----------------------------------------- 3 files changed, 45 insertions(+), 67 deletions(-)
arch/x86/kernel/pci-dma.c +44 -0
@@ -14,6 +14,8 @@ EXPORT_SYMBOL(forbid_dac);const struct dma_mapping_ops *dma_ops;EXPORT_SYMBOL (dma_ops); +int iommu_sac_force__read_mostly =0 ; +#ifdef CONFIG_IOMMU_DEBUG int panic_on_overflow__read_mostly =1 ;int force_iommu__read_mostly =1 ;
@@ -33,6 +35,48 @@ int dma_set_mask(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_set_mask); +int dma_supported (struct device *dev,u64 mask) +{ +#ifdef CONFIG_PCI +if (mask >0xffffffff && forbid_dac >0 ) { +printk (KERN_INFO "PCI: Disallowing DAC for device %s\n" , + dev->bus_id); +return 0 ; + } +#endif + +if (dma_ops->dma_supported) +return dma_ops->dma_supported (dev, mask); + +/* Copied from i386. Doesn't make much sense, because it will +only work for pci_alloc_coherent. +The caller just has to use GFP_DMA in this case. */ +if (mask <DMA_24BIT_MASK ) +return 0 ; + +/* Tell the device to use SAC when IOMMU force is on. This +allows the driver to use cheaper accesses in some cases. + +Problem with this is that if we overflow the IOMMU area and +return DAC as fallback address the device may not handle it +correctly. + +As a special case some controllers have a 39bit address +mode that is as efficient as 32bit (aic79xx). Don't force +SAC for these. Assume all masks <= 40 bits are of this +type. Normally this doesn't make any difference, but gives +more gentle handling of IOMMU overflow. */ +if (iommu_sac_force && (mask >=DMA_40BIT_MASK )) { +printk (KERN_INFO "%s: Force SAC with mask %Lx\n" , + dev->bus_id, mask); +return 0 ; + } + +return 1 ; +} +EXPORT_SYMBOL (dma_supported); + +static int __init pci_iommu_init (void ) {#ifdef CONFIG_CALGARY_IOMMU
arch/x86/kernel/pci-dma_32.c +0 -24
@@ -155,30 +155,6 @@ void *dma_mark_declared_memory_occupied(struct device *dev,EXPORT_SYMBOL (dma_mark_declared_memory_occupied);#ifdef CONFIG_PCI -/* Many VIA bridges seem to corrupt data for DAC. Disable it here */ - -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 ; -} -EXPORT_SYMBOL (dma_supported); -static int check_iommu (char *s) {if (!strcmp (s,"usedac" )) {
arch/x86/kernel/pci-dma_64.c +1 -43
56 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 14/28 x86: merge iommu initialization parameters
In reply to Glauber Costawe merge the iommu initialization parameters in pci-dma.c Nice thing, that both architectures at least recognize the same parameters.
usedac i386 parameter is marked for deprecation
--- Documentation/feature-removal-schedule.txt | 7 +++ arch/x86/kernel/pci-dma.c | 81 ++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 12 ---- arch/x86/kernel/pci-dma_64.c | 79 --------------------------- include/asm-x86/dma-mapping.h | 1 + 5 files changed, 89 insertions(+), 91 deletions(-)
Documentation/feature-removal-schedule.txt +7 -0
@@ -306,3 +306,10 @@ Why: Not used in-tree. The current out-of-tree users used it to code / infrastructure should be in the kernel and not in some out-of-tree driver. Who: Thomas Gleixner <[email protected]> + +---------------------------- + +What: usedac i386 kernel parameter +When: 2.6.27 +Why: replaced by allowdac and no dac combination +Who: Glauber Costa <[email protected]>
arch/x86/kernel/pci-dma.c +81 -0
90 lines not on this page · raw message
arch/x86/kernel/pci-dma_32.c +0 -12
@@ -153,15 +153,3 @@ void *dma_mark_declared_memory_occupied(struct device *dev,return mem->virt_base + (pos <<PAGE_SHIFT ); }EXPORT_SYMBOL (dma_mark_declared_memory_occupied); - -#ifdef CONFIG_PCI -static int check_iommu (char *s) -{ -if (!strcmp (s,"usedac" )) { - forbid_dac =-1 ; -return 1 ; - } -return 0 ; -} -__setup ("iommu=" , check_iommu); -#endif
arch/x86/kernel/pci-dma_64.c +0 -79
91 lines not on this page · raw message
include/asm-x86/dma-mapping.h +1 -0
@@ -15,6 +15,7 @@ extern int iommu_merge;extern struct device fallback_dev;extern int panic_on_overflow;extern int forbid_dac; +extern int force_iommu;struct dma_mapping_ops {int (*mapping_error)(dma_addr_t dma_addr);
Signature · 1 line
1.5.0.6
PATCH 15/28 x86: move dma_coherent functions to pci-dma.c
In reply to Glauber CostaThey are placed in an ifdef, since they are i386 specific the structure definition goes to dma-mapping.h.
--- arch/x86/kernel/pci-dma.c | 81 +++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 85 ----------------------------------------- include/asm-x86/dma-mapping.h | 8 ++++ 3 files changed, 89 insertions(+), 85 deletions(-)
arch/x86/kernel/pci-dma.c +81 -0
@@ -47,6 +47,87 @@ int dma_set_mask(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_set_mask); +#ifdef CONFIG_X86_32 +int dma_declare_coherent_memory (struct device *dev,dma_addr_t bus_addr, +dma_addr_t device_addr,size_t size,int flags) +{ +void __iomem *mem_base =NULL ; +int pages = size >>PAGE_SHIFT ; +int bitmap_size =BITS_TO_LONGS (pages) *sizeof (long ); + +if ((flags & (DMA_MEMORY_MAP |DMA_MEMORY_IO )) ==0 ) + goto out; +if (!size) + goto out; +if (dev->dma_mem) + goto out; + +/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ + + mem_base =ioremap (bus_addr, size); +if (!mem_base) + goto out; + + dev->dma_mem =kzalloc (sizeof (struct dma_coherent_mem ),GFP_KERNEL ); +if (!dev->dma_mem) + goto out; + dev->dma_mem->bitmap =kzalloc (bitmap_size,GFP_KERNEL ); +if (!dev->dma_mem->bitmap) + goto free1_out; + + dev->dma_mem->virt_base = mem_base; + dev->dma_mem->device_base = device_addr; + dev->dma_mem->size = pages; + dev->dma_mem->flags = flags; + +if (flags &DMA_MEMORY_MAP ) +return DMA_MEMORY_MAP ; + +return DMA_MEMORY_IO ; + + free1_out: +kfree (dev->dma_mem); + out: +if (mem_base) +iounmap (mem_base); +return 0 ; +} +EXPORT_SYMBOL (dma_declare_coherent_memory); + +void dma_release_declared_memory (struct device *dev) +{ +struct dma_coherent_mem *mem = dev->dma_mem; + +if (!mem) +return ; + dev->dma_mem =NULL ; +iounmap (mem->virt_base); +kfree (mem->bitmap); +kfree (mem); +} +EXPORT_SYMBOL (dma_release_declared_memory); + +void *dma_mark_declared_memory_occupied (struct device *dev, +dma_addr_t device_addr,size_t size) +{ +struct dma_coherent_mem *mem = dev->dma_mem; +int pos, err; +int pages = (size + (device_addr & ~PAGE_MASK ) +PAGE_SIZE -1 ); + + pages >>=PAGE_SHIFT ; + +if (!mem) +return ERR_PTR (-EINVAL ); + + pos = (device_addr - mem->device_base) >>PAGE_SHIFT ; + err =bitmap_allocate_region (mem->bitmap, pos,get_order (pages)); +if (err !=0 ) +return ERR_PTR (err); +return mem->virt_base + (pos <<PAGE_SHIFT ); +} +EXPORT_SYMBOL (dma_mark_declared_memory_occupied); +#endif /* CONFIG_X86_32 */ +int dma_supported (struct device *dev,u64 mask) {#ifdef CONFIG_PCI
arch/x86/kernel/pci-dma_32.c +0 -85
94 lines not on this page · raw message
include/asm-x86/dma-mapping.h +8 -0
@@ -215,6 +215,14 @@ static inline int dma_get_cache_alignment(void)#ifdef CONFIG_X86_32 # define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY +struct dma_coherent_mem { +void *virt_base; +u32 device_base; +int size; +int flags; +unsigned long *bitmap; +}; +extern int dma_declare_coherent_memory (struct device *dev,dma_addr_t bus_addr,dma_addr_t device_addr,size_t size,int flags);
Signature · 1 line
1.5.0.6
PATCH 16/28 x86: isolate coherent mapping functions
In reply to Glauber Costai386 implements the declare coherent memory API, and x86_64 does not it is reflected in pieces of dma_alloc_coherent and dma_free_coherent. Those pieces are isolated in separate functions, that are declared as empty macros in x86_64. This way we can make the code the same.
--- arch/x86/kernel/pci-dma_32.c | 51 ++++++++++++++++++++++++++++------------- arch/x86/kernel/pci-dma_64.c | 11 ++++++++- 2 files changed, 45 insertions(+), 17 deletions(-)
arch/x86/kernel/pci-dma_32.c +35 -16
@@ -18,27 +18,50 @@dma_addr_t bad_dma_address__read_mostly =0x0 ;EXPORT_SYMBOL (bad_dma_address); -void *dma_alloc_coherent (struct device *dev,size_t size, -dma_addr_t *dma_handle,gfp_t gfp) +static int dma_alloc_from_coherent_mem (struct device *dev,ssize_t size, +dma_addr_t *dma_handle,void **ret) { -void *ret;struct dma_coherent_mem *mem = dev ? dev->dma_mem :NULL ;int order =get_order (size); -/* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);if (mem) {int page =bitmap_find_free_region (mem->bitmap, mem->size, order);if (page >=0 ) { *dma_handle = mem->device_base + (page <<PAGE_SHIFT ); - ret = mem->virt_base + (page <<PAGE_SHIFT ); -memset (ret,0 , size); -return ret; + *ret = mem->virt_base + (page <<PAGE_SHIFT ); +memset (*ret,0 , size); }if (mem->flags &DMA_MEMORY_EXCLUSIVE ) -return NULL ; + *ret =NULL ; + } +return (mem !=NULL ); +} + +static int dma_release_coherent (struct device *dev,int order,void *vaddr) +{ +struct dma_coherent_mem *mem = dev ? dev->dma_mem :NULL ; + +if (mem && vaddr >= mem->virt_base && vaddr < + (mem->virt_base + (mem->size <<PAGE_SHIFT ))) { +int page = (vaddr - mem->virt_base) >>PAGE_SHIFT ; + +bitmap_release_region (mem->bitmap, page, order); +return 1 ; } +return 0 ; +} + +void *dma_alloc_coherent (struct device *dev,size_t size, +dma_addr_t *dma_handle,gfp_t gfp) +{ +void *ret =NULL ; +int order =get_order (size); +/* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + +if (dma_alloc_from_coherent_mem (dev, size, dma_handle, &ret)) +return ret;if (dev ==NULL || (dev->coherent_dma_mask <0xffffffff )) gfp |=GFP_DMA ;
@@ -56,15 +79,11 @@ EXPORT_SYMBOL(dma_alloc_coherent);void dma_free_coherent (struct device *dev,size_t size,void *vaddr,dma_addr_t dma_handle) { -struct dma_coherent_mem *mem = dev ? dev->dma_mem :NULL ;int order =get_order (size);WARN_ON (irqs_disabled ());/* for portability */ -if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size <<PAGE_SHIFT ))) { -int page = (vaddr - mem->virt_base) >>PAGE_SHIFT ; - -bitmap_release_region (mem->bitmap, page, order); - }else -free_pages ((unsigned long )vaddr, order); +if (dma_release_coherent (dev, order, vaddr)) +return ; +free_pages ((unsigned long )vaddr, order); }EXPORT_SYMBOL (dma_free_coherent);
arch/x86/kernel/pci-dma_64.c +10 -1
@@ -39,6 +39,8 @@ dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)return page ?page_address (page) :NULL ; } +#define dma_alloc_from_coherent_mem (dev, size, handle, ret) (0) +#define dma_release_coherent (dev, order, vaddr) (0)/* * Allocate memory for a coherent mapping. */
@@ -50,6 +52,10 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,unsigned long dma_mask =0 ;u64 bus; + +if (dma_alloc_from_coherent_mem (dev, size, dma_handle, &memory)) +return memory; +if (!dev) dev = &fallback_dev; dma_mask = dev->coherent_dma_mask;
@@ -141,9 +147,12 @@ EXPORT_SYMBOL(dma_alloc_coherent);void dma_free_coherent (struct device *dev,size_t size,void *vaddr,dma_addr_t bus) { +int order =get_order (size);WARN_ON (irqs_disabled ());/* for portability */ +if (dma_release_coherent (dev, order, vaddr)) +return ;if (dma_ops->unmap_single) dma_ops->unmap_single (dev, bus, size,0 ); -free_pages ((unsigned long )vaddr,get_order (size)); +free_pages ((unsigned long )vaddr, order); }EXPORT_SYMBOL (dma_free_coherent);
Signature · 1 line
1.5.0.6
PATCH 17/28 x86: adjust dma_free_coherent for i386
In reply to Glauber CostaWe call unmap_single, if available.
--- arch/x86/kernel/pci-dma_32.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86/kernel/pci-dma_32.c +2 -0
@@ -84,6 +84,8 @@ void dma_free_coherent(struct device *dev, size_t size,WARN_ON (irqs_disabled ());/* for portability */ if (dma_release_coherent (dev, order, vaddr))return ; +if (dma_ops->unmap_single) + dma_ops->unmap_single (dev, dma_handle, size,0 );free_pages ((unsigned long )vaddr, order); }EXPORT_SYMBOL (dma_free_coherent);
Signature · 1 line
1.5.0.6
PATCH 18/28 x86: move bad_dma_address
In reply to Glauber CostaIt goes to pci-dma.c, and is removed from the arch-specific files.
--- arch/x86/kernel/pci-dma.c | 2 ++ arch/x86/kernel/pci-dma_32.c | 4 ---- arch/x86/kernel/pci-dma_64.c | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-)
arch/x86/kernel/pci-dma.c +2 -0
@@ -35,6 +35,8 @@ int iommu_detected __read_mostly = 0;int iommu_bio_merge__read_mostly =0 ;EXPORT_SYMBOL (iommu_bio_merge); +dma_addr_t bad_dma_address__read_mostly =0 ; +EXPORT_SYMBOL (bad_dma_address);int dma_set_mask (struct device *dev,u64 mask) {
arch/x86/kernel/pci-dma_32.c +0 -4
@@ -14,10 +14,6 @@#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); -static int dma_alloc_from_coherent_mem (struct device *dev,ssize_t size,dma_addr_t *dma_handle,void **ret) {
arch/x86/kernel/pci-dma_64.c +0 -2
@@ -14,8 +14,6 @@#include <asm/gart.h> #include <asm/calgary.h> -dma_addr_t bad_dma_address__read_mostly ; -EXPORT_SYMBOL (bad_dma_address);/* Dummy device used for NULL arguments (normally ISA). Better would be probably a smaller DMA mask, but this is bug-to-bug compatible
Signature · 1 line
1.5.0.6
PATCH 19/28 x86: remove virt_to_bus in pci-dma_64.c
In reply to Glauber Costavirt_to_bus() is deprecated according to the docs, and moreover, won't return the right thing in i386 if we're dealing with high memory mappings. So we make our allocation function return a page, and then use page_address() (for virtual addr) and page_to_phys() (for physical addr) instead.
--- arch/x86/kernel/pci-dma_64.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/kernel/pci-dma_64.c +7 -7
@@ -28,13 +28,11 @@ struct device fallback_dev = { noinline static void *dma_alloc_pages (struct device *dev,gfp_t gfp,unsigned order) { -struct page *page;int node; node =dev_to_node (dev); - page =alloc_pages_node (node, gfp, order); -return page ?page_address (page) :NULL ; +return alloc_pages_node (node, gfp, order); }#define dma_alloc_from_coherent_mem (dev, size, handle, ret) (0)
@@ -47,6 +45,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) {void *memory; +struct page *page;unsigned long dma_mask =0 ;u64 bus;
@@ -79,13 +78,14 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp |=GFP_DMA32 ; again: - memory =dma_alloc_pages (dev, gfp,get_order (size)); -if (memory ==NULL ) + page =dma_alloc_pages (dev, gfp,get_order (size)); +if (page ==NULL )return NULL ; {int high, mmu; - bus =virt_to_bus (memory); + bus =page_to_phys (page); + memory =page_address (page); high = (bus + size) >= dma_mask; mmu = high;if (force_iommu && !(gfp &GFP_DMA ))
@@ -112,7 +112,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,memset (memory,0 , size);if (!mmu) { - *dma_handle =virt_to_bus (memory); + *dma_handle = bus;return memory; } }
Signature · 1 line
1.5.0.6
PATCH 20/28 x86: use numa allocation function in i386
In reply to Glauber CostaWe can do it here to, in the same way x86_64 does.
--- arch/x86/kernel/pci-dma_32.c | 27 ++++++++++++++++++++++----- 1 files changed, 22 insertions(+), 5 deletions(-)
arch/x86/kernel/pci-dma_32.c +22 -5
@@ -48,10 +48,23 @@ static int dma_release_coherent(struct device *dev, int order, void *vaddr)return 0 ; } +/* Allocate DMA memory on node near device */ +noinline struct page * +dma_alloc_pages (struct device *dev,gfp_t gfp,unsigned order) +{ +int node; + + node =dev_to_node (dev); + +return alloc_pages_node (node, gfp, order); +} +void *dma_alloc_coherent (struct device *dev,size_t size,dma_addr_t *dma_handle,gfp_t gfp) {void *ret =NULL ; +struct page *page; +dma_addr_t bus;int order =get_order (size);/* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
@@ -62,12 +75,16 @@ void *dma_alloc_coherent(struct device *dev, size_t size,if (dev ==NULL || (dev->coherent_dma_mask <0xffffffff )) gfp |=GFP_DMA ; - ret = (void *)__get_free_pages (gfp, order); + page =dma_alloc_pages (dev, gfp, order); +if (page ==NULL ) +return NULL ; + + ret =page_address (page); + bus =page_to_phys (page); + +memset (ret,0 , size); + *dma_handle = bus; -if (ret !=NULL ) { -memset (ret,0 , size); - *dma_handle =virt_to_phys (ret); - }return ret; }EXPORT_SYMBOL (dma_alloc_coherent);
Signature · 1 line
1.5.0.6
PATCH 21/28 x86: retry allocation if failed
In reply to Glauber CostaThis patch puts in the code to retry allocation in case it fails. By its own, it does not make much sense but making the code look like x86_64. But later patches in this series will make we try to allocate from zones other than DMA first, which will possibly fail.
--- arch/x86/kernel/pci-dma_32.c | 34 +++++++++++++++++++++++++++++----- 1 files changed, 29 insertions(+), 5 deletions(-)
arch/x86/kernel/pci-dma_32.c +29 -5
@@ -66,6 +66,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size,struct page *page;dma_addr_t bus;int order =get_order (size); +unsigned long dma_mask =0 ; +/* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
@@ -75,15 +77,37 @@ void *dma_alloc_coherent(struct device *dev, size_t size,if (dev ==NULL || (dev->coherent_dma_mask <0xffffffff )) gfp |=GFP_DMA ; + dma_mask = dev->coherent_dma_mask; +if (dma_mask ==0 ) + dma_mask =DMA_32BIT_MASK ; + + again: page =dma_alloc_pages (dev, gfp, order);if (page ==NULL )return NULL ; - ret =page_address (page); - bus =page_to_phys (page); - -memset (ret,0 , size); - *dma_handle = bus; + { +int high, mmu; + bus =page_to_phys (page); + ret =page_address (page); + high = (bus + size) >= dma_mask; + mmu = high; +if (force_iommu && !(gfp &GFP_DMA )) + mmu =1 ; +else if (high) { +free_pages ((unsigned long )ret, +get_order (size)); + +/* Don't use the 16MB ZONE_DMA unless absolutely +needed. It's better to use remapping first. */ +if (dma_mask <DMA_32BIT_MASK && !(gfp &GFP_DMA )) { + gfp = (gfp & ~GFP_DMA32 ) |GFP_DMA ; + goto again; + } + } +memset (ret,0 , size); + *dma_handle = bus; + }return ret; }
Signature · 1 line
1.5.0.6
PATCH 22/28 x86: use a fallback dev for i386
In reply to Glauber CostaWe can use a fallback dev for cases of a NULL device being passed (mostly ISA) This comes from x86_64 implementation.
--- arch/x86/kernel/pci-dma_32.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
arch/x86/kernel/pci-dma_32.c +13 -0
@@ -14,6 +14,16 @@#include <linux/module.h> #include <asm/io.h> +/* Dummy device used for NULL arguments (normally ISA). Better would +be probably a smaller DMA mask, but this is bug-to-bug compatible +to i386. */ +struct device fallback_dev = { + .bus_id ="fallback device" , + .coherent_dma_mask =DMA_32BIT_MASK , + .dma_mask = &fallback_dev.coherent_dma_mask, +}; + +static int dma_alloc_from_coherent_mem (struct device *dev,ssize_t size,dma_addr_t *dma_handle,void **ret) {
@@ -77,6 +87,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,if (dev ==NULL || (dev->coherent_dma_mask <0xffffffff )) gfp |=GFP_DMA ; +if (!dev) + dev = &fallback_dev; + dma_mask = dev->coherent_dma_mask;if (dma_mask ==0 ) dma_mask =DMA_32BIT_MASK ;
Signature · 1 line
1.5.0.6
PATCH 23/28 x86: don't try to allocate from DMA zone at first
In reply to Glauber CostaIf we fail, we'll loop into the allocation again,
and then allocate in the DMA zone.
--- arch/x86/kernel/pci-dma_32.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/x86/kernel/pci-dma_32.c +0 -3
@@ -84,9 +84,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size,if (dma_alloc_from_coherent_mem (dev, size, dma_handle, &ret))return ret; -if (dev ==NULL || (dev->coherent_dma_mask <0xffffffff )) - gfp |=GFP_DMA ; -if (!dev) dev = &fallback_dev;
Signature · 1 line
1.5.0.6
PATCH 24/28 x86: unify gfp masks
In reply to Glauber CostaUse the same gfp masks for x86_64 and i386.
It involves using HIGHMEM or DMA32 where necessary, for the sake of code compatibility, (no real effect), and using the NORETRY mask for i386.
--- arch/x86/kernel/pci-dma_32.c | 6 ++++-- arch/x86/kernel/pci-dma_64.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-)
arch/x86/kernel/pci-dma_32.c +4 -2
@@ -79,7 +79,7 @@ void *dma_alloc_coherent(struct device *dev, size_t size,unsigned long dma_mask =0 ;/* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);if (dma_alloc_from_coherent_mem (dev, size, dma_handle, &ret))return ret;
@@ -91,7 +91,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,if (dma_mask ==0 ) dma_mask =DMA_32BIT_MASK ; - again: +/* Don't invoke OOM killer */ + gfp |= __GFP_NORETRY; +again: page =dma_alloc_pages (dev, gfp, order);if (page ==NULL )return NULL ;
arch/x86/kernel/pci-dma_64.c +2 -0
@@ -49,6 +49,8 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,unsigned long dma_mask =0 ;u64 bus; +/* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);if (dma_alloc_from_coherent_mem (dev, size, dma_handle, &memory))return memory;
Signature · 1 line
1.5.0.6
PATCH 25/28 x86: remove kludge from x86_64
In reply to Glauber CostaThe claim is that i386 does it. Just it does not.
So remove it.
--- arch/x86/kernel/pci-dma_64.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
arch/x86/kernel/pci-dma_64.c +0 -4
@@ -68,10 +68,6 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,/* Don't invoke OOM killer */ gfp |= __GFP_NORETRY; -/* Kludge to make it bug-to-bug compatible with i386. i386 -uses the normal dma_mask for alloc_coherent. */ - dma_mask &= *dev->dma_mask; -/* Why <=? Even when the mask is smaller than 4GB it is often larger than 16MB and in this case we have a chance of finding fitting memory in the next higher zone first. If
Signature · 1 line
1.5.0.6
PATCH 26/28 x86: return conditional to mmu
In reply to Glauber CostaJust return our allocation if we don't have an mmu. For i386, where this patch is being applied, we never have. So our goal is just to have the code to look like x86_64's.
--- arch/x86/kernel/pci-dma_32.c | 34 ++++++++++++++++++++++++++++++++-- 1 files changed, 32 insertions(+), 2 deletions(-)
arch/x86/kernel/pci-dma_32.c +32 -2
@@ -116,12 +116,42 @@ again: gfp = (gfp & ~GFP_DMA32 ) |GFP_DMA ; goto again; } + +/* Let low level make its own zone decisions */ + gfp &= ~(GFP_DMA32 |GFP_DMA ); + +if (dma_ops->alloc_coherent) +return dma_ops->alloc_coherent (dev, size, + dma_handle, gfp); +return NULL ; + }memset (ret,0 , size); - *dma_handle = bus; +if (!mmu) { + *dma_handle = bus; +return ret; + } + } + +if (dma_ops->alloc_coherent) { +free_pages ((unsigned long )ret,get_order (size)); + gfp &= ~(GFP_DMA |GFP_DMA32 ); +return dma_ops->alloc_coherent (dev, size, dma_handle, gfp); + } + +if (dma_ops->map_simple) { + *dma_handle = dma_ops->map_simple (dev,virt_to_phys (ret), + size, +PCI_DMA_BIDIRECTIONAL ); +if (*dma_handle != bad_dma_address) +return ret; } -return ret; +if (panic_on_overflow) +panic ("dma_alloc_coherent: IOMMU overflow by %lu bytes\n" , + (unsigned long )size); +free_pages ((unsigned long )ret,get_order (size)); +return NULL ; }EXPORT_SYMBOL (dma_alloc_coherent);
Signature · 1 line
1.5.0.6
PATCH 27/28 x86: don't do dma if mask is NULL.
In reply to Glauber Costaif the device hasn't provided a mask, abort allocation. Note that we're using a fallback device now, so it does not cover the case of a NULL device: just drivers passing NULL masks around.
--- arch/x86/kernel/pci-dma_32.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/x86/kernel/pci-dma_32.c +3 -0
@@ -91,6 +91,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,if (dma_mask ==0 ) dma_mask =DMA_32BIT_MASK ; +if (dev->dma_mask ==NULL ) +return NULL ; +/* Don't invoke OOM killer */ gfp |= __GFP_NORETRY; again:
Signature · 1 line
1.5.0.6
PATCH 28/28 x86: integrate pci-dma.c
In reply to Glauber CostaThe code in pci-dma_{32,64}.c are now sufficiently close to each other. We merge them in pci-dma.c.
--- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/pci-dma.c | 175 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 173 ----------------------------------------- arch/x86/kernel/pci-dma_64.c | 154 ------------------------------------- 4 files changed, 176 insertions(+), 328 deletions(-) delete mode 100644 arch/x86/kernel/pci-dma_32.c delete mode 100644 arch/x86/kernel/pci-dma_64.c
arch/x86/kernel/Makefile +1 -1
@@ -23,7 +23,7 @@ obj-y += setup_$(BITS).o i8259_$(BITS).o setup.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o -obj-y += pci-dma_$(BITS).o bootflag.o e820_$(BITS).o +obj-y += bootflag.o e820_$(BITS).o obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o obj-y += alternative.o i8253.o pci-nommu.o obj-$(CONFIG_X86_64) += bugs_64.o
arch/x86/kernel/pci-dma.c +175 -0
193 lines not on this page · raw message
arch/x86/kernel/pci-dma_32.c deleted +0 -173
173 lines not on this page · raw message
arch/x86/kernel/pci-dma_64.c deleted +0 -154
154 lines not on this page · raw message
Signature · 1 line
1.5.0.6