Merge tag 'iommu-updates-v3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU upates from Joerg Roedel:
"This time a few more updates queued up.
- Rework VT-d code to support ACPI devices
- Improvements for memory and PCI hotplug support in the VT-d driver
- Device-tree support for OMAP IOMMU
- Convert OMAP IOMMU to use devm_* interfaces
- Fixed PASID support for AMD IOMMU
- Other random cleanups and fixes for OMAP, ARM-SMMU and SHMOBILE
IOMMU
Most of the changes are in the VT-d driver because some rework was
necessary for better hotplug and ACPI device support"
* tag 'iommu-updates-v3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (75 commits)
iommu/vt-d: Fix error handling in ANDD processing
iommu/vt-d: returning free pointer in get_domain_for_dev()
iommu/vt-d: Only call dmar_acpi_dev_scope_init() if DRHD units present
iommu/vt-d: Check for NULL pointer in dmar_acpi_dev_scope_init()
iommu/amd: Fix logic to determine and checking max PASID
iommu/vt-d: Include ACPI devices in iommu=pt
iommu/vt-d: Finally enable translation for non-PCI devices
iommu/vt-d: Remove to_pci_dev() in intel_map_page()
iommu/vt-d: Remove pdev from intel_iommu_attach_device()
iommu/vt-d: Remove pdev from iommu_no_mapping()
iommu/vt-d: Make domain_add_dev_info() take struct device
iommu/vt-d: Make domain_remove_one_dev_info() take struct device
iommu/vt-d: Rename 'hwdev' variables to 'dev' now that that's the norm
iommu/vt-d: Remove some pointless to_pci_dev() calls
iommu/vt-d: Make get_valid_domain_for_dev() take struct device
iommu/vt-d: Make iommu_should_identity_map() take struct device
iommu/vt-d: Handle RMRRs for non-PCI devices
iommu/vt-d: Make get_domain_for_dev() take struct device
iommu/vt-d: Make domain_context_mapp{ed,ing}() take struct device
iommu/vt-d: Make device_to_iommu() cope with non-PCI devices
...
This commit is contained in:
+13
-2
@@ -424,7 +424,8 @@ enum acpi_dmar_type {
|
||||
ACPI_DMAR_TYPE_RESERVED_MEMORY = 1,
|
||||
ACPI_DMAR_TYPE_ATSR = 2,
|
||||
ACPI_DMAR_HARDWARE_AFFINITY = 3,
|
||||
ACPI_DMAR_TYPE_RESERVED = 4 /* 4 and greater are reserved */
|
||||
ACPI_DMAR_TYPE_ANDD = 4,
|
||||
ACPI_DMAR_TYPE_RESERVED = 5 /* 5 and greater are reserved */
|
||||
};
|
||||
|
||||
/* DMAR Device Scope structure */
|
||||
@@ -445,7 +446,8 @@ enum acpi_dmar_scope_type {
|
||||
ACPI_DMAR_SCOPE_TYPE_BRIDGE = 2,
|
||||
ACPI_DMAR_SCOPE_TYPE_IOAPIC = 3,
|
||||
ACPI_DMAR_SCOPE_TYPE_HPET = 4,
|
||||
ACPI_DMAR_SCOPE_TYPE_RESERVED = 5 /* 5 and greater are reserved */
|
||||
ACPI_DMAR_SCOPE_TYPE_ACPI = 5,
|
||||
ACPI_DMAR_SCOPE_TYPE_RESERVED = 6 /* 6 and greater are reserved */
|
||||
};
|
||||
|
||||
struct acpi_dmar_pci_path {
|
||||
@@ -507,6 +509,15 @@ struct acpi_dmar_rhsa {
|
||||
u32 proximity_domain;
|
||||
};
|
||||
|
||||
/* 4: ACPI Namespace Device Declaration Structure */
|
||||
|
||||
struct acpi_dmar_andd {
|
||||
struct acpi_dmar_header header;
|
||||
u8 reserved[3];
|
||||
u8 device_number;
|
||||
u8 object_name[];
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* HPET - High Precision Event Timer table
|
||||
|
||||
+51
-31
@@ -25,6 +25,8 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
struct acpi_dmar_header;
|
||||
|
||||
@@ -34,13 +36,19 @@ struct acpi_dmar_header;
|
||||
|
||||
struct intel_iommu;
|
||||
|
||||
struct dmar_dev_scope {
|
||||
struct device __rcu *dev;
|
||||
u8 bus;
|
||||
u8 devfn;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DMAR_TABLE
|
||||
extern struct acpi_table_header *dmar_tbl;
|
||||
struct dmar_drhd_unit {
|
||||
struct list_head list; /* list of drhd units */
|
||||
struct acpi_dmar_header *hdr; /* ACPI header */
|
||||
u64 reg_base_addr; /* register base address*/
|
||||
struct pci_dev **devices; /* target device array */
|
||||
struct dmar_dev_scope *devices;/* target device array */
|
||||
int devices_cnt; /* target device count */
|
||||
u16 segment; /* PCI domain */
|
||||
u8 ignored:1; /* ignore drhd */
|
||||
@@ -48,33 +56,66 @@ struct dmar_drhd_unit {
|
||||
struct intel_iommu *iommu;
|
||||
};
|
||||
|
||||
struct dmar_pci_notify_info {
|
||||
struct pci_dev *dev;
|
||||
unsigned long event;
|
||||
int bus;
|
||||
u16 seg;
|
||||
u16 level;
|
||||
struct acpi_dmar_pci_path path[];
|
||||
} __attribute__((packed));
|
||||
|
||||
extern struct rw_semaphore dmar_global_lock;
|
||||
extern struct list_head dmar_drhd_units;
|
||||
|
||||
#define for_each_drhd_unit(drhd) \
|
||||
list_for_each_entry(drhd, &dmar_drhd_units, list)
|
||||
list_for_each_entry_rcu(drhd, &dmar_drhd_units, list)
|
||||
|
||||
#define for_each_active_drhd_unit(drhd) \
|
||||
list_for_each_entry(drhd, &dmar_drhd_units, list) \
|
||||
list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
|
||||
if (drhd->ignored) {} else
|
||||
|
||||
#define for_each_active_iommu(i, drhd) \
|
||||
list_for_each_entry(drhd, &dmar_drhd_units, list) \
|
||||
list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
|
||||
if (i=drhd->iommu, drhd->ignored) {} else
|
||||
|
||||
#define for_each_iommu(i, drhd) \
|
||||
list_for_each_entry(drhd, &dmar_drhd_units, list) \
|
||||
list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
|
||||
if (i=drhd->iommu, 0) {} else
|
||||
|
||||
static inline bool dmar_rcu_check(void)
|
||||
{
|
||||
return rwsem_is_locked(&dmar_global_lock) ||
|
||||
system_state == SYSTEM_BOOTING;
|
||||
}
|
||||
|
||||
#define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check())
|
||||
|
||||
#define for_each_dev_scope(a, c, p, d) \
|
||||
for ((p) = 0; ((d) = (p) < (c) ? dmar_rcu_dereference((a)[(p)].dev) : \
|
||||
NULL, (p) < (c)); (p)++)
|
||||
|
||||
#define for_each_active_dev_scope(a, c, p, d) \
|
||||
for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else
|
||||
|
||||
extern int dmar_table_init(void);
|
||||
extern int dmar_dev_scope_init(void);
|
||||
extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
||||
struct pci_dev ***devices, u16 segment);
|
||||
extern void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt);
|
||||
|
||||
struct dmar_dev_scope **devices, u16 segment);
|
||||
extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
|
||||
extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
|
||||
extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
|
||||
void *start, void*end, u16 segment,
|
||||
struct dmar_dev_scope *devices,
|
||||
int devices_cnt);
|
||||
extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
|
||||
u16 segment, struct dmar_dev_scope *devices,
|
||||
int count);
|
||||
/* Intel IOMMU detection */
|
||||
extern int detect_intel_iommu(void);
|
||||
extern int enable_drhd_fault_handling(void);
|
||||
#else
|
||||
struct dmar_pci_notify_info;
|
||||
static inline int detect_intel_iommu(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
@@ -138,30 +179,9 @@ extern int arch_setup_dmar_msi(unsigned int irq);
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
extern int iommu_detected, no_iommu;
|
||||
extern struct list_head dmar_rmrr_units;
|
||||
struct dmar_rmrr_unit {
|
||||
struct list_head list; /* list of rmrr units */
|
||||
struct acpi_dmar_header *hdr; /* ACPI header */
|
||||
u64 base_address; /* reserved base address*/
|
||||
u64 end_address; /* reserved end address */
|
||||
struct pci_dev **devices; /* target devices */
|
||||
int devices_cnt; /* target device count */
|
||||
};
|
||||
|
||||
#define for_each_rmrr_units(rmrr) \
|
||||
list_for_each_entry(rmrr, &dmar_rmrr_units, list)
|
||||
|
||||
struct dmar_atsr_unit {
|
||||
struct list_head list; /* list of ATSR units */
|
||||
struct acpi_dmar_header *hdr; /* ACPI header */
|
||||
struct pci_dev **devices; /* target devices */
|
||||
int devices_cnt; /* target device count */
|
||||
u8 include_all:1; /* include all ports */
|
||||
};
|
||||
|
||||
int dmar_parse_rmrr_atsr_dev(void);
|
||||
extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header);
|
||||
extern int dmar_parse_one_atsr(struct acpi_dmar_header *header);
|
||||
extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
|
||||
extern int intel_iommu_init(void);
|
||||
#else /* !CONFIG_INTEL_IOMMU: */
|
||||
static inline int intel_iommu_init(void) { return -ENODEV; }
|
||||
@@ -173,7 +193,7 @@ static inline int dmar_parse_one_atsr(struct acpi_dmar_header *header)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int dmar_parse_rmrr_atsr_dev(void)
|
||||
static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@ struct intel_iommu {
|
||||
int agaw; /* agaw of this iommu */
|
||||
int msagaw; /* max sagaw of this iommu */
|
||||
unsigned int irq;
|
||||
u16 segment; /* PCI segment# */
|
||||
unsigned char name[13]; /* Device Name */
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
|
||||
@@ -47,5 +47,7 @@ void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
|
||||
void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
|
||||
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
|
||||
void put_iova_domain(struct iova_domain *iovad);
|
||||
struct iova *split_and_remove_iova(struct iova_domain *iovad,
|
||||
struct iova *iova, unsigned long pfn_lo, unsigned long pfn_hi);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user