summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/dmar.c41
-rw-r--r--drivers/iommu/intel-iommu.c43
-rw-r--r--include/linux/dmar.h18
3 files changed, 59 insertions, 43 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 4c6297d1b421..c1e2e0c82e69 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -97,17 +97,17 @@ void *dmar_alloc_dev_scope(void *start, void *end, int *cnt)
if (*cnt == 0)
return NULL;
- return kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL);
+ return kcalloc(*cnt, sizeof(struct dmar_dev_scope), GFP_KERNEL);
}
-void dmar_free_dev_scope(struct pci_dev __rcu ***devices, int *cnt)
+void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt)
{
int i;
- struct pci_dev *tmp_dev;
+ struct device *tmp_dev;
if (*devices && *cnt) {
for_each_active_dev_scope(*devices, *cnt, i, tmp_dev)
- pci_dev_put(tmp_dev);
+ put_device(tmp_dev);
kfree(*devices);
}
@@ -191,10 +191,11 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
/* Return: > 0 if match found, 0 if no match found, < 0 if error happens */
int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
void *start, void*end, u16 segment,
- struct pci_dev __rcu **devices, int devices_cnt)
+ struct dmar_dev_scope *devices,
+ int devices_cnt)
{
int i, level;
- struct pci_dev *tmp, *dev = info->dev;
+ struct device *tmp, *dev = &info->dev->dev;
struct acpi_dmar_device_scope *scope;
struct acpi_dmar_pci_path *path;
@@ -213,16 +214,18 @@ int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
continue;
if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT) ^
- (dev->hdr_type == PCI_HEADER_TYPE_NORMAL)) {
+ (info->dev->hdr_type == PCI_HEADER_TYPE_NORMAL)) {
pr_warn("Device scope type does not match for %s\n",
- pci_name(dev));
+ pci_name(info->dev));
return -EINVAL;
}
for_each_dev_scope(devices, devices_cnt, i, tmp)
if (tmp == NULL) {
- rcu_assign_pointer(devices[i],
- pci_dev_get(dev));
+ devices[i].bus = info->dev->bus->number;
+ devices[i].devfn = info->dev->devfn;
+ rcu_assign_pointer(devices[i].dev,
+ get_device(dev));
return 1;
}
BUG_ON(i >= devices_cnt);
@@ -232,19 +235,19 @@ int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
}
int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, u16 segment,
- struct pci_dev __rcu **devices, int count)
+ struct dmar_dev_scope *devices, int count)
{
int index;
- struct pci_dev *tmp;
+ struct device *tmp;
if (info->seg != segment)
return 0;
for_each_active_dev_scope(devices, count, index, tmp)
- if (tmp == info->dev) {
- rcu_assign_pointer(devices[index], NULL);
+ if (tmp == &info->dev->dev) {
+ rcu_assign_pointer(devices[index].dev, NULL);
synchronize_rcu();
- pci_dev_put(tmp);
+ put_device(tmp);
return 1;
}
@@ -562,15 +565,15 @@ parse_dmar_table(void)
return ret;
}
-static int dmar_pci_device_match(struct pci_dev __rcu *devices[], int cnt,
- struct pci_dev *dev)
+static int dmar_pci_device_match(struct dmar_dev_scope devices[],
+ int cnt, struct pci_dev *dev)
{
int index;
- struct pci_dev *tmp;
+ struct device *tmp;
while (dev) {
for_each_active_dev_scope(devices, cnt, index, tmp)
- if (dev == tmp)
+ if (dev_is_pci(tmp) && dev == to_pci_dev(tmp))
return 1;
/* Check our parent */
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 1599cb1e041c..ace088eebb45 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -382,14 +382,14 @@ struct dmar_rmrr_unit {
struct acpi_dmar_header *hdr; /* ACPI header */
u64 base_address; /* reserved base address*/
u64 end_address; /* reserved end address */
- struct pci_dev __rcu **devices; /* target devices */
+ struct dmar_dev_scope *devices; /* target devices */
int devices_cnt; /* target device count */
};
struct dmar_atsr_unit {
struct list_head list; /* list of ATSR units */
struct acpi_dmar_header *hdr; /* ACPI header */
- struct pci_dev __rcu **devices; /* target devices */
+ struct dmar_dev_scope *devices; /* target devices */
int devices_cnt; /* target device count */
u8 include_all:1; /* include all ports */
};
@@ -669,7 +669,8 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
{
struct dmar_drhd_unit *drhd = NULL;
struct intel_iommu *iommu;
- struct pci_dev *dev;
+ struct device *dev;
+ struct pci_dev *pdev;
int i;
rcu_read_lock();
@@ -679,11 +680,14 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
for_each_active_dev_scope(drhd->devices,
drhd->devices_cnt, i, dev) {
- if (dev->bus->number == bus && dev->devfn == devfn)
+ if (!dev_is_pci(dev))
+ continue;
+ pdev = to_pci_dev(dev);
+ if (pdev->bus->number == bus && pdev->devfn == devfn)
goto out;
- if (dev->subordinate &&
- dev->subordinate->number <= bus &&
- dev->subordinate->busn_res.end >= bus)
+ if (pdev->subordinate &&
+ pdev->subordinate->number <= bus &&
+ pdev->subordinate->busn_res.end >= bus)
goto out;
}
@@ -2479,7 +2483,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
static bool device_has_rmrr(struct pci_dev *dev)
{
struct dmar_rmrr_unit *rmrr;
- struct pci_dev *tmp;
+ struct device *tmp;
int i;
rcu_read_lock();
@@ -2490,7 +2494,7 @@ static bool device_has_rmrr(struct pci_dev *dev)
*/
for_each_active_dev_scope(rmrr->devices,
rmrr->devices_cnt, i, tmp)
- if (tmp == dev) {
+ if (tmp == &dev->dev) {
rcu_read_unlock();
return true;
}
@@ -2602,7 +2606,7 @@ static int __init init_dmars(void)
{
struct dmar_drhd_unit *drhd;
struct dmar_rmrr_unit *rmrr;
- struct pci_dev *pdev;
+ struct device *dev;
struct intel_iommu *iommu;
int i, ret;
@@ -2746,8 +2750,10 @@ static int __init init_dmars(void)
for_each_rmrr_units(rmrr) {
/* some BIOS lists non-exist devices in DMAR table. */
for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
- i, pdev) {
- ret = iommu_prepare_rmrr_dev(rmrr, pdev);
+ i, dev) {
+ if (!dev_is_pci(dev))
+ continue;
+ ret = iommu_prepare_rmrr_dev(rmrr, to_pci_dev(dev));
if (ret)
printk(KERN_ERR
"IOMMU: mapping reserved region failed\n");
@@ -3434,7 +3440,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quir
static void __init init_no_remapping_devices(void)
{
struct dmar_drhd_unit *drhd;
- struct pci_dev *dev;
+ struct device *dev;
int i;
for_each_drhd_unit(drhd) {
@@ -3442,7 +3448,7 @@ static void __init init_no_remapping_devices(void)
for_each_active_dev_scope(drhd->devices,
drhd->devices_cnt, i, dev)
break;
- /* ignore DMAR unit if no pci devices exist */
+ /* ignore DMAR unit if no devices exist */
if (i == drhd->devices_cnt)
drhd->ignored = 1;
}
@@ -3454,7 +3460,7 @@ static void __init init_no_remapping_devices(void)
for_each_active_dev_scope(drhd->devices,
drhd->devices_cnt, i, dev)
- if (!IS_GFX_DEVICE(dev))
+ if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
break;
if (i < drhd->devices_cnt)
continue;
@@ -3467,7 +3473,7 @@ static void __init init_no_remapping_devices(void)
drhd->ignored = 1;
for_each_active_dev_scope(drhd->devices,
drhd->devices_cnt, i, dev)
- dev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+ dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
}
}
}
@@ -3691,7 +3697,8 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
{
int i, ret = 1;
struct pci_bus *bus;
- struct pci_dev *bridge = NULL, *tmp;
+ struct pci_dev *bridge = NULL;
+ struct device *tmp;
struct acpi_dmar_atsr *atsr;
struct dmar_atsr_unit *atsru;
@@ -3714,7 +3721,7 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
continue;
for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
- if (tmp == bridge)
+ if (tmp == &bridge->dev)
goto out;
if (atsru->include_all)
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 0a92e4d978bc..23c8db129560 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -36,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 __rcu **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 */
@@ -86,7 +92,7 @@ static inline bool dmar_rcu_check(void)
#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)]) : \
+ 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) \
@@ -95,15 +101,15 @@ static inline bool dmar_rcu_check(void)
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);
+ 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 pci_dev __rcu ***devices, 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 pci_dev __rcu **devices,
+ struct dmar_dev_scope *devices,
int devices_cnt);
extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
- u16 segment, struct pci_dev __rcu **devices,
+ u16 segment, struct dmar_dev_scope *devices,
int count);
/* Intel IOMMU detection */
extern int detect_intel_iommu(void);
OpenPOWER on IntegriCloud