core/iommu updates for v2.6.40
Subsystems (4)
Linus,
Please pull the latest core-iommu-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git core-iommu-for-linus
Thanks,
Ingo
------------------>
Joe Perches (1):
arch/x86/kernel/pci-iommu_table.c: Convert sprintf_symbol to %pS
Joerg Roedel (18):
x86/amd-iommu: Move compl-wait command building to own function x86/amd-iommu: Move inv-dte command building to own function x86/amd-iommu: Cleanup inv_pages command handling x86/amd-iommu: Cleanup completion-wait handling x86/amd-iommu: Remove command buffer resetting logic x86/amd-iommu: Rename iommu_flush* to domain_flush* x86/amd-iommu: Improve handling of full command buffer x86/amd-iommu: Rename iommu_flush_device x86/amd-iommu: Flush all internal TLBs when IOMMUs are enabled
PCI: Move ATS declarations in seperate header file x86/amd-iommu: Select PCI_IOV with AMD IOMMU driver x86/amd-iommu: Flush device IOTLB if ATS is enabled x86/amd-iommu: Add flag to indicate IOTLB support x86/amd-iommu: Add ATS enable/disable code x86/amd-iommu: Add extended feature detection x86/amd-iommu: Add support for invalidate_all command x86/amd-iommu: Use threaded interupt handler
x86, gart: Rename pci-gart_64.c to amd_gart_64.c
Stanislaw Gruszka (1):
dma-debug: print information about leaked entry
Documentation/x86/x86_64/boot-options.txt | 2 +-
arch/x86/Kconfig | 1 +
arch/x86/include/asm/amd_iommu_proto.h | 13 +-
arch/x86/include/asm/amd_iommu_types.h | 28 +-
arch/x86/kernel/Makefile | 2 +-
arch/x86/kernel/{pci-gart_64.c => amd_gart_64.c} | 0
arch/x86/kernel/amd_iommu.c | 526 +++++++++++++---------
arch/x86/kernel/amd_iommu_init.c | 48 ++-
arch/x86/kernel/pci-iommu_table.c | 18 +-
drivers/pci/intel-iommu.c | 1 +
drivers/pci/iov.c | 1 +
drivers/pci/pci.h | 37 --
include/linux/pci-ats.h | 52 +++
lib/dma-debug.c | 18 +-
14 files changed, 456 insertions(+), 291 deletions(-)
rename arch/x86/kernel/{pci-gart_64.c => amd_gart_64.c} (100%)
create mode 100644 include/linux/pci-ats.hDocumentation/x86/x86_64/boot-options.txt +1 -1
@@ -206,7 +206,7 @@ IOMMU (input/output memory management unit) (e.g. because you have < 3 GB memory). Kernel boot message: "PCI-DMA: Disabling IOMMU" - 2. <arch/x86_64/kernel/pci-gart.c>: AMD GART based hardware IOMMU. + 2. <arch/x86/kernel/amd_gart_64.c>: AMD GART based hardware IOMMU. Kernel boot message: "PCI-DMA: using GART IOMMU" 3. <arch/x86_64/kernel/pci-swiotlb.c> : Software IOMMU implementation. Used
arch/x86/Kconfig +1 -0
@@ -690,6 +690,7 @@ config AMD_IOMMU bool "AMD IOMMU support" select SWIOTLB select PCI_MSI + select PCI_IOV depends on X86_64 && PCI && ACPI ---help--- With this option you can enable support for AMD IOMMU hardware in
arch/x86/include/asm/amd_iommu_proto.h +10 -3
@@ -19,13 +19,12 @@#ifndef _ASM_X86_AMD_IOMMU_PROTO_H#define _ASM_X86_AMD_IOMMU_PROTO_H -struct amd_iommu ; +#include <asm/amd_iommu_types.h> extern int amd_iommu_init_dma_ops (void );extern int amd_iommu_init_passthrough (void ); +extern irqreturn_t amd_iommu_int_thread (int irq,void *data);extern irqreturn_t amd_iommu_int_handler (int irq,void *data); -extern void amd_iommu_flush_all_domains (void ); -extern void amd_iommu_flush_all_devices (void );extern void amd_iommu_apply_erratum_63 (u16 devid);extern void amd_iommu_reset_cmd_buffer (struct amd_iommu *iommu);extern int amd_iommu_init_devices (void );
@@ -44,4 +43,12 @@ static inline bool is_rd890_iommu(struct pci_dev *pdev) (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); } +static inline bool iommu_feature (struct amd_iommu *iommu,u64 f) +{ +if (!(iommu->cap & (1 <<IOMMU_CAP_EFR ))) +return false; + +return !!(iommu->features & f); +} +#endif /* _ASM_X86_AMD_IOMMU_PROTO_H */
arch/x86/include/asm/amd_iommu_types.h +24 -4
@@ -68,12 +68,25 @@#define MMIO_CONTROL_OFFSET 0x0018#define MMIO_EXCL_BASE_OFFSET 0x0020#define MMIO_EXCL_LIMIT_OFFSET 0x0028 +#define MMIO_EXT_FEATURES 0x0030#define MMIO_CMD_HEAD_OFFSET 0x2000#define MMIO_CMD_TAIL_OFFSET 0x2008#define MMIO_EVT_HEAD_OFFSET 0x2010#define MMIO_EVT_TAIL_OFFSET 0x2018#define MMIO_STATUS_OFFSET 0x2020 + +/* Extended Feature Bits */ +#define FEATURE_PREFETCH (1ULL<<0) +#define FEATURE_PPR (1ULL<<1) +#define FEATURE_X2APIC (1ULL<<2) +#define FEATURE_NX (1ULL<<3) +#define FEATURE_GT (1ULL<<4) +#define FEATURE_IA (1ULL<<6) +#define FEATURE_GA (1ULL<<7) +#define FEATURE_HE (1ULL<<8) +#define FEATURE_PC (1ULL<<9) +/* MMIO status bits */ #define MMIO_STATUS_COM_WAIT_INT_MASK 0x04
@@ -113,7 +126,9 @@/* command specific defines */ #define CMD_COMPL_WAIT 0x01#define CMD_INV_DEV_ENTRY 0x02 -#define CMD_INV_IOMMU_PAGES 0x03 +#define CMD_INV_IOMMU_PAGES 0x03 +#define CMD_INV_IOTLB_PAGES 0x04 +#define CMD_INV_ALL 0x08#define CMD_COMPL_WAIT_STORE_MASK 0x01#define CMD_COMPL_WAIT_INT_MASK 0x02
@@ -215,6 +230,8 @@#define IOMMU_PTE_IR (1ULL << 61)#define IOMMU_PTE_IW (1ULL << 62) +#define DTE_FLAG_IOTLB 0x01 +#define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)#define IOMMU_PTE_PRESENT (pte) ((pte) & IOMMU_PTE_P)#define IOMMU_PTE_PAGE (pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
@@ -227,6 +244,7 @@/* IOMMU capabilities */ #define IOMMU_CAP_IOTLB 24#define IOMMU_CAP_NPCACHE 26 +#define IOMMU_CAP_EFR 27#define MAX_DOMAIN_ID 65536
@@ -249,6 +267,8 @@ extern bool amd_iommu_dump;/* global flag if IOMMUs cache non-present entries */ extern bool amd_iommu_np_cache; +/* Only true if all IOMMUs support device IOTLBs */ +extern bool amd_iommu_iotlb_sup;/* * Make iterating over all IOMMUs easier
@@ -371,6 +391,9 @@ struct amd_iommu {/* flags read from acpi table */ u8 acpi_flags; +/* Extended features */ +u64 features; +/* * Capability pointer. There could be more than one IOMMU per PCI * device function if there are more than one AMD IOMMU capability
@@ -409,9 +432,6 @@ struct amd_iommu {/* if one, we need to send a completion wait command */ bool need_sync; -/* becomes true if a command buffer reset is running */ -bool reset_in_progress; -/* default dma_ops domain for that IOMMU */ struct dma_ops_domain *default_dom;
arch/x86/kernel/Makefile +1 -1
@@ -117,7 +117,7 @@ obj-$(CONFIG_OF) += devicetree.o ifeq ($(CONFIG_X86_64),y) obj-$(CONFIG_AUDIT) += audit_64.o - obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o + obj-$(CONFIG_GART_IOMMU) += amd_gart_64.o aperture_64.o obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu_init.o amd_iommu.o
arch/x86/kernel/amd_gart_64.c renamed from arch/x86/kernel/pci-gart_64.c +0 -0
arch/x86/kernel/amd_iommu.c +308 -218
847 lines not on this page · raw message
arch/x86/kernel/amd_iommu_init.c +40 -8
98 lines not on this page · raw message
arch/x86/kernel/pci-iommu_table.c +4 -14
@@ -50,20 +50,14 @@ void __init check_iommu_entries(struct iommu_table_entry *start, struct iommu_table_entry *finish) {struct iommu_table_entry *p, *q, *x; -char sym_p[KSYM_SYMBOL_LEN ]; -char sym_q[KSYM_SYMBOL_LEN ];/* Simple cyclic dependency checker. */ for (p = start; p < finish; p++) { q =find_dependents_of (start, finish, p); x =find_dependents_of (start, finish, q);if (p == x) { -sprint_symbol (sym_p, (unsigned long )p->detect); -sprint_symbol (sym_q, (unsigned long )q->detect); - -printk (KERN_ERR "CYCLIC DEPENDENCY FOUND! %s depends" \ -" on %s and vice-versa. BREAKING IT.\n" , - sym_p, sym_q); +printk (KERN_ERR "CYCLIC DEPENDENCY FOUND! %pS depends on %pS and vice-versa. BREAKING IT.\n" , + p->detect, q->detect);/* Heavy handed way..*/ x->depend =0 ; }
@@ -72,12 +66,8 @@ void __init check_iommu_entries(struct iommu_table_entry *start,for (p = start; p < finish; p++) { q =find_dependents_of (p, finish, p);if (q && q > p) { -sprint_symbol (sym_p, (unsigned long )p->detect); -sprint_symbol (sym_q, (unsigned long )q->detect); - -printk (KERN_ERR "EXECUTION ORDER INVALID! %s " \ -"should be called before %s!\n" , - sym_p, sym_q); +printk (KERN_ERR "EXECUTION ORDER INVALID! %pS should be called before %pS!\n" , + p->detect, q->detect); } } }
drivers/pci/intel-iommu.c +1 -0
@@ -39,6 +39,7 @@#include <linux/syscore_ops.h> #include <linux/tboot.h> #include <linux/dmi.h> +#include <linux/pci-ats.h> #include <asm/cacheflush.h> #include <asm/iommu.h> #include "pci.h"
drivers/pci/iov.c +1 -0
@@ -13,6 +13,7 @@#include <linux/mutex.h> #include <linux/string.h> #include <linux/delay.h> +#include <linux/pci-ats.h> #include "pci.h" #define VIRTFN_ID_LEN 16
drivers/pci/pci.h +0 -37
@@ -250,15 +250,6 @@ struct pci_sriov {u8 __iomem *mstate;/* VF Migration State Array */ }; -/* Address Translation Service */ -struct pci_ats { -int pos;/* capability position */ -int stu;/* Smallest Translation Unit */ -int qdep;/* Invalidate Queue Depth */ -int ref_cnt;/* Physical Function reference count */ -unsigned int is_enabled:1 ;/* Enable bit is set */ -}; -#ifdef CONFIG_PCI_IOV extern int pci_iov_init (struct pci_dev *dev);extern void pci_iov_release (struct pci_dev *dev);
@@ -269,19 +260,6 @@ extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,extern void pci_restore_iov_state (struct pci_dev *dev);extern int pci_iov_bus_range (struct pci_bus *bus); -extern int pci_enable_ats (struct pci_dev *dev,int ps); -extern void pci_disable_ats (struct pci_dev *dev); -extern int pci_ats_queue_depth (struct pci_dev *dev); -/** -* pci_ats_enabled - query the ATS status -* @dev: the PCI device -* -* Returns 1 if ATS capability is enabled, or 0 if not. -*/ -static inline int pci_ats_enabled (struct pci_dev *dev) -{ -return dev->ats && dev->ats->is_enabled; -}#else static inline int pci_iov_init (struct pci_dev *dev) {
@@ -304,21 +282,6 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)return 0 ; } -static inline int pci_enable_ats (struct pci_dev *dev,int ps) -{ -return -ENODEV ; -} -static inline void pci_disable_ats (struct pci_dev *dev) -{ -} -static inline int pci_ats_queue_depth (struct pci_dev *dev) -{ -return -ENODEV ; -} -static inline int pci_ats_enabled (struct pci_dev *dev) -{ -return 0 ; -}#endif /* CONFIG_PCI_IOV */ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
include/linux/pci-ats.h new file +52 -0
52 lines not on this page · raw message
lib/dma-debug.c +13 -5
@@ -649,7 +649,7 @@ out_err:return -ENOMEM ; } -static int device_dma_allocations (struct device *dev) +static int device_dma_allocations (struct device *dev,struct dma_debug_entry **out_entry) {struct dma_debug_entry *entry;unsigned long flags;
@@ -660,8 +660,10 @@ static int device_dma_allocations(struct device *dev)for (i =0 ; i <HASH_SIZE ; ++i) {spin_lock (&dma_entry_hash[i].lock);list_for_each_entry (entry, &dma_entry_hash[i].list, list) { -if (entry->dev == dev) +if (entry->dev == dev) { count +=1 ; + *out_entry = entry; + } }spin_unlock (&dma_entry_hash[i].lock); }
@@ -674,6 +676,7 @@ static int device_dma_allocations(struct device *dev)static int dma_debug_device_change (struct notifier_block *nb,unsigned long action,void *data) {struct device *dev = data; +struct dma_debug_entry *uninitialized_var (entry );int count;if (global_disable)
@@ -681,12 +684,17 @@ static int dma_debug_device_change(struct notifier_block *nb, unsigned long actiswitch (action) {case BUS_NOTIFY_UNBOUND_DRIVER : - count =device_dma_allocations (dev); + count =device_dma_allocations (dev, &entry);if (count ==0 )break ; -err_printk (dev,NULL ,"DMA-API: device driver has pending " +err_printk (dev, entry,"DMA-API: device driver has pending " "DMA allocations while released from device " -"[count=%d]\n" , count); +"[count=%d]\n" +"One of leaked entries details: " +"[device address=0x%016llx] [size=%llu bytes] " +"[mapped with %s] [mapped as %s]\n" , + count, entry->dev_addr, entry->size, + dir2name[entry->direction], type2name[entry->type]);break ;default :break ;