Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Pull vtd-iommu into release branch

Conflicts:
arch/ia64/kernel/acpi.c

Tony Luck fe393164 22ca532a

+620 -13
+17
arch/ia64/Kconfig
··· 145 145 select NUMA 146 146 select ACPI_NUMA 147 147 select SWIOTLB 148 + select PCI_MSI 148 149 help 149 150 This selects the system type of your hardware. A "generic" kernel 150 151 will run on any supported IA-64 system. However, if you configure ··· 153 152 154 153 generic For any supported IA-64 system 155 154 DIG-compliant For DIG ("Developer's Interface Guide") compliant systems 155 + DIG+Intel+IOMMU For DIG systems with Intel IOMMU 156 156 HP-zx1/sx1000 For HP systems 157 157 HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. 158 158 SGI-SN2 For SGI Altix systems ··· 166 164 config IA64_DIG 167 165 bool "DIG-compliant" 168 166 select SWIOTLB 167 + 168 + config IA64_DIG_VTD 169 + bool "DIG+Intel+IOMMU" 170 + select DMAR 171 + select PCI_MSI 169 172 170 173 config IA64_HP_ZX1 171 174 bool "HP-zx1/sx1000" ··· 620 613 source "drivers/pci/hotplug/Kconfig" 621 614 622 615 source "drivers/pcmcia/Kconfig" 616 + 617 + config DMAR 618 + bool "Support for DMA Remapping Devices (EXPERIMENTAL)" 619 + depends on IA64_GENERIC && ACPI && EXPERIMENTAL 620 + help 621 + DMA remapping (DMAR) devices support enables independent address 622 + translations for Direct Memory Access (DMA) from devices. 623 + These DMA remapping devices are reported via ACPI tables 624 + and include PCI device scope covered by these DMA 625 + remapping devices. 623 626 624 627 endmenu 625 628
+1
arch/ia64/Makefile
··· 53 53 core-y += arch/ia64/kernel/ arch/ia64/mm/ 54 54 core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ 55 55 core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ 56 + core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ 56 57 core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ 57 58 core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ 58 59 core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
+2
arch/ia64/configs/generic_defconfig
··· 233 233 CONFIG_BINFMT_ELF=y 234 234 CONFIG_BINFMT_MISC=m 235 235 236 + # CONFIG_DMAR is not set 237 + 236 238 # 237 239 # Power management and ACPI 238 240 #
+2
arch/ia64/configs/tiger_defconfig
··· 172 172 CONFIG_BINFMT_ELF=y 173 173 CONFIG_BINFMT_MISC=m 174 174 175 + # CONFIG_DMAR is not set 176 + 175 177 # 176 178 # Power management and ACPI 177 179 #
+5
arch/ia64/dig/Makefile
··· 6 6 # 7 7 8 8 obj-y := setup.o 9 + ifeq ($(CONFIG_DMAR), y) 10 + obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o dig_vtd_iommu.o 11 + else 9 12 obj-$(CONFIG_IA64_GENERIC) += machvec.o 13 + endif 14 + obj-$(CONFIG_IA64_DIG_VTD) += dig_vtd_iommu.o
+59
arch/ia64/dig/dig_vtd_iommu.c
··· 1 + #include <linux/types.h> 2 + #include <linux/kernel.h> 3 + #include <linux/module.h> 4 + #include <linux/intel-iommu.h> 5 + 6 + void * 7 + vtd_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, 8 + gfp_t flags) 9 + { 10 + return intel_alloc_coherent(dev, size, dma_handle, flags); 11 + } 12 + EXPORT_SYMBOL_GPL(vtd_alloc_coherent); 13 + 14 + void 15 + vtd_free_coherent(struct device *dev, size_t size, void *vaddr, 16 + dma_addr_t dma_handle) 17 + { 18 + intel_free_coherent(dev, size, vaddr, dma_handle); 19 + } 20 + EXPORT_SYMBOL_GPL(vtd_free_coherent); 21 + 22 + dma_addr_t 23 + vtd_map_single_attrs(struct device *dev, void *addr, size_t size, 24 + int dir, struct dma_attrs *attrs) 25 + { 26 + return intel_map_single(dev, (phys_addr_t)addr, size, dir); 27 + } 28 + EXPORT_SYMBOL_GPL(vtd_map_single_attrs); 29 + 30 + void 31 + vtd_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, 32 + int dir, struct dma_attrs *attrs) 33 + { 34 + intel_unmap_single(dev, iova, size, dir); 35 + } 36 + EXPORT_SYMBOL_GPL(vtd_unmap_single_attrs); 37 + 38 + int 39 + vtd_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, 40 + int dir, struct dma_attrs *attrs) 41 + { 42 + return intel_map_sg(dev, sglist, nents, dir); 43 + } 44 + EXPORT_SYMBOL_GPL(vtd_map_sg_attrs); 45 + 46 + void 47 + vtd_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, 48 + int nents, int dir, struct dma_attrs *attrs) 49 + { 50 + intel_unmap_sg(dev, sglist, nents, dir); 51 + } 52 + EXPORT_SYMBOL_GPL(vtd_unmap_sg_attrs); 53 + 54 + int 55 + vtd_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) 56 + { 57 + return 0; 58 + } 59 + EXPORT_SYMBOL_GPL(vtd_dma_mapping_error);
+3
arch/ia64/dig/machvec_vtd.c
··· 1 + #define MACHVEC_PLATFORM_NAME dig_vtd 2 + #define MACHVEC_PLATFORM_HEADER <asm/machvec_dig_vtd.h> 3 + #include <asm/machvec_init.h>
+2
arch/ia64/include/asm/cacheflush.h
··· 34 34 #define flush_dcache_mmap_unlock(mapping) do { } while (0) 35 35 36 36 extern void flush_icache_range (unsigned long start, unsigned long end); 37 + extern void clflush_cache_range(void *addr, int size); 38 + 37 39 38 40 #define flush_icache_user_range(vma, page, user_addr, len) \ 39 41 do { \
+3
arch/ia64/include/asm/device.h
··· 10 10 #ifdef CONFIG_ACPI 11 11 void *acpi_handle; 12 12 #endif 13 + #ifdef CONFIG_DMAR 14 + void *iommu; /* hook for IOMMU specific extension */ 15 + #endif 13 16 }; 14 17 15 18 #endif /* _ASM_IA64_DEVICE_H */
+50
arch/ia64/include/asm/dma-mapping.h
··· 7 7 */ 8 8 #include <asm/machvec.h> 9 9 #include <linux/scatterlist.h> 10 + #include <asm/swiotlb.h> 11 + 12 + struct dma_mapping_ops { 13 + int (*mapping_error)(struct device *dev, 14 + dma_addr_t dma_addr); 15 + void* (*alloc_coherent)(struct device *dev, size_t size, 16 + dma_addr_t *dma_handle, gfp_t gfp); 17 + void (*free_coherent)(struct device *dev, size_t size, 18 + void *vaddr, dma_addr_t dma_handle); 19 + dma_addr_t (*map_single)(struct device *hwdev, unsigned long ptr, 20 + size_t size, int direction); 21 + void (*unmap_single)(struct device *dev, dma_addr_t addr, 22 + size_t size, int direction); 23 + void (*sync_single_for_cpu)(struct device *hwdev, 24 + dma_addr_t dma_handle, size_t size, 25 + int direction); 26 + void (*sync_single_for_device)(struct device *hwdev, 27 + dma_addr_t dma_handle, size_t size, 28 + int direction); 29 + void (*sync_single_range_for_cpu)(struct device *hwdev, 30 + dma_addr_t dma_handle, unsigned long offset, 31 + size_t size, int direction); 32 + void (*sync_single_range_for_device)(struct device *hwdev, 33 + dma_addr_t dma_handle, unsigned long offset, 34 + size_t size, int direction); 35 + void (*sync_sg_for_cpu)(struct device *hwdev, 36 + struct scatterlist *sg, int nelems, 37 + int direction); 38 + void (*sync_sg_for_device)(struct device *hwdev, 39 + struct scatterlist *sg, int nelems, 40 + int direction); 41 + int (*map_sg)(struct device *hwdev, struct scatterlist *sg, 42 + int nents, int direction); 43 + void (*unmap_sg)(struct device *hwdev, 44 + struct scatterlist *sg, int nents, 45 + int direction); 46 + int (*dma_supported_op)(struct device *hwdev, u64 mask); 47 + int is_phys; 48 + }; 49 + 50 + extern struct dma_mapping_ops *dma_ops; 51 + extern struct ia64_machine_vector ia64_mv; 52 + extern void set_iommu_machvec(void); 10 53 11 54 #define dma_alloc_coherent(dev, size, handle, gfp) \ 12 55 platform_dma_alloc_coherent(dev, size, handle, (gfp) | GFP_DMA) ··· 138 95 } 139 96 140 97 #define dma_is_consistent(d, h) (1) /* all we do is coherent memory... */ 98 + 99 + static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) 100 + { 101 + return dma_ops; 102 + } 103 + 104 + 141 105 142 106 #endif /* _ASM_IA64_DMA_MAPPING_H */
+16
arch/ia64/include/asm/iommu.h
··· 1 + #ifndef _ASM_IA64_IOMMU_H 2 + #define _ASM_IA64_IOMMU_H 1 3 + 4 + #define cpu_has_x2apic 0 5 + /* 10 seconds */ 6 + #define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) 7 + 8 + extern void pci_iommu_shutdown(void); 9 + extern void no_iommu_init(void); 10 + extern int force_iommu, no_iommu; 11 + extern int iommu_detected; 12 + extern void iommu_dma_init(void); 13 + extern void machvec_init(const char *name); 14 + extern int forbid_dac; 15 + 16 + #endif
+2
arch/ia64/include/asm/machvec.h
··· 120 120 # include <asm/machvec_hpsim.h> 121 121 # elif defined (CONFIG_IA64_DIG) 122 122 # include <asm/machvec_dig.h> 123 + # elif defined(CONFIG_IA64_DIG_VTD) 124 + # include <asm/machvec_dig_vtd.h> 123 125 # elif defined (CONFIG_IA64_HP_ZX1) 124 126 # include <asm/machvec_hpzx1.h> 125 127 # elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
+38
arch/ia64/include/asm/machvec_dig_vtd.h
··· 1 + #ifndef _ASM_IA64_MACHVEC_DIG_VTD_h 2 + #define _ASM_IA64_MACHVEC_DIG_VTD_h 3 + 4 + extern ia64_mv_setup_t dig_setup; 5 + extern ia64_mv_dma_alloc_coherent vtd_alloc_coherent; 6 + extern ia64_mv_dma_free_coherent vtd_free_coherent; 7 + extern ia64_mv_dma_map_single_attrs vtd_map_single_attrs; 8 + extern ia64_mv_dma_unmap_single_attrs vtd_unmap_single_attrs; 9 + extern ia64_mv_dma_map_sg_attrs vtd_map_sg_attrs; 10 + extern ia64_mv_dma_unmap_sg_attrs vtd_unmap_sg_attrs; 11 + extern ia64_mv_dma_supported iommu_dma_supported; 12 + extern ia64_mv_dma_mapping_error vtd_dma_mapping_error; 13 + extern ia64_mv_dma_init pci_iommu_alloc; 14 + 15 + /* 16 + * This stuff has dual use! 17 + * 18 + * For a generic kernel, the macros are used to initialize the 19 + * platform's machvec structure. When compiling a non-generic kernel, 20 + * the macros are used directly. 21 + */ 22 + #define platform_name "dig_vtd" 23 + #define platform_setup dig_setup 24 + #define platform_dma_init pci_iommu_alloc 25 + #define platform_dma_alloc_coherent vtd_alloc_coherent 26 + #define platform_dma_free_coherent vtd_free_coherent 27 + #define platform_dma_map_single_attrs vtd_map_single_attrs 28 + #define platform_dma_unmap_single_attrs vtd_unmap_single_attrs 29 + #define platform_dma_map_sg_attrs vtd_map_sg_attrs 30 + #define platform_dma_unmap_sg_attrs vtd_unmap_sg_attrs 31 + #define platform_dma_sync_single_for_cpu machvec_dma_sync_single 32 + #define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg 33 + #define platform_dma_sync_single_for_device machvec_dma_sync_single 34 + #define platform_dma_sync_sg_for_device machvec_dma_sync_sg 35 + #define platform_dma_supported iommu_dma_supported 36 + #define platform_dma_mapping_error vtd_dma_mapping_error 37 + 38 + #endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */
+1
arch/ia64/include/asm/machvec_init.h
··· 1 + #include <asm/iommu.h> 1 2 #include <asm/machvec.h> 2 3 3 4 extern ia64_mv_send_ipi_t ia64_send_ipi;
+3
arch/ia64/include/asm/pci.h
··· 164 164 return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14); 165 165 } 166 166 167 + #ifdef CONFIG_DMAR 168 + extern void pci_iommu_alloc(void); 169 + #endif 167 170 #endif /* _ASM_IA64_PCI_H */
+56
arch/ia64/include/asm/swiotlb.h
··· 1 + #ifndef ASM_IA64__SWIOTLB_H 2 + #define ASM_IA64__SWIOTLB_H 3 + 4 + #include <linux/dma-mapping.h> 5 + 6 + /* SWIOTLB interface */ 7 + 8 + extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, 9 + size_t size, int dir); 10 + extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size, 11 + dma_addr_t *dma_handle, gfp_t flags); 12 + extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, 13 + size_t size, int dir); 14 + extern void swiotlb_sync_single_for_cpu(struct device *hwdev, 15 + dma_addr_t dev_addr, 16 + size_t size, int dir); 17 + extern void swiotlb_sync_single_for_device(struct device *hwdev, 18 + dma_addr_t dev_addr, 19 + size_t size, int dir); 20 + extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev, 21 + dma_addr_t dev_addr, 22 + unsigned long offset, 23 + size_t size, int dir); 24 + extern void swiotlb_sync_single_range_for_device(struct device *hwdev, 25 + dma_addr_t dev_addr, 26 + unsigned long offset, 27 + size_t size, int dir); 28 + extern void swiotlb_sync_sg_for_cpu(struct device *hwdev, 29 + struct scatterlist *sg, int nelems, 30 + int dir); 31 + extern void swiotlb_sync_sg_for_device(struct device *hwdev, 32 + struct scatterlist *sg, int nelems, 33 + int dir); 34 + extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, 35 + int nents, int direction); 36 + extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, 37 + int nents, int direction); 38 + extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr); 39 + extern void swiotlb_free_coherent(struct device *hwdev, size_t size, 40 + void *vaddr, dma_addr_t dma_handle); 41 + extern int swiotlb_dma_supported(struct device *hwdev, u64 mask); 42 + extern void swiotlb_init(void); 43 + 44 + extern int swiotlb_force; 45 + 46 + #ifdef CONFIG_SWIOTLB 47 + extern int swiotlb; 48 + extern void pci_swiotlb_init(void); 49 + #else 50 + #define swiotlb 0 51 + static inline void pci_swiotlb_init(void) 52 + { 53 + } 54 + #endif 55 + 56 + #endif /* ASM_IA64__SWIOTLB_H */
+4
arch/ia64/kernel/Makefile
··· 42 42 ifneq ($(CONFIG_IA64_ESI),) 43 43 obj-y += esi_stub.o # must be in kernel proper 44 44 endif 45 + obj-$(CONFIG_DMAR) += pci-dma.o 46 + ifeq ($(CONFIG_DMAR), y) 47 + obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o 48 + endif 45 49 46 50 # The gate DSO image is built using a special linker script. 47 51 targets += gate.so gate-syms.o
+17
arch/ia64/kernel/acpi.c
··· 92 92 struct acpi_table_rsdp *rsdp; 93 93 struct acpi_table_xsdt *xsdt; 94 94 struct acpi_table_header *hdr; 95 + #ifdef CONFIG_DMAR 96 + u64 i, nentries; 97 + #endif 95 98 96 99 rsdp_phys = acpi_find_rsdp(); 97 100 if (!rsdp_phys) { ··· 129 126 return "xen"; 130 127 } 131 128 129 + #ifdef CONFIG_DMAR 130 + /* Look for Intel IOMMU */ 131 + nentries = (hdr->length - sizeof(*hdr)) / 132 + sizeof(xsdt->table_offset_entry[0]); 133 + for (i = 0; i < nentries; i++) { 134 + hdr = __va(xsdt->table_offset_entry[i]); 135 + if (strncmp(hdr->signature, ACPI_SIG_DMAR, 136 + sizeof(ACPI_SIG_DMAR) - 1) == 0) 137 + return "dig_vtd"; 138 + } 139 + #endif 140 + 132 141 return "dig"; 133 142 #else 134 143 # if defined (CONFIG_IA64_HP_SIM) ··· 157 142 return "dig"; 158 143 # elif defined (CONFIG_IA64_XEN_GUEST) 159 144 return "xen"; 145 + # elif defined(CONFIG_IA64_DIG_VTD) 146 + return "dig_vtd"; 160 147 # else 161 148 # error Unknown platform. Fix acpi.c. 162 149 # endif
+80
arch/ia64/kernel/msi_ia64.c
··· 5 5 #include <linux/pci.h> 6 6 #include <linux/irq.h> 7 7 #include <linux/msi.h> 8 + #include <linux/dmar.h> 8 9 #include <asm/smp.h> 9 10 10 11 /* ··· 163 162 164 163 return ia64_teardown_msi_irq(irq); 165 164 } 165 + 166 + #ifdef CONFIG_DMAR 167 + #ifdef CONFIG_SMP 168 + static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) 169 + { 170 + struct irq_cfg *cfg = irq_cfg + irq; 171 + struct msi_msg msg; 172 + int cpu = first_cpu(mask); 173 + 174 + 175 + if (!cpu_online(cpu)) 176 + return; 177 + 178 + if (irq_prepare_move(irq, cpu)) 179 + return; 180 + 181 + dmar_msi_read(irq, &msg); 182 + 183 + msg.data &= ~MSI_DATA_VECTOR_MASK; 184 + msg.data |= MSI_DATA_VECTOR(cfg->vector); 185 + msg.address_lo &= ~MSI_ADDR_DESTID_MASK; 186 + msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); 187 + 188 + dmar_msi_write(irq, &msg); 189 + irq_desc[irq].affinity = mask; 190 + } 191 + #endif /* CONFIG_SMP */ 192 + 193 + struct irq_chip dmar_msi_type = { 194 + .name = "DMAR_MSI", 195 + .unmask = dmar_msi_unmask, 196 + .mask = dmar_msi_mask, 197 + .ack = ia64_ack_msi_irq, 198 + #ifdef CONFIG_SMP 199 + .set_affinity = dmar_msi_set_affinity, 200 + #endif 201 + .retrigger = ia64_msi_retrigger_irq, 202 + }; 203 + 204 + static int 205 + msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 206 + { 207 + struct irq_cfg *cfg = irq_cfg + irq; 208 + unsigned dest; 209 + cpumask_t mask; 210 + 211 + cpus_and(mask, irq_to_domain(irq), cpu_online_map); 212 + dest = cpu_physical_id(first_cpu(mask)); 213 + 214 + msg->address_hi = 0; 215 + msg->address_lo = 216 + MSI_ADDR_HEADER | 217 + MSI_ADDR_DESTMODE_PHYS | 218 + MSI_ADDR_REDIRECTION_CPU | 219 + MSI_ADDR_DESTID_CPU(dest); 220 + 221 + msg->data = 222 + MSI_DATA_TRIGGER_EDGE | 223 + MSI_DATA_LEVEL_ASSERT | 224 + MSI_DATA_DELIVERY_FIXED | 225 + MSI_DATA_VECTOR(cfg->vector); 226 + return 0; 227 + } 228 + 229 + int arch_setup_dmar_msi(unsigned int irq) 230 + { 231 + int ret; 232 + struct msi_msg msg; 233 + 234 + ret = msi_compose_msg(NULL, irq, &msg); 235 + if (ret < 0) 236 + return ret; 237 + dmar_msi_write(irq, &msg); 238 + set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, 239 + "edge"); 240 + return 0; 241 + } 242 + #endif /* CONFIG_DMAR */ 243 +
+129
arch/ia64/kernel/pci-dma.c
··· 1 + /* 2 + * Dynamic DMA mapping support. 3 + */ 4 + 5 + #include <linux/types.h> 6 + #include <linux/mm.h> 7 + #include <linux/string.h> 8 + #include <linux/pci.h> 9 + #include <linux/module.h> 10 + #include <linux/dmar.h> 11 + #include <asm/iommu.h> 12 + #include <asm/machvec.h> 13 + #include <linux/dma-mapping.h> 14 + 15 + #include <asm/machvec.h> 16 + #include <asm/system.h> 17 + 18 + #ifdef CONFIG_DMAR 19 + 20 + #include <linux/kernel.h> 21 + #include <linux/string.h> 22 + 23 + #include <asm/page.h> 24 + #include <asm/iommu.h> 25 + 26 + dma_addr_t bad_dma_address __read_mostly; 27 + EXPORT_SYMBOL(bad_dma_address); 28 + 29 + static int iommu_sac_force __read_mostly; 30 + 31 + int no_iommu __read_mostly; 32 + #ifdef CONFIG_IOMMU_DEBUG 33 + int force_iommu __read_mostly = 1; 34 + #else 35 + int force_iommu __read_mostly; 36 + #endif 37 + 38 + /* Set this to 1 if there is a HW IOMMU in the system */ 39 + int iommu_detected __read_mostly; 40 + 41 + /* Dummy device used for NULL arguments (normally ISA). Better would 42 + be probably a smaller DMA mask, but this is bug-to-bug compatible 43 + to i386. */ 44 + struct device fallback_dev = { 45 + .bus_id = "fallback device", 46 + .coherent_dma_mask = DMA_32BIT_MASK, 47 + .dma_mask = &fallback_dev.coherent_dma_mask, 48 + }; 49 + 50 + void __init pci_iommu_alloc(void) 51 + { 52 + /* 53 + * The order of these functions is important for 54 + * fall-back/fail-over reasons 55 + */ 56 + detect_intel_iommu(); 57 + 58 + #ifdef CONFIG_SWIOTLB 59 + pci_swiotlb_init(); 60 + #endif 61 + } 62 + 63 + static int __init pci_iommu_init(void) 64 + { 65 + if (iommu_detected) 66 + intel_iommu_init(); 67 + 68 + return 0; 69 + } 70 + 71 + /* Must execute after PCI subsystem */ 72 + fs_initcall(pci_iommu_init); 73 + 74 + void pci_iommu_shutdown(void) 75 + { 76 + return; 77 + } 78 + 79 + void __init 80 + iommu_dma_init(void) 81 + { 82 + return; 83 + } 84 + 85 + struct dma_mapping_ops *dma_ops; 86 + EXPORT_SYMBOL(dma_ops); 87 + 88 + int iommu_dma_supported(struct device *dev, u64 mask) 89 + { 90 + struct dma_mapping_ops *ops = get_dma_ops(dev); 91 + 92 + #ifdef CONFIG_PCI 93 + if (mask > 0xffffffff && forbid_dac > 0) { 94 + dev_info(dev, "Disallowing DAC for device\n"); 95 + return 0; 96 + } 97 + #endif 98 + 99 + if (ops->dma_supported_op) 100 + return ops->dma_supported_op(dev, mask); 101 + 102 + /* Copied from i386. Doesn't make much sense, because it will 103 + only work for pci_alloc_coherent. 104 + The caller just has to use GFP_DMA in this case. */ 105 + if (mask < DMA_24BIT_MASK) 106 + return 0; 107 + 108 + /* Tell the device to use SAC when IOMMU force is on. This 109 + allows the driver to use cheaper accesses in some cases. 110 + 111 + Problem with this is that if we overflow the IOMMU area and 112 + return DAC as fallback address the device may not handle it 113 + correctly. 114 + 115 + As a special case some controllers have a 39bit address 116 + mode that is as efficient as 32bit (aic79xx). Don't force 117 + SAC for these. Assume all masks <= 40 bits are of this 118 + type. Normally this doesn't make any difference, but gives 119 + more gentle handling of IOMMU overflow. */ 120 + if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) { 121 + dev_info(dev, "Force SAC with mask %lx\n", mask); 122 + return 0; 123 + } 124 + 125 + return 1; 126 + } 127 + EXPORT_SYMBOL(iommu_dma_supported); 128 + 129 + #endif
+46
arch/ia64/kernel/pci-swiotlb.c
··· 1 + /* Glue code to lib/swiotlb.c */ 2 + 3 + #include <linux/pci.h> 4 + #include <linux/cache.h> 5 + #include <linux/module.h> 6 + #include <linux/dma-mapping.h> 7 + 8 + #include <asm/swiotlb.h> 9 + #include <asm/dma.h> 10 + #include <asm/iommu.h> 11 + #include <asm/machvec.h> 12 + 13 + int swiotlb __read_mostly; 14 + EXPORT_SYMBOL(swiotlb); 15 + 16 + struct dma_mapping_ops swiotlb_dma_ops = { 17 + .mapping_error = swiotlb_dma_mapping_error, 18 + .alloc_coherent = swiotlb_alloc_coherent, 19 + .free_coherent = swiotlb_free_coherent, 20 + .map_single = swiotlb_map_single, 21 + .unmap_single = swiotlb_unmap_single, 22 + .sync_single_for_cpu = swiotlb_sync_single_for_cpu, 23 + .sync_single_for_device = swiotlb_sync_single_for_device, 24 + .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, 25 + .sync_single_range_for_device = swiotlb_sync_single_range_for_device, 26 + .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, 27 + .sync_sg_for_device = swiotlb_sync_sg_for_device, 28 + .map_sg = swiotlb_map_sg, 29 + .unmap_sg = swiotlb_unmap_sg, 30 + .dma_supported_op = swiotlb_dma_supported, 31 + }; 32 + 33 + void __init pci_swiotlb_init(void) 34 + { 35 + if (!iommu_detected) { 36 + #ifdef CONFIG_IA64_GENERIC 37 + swiotlb = 1; 38 + printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n"); 39 + machvec_init("dig"); 40 + swiotlb_init(); 41 + dma_ops = &swiotlb_dma_ops; 42 + #else 43 + panic("Unable to find Intel IOMMU"); 44 + #endif 45 + } 46 + }
+29 -13
arch/ia64/kernel/setup.c
··· 116 116 */ 117 117 #define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */ 118 118 unsigned long ia64_i_cache_stride_shift = ~0; 119 + /* 120 + * "clflush_cache_range()" needs to know what processor dependent stride size to 121 + * use when it flushes cache lines including both d-cache and i-cache. 122 + */ 123 + /* Safest way to go: 32 bytes by 32 bytes */ 124 + #define CACHE_STRIDE_SHIFT 5 125 + unsigned long ia64_cache_stride_shift = ~0; 119 126 120 127 /* 121 128 * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This ··· 854 847 } 855 848 856 849 /* 857 - * Calculate the max. cache line size. 850 + * Do the following calculations: 858 851 * 859 - * In addition, the minimum of the i-cache stride sizes is calculated for 860 - * "flush_icache_range()". 852 + * 1. the max. cache line size. 853 + * 2. the minimum of the i-cache stride sizes for "flush_icache_range()". 854 + * 3. the minimum of the cache stride sizes for "clflush_cache_range()". 861 855 */ 862 856 static void __cpuinit 863 - get_max_cacheline_size (void) 857 + get_cache_info(void) 864 858 { 865 859 unsigned long line_size, max = 1; 866 860 u64 l, levels, unique_caches; ··· 875 867 max = SMP_CACHE_BYTES; 876 868 /* Safest setup for "flush_icache_range()" */ 877 869 ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; 870 + /* Safest setup for "clflush_cache_range()" */ 871 + ia64_cache_stride_shift = CACHE_STRIDE_SHIFT; 878 872 goto out; 879 873 } 880 874 881 875 for (l = 0; l < levels; ++l) { 882 - status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, 883 - &cci); 876 + /* cache_type (data_or_unified)=2 */ 877 + status = ia64_pal_cache_config_info(l, 2, &cci); 884 878 if (status != 0) { 885 879 printk(KERN_ERR 886 880 "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n", ··· 890 880 max = SMP_CACHE_BYTES; 891 881 /* The safest setup for "flush_icache_range()" */ 892 882 cci.pcci_stride = I_CACHE_STRIDE_SHIFT; 883 + /* The safest setup for "clflush_cache_range()" */ 884 + ia64_cache_stride_shift = CACHE_STRIDE_SHIFT; 893 885 cci.pcci_unified = 1; 886 + } else { 887 + if (cci.pcci_stride < ia64_cache_stride_shift) 888 + ia64_cache_stride_shift = cci.pcci_stride; 889 + 890 + line_size = 1 << cci.pcci_line_size; 891 + if (line_size > max) 892 + max = line_size; 894 893 } 895 - line_size = 1 << cci.pcci_line_size; 896 - if (line_size > max) 897 - max = line_size; 894 + 898 895 if (!cci.pcci_unified) { 899 - status = ia64_pal_cache_config_info(l, 900 - /* cache_type (instruction)= */ 1, 901 - &cci); 896 + /* cache_type (instruction)=1*/ 897 + status = ia64_pal_cache_config_info(l, 1, &cci); 902 898 if (status != 0) { 903 899 printk(KERN_ERR 904 900 "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n", ··· 958 942 } 959 943 #endif 960 944 961 - get_max_cacheline_size(); 945 + get_cache_info(); 962 946 963 947 /* 964 948 * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
+55
arch/ia64/lib/flush.S
··· 60 60 mov ar.lc=r3 // restore ar.lc 61 61 br.ret.sptk.many rp 62 62 END(flush_icache_range) 63 + 64 + /* 65 + * clflush_cache_range(start,size) 66 + * 67 + * Flush cache lines from start to start+size-1. 68 + * 69 + * Must deal with range from start to start+size-1 but nothing else 70 + * (need to be careful not to touch addresses that may be 71 + * unmapped). 72 + * 73 + * Note: "in0" and "in1" are preserved for debugging purposes. 74 + */ 75 + .section .kprobes.text,"ax" 76 + GLOBAL_ENTRY(clflush_cache_range) 77 + 78 + .prologue 79 + alloc r2=ar.pfs,2,0,0,0 80 + movl r3=ia64_cache_stride_shift 81 + mov r21=1 82 + add r22=in1,in0 83 + ;; 84 + ld8 r20=[r3] // r20: stride shift 85 + sub r22=r22,r0,1 // last byte address 86 + ;; 87 + shr.u r23=in0,r20 // start / (stride size) 88 + shr.u r22=r22,r20 // (last byte address) / (stride size) 89 + shl r21=r21,r20 // r21: stride size of the i-cache(s) 90 + ;; 91 + sub r8=r22,r23 // number of strides - 1 92 + shl r24=r23,r20 // r24: addresses for "fc" = 93 + // "start" rounded down to stride 94 + // boundary 95 + .save ar.lc,r3 96 + mov r3=ar.lc // save ar.lc 97 + ;; 98 + 99 + .body 100 + mov ar.lc=r8 101 + ;; 102 + /* 103 + * 32 byte aligned loop, even number of (actually 2) bundles 104 + */ 105 + .Loop_fc: 106 + fc r24 // issuable on M0 only 107 + add r24=r21,r24 // we flush "stride size" bytes per iteration 108 + nop.i 0 109 + br.cloop.sptk.few .Loop_fc 110 + ;; 111 + sync.i 112 + ;; 113 + srlz.i 114 + ;; 115 + mov ar.lc=r3 // restore ar.lc 116 + br.ret.sptk.many rp 117 + END(clflush_cache_range)