iommu.lists.linux-foundation.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/33] iommu/vt-d: Add support for DMA mapping of ACPI-enumerated devices
@ 2014-03-21 17:18 David Woodhouse
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Version 2.2 of the VT-d specification adds support for DMA mapping of ACPI
devices, by adding fields to the DMAR table which indicate the ACPI path
of each	DMA-capable device and the PCI bus/dev/fn from which its DMA will
*appear* to come.

The bulk of this patch series is going through the code and changing all
the hardcoded assumptions about	'struct	pci_dev' to use	'struct	device'
instead. The rest is fairly boring; just storing the bus/devfn in the
scope arrays and using them accordingly.

I've pushed this out to git://git.infradead.org/iommu-2.6.git along with
the previous 4-patch series to clean up and fix the page table unmapping.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 01/33] iommu/vt-d: Add ACPI namespace device reporting structures
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 02/33] iommu/vt-d: Parse ANDD records David Woodhouse
                     ` (32 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 include/acpi/actbl2.h | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 094a906..da5b057 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -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
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 02/33] iommu/vt-d: Parse ANDD records
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  2014-03-21 17:18   ` [PATCH 01/33] iommu/vt-d: Add ACPI namespace device reporting structures David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 03/33] iommu/vt-d: Allocate space for ACPI devices David Woodhouse
                     ` (31 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/dmar.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index b19f9f4..eb95020 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -373,6 +373,26 @@ static void dmar_free_drhd(struct dmar_drhd_unit *dmaru)
 	kfree(dmaru);
 }
 
+static int __init dmar_parse_one_andd(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_andd *andd = (void *)header;
+
+	/* Check for NUL termination within the designated length */
+	if (strnlen(andd->object_name, header->length - 8) == header->length - 8) {
+		WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
+			   "Your BIOS is broken; ANDD object name is not NUL-terminated\n"
+			   "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			   dmi_get_system_info(DMI_BIOS_VENDOR),
+			   dmi_get_system_info(DMI_BIOS_VERSION),
+			   dmi_get_system_info(DMI_PRODUCT_VERSION));
+		return -EINVAL;
+	}
+	pr_info("ANDD device: %x name: %s\n", andd->device_number,
+		andd->object_name);
+
+	return 0;
+}
+
 #ifdef CONFIG_ACPI_NUMA
 static int __init
 dmar_parse_one_rhsa(struct acpi_dmar_header *header)
@@ -436,6 +456,10 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
 		       (unsigned long long)rhsa->base_address,
 		       rhsa->proximity_domain);
 		break;
+	case ACPI_DMAR_TYPE_ANDD:
+		/* We don't print this here because we need to sanity-check
+		   it first. So print it in dmar_parse_one_andd() instead. */
+		break;
 	}
 }
 
@@ -521,6 +545,9 @@ parse_dmar_table(void)
 			ret = dmar_parse_one_rhsa(entry_header);
 #endif
 			break;
+		case ACPI_DMAR_TYPE_ANDD:
+			ret = dmar_parse_one_andd(entry_header);
+			break;
 		default:
 			pr_warn("Unknown DMAR structure type %d\n",
 				entry_header->type);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 03/33] iommu/vt-d: Allocate space for ACPI devices
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  2014-03-21 17:18   ` [PATCH 01/33] iommu/vt-d: Add ACPI namespace device reporting structures David Woodhouse
  2014-03-21 17:18   ` [PATCH 02/33] iommu/vt-d: Parse ANDD records David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 04/33] iommu/vt-d: Change scope lists to struct device, bus, devfn David Woodhouse
                     ` (30 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/dmar.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index eb95020..4c6297d 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -84,7 +84,8 @@ void *dmar_alloc_dev_scope(void *start, void *end, int *cnt)
 	*cnt = 0;
 	while (start < end) {
 		scope = start;
-		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
+		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ACPI ||
+		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
 		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
 			(*cnt)++;
 		else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC &&
@@ -342,21 +343,18 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
 	dmaru->reg_base_addr = drhd->address;
 	dmaru->segment = drhd->segment;
 	dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
-	if (!dmaru->include_all) {
-		dmaru->devices = dmar_alloc_dev_scope((void *)(drhd + 1),
-					((void *)drhd) + drhd->header.length,
-					&dmaru->devices_cnt);
-		if (dmaru->devices_cnt && dmaru->devices == NULL) {
-			kfree(dmaru);
-			return -ENOMEM;
-		}
+	dmaru->devices = dmar_alloc_dev_scope((void *)(drhd + 1),
+					      ((void *)drhd) + drhd->header.length,
+					      &dmaru->devices_cnt);
+	if (dmaru->devices_cnt && dmaru->devices == NULL) {
+		kfree(dmaru);
+		return -ENOMEM;
 	}
 
 	ret = alloc_iommu(dmaru);
 	if (ret) {
-		if (!dmaru->include_all)
-			dmar_free_dev_scope(&dmaru->devices,
-					    &dmaru->devices_cnt);
+		dmar_free_dev_scope(&dmaru->devices,
+				    &dmaru->devices_cnt);
 		kfree(dmaru);
 		return ret;
 	}
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 04/33] iommu/vt-d: Change scope lists to struct device, bus, devfn
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (2 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 03/33] iommu/vt-d: Allocate space for ACPI devices David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 05/33] iommu/vt-d: Add ACPI devices into dmaru->devices[] array David Woodhouse
                     ` (29 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

It's not only for PCI devices any more, and the scope information for an
ACPI device provides the bus and devfn so that has to be stored here too.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/dmar.c        | 41 ++++++++++++++++++++++-------------------
 drivers/iommu/intel-iommu.c | 43 +++++++++++++++++++++++++------------------
 include/linux/dmar.h        | 18 ++++++++++++------
 3 files changed, 59 insertions(+), 43 deletions(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 4c6297d..34d271e 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 __rcu **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 __rcu *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 __rcu *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 __rcu 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 1599cb1..f38f482 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 __rcu *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 __rcu *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 0a92e4d..4c2caab 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 *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 __rcu *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 __rcu **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 __rcu *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 __rcu *devices,
 				 int count);
 /* Intel IOMMU detection */
 extern int detect_intel_iommu(void);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 05/33] iommu/vt-d: Add ACPI devices into dmaru->devices[] array
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (3 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 04/33] iommu/vt-d: Change scope lists to struct device, bus, devfn David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
       [not found]     ` <1395422354-19762-6-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  2014-03-21 17:18   ` [PATCH 06/33] iommu/vt-d: Make iommu_dummy() take struct device instead of struct pci_dev David Woodhouse
                     ` (28 subsequent siblings)
  33 siblings, 1 reply; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/dmar.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 34d271e..382f63d 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -612,6 +612,79 @@ out:
 	return dmaru;
 }
 
+static void __init dmar_acpi_insert_dev_scope(u8 device_number,
+					      struct acpi_device *adev)
+{
+	struct dmar_drhd_unit *dmaru;
+	struct acpi_dmar_hardware_unit *drhd;
+	struct acpi_dmar_device_scope *scope;
+	struct device *tmp;
+	int i;
+	struct acpi_dmar_pci_path *path;
+
+	for_each_drhd_unit(dmaru) {
+		drhd = container_of(dmaru->hdr,
+				    struct acpi_dmar_hardware_unit,
+				    header);
+
+		for (scope = (void *)(drhd + 1);
+		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
+		     scope = ((void *)scope) + scope->length) {
+			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI)
+				continue;
+			if (scope->enumeration_id != device_number)
+				continue;
+
+			path = (void *)(scope + 1);
+			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
+				dev_name(&adev->dev), dmaru->reg_base_addr,
+				scope->bus, path->device, path->function);
+			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
+				if (tmp == NULL) {
+					dmaru->devices[i].bus = scope->bus;
+					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
+									    path->function);
+					rcu_assign_pointer(dmaru->devices[i].dev,
+							   get_device(&adev->dev));
+					return;
+				}
+			BUG_ON(i >= dmaru->devices_cnt);
+		}
+	}
+	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
+		device_number, dev_name(&adev->dev));
+}
+
+static int __init dmar_acpi_dev_scope_init(void)
+{
+	struct acpi_dmar_andd *andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar);
+
+	while (((unsigned long)andd) <
+	       ((unsigned long)dmar_tbl) + dmar_tbl->length) {
+		if (andd->header.type == ACPI_DMAR_TYPE_ANDD) {
+			acpi_handle h;
+			struct acpi_device *adev;
+
+			if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT,
+							  andd->object_name,
+							  &h))) {
+				pr_err("Failed to find handle for ACPI object %s\n",
+				       andd->object_name);
+				continue;
+			}
+			acpi_bus_get_device(h, &adev);
+			if (!adev) {
+				pr_err("Failed to get device for ACPI object %s\n",
+				       andd->object_name);
+				continue;
+			}
+			dmar_acpi_insert_dev_scope(andd->device_number, adev);
+		}
+		andd = ((void *)andd) + andd->header.length;
+	}
+	return 0;
+}
+
 int __init dmar_dev_scope_init(void)
 {
 	struct pci_dev *dev = NULL;
@@ -620,6 +693,8 @@ int __init dmar_dev_scope_init(void)
 	if (dmar_dev_scope_status != 1)
 		return dmar_dev_scope_status;
 
+	dmar_acpi_dev_scope_init();
+
 	if (list_empty(&dmar_drhd_units)) {
 		dmar_dev_scope_status = -ENODEV;
 	} else {
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 06/33] iommu/vt-d: Make iommu_dummy() take struct device instead of struct pci_dev
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (4 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 05/33] iommu/vt-d: Add ACPI devices into dmaru->devices[] array David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 07/33] iommu/vt-d: Make dmar_insert_dev_info() " David Woodhouse
                     ` (27 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f38f482..db7e44b 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2882,9 +2882,9 @@ static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev)
 	return __get_valid_domain_for_dev(dev);
 }
 
-static int iommu_dummy(struct pci_dev *pdev)
+static int iommu_dummy(struct device *dev)
 {
-	return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
+	return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
 }
 
 /* Check if the pdev needs to go through non-identity map and unmap process.*/
@@ -2896,13 +2896,13 @@ static int iommu_no_mapping(struct device *dev)
 	if (unlikely(!dev_is_pci(dev)))
 		return 1;
 
-	pdev = to_pci_dev(dev);
-	if (iommu_dummy(pdev))
+	if (iommu_dummy(dev))
 		return 1;
 
 	if (!iommu_identity_mapping)
 		return 0;
 
+	pdev = to_pci_dev(dev);
 	found = identity_mapping(pdev);
 	if (found) {
 		if (iommu_should_identity_map(pdev, 0))
@@ -3801,7 +3801,7 @@ static int device_notifier(struct notifier_block *nb,
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
 
-	if (iommu_dummy(pdev))
+	if (iommu_dummy(dev))
 		return 0;
 
 	if (action != BUS_NOTIFY_UNBOUND_DRIVER &&
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 07/33] iommu/vt-d: Make dmar_insert_dev_info() take struct device instead of struct pci_dev
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (5 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 06/33] iommu/vt-d: Make iommu_dummy() take struct device instead of struct pci_dev David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 08/33] iommu/vt-d: Use struct device in device_domain_info, not " David Woodhouse
                     ` (26 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index db7e44b..85ec773 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2113,15 +2113,14 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
 
 /*
  * find_domain
- * Note: we use struct pci_dev->dev.archdata.iommu stores the info
+ * Note: we use struct device->archdata.iommu stores the info
  */
-static struct dmar_domain *
-find_domain(struct pci_dev *pdev)
+static struct dmar_domain *find_domain(struct device *dev)
 {
 	struct device_domain_info *info;
 
 	/* No lock here, assumes no domain exit in normal case */
-	info = pdev->dev.archdata.iommu;
+	info = dev->archdata.iommu;
 	if (info)
 		return info->domain;
 	return NULL;
@@ -2161,7 +2160,7 @@ static int dmar_insert_dev_info(int segment, int bus, int devfn,
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	if (dev)
-		found = find_domain(dev);
+		found = find_domain(&dev->dev);
 	else
 		found = dmar_search_domain_by_dev_info(segment, bus, devfn);
 	if (found) {
@@ -2193,7 +2192,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 	int bus = 0, devfn = 0;
 	int segment;
 
-	domain = find_domain(pdev);
+	domain = find_domain(&pdev->dev);
 	if (domain)
 		return domain;
 
@@ -2252,7 +2251,7 @@ error:
 	if (free)
 		domain_exit(free);
 	/* recheck it here, maybe others set it */
-	return find_domain(pdev);
+	return find_domain(&pdev->dev);
 }
 
 static int iommu_identity_mapping;
@@ -3108,7 +3107,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 	if (iommu_no_mapping(dev))
 		return;
 
-	domain = find_domain(pdev);
+	domain = find_domain(dev);
 	BUG_ON(!domain);
 
 	iommu = domain_get_iommu(domain);
@@ -3200,7 +3199,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	if (iommu_no_mapping(hwdev))
 		return;
 
-	domain = find_domain(pdev);
+	domain = find_domain(hwdev);
 	BUG_ON(!domain);
 
 	iommu = domain_get_iommu(domain);
@@ -3808,7 +3807,7 @@ static int device_notifier(struct notifier_block *nb,
 	    action != BUS_NOTIFY_DEL_DEVICE)
 		return 0;
 
-	domain = find_domain(pdev);
+	domain = find_domain(dev);
 	if (!domain)
 		return 0;
 
@@ -4147,7 +4146,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 	if (unlikely(domain_context_mapped(pdev))) {
 		struct dmar_domain *old_domain;
 
-		old_domain = find_domain(pdev);
+		old_domain = find_domain(dev);
 		if (old_domain) {
 			if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
 			    dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 08/33] iommu/vt-d: Use struct device in device_domain_info, not struct pci_dev
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (6 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 07/33] iommu/vt-d: Make dmar_insert_dev_info() " David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 09/33] iommu/vt-d: Pass iommu to domain_context_mapping_one() and iommu_support_dev_iotlb() David Woodhouse
                     ` (25 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 54 +++++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 85ec773..ccef436 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -372,7 +372,7 @@ struct device_domain_info {
 	int segment;		/* PCI domain */
 	u8 bus;			/* PCI bus number */
 	u8 devfn;		/* PCI devfn number */
-	struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */
+	struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
 	struct intel_iommu *iommu; /* IOMMU used by this device */
 	struct dmar_domain *domain; /* pointer to domain */
 };
@@ -428,7 +428,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain);
 static void domain_remove_one_dev_info(struct dmar_domain *domain,
 				       struct pci_dev *pdev);
 static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
-					   struct pci_dev *pdev);
+					   struct device *dev);
 
 #ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
 int dmar_disabled = 0;
@@ -1247,6 +1247,7 @@ static struct device_domain_info *iommu_support_dev_iotlb(
 	unsigned long flags;
 	struct device_domain_info *info;
 	struct intel_iommu *iommu = device_to_iommu(segment, bus, devfn);
+	struct pci_dev *pdev;
 
 	if (!ecap_dev_iotlb_support(iommu->ecap))
 		return NULL;
@@ -1262,13 +1263,15 @@ static struct device_domain_info *iommu_support_dev_iotlb(
 		}
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 
-	if (!found || !info->dev)
+	if (!found || !info->dev || !dev_is_pci(info->dev))
 		return NULL;
 
-	if (!pci_find_ext_capability(info->dev, PCI_EXT_CAP_ID_ATS))
+	pdev = to_pci_dev(info->dev);
+
+	if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS))
 		return NULL;
 
-	if (!dmar_find_matched_atsr_unit(info->dev))
+	if (!dmar_find_matched_atsr_unit(pdev))
 		return NULL;
 
 	info->iommu = iommu;
@@ -1278,18 +1281,19 @@ static struct device_domain_info *iommu_support_dev_iotlb(
 
 static void iommu_enable_dev_iotlb(struct device_domain_info *info)
 {
-	if (!info)
+	if (!info || !dev_is_pci(info->dev))
 		return;
 
-	pci_enable_ats(info->dev, VTD_PAGE_SHIFT);
+	pci_enable_ats(to_pci_dev(info->dev), VTD_PAGE_SHIFT);
 }
 
 static void iommu_disable_dev_iotlb(struct device_domain_info *info)
 {
-	if (!info->dev || !pci_ats_enabled(info->dev))
+	if (!info->dev || !dev_is_pci(info->dev) ||
+	    !pci_ats_enabled(to_pci_dev(info->dev)))
 		return;
 
-	pci_disable_ats(info->dev);
+	pci_disable_ats(to_pci_dev(info->dev));
 }
 
 static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
@@ -1301,11 +1305,16 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	list_for_each_entry(info, &domain->devices, link) {
-		if (!info->dev || !pci_ats_enabled(info->dev))
+		struct pci_dev *pdev;
+		if (!info->dev || !dev_is_pci(info->dev))
+			continue;
+
+		pdev = to_pci_dev(info->dev);
+		if (!pci_ats_enabled(pdev))
 			continue;
 
 		sid = info->bus << 8 | info->devfn;
-		qdep = pci_ats_queue_depth(info->dev);
+		qdep = pci_ats_queue_depth(pdev);
 		qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
 	}
 	spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -2071,7 +2080,7 @@ static inline void unlink_domain_info(struct device_domain_info *info)
 	list_del(&info->link);
 	list_del(&info->global);
 	if (info->dev)
-		info->dev->dev.archdata.iommu = NULL;
+		info->dev->archdata.iommu = NULL;
 }
 
 static void domain_remove_dev_info(struct dmar_domain *domain)
@@ -2140,7 +2149,7 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 }
 
 static int dmar_insert_dev_info(int segment, int bus, int devfn,
-				struct pci_dev *dev, struct dmar_domain **domp)
+				struct device *dev, struct dmar_domain **domp)
 {
 	struct dmar_domain *found, *domain = *domp;
 	struct device_domain_info *info;
@@ -2160,7 +2169,7 @@ static int dmar_insert_dev_info(int segment, int bus, int devfn,
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	if (dev)
-		found = find_domain(&dev->dev);
+		found = find_domain(dev);
 	else
 		found = dmar_search_domain_by_dev_info(segment, bus, devfn);
 	if (found) {
@@ -2174,7 +2183,7 @@ static int dmar_insert_dev_info(int segment, int bus, int devfn,
 		list_add(&info->link, &domain->devices);
 		list_add(&info->global, &device_domain_list);
 		if (dev)
-			dev->dev.archdata.iommu = info;
+			dev->archdata.iommu = info;
 		spin_unlock_irqrestore(&device_domain_lock, flags);
 	}
 
@@ -2245,7 +2254,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
 found_domain:
 	if (dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
-				 pdev, &domain) == 0)
+				 &pdev->dev, &domain) == 0)
 		return domain;
 error:
 	if (free)
@@ -2458,7 +2467,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 	info->segment = pci_domain_nr(pdev->bus);
 	info->bus = pdev->bus->number;
 	info->devfn = pdev->devfn;
-	info->dev = pdev;
+	info->dev = &pdev->dev;
 	info->domain = domain;
 
 	spin_lock_irqsave(&device_domain_lock, flags);
@@ -3189,7 +3198,6 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 			   int nelems, enum dma_data_direction dir,
 			   struct dma_attrs *attrs)
 {
-	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
 	unsigned long start_pfn, last_pfn;
 	struct iova *iova;
@@ -3985,13 +3993,15 @@ out_free_dmar:
 }
 
 static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
-					   struct pci_dev *pdev)
+					   struct device *dev)
 {
-	struct pci_dev *tmp, *parent;
+	struct pci_dev *tmp, *parent, *pdev;
 
-	if (!iommu || !pdev)
+	if (!iommu || !dev || !dev_is_pci(dev))
 		return;
 
+	pdev = to_pci_dev(dev);
+
 	/* dependent device detach */
 	tmp = pci_find_upstream_pcie_bridge(pdev);
 	/* Secondary interface's bus number and devfn 0 */
@@ -4034,7 +4044,7 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
 
 			iommu_disable_dev_iotlb(info);
 			iommu_detach_dev(iommu, info->bus, info->devfn);
-			iommu_detach_dependent_devices(iommu, pdev);
+			iommu_detach_dependent_devices(iommu, &pdev->dev);
 			free_devinfo_mem(info);
 
 			spin_lock_irqsave(&device_domain_lock, flags);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 09/33] iommu/vt-d: Pass iommu to domain_context_mapping_one() and iommu_support_dev_iotlb()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (7 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 08/33] iommu/vt-d: Use struct device in device_domain_info, not " David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 10/33] iommu/vt-d: Stop dmar_insert_dev_info() freeing domains on losing race David Woodhouse
                     ` (24 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index ccef436..1ab7c18 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1240,13 +1240,13 @@ static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
 			(unsigned long long)DMA_TLB_IAIG(val));
 }
 
-static struct device_domain_info *iommu_support_dev_iotlb(
-	struct dmar_domain *domain, int segment, u8 bus, u8 devfn)
+static struct device_domain_info *
+iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
+			 u8 bus, u8 devfn)
 {
 	int found = 0;
 	unsigned long flags;
 	struct device_domain_info *info;
-	struct intel_iommu *iommu = device_to_iommu(segment, bus, devfn);
 	struct pci_dev *pdev;
 
 	if (!ecap_dev_iotlb_support(iommu->ecap))
@@ -1700,12 +1700,12 @@ static void domain_exit(struct dmar_domain *domain)
 	free_domain_mem(domain);
 }
 
-static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
-				 u8 bus, u8 devfn, int translation)
+static int domain_context_mapping_one(struct dmar_domain *domain,
+				      struct intel_iommu *iommu,
+				      u8 bus, u8 devfn, int translation)
 {
 	struct context_entry *context;
 	unsigned long flags;
-	struct intel_iommu *iommu;
 	struct dma_pte *pgd;
 	unsigned long num;
 	unsigned long ndomains;
@@ -1720,10 +1720,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
 	BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
 	       translation != CONTEXT_TT_MULTI_LEVEL);
 
-	iommu = device_to_iommu(segment, bus, devfn);
-	if (!iommu)
-		return -ENODEV;
-
 	context = device_to_context_entry(iommu, bus, devfn);
 	if (!context)
 		return -ENOMEM;
@@ -1781,7 +1777,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
 	context_set_domain_id(context, id);
 
 	if (translation != CONTEXT_TT_PASS_THROUGH) {
-		info = iommu_support_dev_iotlb(domain, segment, bus, devfn);
+		info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
 		translation = info ? CONTEXT_TT_DEV_IOTLB :
 				     CONTEXT_TT_MULTI_LEVEL;
 	}
@@ -1836,8 +1832,14 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
 {
 	int ret;
 	struct pci_dev *tmp, *parent;
+	struct intel_iommu *iommu;
+
+	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
+				pdev->devfn);
+	if (!iommu)
+		return -ENODEV;
 
-	ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus),
+	ret = domain_context_mapping_one(domain, iommu,
 					 pdev->bus->number, pdev->devfn,
 					 translation);
 	if (ret)
@@ -1850,8 +1852,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
 	/* Secondary interface's bus number and devfn 0 */
 	parent = pdev->bus->self;
 	while (parent != tmp) {
-		ret = domain_context_mapping_one(domain,
-						 pci_domain_nr(parent->bus),
+		ret = domain_context_mapping_one(domain, iommu,
 						 parent->bus->number,
 						 parent->devfn, translation);
 		if (ret)
@@ -1859,13 +1860,11 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
 		parent = parent->bus->self;
 	}
 	if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
-		return domain_context_mapping_one(domain,
-					pci_domain_nr(tmp->subordinate),
+		return domain_context_mapping_one(domain, iommu,
 					tmp->subordinate->number, 0,
 					translation);
 	else /* this is a legacy PCI bridge */
-		return domain_context_mapping_one(domain,
-						  pci_domain_nr(tmp->bus),
+		return domain_context_mapping_one(domain, iommu,
 						  tmp->bus->number,
 						  tmp->devfn,
 						  translation);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 10/33] iommu/vt-d: Stop dmar_insert_dev_info() freeing domains on losing race
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (8 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 09/33] iommu/vt-d: Pass iommu to domain_context_mapping_one() and iommu_support_dev_iotlb() David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 11/33] iommu/vt-d: use dmar_insert_dev_info() from dma_add_dev_info() David Woodhouse
                     ` (23 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

By moving this into get_domain_for_dev() we can make dmar_insert_dev_info()
suitable for use with "special" domains such as the si_domain, which
currently use domain_add_dev_info().

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 1ab7c18..b50d1d6 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2147,16 +2147,17 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 	return NULL;
 }
 
-static int dmar_insert_dev_info(int segment, int bus, int devfn,
-				struct device *dev, struct dmar_domain **domp)
+static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn,
+						struct device *dev,
+						struct dmar_domain *domain)
 {
-	struct dmar_domain *found, *domain = *domp;
+	struct dmar_domain *found;
 	struct device_domain_info *info;
 	unsigned long flags;
 
 	info = alloc_devinfo_mem();
 	if (!info)
-		return -ENOMEM;
+		return NULL;
 
 	info->segment = segment;
 	info->bus = bus;
@@ -2174,19 +2175,17 @@ static int dmar_insert_dev_info(int segment, int bus, int devfn,
 	if (found) {
 		spin_unlock_irqrestore(&device_domain_lock, flags);
 		free_devinfo_mem(info);
-		if (found != domain) {
-			domain_exit(domain);
-			*domp = found;
-		}
-	} else {
-		list_add(&info->link, &domain->devices);
-		list_add(&info->global, &device_domain_list);
-		if (dev)
-			dev->archdata.iommu = info;
-		spin_unlock_irqrestore(&device_domain_lock, flags);
+		/* Caller must free the original domain */
+		return found;
 	}
 
-	return 0;
+	list_add(&info->link, &domain->devices);
+	list_add(&info->global, &device_domain_list);
+	if (dev)
+		dev->archdata.iommu = info;
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+
+	return domain;
 }
 
 /* domain is initialized */
@@ -2245,21 +2244,19 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
 	/* register pcie-to-pci device */
 	if (dev_tmp) {
-		if (dmar_insert_dev_info(segment, bus, devfn, NULL, &domain))
+		domain = dmar_insert_dev_info(segment, bus, devfn, NULL, domain);
+		if (!domain)
 			goto error;
-		else
-			free = NULL;
 	}
 
 found_domain:
-	if (dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
-				 &pdev->dev, &domain) == 0)
-		return domain;
+	domain = dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
+				      &pdev->dev, domain);
 error:
-	if (free)
+	if (free != domain)
 		domain_exit(free);
-	/* recheck it here, maybe others set it */
-	return find_domain(&pdev->dev);
+
+	return domain;
 }
 
 static int iommu_identity_mapping;
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 11/33] iommu/vt-d: use dmar_insert_dev_info() from dma_add_dev_info()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (9 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 10/33] iommu/vt-d: Stop dmar_insert_dev_info() freeing domains on losing race David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 12/33] iommu/vt-d: Use domain_remove_one_dev_info() in domain_add_dev_info() error path David Woodhouse
                     ` (22 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 22 +++++++---------------
 1 file changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index b50d1d6..3342d65 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2452,29 +2452,21 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 			       struct pci_dev *pdev,
 			       int translation)
 {
+	struct dmar_domain *ndomain;
 	struct device_domain_info *info;
 	unsigned long flags;
 	int ret;
 
-	info = alloc_devinfo_mem();
-	if (!info)
-		return -ENOMEM;
-
-	info->segment = pci_domain_nr(pdev->bus);
-	info->bus = pdev->bus->number;
-	info->devfn = pdev->devfn;
-	info->dev = &pdev->dev;
-	info->domain = domain;
-
-	spin_lock_irqsave(&device_domain_lock, flags);
-	list_add(&info->link, &domain->devices);
-	list_add(&info->global, &device_domain_list);
-	pdev->dev.archdata.iommu = info;
-	spin_unlock_irqrestore(&device_domain_lock, flags);
+	ndomain = dmar_insert_dev_info(pci_domain_nr(pdev->bus),
+				       pdev->bus->number, pdev->devfn,
+				       &pdev->dev, domain);
+	if (ndomain != domain)
+		return -EBUSY;
 
 	ret = domain_context_mapping(domain, pdev, translation);
 	if (ret) {
 		spin_lock_irqsave(&device_domain_lock, flags);
+		info = pdev->dev.archdata.iommu;
 		unlink_domain_info(info);
 		spin_unlock_irqrestore(&device_domain_lock, flags);
 		free_devinfo_mem(info);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 12/33] iommu/vt-d: Use domain_remove_one_dev_info() in domain_add_dev_info() error path
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (10 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 11/33] iommu/vt-d: use dmar_insert_dev_info() from dma_add_dev_info() David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 13/33] iommu/vt-d: Always store iommu in device_domain_info David Woodhouse
                     ` (21 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 3342d65..0751f6d 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2453,8 +2453,6 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 			       int translation)
 {
 	struct dmar_domain *ndomain;
-	struct device_domain_info *info;
-	unsigned long flags;
 	int ret;
 
 	ndomain = dmar_insert_dev_info(pci_domain_nr(pdev->bus),
@@ -2465,11 +2463,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 
 	ret = domain_context_mapping(domain, pdev, translation);
 	if (ret) {
-		spin_lock_irqsave(&device_domain_lock, flags);
-		info = pdev->dev.archdata.iommu;
-		unlink_domain_info(info);
-		spin_unlock_irqrestore(&device_domain_lock, flags);
-		free_devinfo_mem(info);
+		domain_remove_one_dev_info(domain, pdev);
 		return ret;
 	}
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 13/33] iommu/vt-d: Always store iommu in device_domain_info
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (11 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 12/33] iommu/vt-d: Use domain_remove_one_dev_info() in domain_add_dev_info() error path David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 14/33] iommu/vt-d: Simplify iommu check in domain_remove_one_dev_info() David Woodhouse
                     ` (20 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 47 ++++++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 0751f6d..309ee18 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1274,8 +1274,6 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
 	if (!dmar_find_matched_atsr_unit(pdev))
 		return NULL;
 
-	info->iommu = iommu;
-
 	return info;
 }
 
@@ -2134,7 +2132,7 @@ static struct dmar_domain *find_domain(struct device *dev)
 	return NULL;
 }
 
-static inline struct dmar_domain *
+static inline struct device_domain_info *
 dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 {
 	struct device_domain_info *info;
@@ -2142,16 +2140,17 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 	list_for_each_entry(info, &device_domain_list, global)
 		if (info->segment == segment && info->bus == bus &&
 		    info->devfn == devfn)
-			return info->domain;
+			return info;
 
 	return NULL;
 }
 
-static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn,
+static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
+						int segment, int bus, int devfn,
 						struct device *dev,
 						struct dmar_domain *domain)
 {
-	struct dmar_domain *found;
+	struct dmar_domain *found = NULL;
 	struct device_domain_info *info;
 	unsigned long flags;
 
@@ -2164,14 +2163,19 @@ static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn,
 	info->devfn = devfn;
 	info->dev = dev;
 	info->domain = domain;
+	info->iommu = iommu;
 	if (!dev)
 		domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	if (dev)
 		found = find_domain(dev);
-	else
-		found = dmar_search_domain_by_dev_info(segment, bus, devfn);
+	else {
+		struct device_domain_info *info2;
+		info2 = dmar_search_domain_by_dev_info(segment, bus, devfn);
+		if (info2)
+			found = info2->domain;
+	}
 	if (found) {
 		spin_unlock_irqrestore(&device_domain_lock, flags);
 		free_devinfo_mem(info);
@@ -2192,7 +2196,8 @@ static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn,
 static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 {
 	struct dmar_domain *domain, *free = NULL;
-	struct intel_iommu *iommu;
+	struct intel_iommu *iommu = NULL;
+	struct device_domain_info *info;
 	struct dmar_drhd_unit *drhd;
 	struct pci_dev *dev_tmp;
 	unsigned long flags;
@@ -2215,10 +2220,13 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 			devfn = dev_tmp->devfn;
 		}
 		spin_lock_irqsave(&device_domain_lock, flags);
-		domain = dmar_search_domain_by_dev_info(segment, bus, devfn);
+		info = dmar_search_domain_by_dev_info(segment, bus, devfn);
+		if (info) {
+			iommu = info->iommu;
+			domain = info->domain;
+		}
 		spin_unlock_irqrestore(&device_domain_lock, flags);
-		/* pcie-pci bridge already has a domain, uses it */
-		if (domain)
+		if (info)
 			goto found_domain;
 	}
 
@@ -2244,14 +2252,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
 	/* register pcie-to-pci device */
 	if (dev_tmp) {
-		domain = dmar_insert_dev_info(segment, bus, devfn, NULL, domain);
+		domain = dmar_insert_dev_info(iommu, segment, bus, devfn, NULL,
+					      domain);
 		if (!domain)
 			goto error;
 	}
 
 found_domain:
-	domain = dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
-				      &pdev->dev, domain);
+	domain = dmar_insert_dev_info(iommu, segment, pdev->bus->number,
+				      pdev->devfn, &pdev->dev, domain);
 error:
 	if (free != domain)
 		domain_exit(free);
@@ -2453,9 +2462,15 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 			       int translation)
 {
 	struct dmar_domain *ndomain;
+	struct intel_iommu *iommu;
 	int ret;
 
-	ndomain = dmar_insert_dev_info(pci_domain_nr(pdev->bus),
+	iommu = device_to_iommu(pci_domain_nr(pdev->bus),
+				pdev->bus->number, pdev->devfn);
+	if (!iommu)
+		return -ENODEV;
+
+	ndomain = dmar_insert_dev_info(iommu, pci_domain_nr(pdev->bus),
 				       pdev->bus->number, pdev->devfn,
 				       &pdev->dev, domain);
 	if (ndomain != domain)
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 14/33] iommu/vt-d: Simplify iommu check in domain_remove_one_dev_info()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (12 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 13/33] iommu/vt-d: Always store iommu in device_domain_info David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 15/33] iommu/vt-d: Remove device_to_iommu() call from domain_remove_dev_info() David Woodhouse
                     ` (19 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Now we store the iommu in the device_domain_info, we don't need to do a
lookup.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 309ee18..7e540a0 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4056,8 +4056,7 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
 		 * owned by this domain, clear this iommu in iommu_bmp
 		 * update iommu count and coherency
 		 */
-		if (iommu == device_to_iommu(info->segment, info->bus,
-					    info->devfn))
+		if (info->iommu == iommu)
 			found = 1;
 	}
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 15/33] iommu/vt-d: Remove device_to_iommu() call from domain_remove_dev_info()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (13 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 14/33] iommu/vt-d: Simplify iommu check in domain_remove_one_dev_info() David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 16/33] iommu/vt-d: Store PCI segment number in struct intel_iommu David Woodhouse
                     ` (18 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

This was problematic because it works by domain/bus/devfn and we want
to make device_to_iommu() use only a struct device * (for handling non-PCI
devices). Now that the iommu pointer is reliably stored in the
device_domain_info, we don't need to look it up.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 7e540a0..75ff1a1 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2084,7 +2084,6 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
 {
 	struct device_domain_info *info;
 	unsigned long flags, flags2;
-	struct intel_iommu *iommu;
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	while (!list_empty(&domain->devices)) {
@@ -2094,16 +2093,15 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
 		spin_unlock_irqrestore(&device_domain_lock, flags);
 
 		iommu_disable_dev_iotlb(info);
-		iommu = device_to_iommu(info->segment, info->bus, info->devfn);
-		iommu_detach_dev(iommu, info->bus, info->devfn);
+		iommu_detach_dev(info->iommu, info->bus, info->devfn);
 
 		if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
-			iommu_detach_dependent_devices(iommu, info->dev);
+			iommu_detach_dependent_devices(info->iommu, info->dev);
 			/* clear this iommu in iommu_bmp, update iommu count
 			 * and capabilities
 			 */
 			spin_lock_irqsave(&domain->iommu_lock, flags2);
-			if (test_and_clear_bit(iommu->seq_id,
+			if (test_and_clear_bit(info->iommu->seq_id,
 					       domain->iommu_bmp)) {
 				domain->iommu_count--;
 				domain_update_iommu_cap(domain);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 16/33] iommu/vt-d: Store PCI segment number in struct intel_iommu
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (14 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 15/33] iommu/vt-d: Remove device_to_iommu() call from domain_remove_dev_info() David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 17/33] iommu/vt-d: Remove segment from struct device_domain_info() David Woodhouse
                     ` (17 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/dmar.c        | 1 +
 include/linux/intel-iommu.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 382f63d..cd05a4b 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -952,6 +952,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
 	}
 	iommu->agaw = agaw;
 	iommu->msagaw = msagaw;
+	iommu->segment = drhd->segment;
 
 	iommu->node = -1;
 
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 2c4bed5..093ae31 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -322,6 +322,7 @@ struct intel_iommu {
 	unsigned char 	name[13];    /* Device Name */
 
 #ifdef CONFIG_INTEL_IOMMU
+	u16		segment;	/* PCI segment# */
 	unsigned long 	*domain_ids; /* bitmap of domains */
 	struct dmar_domain **domains; /* ptr to domains */
 	spinlock_t	lock; /* protect context, domain ids */
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 17/33] iommu/vt-d: Remove segment from struct device_domain_info()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (15 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 16/33] iommu/vt-d: Store PCI segment number in struct intel_iommu David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:18   ` [PATCH 18/33] iommu/vt-d: Make identity_mapping() take struct device not struct pci_dev David Woodhouse
                     ` (16 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

It's accessible via info->iommu->segment so this is redundant.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 75ff1a1..81f52d3 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -369,7 +369,6 @@ struct dmar_domain {
 struct device_domain_info {
 	struct list_head link;	/* link to domain siblings */
 	struct list_head global; /* link to global list */
-	int segment;		/* PCI domain */
 	u8 bus;			/* PCI bus number */
 	u8 devfn;		/* PCI devfn number */
 	struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
@@ -2136,7 +2135,7 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 	struct device_domain_info *info;
 
 	list_for_each_entry(info, &device_domain_list, global)
-		if (info->segment == segment && info->bus == bus &&
+		if (info->iommu->segment == segment && info->bus == bus &&
 		    info->devfn == devfn)
 			return info;
 
@@ -2144,7 +2143,7 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 }
 
 static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
-						int segment, int bus, int devfn,
+						int bus, int devfn,
 						struct device *dev,
 						struct dmar_domain *domain)
 {
@@ -2156,7 +2155,6 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
 	if (!info)
 		return NULL;
 
-	info->segment = segment;
 	info->bus = bus;
 	info->devfn = devfn;
 	info->dev = dev;
@@ -2170,7 +2168,7 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
 		found = find_domain(dev);
 	else {
 		struct device_domain_info *info2;
-		info2 = dmar_search_domain_by_dev_info(segment, bus, devfn);
+		info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
 		if (info2)
 			found = info2->domain;
 	}
@@ -2250,14 +2248,14 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
 	/* register pcie-to-pci device */
 	if (dev_tmp) {
-		domain = dmar_insert_dev_info(iommu, segment, bus, devfn, NULL,
+		domain = dmar_insert_dev_info(iommu, bus, devfn, NULL,
 					      domain);
 		if (!domain)
 			goto error;
 	}
 
 found_domain:
-	domain = dmar_insert_dev_info(iommu, segment, pdev->bus->number,
+	domain = dmar_insert_dev_info(iommu, pdev->bus->number,
 				      pdev->devfn, &pdev->dev, domain);
 error:
 	if (free != domain)
@@ -2468,8 +2466,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 	if (!iommu)
 		return -ENODEV;
 
-	ndomain = dmar_insert_dev_info(iommu, pci_domain_nr(pdev->bus),
-				       pdev->bus->number, pdev->devfn,
+	ndomain = dmar_insert_dev_info(iommu, pdev->bus->number, pdev->devfn,
 				       &pdev->dev, domain);
 	if (ndomain != domain)
 		return -EBUSY;
@@ -4031,7 +4028,7 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	list_for_each_entry_safe(info, tmp, &domain->devices, link) {
-		if (info->segment == pci_domain_nr(pdev->bus) &&
+		if (info->iommu->segment == pci_domain_nr(pdev->bus) &&
 		    info->bus == pdev->bus->number &&
 		    info->devfn == pdev->devfn) {
 			unlink_domain_info(info);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 18/33] iommu/vt-d: Make identity_mapping() take struct device not struct pci_dev
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (16 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 17/33] iommu/vt-d: Remove segment from struct device_domain_info() David Woodhouse
@ 2014-03-21 17:18   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 19/33] iommu/vt-d: Make device_to_iommu() cope with non-PCI devices David Woodhouse
                     ` (15 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:18 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 81f52d3..4a028c9 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2439,14 +2439,14 @@ static int __init si_domain_init(int hw)
 	return 0;
 }
 
-static int identity_mapping(struct pci_dev *pdev)
+static int identity_mapping(struct device *dev)
 {
 	struct device_domain_info *info;
 
 	if (likely(!iommu_identity_mapping))
 		return 0;
 
-	info = pdev->dev.archdata.iommu;
+	info = dev->archdata.iommu;
 	if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
 		return (info->domain == si_domain);
 
@@ -2903,7 +2903,7 @@ static int iommu_no_mapping(struct device *dev)
 		return 0;
 
 	pdev = to_pci_dev(dev);
-	found = identity_mapping(pdev);
+	found = identity_mapping(dev);
 	if (found) {
 		if (iommu_should_identity_map(pdev, 0))
 			return 1;
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 19/33] iommu/vt-d: Make device_to_iommu() cope with non-PCI devices
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (17 preceding siblings ...)
  2014-03-21 17:18   ` [PATCH 18/33] iommu/vt-d: Make identity_mapping() take struct device not struct pci_dev David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 20/33] iommu/vt-d: Make domain_context_mapp{ed, ing}() take struct device David Woodhouse
                     ` (14 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Pass the struct device to it, and also make it return the bus/devfn to use,
since that is also stored in the DMAR table.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 78 ++++++++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 32 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 4a028c9..a24611f 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -664,37 +664,53 @@ static void domain_update_iommu_cap(struct dmar_domain *domain)
 	domain_update_iommu_superpage(domain);
 }
 
-static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
+static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
 {
 	struct dmar_drhd_unit *drhd = NULL;
 	struct intel_iommu *iommu;
-	struct device *dev;
-	struct pci_dev *pdev;
+	struct device *tmp;
+	struct pci_dev *ptmp, *pdev = NULL;
+	u16 segment;
 	int i;
 
+	if (dev_is_pci(dev)) {
+		pdev = to_pci_dev(dev);
+		segment = pci_domain_nr(pdev->bus);
+	} else if (ACPI_COMPANION(dev))
+		dev = &ACPI_COMPANION(dev)->dev;
+
 	rcu_read_lock();
 	for_each_active_iommu(iommu, drhd) {
-		if (segment != drhd->segment)
+		if (pdev && segment != drhd->segment)
 			continue;
 
 		for_each_active_dev_scope(drhd->devices,
-					  drhd->devices_cnt, i, dev) {
-			if (!dev_is_pci(dev))
-				continue;
-			pdev = to_pci_dev(dev);
-			if (pdev->bus->number == bus && pdev->devfn == devfn)
-				goto out;
-			if (pdev->subordinate &&
-			    pdev->subordinate->number <= bus &&
-			    pdev->subordinate->busn_res.end >= bus)
+					  drhd->devices_cnt, i, tmp) {
+			if (tmp == dev) {
+				*bus = drhd->devices[i].bus;
+				*devfn = drhd->devices[i].devfn;
 				goto out;
+			}
+
+			if (!pdev || !dev_is_pci(tmp))
+				continue;
+
+			ptmp = to_pci_dev(tmp);
+			if (ptmp->subordinate &&
+			    ptmp->subordinate->number <= pdev->bus->number &&
+			    ptmp->subordinate->busn_res.end >= pdev->bus->number)
+				goto got_pdev;
 		}
 
-		if (drhd->include_all)
+		if (pdev && drhd->include_all) {
+		got_pdev:
+			*bus = pdev->bus->number;
+			*devfn = pdev->devfn;
 			goto out;
+		}
 	}
 	iommu = NULL;
-out:
+ out:
 	rcu_read_unlock();
 
 	return iommu;
@@ -1830,14 +1846,13 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
 	int ret;
 	struct pci_dev *tmp, *parent;
 	struct intel_iommu *iommu;
+	u8 bus, devfn;
 
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
+	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
-	ret = domain_context_mapping_one(domain, iommu,
-					 pdev->bus->number, pdev->devfn,
+	ret = domain_context_mapping_one(domain, iommu, bus, devfn,
 					 translation);
 	if (ret)
 		return ret;
@@ -1872,13 +1887,13 @@ static int domain_context_mapped(struct pci_dev *pdev)
 	int ret;
 	struct pci_dev *tmp, *parent;
 	struct intel_iommu *iommu;
+	u8 bus, devfn;
 
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
+	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
-	ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn);
+	ret = device_context_mapped(iommu, bus, devfn);
 	if (!ret)
 		return ret;
 	/* dependent device mapping */
@@ -2459,15 +2474,14 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 {
 	struct dmar_domain *ndomain;
 	struct intel_iommu *iommu;
+	u8 bus, devfn;
 	int ret;
 
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus),
-				pdev->bus->number, pdev->devfn);
+	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
-	ndomain = dmar_insert_dev_info(iommu, pdev->bus->number, pdev->devfn,
-				       &pdev->dev, domain);
+	ndomain = dmar_insert_dev_info(iommu, bus, devfn, &pdev->dev, domain);
 	if (ndomain != domain)
 		return -EBUSY;
 
@@ -4020,9 +4034,9 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
 	struct intel_iommu *iommu;
 	unsigned long flags;
 	int found = 0;
+	u8 bus, devfn;
 
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
+	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
 	if (!iommu)
 		return;
 
@@ -4142,6 +4156,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct intel_iommu *iommu;
 	int addr_width;
+	u8 bus, devfn;
 
 	/* normally pdev is not mapped */
 	if (unlikely(domain_context_mapped(pdev))) {
@@ -4157,8 +4172,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 		}
 	}
 
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
+	iommu = device_to_iommu(dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
@@ -4324,9 +4338,9 @@ static int intel_iommu_add_device(struct device *dev)
 	struct pci_dev *bridge, *dma_pdev = NULL;
 	struct iommu_group *group;
 	int ret;
+	u8 bus, devfn;
 
-	if (!device_to_iommu(pci_domain_nr(pdev->bus),
-			     pdev->bus->number, pdev->devfn))
+	if (!device_to_iommu(dev, &bus, &devfn))
 		return -ENODEV;
 
 	bridge = pci_find_upstream_pcie_bridge(pdev);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 20/33] iommu/vt-d: Make domain_context_mapp{ed, ing}() take struct device
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (18 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 19/33] iommu/vt-d: Make device_to_iommu() cope with non-PCI devices David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() " David Woodhouse
                     ` (13 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a24611f..741fb1d 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1840,24 +1840,25 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
 }
 
 static int
-domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
-			int translation)
+domain_context_mapping(struct dmar_domain *domain, struct device *dev,
+		       int translation)
 {
 	int ret;
-	struct pci_dev *tmp, *parent;
+	struct pci_dev *pdev, *tmp, *parent;
 	struct intel_iommu *iommu;
 	u8 bus, devfn;
 
-	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
+	iommu = device_to_iommu(dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
 	ret = domain_context_mapping_one(domain, iommu, bus, devfn,
 					 translation);
-	if (ret)
+	if (ret || !dev_is_pci(dev))
 		return ret;
 
 	/* dependent device mapping */
+	pdev = to_pci_dev(dev);
 	tmp = pci_find_upstream_pcie_bridge(pdev);
 	if (!tmp)
 		return 0;
@@ -1882,21 +1883,23 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
 						  translation);
 }
 
-static int domain_context_mapped(struct pci_dev *pdev)
+static int domain_context_mapped(struct device *dev)
 {
 	int ret;
-	struct pci_dev *tmp, *parent;
+	struct pci_dev *pdev, *tmp, *parent;
 	struct intel_iommu *iommu;
 	u8 bus, devfn;
 
-	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
+	iommu = device_to_iommu(dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
 	ret = device_context_mapped(iommu, bus, devfn);
-	if (!ret)
+	if (!ret || !dev_is_pci(dev))
 		return ret;
+
 	/* dependent device mapping */
+	pdev = to_pci_dev(dev);
 	tmp = pci_find_upstream_pcie_bridge(pdev);
 	if (!tmp)
 		return ret;
@@ -2361,7 +2364,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
 		goto error;
 
 	/* context entry init */
-	ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
+	ret = domain_context_mapping(domain, &pdev->dev, CONTEXT_TT_MULTI_LEVEL);
 	if (ret)
 		goto error;
 
@@ -2485,7 +2488,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 	if (ndomain != domain)
 		return -EBUSY;
 
-	ret = domain_context_mapping(domain, pdev, translation);
+	ret = domain_context_mapping(domain, &pdev->dev, translation);
 	if (ret) {
 		domain_remove_one_dev_info(domain, pdev);
 		return ret;
@@ -2870,8 +2873,8 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
 	}
 
 	/* make sure context mapping is ok */
-	if (unlikely(!domain_context_mapped(pdev))) {
-		ret = domain_context_mapping(domain, pdev,
+	if (unlikely(!domain_context_mapped(&pdev->dev))) {
+		ret = domain_context_mapping(domain, &pdev->dev,
 					     CONTEXT_TT_MULTI_LEVEL);
 		if (ret) {
 			printk(KERN_ERR
@@ -4159,7 +4162,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 	u8 bus, devfn;
 
 	/* normally pdev is not mapped */
-	if (unlikely(domain_context_mapped(pdev))) {
+	if (unlikely(domain_context_mapped(&pdev->dev))) {
 		struct dmar_domain *old_domain;
 
 		old_domain = find_domain(dev);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() take struct device
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (19 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 20/33] iommu/vt-d: Make domain_context_mapp{ed, ing}() take struct device David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
       [not found]     ` <1395422354-19762-22-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  2014-03-21 17:19   ` [PATCH 22/33] iommu/vt-d: Handle RMRRs for non-PCI devices David Woodhouse
                     ` (12 subsequent siblings)
  33 siblings, 1 reply; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 75 ++++++++++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 39 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 741fb1d..05c5214 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2207,52 +2207,51 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
 }
 
 /* domain is initialized */
-static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
+static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
 {
 	struct dmar_domain *domain, *free = NULL;
 	struct intel_iommu *iommu = NULL;
 	struct device_domain_info *info;
-	struct dmar_drhd_unit *drhd;
-	struct pci_dev *dev_tmp;
+	struct pci_dev *dev_tmp = NULL;
 	unsigned long flags;
-	int bus = 0, devfn = 0;
-	int segment;
+	u8 bus, devfn, bridge_bus, bridge_devfn;
 
-	domain = find_domain(&pdev->dev);
+	domain = find_domain(dev);
 	if (domain)
 		return domain;
 
-	segment = pci_domain_nr(pdev->bus);
+	if (dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		u16 segment;
 
-	dev_tmp = pci_find_upstream_pcie_bridge(pdev);
-	if (dev_tmp) {
-		if (pci_is_pcie(dev_tmp)) {
-			bus = dev_tmp->subordinate->number;
-			devfn = 0;
-		} else {
-			bus = dev_tmp->bus->number;
-			devfn = dev_tmp->devfn;
-		}
-		spin_lock_irqsave(&device_domain_lock, flags);
-		info = dmar_search_domain_by_dev_info(segment, bus, devfn);
-		if (info) {
-			iommu = info->iommu;
-			domain = info->domain;
+		segment = pci_domain_nr(pdev->bus);
+		dev_tmp = pci_find_upstream_pcie_bridge(pdev);
+		if (dev_tmp) {
+			if (pci_is_pcie(dev_tmp)) {
+				bridge_bus = dev_tmp->subordinate->number;
+				bridge_devfn = 0;
+			} else {
+				bridge_bus = dev_tmp->bus->number;
+				bridge_devfn = dev_tmp->devfn;
+			}
+			spin_lock_irqsave(&device_domain_lock, flags);
+			info = dmar_search_domain_by_dev_info(segment, bus, devfn);
+			if (info) {
+				iommu = info->iommu;
+				domain = info->domain;
+			}
+			spin_unlock_irqrestore(&device_domain_lock, flags);
+			/* pcie-pci bridge already has a domain, uses it */
+			if (info)
+				goto found_domain;
 		}
-		spin_unlock_irqrestore(&device_domain_lock, flags);
-		if (info)
-			goto found_domain;
 	}
 
-	drhd = dmar_find_matched_drhd_unit(pdev);
-	if (!drhd) {
-		printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
-			pci_name(pdev));
-		return NULL;
-	}
-	iommu = drhd->iommu;
+	iommu = device_to_iommu(dev, &bus, &devfn);
+	if (!iommu)
+		goto error;
 
-	/* Allocate and intialize new domain for the device */
+	/* Allocate and initialize new domain for the device */
 	domain = alloc_domain(false);
 	if (!domain)
 		goto error;
@@ -2266,15 +2265,14 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
 	/* register pcie-to-pci device */
 	if (dev_tmp) {
-		domain = dmar_insert_dev_info(iommu, bus, devfn, NULL,
-					      domain);
+		domain = dmar_insert_dev_info(iommu, bridge_bus, bridge_devfn,
+					      NULL, domain);
 		if (!domain)
 			goto error;
 	}
 
 found_domain:
-	domain = dmar_insert_dev_info(iommu, pdev->bus->number,
-				      pdev->devfn, &pdev->dev, domain);
+	domain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
 error:
 	if (free != domain)
 		domain_exit(free);
@@ -2320,7 +2318,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
 	struct dmar_domain *domain;
 	int ret;
 
-	domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 	if (!domain)
 		return -ENOMEM;
 
@@ -2864,8 +2862,7 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
 	struct dmar_domain *domain;
 	int ret;
 
-	domain = get_domain_for_dev(pdev,
-			DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 	if (!domain) {
 		printk(KERN_ERR
 			"Allocating domain for %s failed", pci_name(pdev));
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 22/33] iommu/vt-d: Handle RMRRs for non-PCI devices
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (20 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() " David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 23/33] iommu/vt-d: Make iommu_should_identity_map() take struct device David Woodhouse
                     ` (11 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Should hopefully never happen (RMRRs are an abomination) but while we're
busy eliminating all the PCI assumptions, we might as well do it.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 05c5214..acb9268 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2311,14 +2311,14 @@ static int iommu_domain_identity_map(struct dmar_domain *domain,
 				  DMA_PTE_READ|DMA_PTE_WRITE);
 }
 
-static int iommu_prepare_identity_map(struct pci_dev *pdev,
+static int iommu_prepare_identity_map(struct device *dev,
 				      unsigned long long start,
 				      unsigned long long end)
 {
 	struct dmar_domain *domain;
 	int ret;
 
-	domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 	if (!domain)
 		return -ENOMEM;
 
@@ -2328,13 +2328,13 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
 	   up to start with in si_domain */
 	if (domain == si_domain && hw_pass_through) {
 		printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
-		       pci_name(pdev), start, end);
+		       dev_name(dev), start, end);
 		return 0;
 	}
 
 	printk(KERN_INFO
 	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
-	       pci_name(pdev), start, end);
+	       dev_name(dev), start, end);
 	
 	if (end < start) {
 		WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
@@ -2362,7 +2362,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
 		goto error;
 
 	/* context entry init */
-	ret = domain_context_mapping(domain, &pdev->dev, CONTEXT_TT_MULTI_LEVEL);
+	ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
 	if (ret)
 		goto error;
 
@@ -2374,12 +2374,12 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
 }
 
 static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
-	struct pci_dev *pdev)
+					 struct device *dev)
 {
-	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+	if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
 		return 0;
-	return iommu_prepare_identity_map(pdev, rmrr->base_address,
-		rmrr->end_address);
+	return iommu_prepare_identity_map(dev, rmrr->base_address,
+					  rmrr->end_address);
 }
 
 #ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
@@ -2393,7 +2393,7 @@ static inline void iommu_prepare_isa(void)
 		return;
 
 	printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
-	ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024 - 1);
+	ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
 
 	if (ret)
 		printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
@@ -2495,7 +2495,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 	return 0;
 }
 
-static bool device_has_rmrr(struct pci_dev *dev)
+static bool device_has_rmrr(struct device *dev)
 {
 	struct dmar_rmrr_unit *rmrr;
 	struct device *tmp;
@@ -2509,7 +2509,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->dev) {
+			if (tmp == dev) {
 				rcu_read_unlock();
 				return true;
 			}
@@ -2529,7 +2529,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
 	 * from this process due to their usage of RMRRs that are known
 	 * to not be needed after BIOS hand-off to OS.
 	 */
-	if (device_has_rmrr(pdev) &&
+	if (device_has_rmrr(&pdev->dev) &&
 	    (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
 		return 0;
 
@@ -2766,9 +2766,7 @@ static int __init init_dmars(void)
 		/* some BIOS lists non-exist devices in DMAR table. */
 		for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
 					  i, dev) {
-			if (!dev_is_pci(dev))
-				continue;
-			ret = iommu_prepare_rmrr_dev(rmrr, to_pci_dev(dev));
+			ret = iommu_prepare_rmrr_dev(rmrr, dev);
 			if (ret)
 				printk(KERN_ERR
 				       "IOMMU: mapping reserved region failed\n");
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 23/33] iommu/vt-d: Make iommu_should_identity_map() take struct device
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (21 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 22/33] iommu/vt-d: Handle RMRRs for non-PCI devices David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 24/33] iommu/vt-d: Make get_valid_domain_for_dev() " David Woodhouse
                     ` (10 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---
 drivers/iommu/intel-iommu.c | 107 +++++++++++++++++++++++---------------------
 1 file changed, 57 insertions(+), 50 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index acb9268..15371ec 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2518,58 +2518,65 @@ static bool device_has_rmrr(struct device *dev)
 	return false;
 }
 
-static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
+static int iommu_should_identity_map(struct device *dev, int startup)
 {
 
-	/*
-	 * We want to prevent any device associated with an RMRR from
-	 * getting placed into the SI Domain. This is done because
-	 * problems exist when devices are moved in and out of domains
-	 * and their respective RMRR info is lost. We exempt USB devices
-	 * from this process due to their usage of RMRRs that are known
-	 * to not be needed after BIOS hand-off to OS.
-	 */
-	if (device_has_rmrr(&pdev->dev) &&
-	    (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
-		return 0;
+	if (dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
 
-	if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
-		return 1;
+		/*
+		 * We want to prevent any device associated with an RMRR from
+		 * getting placed into the SI Domain. This is done because
+		 * problems exist when devices are moved in and out of domains
+		 * and their respective RMRR info is lost. We exempt USB devices
+		 * from this process due to their usage of RMRRs that are known
+		 * to not be needed after BIOS hand-off to OS.
+		 */
+		if (device_has_rmrr(dev) &&
+		    (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
+			return 0;
 
-	if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
-		return 1;
+		if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
+			return 1;
 
-	if (!(iommu_identity_mapping & IDENTMAP_ALL))
-		return 0;
+		if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
+			return 1;
 
-	/*
-	 * We want to start off with all devices in the 1:1 domain, and
-	 * take them out later if we find they can't access all of memory.
-	 *
-	 * However, we can't do this for PCI devices behind bridges,
-	 * because all PCI devices behind the same bridge will end up
-	 * with the same source-id on their transactions.
-	 *
-	 * Practically speaking, we can't change things around for these
-	 * devices at run-time, because we can't be sure there'll be no
-	 * DMA transactions in flight for any of their siblings.
-	 * 
-	 * So PCI devices (unless they're on the root bus) as well as
-	 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
-	 * the 1:1 domain, just in _case_ one of their siblings turns out
-	 * not to be able to map all of memory.
-	 */
-	if (!pci_is_pcie(pdev)) {
-		if (!pci_is_root_bus(pdev->bus))
+		if (!(iommu_identity_mapping & IDENTMAP_ALL))
 			return 0;
-		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
+
+		/*
+		 * We want to start off with all devices in the 1:1 domain, and
+		 * take them out later if we find they can't access all of memory.
+		 *
+		 * However, we can't do this for PCI devices behind bridges,
+		 * because all PCI devices behind the same bridge will end up
+		 * with the same source-id on their transactions.
+		 *
+		 * Practically speaking, we can't change things around for these
+		 * devices at run-time, because we can't be sure there'll be no
+		 * DMA transactions in flight for any of their siblings.
+		 *
+		 * So PCI devices (unless they're on the root bus) as well as
+		 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
+		 * the 1:1 domain, just in _case_ one of their siblings turns out
+		 * not to be able to map all of memory.
+		 */
+		if (!pci_is_pcie(pdev)) {
+			if (!pci_is_root_bus(pdev->bus))
+				return 0;
+			if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
+				return 0;
+		} else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
 			return 0;
-	} else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
-		return 0;
+	} else {
+		if (device_has_rmrr(dev))
+			return 0;
+	}
 
-	/* 
+	/*
 	 * At boot time, we don't yet know if devices will be 64-bit capable.
-	 * Assume that they will -- if they turn out not to be, then we can 
+	 * Assume that they will — if they turn out not to be, then we can
 	 * take them out of the 1:1 domain later.
 	 */
 	if (!startup) {
@@ -2577,13 +2584,13 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
 		 * If the device's dma_mask is less than the system's memory
 		 * size then this is not a candidate for identity mapping.
 		 */
-		u64 dma_mask = pdev->dma_mask;
+		u64 dma_mask = *dev->dma_mask;
 
-		if (pdev->dev.coherent_dma_mask &&
-		    pdev->dev.coherent_dma_mask < dma_mask)
-			dma_mask = pdev->dev.coherent_dma_mask;
+		if (dev->coherent_dma_mask &&
+		    dev->coherent_dma_mask < dma_mask)
+			dma_mask = dev->coherent_dma_mask;
 
-		return dma_mask >= dma_get_required_mask(&pdev->dev);
+		return dma_mask >= dma_get_required_mask(dev);
 	}
 
 	return 1;
@@ -2599,7 +2606,7 @@ static int __init iommu_prepare_static_identity_mapping(int hw)
 		return -EFAULT;
 
 	for_each_pci_dev(pdev) {
-		if (iommu_should_identity_map(pdev, 1)) {
+		if (iommu_should_identity_map(&pdev->dev, 1)) {
 			ret = domain_add_dev_info(si_domain, pdev,
 					     hw ? CONTEXT_TT_PASS_THROUGH :
 						  CONTEXT_TT_MULTI_LEVEL);
@@ -2917,7 +2924,7 @@ static int iommu_no_mapping(struct device *dev)
 	pdev = to_pci_dev(dev);
 	found = identity_mapping(dev);
 	if (found) {
-		if (iommu_should_identity_map(pdev, 0))
+		if (iommu_should_identity_map(&pdev->dev, 0))
 			return 1;
 		else {
 			/*
@@ -2934,7 +2941,7 @@ static int iommu_no_mapping(struct device *dev)
 		 * In case of a detached 64 bit DMA device from vm, the device
 		 * is put into si_domain for identity mapping.
 		 */
-		if (iommu_should_identity_map(pdev, 0)) {
+		if (iommu_should_identity_map(&pdev->dev, 0)) {
 			int ret;
 			ret = domain_add_dev_info(si_domain, pdev,
 						  hw_pass_through ?
-- 
1.8.5.3

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 24/33] iommu/vt-d: Make get_valid_domain_for_dev() take struct device
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (22 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 23/33] iommu/vt-d: Make iommu_should_identity_map() take struct device David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 25/33] iommu/vt-d: Remove some pointless to_pci_dev() calls David Woodhouse
                     ` (9 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 15371ec..41eafc3 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2862,26 +2862,24 @@ static struct iova *intel_alloc_iova(struct device *dev,
 	return iova;
 }
 
-static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
+static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
 {
 	struct dmar_domain *domain;
 	int ret;
 
-	domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 	if (!domain) {
-		printk(KERN_ERR
-			"Allocating domain for %s failed", pci_name(pdev));
+		printk(KERN_ERR "Allocating domain for %s failed",
+		       dev_name(dev));
 		return NULL;
 	}
 
 	/* make sure context mapping is ok */
-	if (unlikely(!domain_context_mapped(&pdev->dev))) {
-		ret = domain_context_mapping(domain, &pdev->dev,
-					     CONTEXT_TT_MULTI_LEVEL);
+	if (unlikely(!domain_context_mapped(dev))) {
+		ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
 		if (ret) {
-			printk(KERN_ERR
-				"Domain context map for %s failed",
-				pci_name(pdev));
+			printk(KERN_ERR "Domain context map for %s failed",
+			       dev_name(dev));
 			return NULL;
 		}
 	}
@@ -2889,12 +2887,12 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
 	return domain;
 }
 
-static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev)
+static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
 {
 	struct device_domain_info *info;
 
 	/* No lock here, assumes no domain exit in normal case */
-	info = dev->dev.archdata.iommu;
+	info = dev->archdata.iommu;
 	if (likely(info))
 		return info->domain;
 
@@ -2975,7 +2973,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	if (iommu_no_mapping(hwdev))
 		return paddr;
 
-	domain = get_valid_domain_for_dev(pdev);
+	domain = get_valid_domain_for_dev(hwdev);
 	if (!domain)
 		return 0;
 
@@ -3280,7 +3278,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 	if (iommu_no_mapping(hwdev))
 		return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
 
-	domain = get_valid_domain_for_dev(pdev);
+	domain = get_valid_domain_for_dev(hwdev);
 	if (!domain)
 		return 0;
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 25/33] iommu/vt-d: Remove some pointless to_pci_dev() calls
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (23 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 24/33] iommu/vt-d: Make get_valid_domain_for_dev() " David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 26/33] iommu/vt-d: Rename 'hwdev' variables to 'dev' now that that's the norm David Woodhouse
                     ` (8 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Mostly made redundant by using dev_name() instead of pci_name(), and one
instance of using *dev->dma_mask instead of pdev->dma_mask.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 41eafc3..cfe08ea 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2835,7 +2835,6 @@ static struct iova *intel_alloc_iova(struct device *dev,
 				     struct dmar_domain *domain,
 				     unsigned long nrpages, uint64_t dma_mask)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
 	struct iova *iova = NULL;
 
 	/* Restrict dma_mask to the width that the iommu can handle */
@@ -2855,7 +2854,7 @@ static struct iova *intel_alloc_iova(struct device *dev,
 	iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
 	if (unlikely(!iova)) {
 		printk(KERN_ERR "Allocating %ld-page iova for %s failed",
-		       nrpages, pci_name(pdev));
+		       nrpages, dev_name(dev));
 		return NULL;
 	}
 
@@ -2959,7 +2958,6 @@ static int iommu_no_mapping(struct device *dev)
 static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 				     size_t size, int dir, u64 dma_mask)
 {
-	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
 	phys_addr_t start_paddr;
 	struct iova *iova;
@@ -3018,7 +3016,7 @@ error:
 	if (iova)
 		__free_iova(&domain->iovad, iova);
 	printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
-		pci_name(pdev), size, (unsigned long long)paddr, dir);
+		dev_name(hwdev), size, (unsigned long long)paddr, dir);
 	return 0;
 }
 
@@ -3115,7 +3113,6 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 			     size_t size, enum dma_data_direction dir,
 			     struct dma_attrs *attrs)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
 	unsigned long start_pfn, last_pfn;
 	struct iova *iova;
@@ -3139,7 +3136,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 	last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
 
 	pr_debug("Device %s unmapping: pfn %lx-%lx\n",
-		 pci_name(pdev), start_pfn, last_pfn);
+		 dev_name(dev), start_pfn, last_pfn);
 
 	freelist = domain_unmap(domain, start_pfn, last_pfn);
 
@@ -3264,7 +3261,6 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 			enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	int i;
-	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
 	size_t size = 0;
 	int prot = 0;
@@ -3288,7 +3284,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 		size += aligned_nrpages(sg->offset, sg->length);
 
 	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
-				pdev->dma_mask);
+				*hwdev->dma_mask);
 	if (!iova) {
 		sglist->dma_length = 0;
 		return 0;
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 26/33] iommu/vt-d: Rename 'hwdev' variables to 'dev' now that that's the norm
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (24 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 25/33] iommu/vt-d: Remove some pointless to_pci_dev() calls David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 27/33] iommu/vt-d: Make domain_remove_one_dev_info() take struct device David Woodhouse
                     ` (7 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index cfe08ea..f3c1624 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2955,7 +2955,7 @@ static int iommu_no_mapping(struct device *dev)
 	return 0;
 }
 
-static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
+static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
 				     size_t size, int dir, u64 dma_mask)
 {
 	struct dmar_domain *domain;
@@ -2968,17 +2968,17 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 
 	BUG_ON(dir == DMA_NONE);
 
-	if (iommu_no_mapping(hwdev))
+	if (iommu_no_mapping(dev))
 		return paddr;
 
-	domain = get_valid_domain_for_dev(hwdev);
+	domain = get_valid_domain_for_dev(dev);
 	if (!domain)
 		return 0;
 
 	iommu = domain_get_iommu(domain);
 	size = aligned_nrpages(paddr, size);
 
-	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask);
+	iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
 	if (!iova)
 		goto error;
 
@@ -3016,7 +3016,7 @@ error:
 	if (iova)
 		__free_iova(&domain->iovad, iova);
 	printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
-		dev_name(hwdev), size, (unsigned long long)paddr, dir);
+		dev_name(dev), size, (unsigned long long)paddr, dir);
 	return 0;
 }
 
@@ -3155,7 +3155,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 	}
 }
 
-static void *intel_alloc_coherent(struct device *hwdev, size_t size,
+static void *intel_alloc_coherent(struct device *dev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flags,
 				  struct dma_attrs *attrs)
 {
@@ -3165,10 +3165,10 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size,
 	size = PAGE_ALIGN(size);
 	order = get_order(size);
 
-	if (!iommu_no_mapping(hwdev))
+	if (!iommu_no_mapping(dev))
 		flags &= ~(GFP_DMA | GFP_DMA32);
-	else if (hwdev->coherent_dma_mask < dma_get_required_mask(hwdev)) {
-		if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32))
+	else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
+		if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
 			flags |= GFP_DMA;
 		else
 			flags |= GFP_DMA32;
@@ -3179,16 +3179,16 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size,
 		return NULL;
 	memset(vaddr, 0, size);
 
-	*dma_handle = __intel_map_single(hwdev, virt_to_bus(vaddr), size,
+	*dma_handle = __intel_map_single(dev, virt_to_bus(vaddr), size,
 					 DMA_BIDIRECTIONAL,
-					 hwdev->coherent_dma_mask);
+					 dev->coherent_dma_mask);
 	if (*dma_handle)
 		return vaddr;
 	free_pages((unsigned long)vaddr, order);
 	return NULL;
 }
 
-static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
+static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
 				dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
 	int order;
@@ -3196,11 +3196,11 @@ static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 	size = PAGE_ALIGN(size);
 	order = get_order(size);
 
-	intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
+	intel_unmap_page(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
 	free_pages((unsigned long)vaddr, order);
 }
 
-static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
+static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			   int nelems, enum dma_data_direction dir,
 			   struct dma_attrs *attrs)
 {
@@ -3210,10 +3210,10 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	struct intel_iommu *iommu;
 	struct page *freelist;
 
-	if (iommu_no_mapping(hwdev))
+	if (iommu_no_mapping(dev))
 		return;
 
-	domain = find_domain(hwdev);
+	domain = find_domain(dev);
 	BUG_ON(!domain);
 
 	iommu = domain_get_iommu(domain);
@@ -3257,7 +3257,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 	return nelems;
 }
 
-static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
+static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
 			enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	int i;
@@ -3271,10 +3271,10 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 	struct intel_iommu *iommu;
 
 	BUG_ON(dir == DMA_NONE);
-	if (iommu_no_mapping(hwdev))
-		return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
+	if (iommu_no_mapping(dev))
+		return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
 
-	domain = get_valid_domain_for_dev(hwdev);
+	domain = get_valid_domain_for_dev(dev);
 	if (!domain)
 		return 0;
 
@@ -3283,8 +3283,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 	for_each_sg(sglist, sg, nelems, i)
 		size += aligned_nrpages(sg->offset, sg->length);
 
-	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
-				*hwdev->dma_mask);
+	iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
+				*dev->dma_mask);
 	if (!iova) {
 		sglist->dma_length = 0;
 		return 0;
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 27/33] iommu/vt-d: Make domain_remove_one_dev_info() take struct device
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (25 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 26/33] iommu/vt-d: Rename 'hwdev' variables to 'dev' now that that's the norm David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 28/33] iommu/vt-d: Make domain_add_dev_info() " David Woodhouse
                     ` (6 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f3c1624..270a25b 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -425,7 +425,7 @@ static long list_size;
 static void domain_exit(struct dmar_domain *domain);
 static void domain_remove_dev_info(struct dmar_domain *domain);
 static void domain_remove_one_dev_info(struct dmar_domain *domain,
-				       struct pci_dev *pdev);
+				       struct device *dev);
 static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
 					   struct device *dev);
 
@@ -2488,7 +2488,7 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 
 	ret = domain_context_mapping(domain, &pdev->dev, translation);
 	if (ret) {
-		domain_remove_one_dev_info(domain, pdev);
+		domain_remove_one_dev_info(domain, &pdev->dev);
 		return ret;
 	}
 
@@ -2928,7 +2928,7 @@ static int iommu_no_mapping(struct device *dev)
 			 * 32 bit DMA is removed from si_domain and fall back
 			 * to non-identity mapping.
 			 */
-			domain_remove_one_dev_info(si_domain, pdev);
+			domain_remove_one_dev_info(si_domain, dev);
 			printk(KERN_INFO "32bit %s uses non-identity mapping\n",
 			       pci_name(pdev));
 			return 0;
@@ -3810,7 +3810,6 @@ static int device_notifier(struct notifier_block *nb,
 				  unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
 
 	if (iommu_dummy(dev))
@@ -3825,7 +3824,7 @@ static int device_notifier(struct notifier_block *nb,
 		return 0;
 
 	down_read(&dmar_global_lock);
-	domain_remove_one_dev_info(domain, pdev);
+	domain_remove_one_dev_info(domain, dev);
 	if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
 	    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
 	    list_empty(&domain->devices))
@@ -4027,7 +4026,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
 }
 
 static void domain_remove_one_dev_info(struct dmar_domain *domain,
-					  struct pci_dev *pdev)
+				       struct device *dev)
 {
 	struct device_domain_info *info, *tmp;
 	struct intel_iommu *iommu;
@@ -4035,21 +4034,20 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
 	int found = 0;
 	u8 bus, devfn;
 
-	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
+	iommu = device_to_iommu(dev, &bus, &devfn);
 	if (!iommu)
 		return;
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	list_for_each_entry_safe(info, tmp, &domain->devices, link) {
-		if (info->iommu->segment == pci_domain_nr(pdev->bus) &&
-		    info->bus == pdev->bus->number &&
-		    info->devfn == pdev->devfn) {
+		if (info->iommu == iommu && info->bus == bus &&
+		    info->devfn == devfn) {
 			unlink_domain_info(info);
 			spin_unlock_irqrestore(&device_domain_lock, flags);
 
 			iommu_disable_dev_iotlb(info);
 			iommu_detach_dev(iommu, info->bus, info->devfn);
-			iommu_detach_dependent_devices(iommu, &pdev->dev);
+			iommu_detach_dependent_devices(iommu, dev);
 			free_devinfo_mem(info);
 
 			spin_lock_irqsave(&device_domain_lock, flags);
@@ -4165,7 +4163,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 		if (old_domain) {
 			if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
 			    dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
-				domain_remove_one_dev_info(old_domain, pdev);
+				domain_remove_one_dev_info(old_domain, dev);
 			else
 				domain_remove_dev_info(old_domain);
 		}
@@ -4210,9 +4208,8 @@ static void intel_iommu_detach_device(struct iommu_domain *domain,
 				      struct device *dev)
 {
 	struct dmar_domain *dmar_domain = domain->priv;
-	struct pci_dev *pdev = to_pci_dev(dev);
 
-	domain_remove_one_dev_info(dmar_domain, pdev);
+	domain_remove_one_dev_info(dmar_domain, dev);
 }
 
 static int intel_iommu_map(struct iommu_domain *domain,
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 28/33] iommu/vt-d: Make domain_add_dev_info() take struct device
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (26 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 27/33] iommu/vt-d: Make domain_remove_one_dev_info() take struct device David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 29/33] iommu/vt-d: Remove pdev from iommu_no_mapping() David Woodhouse
                     ` (5 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 270a25b..3e15050 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2470,25 +2470,24 @@ static int identity_mapping(struct device *dev)
 }
 
 static int domain_add_dev_info(struct dmar_domain *domain,
-			       struct pci_dev *pdev,
-			       int translation)
+			       struct device *dev, int translation)
 {
 	struct dmar_domain *ndomain;
 	struct intel_iommu *iommu;
 	u8 bus, devfn;
 	int ret;
 
-	iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
+	iommu = device_to_iommu(dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
-	ndomain = dmar_insert_dev_info(iommu, bus, devfn, &pdev->dev, domain);
+	ndomain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
 	if (ndomain != domain)
 		return -EBUSY;
 
-	ret = domain_context_mapping(domain, &pdev->dev, translation);
+	ret = domain_context_mapping(domain, dev, translation);
 	if (ret) {
-		domain_remove_one_dev_info(domain, &pdev->dev);
+		domain_remove_one_dev_info(domain, dev);
 		return ret;
 	}
 
@@ -2607,7 +2606,7 @@ static int __init iommu_prepare_static_identity_mapping(int hw)
 
 	for_each_pci_dev(pdev) {
 		if (iommu_should_identity_map(&pdev->dev, 1)) {
-			ret = domain_add_dev_info(si_domain, pdev,
+			ret = domain_add_dev_info(si_domain, &pdev->dev,
 					     hw ? CONTEXT_TT_PASS_THROUGH :
 						  CONTEXT_TT_MULTI_LEVEL);
 			if (ret) {
@@ -2940,7 +2939,7 @@ static int iommu_no_mapping(struct device *dev)
 		 */
 		if (iommu_should_identity_map(&pdev->dev, 0)) {
 			int ret;
-			ret = domain_add_dev_info(si_domain, pdev,
+			ret = domain_add_dev_info(si_domain, dev,
 						  hw_pass_through ?
 						  CONTEXT_TT_PASS_THROUGH :
 						  CONTEXT_TT_MULTI_LEVEL);
@@ -4201,7 +4200,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 		dmar_domain->agaw--;
 	}
 
-	return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
+	return domain_add_dev_info(dmar_domain, dev, CONTEXT_TT_MULTI_LEVEL);
 }
 
 static void intel_iommu_detach_device(struct iommu_domain *domain,
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 29/33] iommu/vt-d: Remove pdev from iommu_no_mapping()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (27 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 28/33] iommu/vt-d: Make domain_add_dev_info() " David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 30/33] iommu/vt-d: Remove pdev from intel_iommu_attach_device() David Woodhouse
                     ` (4 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 3e15050..7b73c42 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2902,10 +2902,9 @@ static int iommu_dummy(struct device *dev)
 	return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
 }
 
-/* Check if the pdev needs to go through non-identity map and unmap process.*/
+/* Check if the dev needs to go through non-identity map and unmap process.*/
 static int iommu_no_mapping(struct device *dev)
 {
-	struct pci_dev *pdev;
 	int found;
 
 	if (unlikely(!dev_is_pci(dev)))
@@ -2917,10 +2916,9 @@ static int iommu_no_mapping(struct device *dev)
 	if (!iommu_identity_mapping)
 		return 0;
 
-	pdev = to_pci_dev(dev);
 	found = identity_mapping(dev);
 	if (found) {
-		if (iommu_should_identity_map(&pdev->dev, 0))
+		if (iommu_should_identity_map(dev, 0))
 			return 1;
 		else {
 			/*
@@ -2929,7 +2927,7 @@ static int iommu_no_mapping(struct device *dev)
 			 */
 			domain_remove_one_dev_info(si_domain, dev);
 			printk(KERN_INFO "32bit %s uses non-identity mapping\n",
-			       pci_name(pdev));
+			       dev_name(dev));
 			return 0;
 		}
 	} else {
@@ -2937,7 +2935,7 @@ static int iommu_no_mapping(struct device *dev)
 		 * In case of a detached 64 bit DMA device from vm, the device
 		 * is put into si_domain for identity mapping.
 		 */
-		if (iommu_should_identity_map(&pdev->dev, 0)) {
+		if (iommu_should_identity_map(dev, 0)) {
 			int ret;
 			ret = domain_add_dev_info(si_domain, dev,
 						  hw_pass_through ?
@@ -2945,7 +2943,7 @@ static int iommu_no_mapping(struct device *dev)
 						  CONTEXT_TT_MULTI_LEVEL);
 			if (!ret) {
 				printk(KERN_INFO "64bit %s uses identity mapping\n",
-				       pci_name(pdev));
+				       dev_name(dev));
 				return 1;
 			}
 		}
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 30/33] iommu/vt-d: Remove pdev from intel_iommu_attach_device()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (28 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 29/33] iommu/vt-d: Remove pdev from iommu_no_mapping() David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 31/33] iommu/vt-d: Remove to_pci_dev() in intel_map_page() David Woodhouse
                     ` (3 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 7b73c42..9a66bf7 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4147,13 +4147,12 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 				     struct device *dev)
 {
 	struct dmar_domain *dmar_domain = domain->priv;
-	struct pci_dev *pdev = to_pci_dev(dev);
 	struct intel_iommu *iommu;
 	int addr_width;
 	u8 bus, devfn;
 
-	/* normally pdev is not mapped */
-	if (unlikely(domain_context_mapped(&pdev->dev))) {
+	/* normally dev is not mapped */
+	if (unlikely(domain_context_mapped(dev))) {
 		struct dmar_domain *old_domain;
 
 		old_domain = find_domain(dev);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 31/33] iommu/vt-d: Remove to_pci_dev() in intel_map_page()
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (29 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 30/33] iommu/vt-d: Remove pdev from intel_iommu_attach_device() David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 32/33] iommu/vt-d: Finally enable translation for non-PCI devices David Woodhouse
                     ` (2 subsequent siblings)
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

It might not be...

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 9a66bf7..b1235dc 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3023,7 +3023,7 @@ static dma_addr_t intel_map_page(struct device *dev, struct page *page,
 				 struct dma_attrs *attrs)
 {
 	return __intel_map_single(dev, page_to_phys(page) + offset, size,
-				  dir, to_pci_dev(dev)->dma_mask);
+				  dir, *dev->dma_mask);
 }
 
 static void flush_unmaps(void)
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 32/33] iommu/vt-d: Finally enable translation for non-PCI devices
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (30 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 31/33] iommu/vt-d: Remove to_pci_dev() in intel_map_page() David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-21 17:19   ` [PATCH 33/33] iommu/vt-d: Include ACPI devices in iommu=pt David Woodhouse
  2014-03-24 13:52   ` [PATCH 34/33] iommu/vt-d: Fix RCU annotations on device scope lists Woodhouse, David
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index b1235dc..0f065bc 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2907,9 +2907,6 @@ static int iommu_no_mapping(struct device *dev)
 {
 	int found;
 
-	if (unlikely(!dev_is_pci(dev)))
-		return 1;
-
 	if (iommu_dummy(dev))
 		return 1;
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 33/33] iommu/vt-d: Include ACPI devices in iommu=pt
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (31 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 32/33] iommu/vt-d: Finally enable translation for non-PCI devices David Woodhouse
@ 2014-03-21 17:19   ` David Woodhouse
  2014-03-24 13:52   ` [PATCH 34/33] iommu/vt-d: Fix RCU annotations on device scope lists Woodhouse, David
  33 siblings, 0 replies; 40+ messages in thread
From: David Woodhouse @ 2014-03-21 17:19 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/intel-iommu.c | 61 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 48 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 0f065bc..53996d9 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2595,30 +2595,65 @@ static int iommu_should_identity_map(struct device *dev, int startup)
 	return 1;
 }
 
+static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
+{
+	int ret;
+
+	if (!iommu_should_identity_map(dev, 1))
+		return 0;
+
+	ret = domain_add_dev_info(si_domain, dev,
+				  hw ? CONTEXT_TT_PASS_THROUGH :
+				       CONTEXT_TT_MULTI_LEVEL);
+	if (!ret)
+		pr_info("IOMMU: %s identity mapping for device %s\n",
+			hw ? "hardware" : "software", dev_name(dev));
+	else if (ret == -ENODEV)
+		/* device not associated with an iommu */
+		ret = 0;
+
+	return ret;
+}
+
+
 static int __init iommu_prepare_static_identity_mapping(int hw)
 {
 	struct pci_dev *pdev = NULL;
-	int ret;
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu;
+	struct device *dev;
+	int i;
+	int ret = 0;
 
 	ret = si_domain_init(hw);
 	if (ret)
 		return -EFAULT;
 
 	for_each_pci_dev(pdev) {
-		if (iommu_should_identity_map(&pdev->dev, 1)) {
-			ret = domain_add_dev_info(si_domain, &pdev->dev,
-					     hw ? CONTEXT_TT_PASS_THROUGH :
-						  CONTEXT_TT_MULTI_LEVEL);
-			if (ret) {
-				/* device not associated with an iommu */
-				if (ret == -ENODEV)
-					continue;
-				return ret;
+		ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
+		if (ret)
+			return ret;
+	}
+
+	for_each_active_iommu(iommu, drhd)
+		for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
+			struct acpi_device_physical_node *pn;
+			struct acpi_device *adev;
+
+			if (dev->bus != &acpi_bus_type)
+				continue;
+				
+			adev= to_acpi_device(dev);
+			mutex_lock(&adev->physical_node_lock);
+			list_for_each_entry(pn, &adev->physical_node_list, node) {
+				ret = dev_prepare_static_identity_mapping(pn->dev, hw);
+				if (ret)
+					break;
 			}
-			pr_info("IOMMU: %s identity mapping for device %s\n",
-				hw ? "hardware" : "software", pci_name(pdev));
+			mutex_unlock(&adev->physical_node_lock);
+			if (ret)
+				return ret;
 		}
-	}
 
 	return 0;
 }
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 34/33] iommu/vt-d: Fix RCU annotations on device scope lists
       [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                     ` (32 preceding siblings ...)
  2014-03-21 17:19   ` [PATCH 33/33] iommu/vt-d: Include ACPI devices in iommu=pt David Woodhouse
@ 2014-03-24 13:52   ` Woodhouse, David
  33 siblings, 0 replies; 40+ messages in thread
From: Woodhouse, David @ 2014-03-24 13:52 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
  Cc: Wu, Fengguang


[-- Attachment #1.1: Type: text/plain, Size: 5308 bytes --]

In commit d78e0ac577 ("iommu/vt-d: Change scope lists to struct device,
bus, devfn") I converted the 'struct device *' arrays into an array of
'struct dmar_dev_scope', where:

struct dmar_dev_scope {
       struct device *dev;
       u8 bus;
       u8 devfn;
};

That commit contained changes such as this:

-extern void dmar_free_dev_scope(struct pci_dev __rcu ***devices, int *cnt);
+extern void dmar_free_dev_scope(struct dmar_dev_scope __rcu **devices, int *cnt);

This was wrong; it is the device pointer which needs to be protected
with RCU, and the above-cited change was moving the __rcu annotation so
that it actually referred to the enclosing structure, not the device
pointer itself.

Reported by the Intel 0-day build testing infrastructure. Thanks, Fengguang.

Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iommu/dmar.c        |  8 ++++----
 drivers/iommu/intel-iommu.c |  4 ++--
 include/linux/dmar.h        | 10 +++++-----
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index cd05a4b..56e1c79 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -100,7 +100,7 @@ void *dmar_alloc_dev_scope(void *start, void *end, int *cnt)
 	return kcalloc(*cnt, sizeof(struct dmar_dev_scope), GFP_KERNEL);
 }
 
-void dmar_free_dev_scope(struct dmar_dev_scope __rcu **devices, int *cnt)
+void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt)
 {
 	int i;
 	struct device *tmp_dev;
@@ -191,7 +191,7 @@ 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 dmar_dev_scope __rcu *devices,
+			  struct dmar_dev_scope *devices,
 			  int devices_cnt)
 {
 	int i, level;
@@ -235,7 +235,7 @@ 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 dmar_dev_scope __rcu *devices, int count)
+			  struct dmar_dev_scope *devices, int count)
 {
 	int index;
 	struct device *tmp;
@@ -565,7 +565,7 @@ parse_dmar_table(void)
 	return ret;
 }
 
-static int dmar_pci_device_match(struct dmar_dev_scope __rcu devices[],
+static int dmar_pci_device_match(struct dmar_dev_scope devices[],
 				 int cnt, struct pci_dev *dev)
 {
 	int index;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 53996d9..6fbce01 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -381,14 +381,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 dmar_dev_scope __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 dmar_dev_scope __rcu *devices;	/* target devices */
+	struct dmar_dev_scope *devices;	/* target devices */
 	int devices_cnt;		/* target device count */
 	u8 include_all:1;		/* include all ports */
 };
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 4c2caab..23c8db1 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -37,7 +37,7 @@ struct acpi_dmar_header;
 struct intel_iommu;
 
 struct dmar_dev_scope {
-	struct device *dev;
+	struct device __rcu *dev;
 	u8 bus;
 	u8 devfn;
 };
@@ -48,7 +48,7 @@ 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	dmar_dev_scope __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		*/
@@ -103,13 +103,13 @@ extern int dmar_dev_scope_init(void);
 extern int dmar_parse_dev_scope(void *start, void *end, 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 __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 dmar_dev_scope __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 dmar_dev_scope __rcu *devices,
+				 u16 segment, struct dmar_dev_scope *devices,
 				 int count);
 /* Intel IOMMU detection */
 extern int detect_intel_iommu(void);
-- 
1.8.5.3


-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org                              Intel Corporation

[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6242 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH] iommu/vt-d: Check for NULL pointer in dmar_acpi_dev_scope_init() array
       [not found]     ` <1395422354-19762-6-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2014-03-25 19:30       ` Joerg Roedel
       [not found]         ` <20140325193015.GI13491-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Joerg Roedel @ 2014-03-25 19:30 UTC (permalink / raw)
  To: David Woodhouse; +Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Hi David,

On Fri, Mar 21, 2014 at 05:18:46PM +0000, David Woodhouse wrote:
> +static int __init dmar_acpi_dev_scope_init(void)
> +{
> +	struct acpi_dmar_andd *andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar);
> +
> +	while (((unsigned long)andd) <
> +	       ((unsigned long)dmar_tbl) + dmar_tbl->length) {

This is causing a kernel crash on AMD IOMMU systems. I will queue
attached patch on the x86/vt-d to fix the issue. A better solution would
be to not call ir_dev_scope_init() by a rootfs-initcall, but this is
more complicated and better not done that close to the merge-window.
Do you have objections?


	Joerg

>From 0e1ad789087ea3b142ee4a169662db0ec77425ff Mon Sep 17 00:00:00 2001
From: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
Date: Tue, 25 Mar 2014 20:16:40 +0100
Subject: [PATCH] iommu/vt-d: Check for NULL pointer in dmar_acpi_dev_scope_init()

When ir_dev_scope_init() is called via a rootfs initcall it
will check for irq_remapping_enabled before it calls
(indirectly) into dmar_acpi_dev_scope_init() which uses the
dmar_tbl pointer without any checks.

The AMD IOMMU driver also sets the irq_remapping_enabled
flag which causes the dmar_acpi_dev_scope_init() function to
be called on systems with AMD IOMMU hardware too, causing a
boot-time kernel crash.

Signed-off-by: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
---
 drivers/iommu/dmar.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 56e1c79..e531a2b 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -657,7 +657,12 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number,
 
 static int __init dmar_acpi_dev_scope_init(void)
 {
-	struct acpi_dmar_andd *andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar);
+	struct acpi_dmar_andd *andd;
+
+	if (dmar_tbl == NULL)
+		return -ENODEV;
+
+	andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar);
 
 	while (((unsigned long)andd) <
 	       ((unsigned long)dmar_tbl) + dmar_tbl->length) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH] iommu/vt-d: Check for NULL pointer in dmar_acpi_dev_scope_init() array
       [not found]         ` <20140325193015.GI13491-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
@ 2014-03-26  9:16           ` Woodhouse, David
  0 siblings, 0 replies; 40+ messages in thread
From: Woodhouse, David @ 2014-03-26  9:16 UTC (permalink / raw)
  To: joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org
  Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org


[-- Attachment #1.1: Type: text/plain, Size: 2022 bytes --]

On Tue, 2014-03-25 at 20:30 +0100, Joerg Roedel wrote:
> 
> When ir_dev_scope_init() is called via a rootfs initcall it
> will check for irq_remapping_enabled before it calls
> (indirectly) into dmar_acpi_dev_scope_init() which uses the
> dmar_tbl pointer without any checks.

Ew. If irq_remapping_enabled is not (any more?) Intel-specific, then
ir_dev_scope_init() ought to be checking something more appropriate.

But defensively fixing dmar_dev_scope_init() as you have done certainly
seems reasonable. On a slow path, it doesn't hurt to check for NULL.

Acked-by: David Woodhouse <david.woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>


However, I note that dmar_dev_scope_init() already *does* effectively
check for the existence of Intel IOMMU hardware, because it checks the
dmar_drhd_units list. So the patch below would also make sense, and
should be sufficient to fix the problem on its own...



From: David Woodhouse <david.woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Subject: iommu/vt-d: Only call dmar_acpi_dev_scope_init() if there are DRHD units

For arcane reasons, this code path gets exercised even on AMD systems
when IRQ remapping is enabled.

Signed-off-by: David Woodhouse <david.woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 56e1c79..8e1a4ae 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -693,13 +693,13 @@ int __init dmar_dev_scope_init(void)
 	if (dmar_dev_scope_status != 1)
 		return dmar_dev_scope_status;
 
-	dmar_acpi_dev_scope_init();
-
 	if (list_empty(&dmar_drhd_units)) {
 		dmar_dev_scope_status = -ENODEV;
 	} else {
 		dmar_dev_scope_status = 0;
 
+		dmar_acpi_dev_scope_init();
+
 		for_each_pci_dev(dev) {
 			if (dev->is_virtfn)
 				continue;



-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org                              Intel Corporation

[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6242 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() take struct device
       [not found]     ` <1395422354-19762-22-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2014-04-14 21:22       ` Alex Williamson
       [not found]         ` <1397510541.3060.15.camel-85EaTFmN5p//9pzu0YdTqQ@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Alex Williamson @ 2014-04-14 21:22 UTC (permalink / raw)
  To: David Woodhouse; +Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

On Fri, 2014-03-21 at 17:19 +0000, David Woodhouse wrote:
> Signed-off-by: David Woodhouse <David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/iommu/intel-iommu.c | 75 ++++++++++++++++++++++-----------------------
>  1 file changed, 36 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 741fb1d..05c5214 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -2207,52 +2207,51 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
>  }
>  
>  /* domain is initialized */
> -static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
> +static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
>  {
>  	struct dmar_domain *domain, *free = NULL;
>  	struct intel_iommu *iommu = NULL;
>  	struct device_domain_info *info;
> -	struct dmar_drhd_unit *drhd;
> -	struct pci_dev *dev_tmp;
> +	struct pci_dev *dev_tmp = NULL;
>  	unsigned long flags;
> -	int bus = 0, devfn = 0;
> -	int segment;
> +	u8 bus, devfn, bridge_bus, bridge_devfn;
>  
> -	domain = find_domain(&pdev->dev);
> +	domain = find_domain(dev);
>  	if (domain)
>  		return domain;
>  
> -	segment = pci_domain_nr(pdev->bus);
> +	if (dev_is_pci(dev)) {
> +		struct pci_dev *pdev = to_pci_dev(dev);
> +		u16 segment;
>  
> -	dev_tmp = pci_find_upstream_pcie_bridge(pdev);
> -	if (dev_tmp) {
> -		if (pci_is_pcie(dev_tmp)) {
> -			bus = dev_tmp->subordinate->number;
> -			devfn = 0;
> -		} else {
> -			bus = dev_tmp->bus->number;
> -			devfn = dev_tmp->devfn;
> -		}
> -		spin_lock_irqsave(&device_domain_lock, flags);
> -		info = dmar_search_domain_by_dev_info(segment, bus, devfn);
> -		if (info) {
> -			iommu = info->iommu;
> -			domain = info->domain;
> +		segment = pci_domain_nr(pdev->bus);
> +		dev_tmp = pci_find_upstream_pcie_bridge(pdev);
> +		if (dev_tmp) {
> +			if (pci_is_pcie(dev_tmp)) {
> +				bridge_bus = dev_tmp->subordinate->number;
> +				bridge_devfn = 0;
> +			} else {
> +				bridge_bus = dev_tmp->bus->number;
> +				bridge_devfn = dev_tmp->devfn;
> +			}
> +			spin_lock_irqsave(&device_domain_lock, flags);
> +			info = dmar_search_domain_by_dev_info(segment, bus, devfn);


bus and devfn are uninitialized here, CID 1197747 & 1197746.  Thanks,

Alex


> +			if (info) {
> +				iommu = info->iommu;
> +				domain = info->domain;
> +			}
> +			spin_unlock_irqrestore(&device_domain_lock, flags);
> +			/* pcie-pci bridge already has a domain, uses it */
> +			if (info)
> +				goto found_domain;
>  		}
> -		spin_unlock_irqrestore(&device_domain_lock, flags);
> -		if (info)
> -			goto found_domain;
>  	}
>  
> -	drhd = dmar_find_matched_drhd_unit(pdev);
> -	if (!drhd) {
> -		printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
> -			pci_name(pdev));
> -		return NULL;
> -	}
> -	iommu = drhd->iommu;
> +	iommu = device_to_iommu(dev, &bus, &devfn);
> +	if (!iommu)
> +		goto error;
>  
> -	/* Allocate and intialize new domain for the device */
> +	/* Allocate and initialize new domain for the device */
>  	domain = alloc_domain(false);
>  	if (!domain)
>  		goto error;
> @@ -2266,15 +2265,14 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
>  
>  	/* register pcie-to-pci device */
>  	if (dev_tmp) {
> -		domain = dmar_insert_dev_info(iommu, bus, devfn, NULL,
> -					      domain);
> +		domain = dmar_insert_dev_info(iommu, bridge_bus, bridge_devfn,
> +					      NULL, domain);
>  		if (!domain)
>  			goto error;
>  	}
>  
>  found_domain:
> -	domain = dmar_insert_dev_info(iommu, pdev->bus->number,
> -				      pdev->devfn, &pdev->dev, domain);
> +	domain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
>  error:
>  	if (free != domain)
>  		domain_exit(free);
> @@ -2320,7 +2318,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
>  	struct dmar_domain *domain;
>  	int ret;
>  
> -	domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
> +	domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
>  	if (!domain)
>  		return -ENOMEM;
>  
> @@ -2864,8 +2862,7 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
>  	struct dmar_domain *domain;
>  	int ret;
>  
> -	domain = get_domain_for_dev(pdev,
> -			DEFAULT_DOMAIN_ADDRESS_WIDTH);
> +	domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
>  	if (!domain) {
>  		printk(KERN_ERR
>  			"Allocating domain for %s failed", pci_name(pdev));

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() take struct device
       [not found]         ` <1397510541.3060.15.camel-85EaTFmN5p//9pzu0YdTqQ@public.gmane.org>
@ 2014-04-14 21:40           ` Woodhouse, David
       [not found]             ` <1397511643.19944.217.camel-Fexsq3y4057IgHVZqg5X0TlWvGAXklZc@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Woodhouse, David @ 2014-04-14 21:40 UTC (permalink / raw)
  To: alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org
  Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org


[-- Attachment #1.1: Type: text/plain, Size: 1005 bytes --]

On Mon, 2014-04-14 at 15:22 -0600, Alex Williamson wrote:
> 
> > +             if (dev_tmp) {
> > +                     if (pci_is_pcie(dev_tmp)) {
> > +                             bridge_bus = dev_tmp->subordinate->number;
> > +                             bridge_devfn = 0;
> > +                     } else {
> > +                             bridge_bus = dev_tmp->bus->number;
> > +                             bridge_devfn = dev_tmp->devfn;
> > +                     }
> > +                     spin_lock_irqsave(&device_domain_lock, flags);
> > +                     info = dmar_search_domain_by_dev_info(segment, bus, devfn);
> 
> 
> bus and devfn are uninitialized here, CID 1197747 & 1197746.  Thanks,

Oops. That should be using bridge_bus and bridge_devfn, shouldn't it?

Will fix; thanks.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org                              Intel Corporation

[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 3437 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() take struct device
       [not found]             ` <1397511643.19944.217.camel-Fexsq3y4057IgHVZqg5X0TlWvGAXklZc@public.gmane.org>
@ 2014-04-14 21:52               ` Alex Williamson
  0 siblings, 0 replies; 40+ messages in thread
From: Alex Williamson @ 2014-04-14 21:52 UTC (permalink / raw)
  To: Woodhouse, David
  Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org

On Mon, 2014-04-14 at 21:40 +0000, Woodhouse, David wrote:
> On Mon, 2014-04-14 at 15:22 -0600, Alex Williamson wrote:
> > 
> > > +             if (dev_tmp) {
> > > +                     if (pci_is_pcie(dev_tmp)) {
> > > +                             bridge_bus = dev_tmp->subordinate->number;
> > > +                             bridge_devfn = 0;
> > > +                     } else {
> > > +                             bridge_bus = dev_tmp->bus->number;
> > > +                             bridge_devfn = dev_tmp->devfn;
> > > +                     }
> > > +                     spin_lock_irqsave(&device_domain_lock, flags);
> > > +                     info = dmar_search_domain_by_dev_info(segment, bus, devfn);
> > 
> > 
> > bus and devfn are uninitialized here, CID 1197747 & 1197746.  Thanks,
> 
> Oops. That should be using bridge_bus and bridge_devfn, shouldn't it?
> 
> Will fix; thanks.
> 

Yep, I think it was supposed to be bridge_*.  Thanks,

Alex

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2014-04-14 21:52 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-21 17:18 [PATCH 00/33] iommu/vt-d: Add support for DMA mapping of ACPI-enumerated devices David Woodhouse
     [not found] ` <1395422354-19762-1-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-03-21 17:18   ` [PATCH 01/33] iommu/vt-d: Add ACPI namespace device reporting structures David Woodhouse
2014-03-21 17:18   ` [PATCH 02/33] iommu/vt-d: Parse ANDD records David Woodhouse
2014-03-21 17:18   ` [PATCH 03/33] iommu/vt-d: Allocate space for ACPI devices David Woodhouse
2014-03-21 17:18   ` [PATCH 04/33] iommu/vt-d: Change scope lists to struct device, bus, devfn David Woodhouse
2014-03-21 17:18   ` [PATCH 05/33] iommu/vt-d: Add ACPI devices into dmaru->devices[] array David Woodhouse
     [not found]     ` <1395422354-19762-6-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-03-25 19:30       ` [PATCH] iommu/vt-d: Check for NULL pointer in dmar_acpi_dev_scope_init() array Joerg Roedel
     [not found]         ` <20140325193015.GI13491-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2014-03-26  9:16           ` Woodhouse, David
2014-03-21 17:18   ` [PATCH 06/33] iommu/vt-d: Make iommu_dummy() take struct device instead of struct pci_dev David Woodhouse
2014-03-21 17:18   ` [PATCH 07/33] iommu/vt-d: Make dmar_insert_dev_info() " David Woodhouse
2014-03-21 17:18   ` [PATCH 08/33] iommu/vt-d: Use struct device in device_domain_info, not " David Woodhouse
2014-03-21 17:18   ` [PATCH 09/33] iommu/vt-d: Pass iommu to domain_context_mapping_one() and iommu_support_dev_iotlb() David Woodhouse
2014-03-21 17:18   ` [PATCH 10/33] iommu/vt-d: Stop dmar_insert_dev_info() freeing domains on losing race David Woodhouse
2014-03-21 17:18   ` [PATCH 11/33] iommu/vt-d: use dmar_insert_dev_info() from dma_add_dev_info() David Woodhouse
2014-03-21 17:18   ` [PATCH 12/33] iommu/vt-d: Use domain_remove_one_dev_info() in domain_add_dev_info() error path David Woodhouse
2014-03-21 17:18   ` [PATCH 13/33] iommu/vt-d: Always store iommu in device_domain_info David Woodhouse
2014-03-21 17:18   ` [PATCH 14/33] iommu/vt-d: Simplify iommu check in domain_remove_one_dev_info() David Woodhouse
2014-03-21 17:18   ` [PATCH 15/33] iommu/vt-d: Remove device_to_iommu() call from domain_remove_dev_info() David Woodhouse
2014-03-21 17:18   ` [PATCH 16/33] iommu/vt-d: Store PCI segment number in struct intel_iommu David Woodhouse
2014-03-21 17:18   ` [PATCH 17/33] iommu/vt-d: Remove segment from struct device_domain_info() David Woodhouse
2014-03-21 17:18   ` [PATCH 18/33] iommu/vt-d: Make identity_mapping() take struct device not struct pci_dev David Woodhouse
2014-03-21 17:19   ` [PATCH 19/33] iommu/vt-d: Make device_to_iommu() cope with non-PCI devices David Woodhouse
2014-03-21 17:19   ` [PATCH 20/33] iommu/vt-d: Make domain_context_mapp{ed, ing}() take struct device David Woodhouse
2014-03-21 17:19   ` [PATCH 21/33] iommu/vt-d: Make get_domain_for_dev() " David Woodhouse
     [not found]     ` <1395422354-19762-22-git-send-email-David.Woodhouse-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-04-14 21:22       ` Alex Williamson
     [not found]         ` <1397510541.3060.15.camel-85EaTFmN5p//9pzu0YdTqQ@public.gmane.org>
2014-04-14 21:40           ` Woodhouse, David
     [not found]             ` <1397511643.19944.217.camel-Fexsq3y4057IgHVZqg5X0TlWvGAXklZc@public.gmane.org>
2014-04-14 21:52               ` Alex Williamson
2014-03-21 17:19   ` [PATCH 22/33] iommu/vt-d: Handle RMRRs for non-PCI devices David Woodhouse
2014-03-21 17:19   ` [PATCH 23/33] iommu/vt-d: Make iommu_should_identity_map() take struct device David Woodhouse
2014-03-21 17:19   ` [PATCH 24/33] iommu/vt-d: Make get_valid_domain_for_dev() " David Woodhouse
2014-03-21 17:19   ` [PATCH 25/33] iommu/vt-d: Remove some pointless to_pci_dev() calls David Woodhouse
2014-03-21 17:19   ` [PATCH 26/33] iommu/vt-d: Rename 'hwdev' variables to 'dev' now that that's the norm David Woodhouse
2014-03-21 17:19   ` [PATCH 27/33] iommu/vt-d: Make domain_remove_one_dev_info() take struct device David Woodhouse
2014-03-21 17:19   ` [PATCH 28/33] iommu/vt-d: Make domain_add_dev_info() " David Woodhouse
2014-03-21 17:19   ` [PATCH 29/33] iommu/vt-d: Remove pdev from iommu_no_mapping() David Woodhouse
2014-03-21 17:19   ` [PATCH 30/33] iommu/vt-d: Remove pdev from intel_iommu_attach_device() David Woodhouse
2014-03-21 17:19   ` [PATCH 31/33] iommu/vt-d: Remove to_pci_dev() in intel_map_page() David Woodhouse
2014-03-21 17:19   ` [PATCH 32/33] iommu/vt-d: Finally enable translation for non-PCI devices David Woodhouse
2014-03-21 17:19   ` [PATCH 33/33] iommu/vt-d: Include ACPI devices in iommu=pt David Woodhouse
2014-03-24 13:52   ` [PATCH 34/33] iommu/vt-d: Fix RCU annotations on device scope lists Woodhouse, David

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).