public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [git pull] IOMMU updates for 2.6.33
@ 2009-11-27 13:55 Joerg Roedel
  2009-11-27 13:55 ` [PATCH 01/34] x86/amd-iommu: Separate internal interface definitions Joerg Roedel
                   ` (34 more replies)
  0 siblings, 35 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel

Hi Ingo,


The following changes since commit 273bee27fa9f79d94b78c83506016f2e41e78983:
  FUJITA Tomonori (1):
        x86: Fix iommu=soft boot option

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git amd-iommu/2.6.33

Joerg Roedel (35):
      x86/amd-iommu: Separate internal interface definitions
      x86/amd-iommu: Update copyright headers
      x86/amd-iommu: Add an index field to struct amd_iommu
      x86/amd-iommu: Add per IOMMU reference counting
      x86/amd-iommu: Add function to complete a tlb flush
      x86/amd-iommu: Make iommu_flush_pages aware of multiple IOMMUs
      x86/amd-iommu: Use __iommu_flush_pages for tlb flushes
      x86/amd-iommu: Remove iommu_flush_domain function
      x86/amd-iommu: Implement protection domain list
      x86/amd-iommu: Reimplement amd_iommu_flush_all_domains()
      x86/amd-iommu: Reimplement flush_all_domains_on_iommu()
      x86/amd-iommu: Make np-cache a global flag
      x86/amd-iommu: Use check_device for amd_iommu_dma_supported
      x86/amd-iommu: Use check_device in get_device_resources
      x86/amd-iommu: Remove iommu parameter from dma_ops_domain_(un)map
      x86/amd-iommu: Make alloc_new_range aware of multiple IOMMUs
      x86/amd-iommu: Remove iommu parameter from __(un)map_single
      x86/amd-iommu: Remove iommu specific handling from dma_ops path
      x86/amd-iommu: Let domain_for_device handle aliases
      x86/amd-iommu: Simplify get_device_resources()
      x86/amd-iommu: Move find_protection_domain to helper functions
      x86/amd-iommu: Use get_device_id and check_device where appropriate
      x86/amd-iommu: Remove iommu parameter from dma_ops_domain_alloc
      x86/amd-iommu: Move some pte allocation functions in the right section
      x86/amd-iommu: Rearrange dma_ops related functions
      x86/amd-iommu: Remove support for domain sharing
      x86/amd-iommu: Use dev->arch->iommu to store iommu related information
      x86/amd-iommu: Add device bind reference counting
      x86/amd-iommu: Keep devices per domain in a list
      x86/amd-iommu: Cleanup attach/detach_device code
      x86/amd-iommu: Introduce iommu_flush_device() function
      x86/amd-iommu: Cleanup DTE flushing code
      x86/amd-iommu: Move reset_iommu_command_buffer out of locked code
      x86/amd-iommu: Remove amd_iommu_pd_table
      Merge branch 'gart/fixes' into amd-iommu/2.6.33

Pavel Vasilyev (1):
      agp/amd64: Remove GART dependency on AGP_AMD64

 arch/x86/include/asm/amd_iommu.h       |   12 +-
 arch/x86/include/asm/amd_iommu_proto.h |   38 +
 arch/x86/include/asm/amd_iommu_types.h |   54 ++-
 arch/x86/include/asm/device.h          |    2 +-
 arch/x86/kernel/amd_iommu.c            | 1230 +++++++++++++++++---------------
 arch/x86/kernel/amd_iommu_init.c       |   67 +-
 drivers/char/agp/Kconfig               |    3 +-
 7 files changed, 777 insertions(+), 629 deletions(-)
 create mode 100644 arch/x86/include/asm/amd_iommu_proto.h

Most of the changes are for AMD IOMMU driver. The changes there are bigger than
usual because I did a lot of changes to the data structures storing the
relations between devices, protection domains and iommus. A major change is
that the amd_iommu_pd_table is now gone and replaced by a struct iommu_dev_data
for each device stored in dev->archdata->iommu.
These changes result in a more robust reference counting, especially for
devices with an alias and simplified code in many places.
Also included are some related cleanups which separated the internal function
prototypes to a several header and code movement to get rid of most function
forward declarations. Please pull.

	Joerg



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

* [PATCH 01/34] x86/amd-iommu: Separate internal interface definitions
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 02/34] x86/amd-iommu: Update copyright headers Joerg Roedel
                   ` (33 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch moves all function declarations which are only
used inside the driver code to a seperate header file.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu.h       |   10 +++-----
 arch/x86/include/asm/amd_iommu_proto.h |   38 ++++++++++++++++++++++++++++++++
 arch/x86/include/asm/amd_iommu_types.h |    5 ----
 arch/x86/kernel/amd_iommu.c            |    1 +
 arch/x86/kernel/amd_iommu_init.c       |    1 +
 5 files changed, 44 insertions(+), 11 deletions(-)
 create mode 100644 arch/x86/include/asm/amd_iommu_proto.h

diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h
index b8ef2ee..0891338 100644
--- a/arch/x86/include/asm/amd_iommu.h
+++ b/arch/x86/include/asm/amd_iommu.h
@@ -23,15 +23,13 @@
 #include <linux/irqreturn.h>
 
 #ifdef CONFIG_AMD_IOMMU
-extern int amd_iommu_init_dma_ops(void);
-extern int amd_iommu_init_passthrough(void);
+
 extern void amd_iommu_detect(void);
-extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
-extern void amd_iommu_flush_all_domains(void);
-extern void amd_iommu_flush_all_devices(void);
-extern void amd_iommu_apply_erratum_63(u16 devid);
+
 #else
+
 static inline void amd_iommu_detect(void) { }
+
 #endif
 
 #endif /* _ASM_X86_AMD_IOMMU_H */
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h
new file mode 100644
index 0000000..84786fb
--- /dev/null
+++ b/arch/x86/include/asm/amd_iommu_proto.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _ASM_X86_AMD_IOMMU_PROTO_H
+#define _ASM_X86_AMD_IOMMU_PROTO_H
+
+struct amd_iommu;
+
+extern int amd_iommu_init_dma_ops(void);
+extern int amd_iommu_init_passthrough(void);
+extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
+extern void amd_iommu_flush_all_domains(void);
+extern void amd_iommu_flush_all_devices(void);
+extern void amd_iommu_apply_erratum_63(u16 devid);
+extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
+
+#ifndef CONFIG_AMD_IOMMU_STATS
+
+static inline void amd_iommu_stats_init(void) { }
+
+#endif /* !CONFIG_AMD_IOMMU_STATS */
+
+#endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 2a2cc7a..27db7f9 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -462,11 +462,6 @@ struct __iommu_counter {
 #define ADD_STATS_COUNTER(name, x)
 #define SUB_STATS_COUNTER(name, x)
 
-static inline void amd_iommu_stats_init(void) { }
-
 #endif /* CONFIG_AMD_IOMMU_STATS */
 
-/* some function prototypes */
-extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
-
 #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index b74b212..50d2b05 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -28,6 +28,7 @@
 #include <asm/proto.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
+#include <asm/amd_iommu_proto.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
 
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 72bdbda..db30cfe 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/msi.h>
 #include <asm/pci-direct.h>
+#include <asm/amd_iommu_proto.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
 #include <asm/iommu.h>
-- 
1.6.5.3



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

* [PATCH 02/34] x86/amd-iommu: Update copyright headers
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
  2009-11-27 13:55 ` [PATCH 01/34] x86/amd-iommu: Separate internal interface definitions Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 03/34] x86/amd-iommu: Add an index field to struct amd_iommu Joerg Roedel
                   ` (32 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch updates the copyright headers in the relevant AMD
IOMMU driver files to match the date of the latest changes.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu.h       |    2 +-
 arch/x86/include/asm/amd_iommu_types.h |    2 +-
 arch/x86/kernel/amd_iommu.c            |    2 +-
 arch/x86/kernel/amd_iommu_init.c       |    2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h
index 0891338..5af2982 100644
--- a/arch/x86/include/asm/amd_iommu.h
+++ b/arch/x86/include/asm/amd_iommu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 27db7f9..df5e9c8 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 50d2b05..7fe28be 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index db30cfe..cee1142 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
-- 
1.6.5.3



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

* [PATCH 03/34] x86/amd-iommu: Add an index field to struct amd_iommu
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
  2009-11-27 13:55 ` [PATCH 01/34] x86/amd-iommu: Separate internal interface definitions Joerg Roedel
  2009-11-27 13:55 ` [PATCH 02/34] x86/amd-iommu: Update copyright headers Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 04/34] x86/amd-iommu: Add per IOMMU reference counting Joerg Roedel
                   ` (31 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch adds an index field to struct amd_iommu which can
be used to lookup it up in an array. This index will be used
in struct protection_domain to keep track which protection
domain has devices behind which IOMMU.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |   17 +++++++++++++++++
 arch/x86/kernel/amd_iommu_init.c       |   15 +++++++++++++++
 2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index df5e9c8..ab3e7bf 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -25,6 +25,11 @@
 #include <linux/spinlock.h>
 
 /*
+ * Maximum number of IOMMUs supported
+ */
+#define MAX_IOMMUS	32
+
+/*
  * some size calculation constants
  */
 #define DEV_TABLE_ENTRY_SIZE		32
@@ -291,6 +296,9 @@ struct dma_ops_domain {
 struct amd_iommu {
 	struct list_head list;
 
+	/* Index within the IOMMU array */
+	int index;
+
 	/* locks the accesses to the hardware */
 	spinlock_t lock;
 
@@ -357,6 +365,15 @@ struct amd_iommu {
 extern struct list_head amd_iommu_list;
 
 /*
+ * Array with pointers to each IOMMU struct
+ * The indices are referenced in the protection domains
+ */
+extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
+
+/* Number of IOMMUs present in the system */
+extern int amd_iommus_present;
+
+/*
  * Structure defining one entry in the device table
  */
 struct dev_table_entry {
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index cee1142..8567d16 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -137,6 +137,10 @@ bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */
 LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
 					   system */
 
+/* Array to assign indices to IOMMUs*/
+struct amd_iommu *amd_iommus[MAX_IOMMUS];
+int amd_iommus_present;
+
 /*
  * Pointer to the device table which is shared by all AMD IOMMUs
  * it is indexed by the PCI device id or the HT unit id and contains
@@ -840,7 +844,18 @@ static void __init free_iommu_all(void)
 static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 {
 	spin_lock_init(&iommu->lock);
+
+	/* Add IOMMU to internal data structures */
 	list_add_tail(&iommu->list, &amd_iommu_list);
+	iommu->index             = amd_iommus_present++;
+
+	if (unlikely(iommu->index >= MAX_IOMMUS)) {
+		WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n");
+		return -ENOSYS;
+	}
+
+	/* Index is fine - add IOMMU to the array */
+	amd_iommus[iommu->index] = iommu;
 
 	/*
 	 * Copy data from ACPI table entry to the iommu struct
-- 
1.6.5.3



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

* [PATCH 04/34] x86/amd-iommu: Add per IOMMU reference counting
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (2 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 03/34] x86/amd-iommu: Add an index field to struct amd_iommu Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 05/34] x86/amd-iommu: Add function to complete a tlb flush Joerg Roedel
                   ` (30 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch adds reference counting for protection domains
per IOMMU. This allows a smarter TLB flushing strategy.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    2 ++
 arch/x86/kernel/amd_iommu.c            |   12 +++++++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index ab3e7bf..e68b148 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -238,7 +238,9 @@ struct protection_domain {
 	unsigned long flags;	/* flags to find out type of domain */
 	bool updated;		/* complete domain flush required */
 	unsigned dev_cnt;	/* devices assigned to this domain */
+	unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
 	void *priv;		/* private data */
+
 };
 
 /*
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 7fe28be..8c38f00 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1175,7 +1175,9 @@ static void __attach_device(struct amd_iommu *iommu,
 	/* update DTE entry */
 	set_dte_entry(devid, domain);
 
-	domain->dev_cnt += 1;
+	/* Do reference counting */
+	domain->dev_iommu[iommu->index] += 1;
+	domain->dev_cnt                 += 1;
 
 	/* ready */
 	spin_unlock(&domain->lock);
@@ -1209,6 +1211,9 @@ static void attach_device(struct amd_iommu *iommu,
  */
 static void __detach_device(struct protection_domain *domain, u16 devid)
 {
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+	BUG_ON(!iommu);
 
 	/* lock domain */
 	spin_lock(&domain->lock);
@@ -1223,8 +1228,9 @@ static void __detach_device(struct protection_domain *domain, u16 devid)
 
 	amd_iommu_apply_erratum_63(devid);
 
-	/* decrease reference counter */
-	domain->dev_cnt -= 1;
+	/* decrease reference counters */
+	domain->dev_iommu[iommu->index] -= 1;
+	domain->dev_cnt                 -= 1;
 
 	/* ready */
 	spin_unlock(&domain->lock);
-- 
1.6.5.3



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

* [PATCH 05/34] x86/amd-iommu: Add function to complete a tlb flush
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (3 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 04/34] x86/amd-iommu: Add per IOMMU reference counting Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 06/34] x86/amd-iommu: Make iommu_flush_pages aware of multiple IOMMUs Joerg Roedel
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch adds a function to the AMD IOMMU driver which
completes all queued commands an all IOMMUs a specific
domain has devices attached on. This is required in a later
patch when per-domain flushing is implemented.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   28 ++++++++++++++++++++++------
 1 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 8c38f00..8fa5cc3 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -376,6 +376,22 @@ out:
 	return 0;
 }
 
+static void iommu_flush_complete(struct protection_domain *domain)
+{
+	int i;
+
+	for (i = 0; i < amd_iommus_present; ++i) {
+		if (!domain->dev_iommu[i])
+			continue;
+
+		/*
+		 * Devices of this domain are behind this IOMMU
+		 * We need to wait for completion of all commands.
+		 */
+		iommu_completion_wait(amd_iommus[i]);
+	}
+}
+
 /*
  * Command send function for invalidating a device table entry
  */
@@ -1758,7 +1774,7 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
 	if (addr == DMA_ERROR_CODE)
 		goto out;
 
-	iommu_completion_wait(iommu);
+	iommu_flush_complete(domain);
 
 out:
 	spin_unlock_irqrestore(&domain->lock, flags);
@@ -1791,7 +1807,7 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 
 	__unmap_single(iommu, domain->priv, dma_addr, size, dir);
 
-	iommu_completion_wait(iommu);
+	iommu_flush_complete(domain);
 
 	spin_unlock_irqrestore(&domain->lock, flags);
 }
@@ -1863,7 +1879,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 			goto unmap;
 	}
 
-	iommu_completion_wait(iommu);
+	iommu_flush_complete(domain);
 
 out:
 	spin_unlock_irqrestore(&domain->lock, flags);
@@ -1914,7 +1930,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 		s->dma_address = s->dma_length = 0;
 	}
 
-	iommu_completion_wait(iommu);
+	iommu_flush_complete(domain);
 
 	spin_unlock_irqrestore(&domain->lock, flags);
 }
@@ -1969,7 +1985,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
 		goto out_free;
 	}
 
-	iommu_completion_wait(iommu);
+	iommu_flush_complete(domain);
 
 	spin_unlock_irqrestore(&domain->lock, flags);
 
@@ -2010,7 +2026,7 @@ static void free_coherent(struct device *dev, size_t size,
 
 	__unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
 
-	iommu_completion_wait(iommu);
+	iommu_flush_complete(domain);
 
 	spin_unlock_irqrestore(&domain->lock, flags);
 
-- 
1.6.5.3



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

* [PATCH 06/34] x86/amd-iommu: Make iommu_flush_pages aware of multiple IOMMUs
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (4 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 05/34] x86/amd-iommu: Add function to complete a tlb flush Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 07/34] x86/amd-iommu: Use __iommu_flush_pages for tlb flushes Joerg Roedel
                   ` (28 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch extends the iommu_flush_pages function to flush
the TLB entries on all IOMMUs the domain has devices on.
This basically gives up the former assumption that dma_ops
domains are only bound to one IOMMU in the system.
For dma_ops domains this is still true but not for
IOMMU-API managed domains. Giving this assumption up for
dma_ops domains too allows code simplification.
Further it splits out the main logic into a generic function
which can be used by iommu_flush_tlb too.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   31 ++++++++++++++++++++++++-------
 1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 8fa5cc3..7c06e57 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -447,10 +447,10 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
  * It invalidates a single PTE if the range to flush is within a single
  * page. Otherwise it flushes the whole TLB of the IOMMU.
  */
-static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
-		u64 address, size_t size)
+static void __iommu_flush_pages(struct protection_domain *domain,
+				u64 address, size_t size, int pde)
 {
-	int s = 0;
+	int s = 0, i;
 	unsigned pages = iommu_num_pages(address, size, PAGE_SIZE);
 
 	address &= PAGE_MASK;
@@ -464,9 +464,26 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
 		s = 1;
 	}
 
-	iommu_queue_inv_iommu_pages(iommu, address, domid, 0, s);
 
-	return 0;
+	for (i = 0; i < amd_iommus_present; ++i) {
+		if (!domain->dev_iommu[i])
+			continue;
+
+		/*
+		 * Devices of this domain are behind this IOMMU
+		 * We need a TLB flush
+		 */
+		iommu_queue_inv_iommu_pages(amd_iommus[i], address,
+					    domain->id, pde, s);
+	}
+
+	return;
+}
+
+static void iommu_flush_pages(struct protection_domain *domain,
+			     u64 address, size_t size)
+{
+	__iommu_flush_pages(domain, address, size, 0);
 }
 
 /* Flush the whole IO/TLB for a given protection domain */
@@ -1683,7 +1700,7 @@ retry:
 		iommu_flush_tlb(iommu, dma_dom->domain.id);
 		dma_dom->need_flush = false;
 	} else if (unlikely(iommu_has_npcache(iommu)))
-		iommu_flush_pages(iommu, dma_dom->domain.id, address, size);
+		iommu_flush_pages(&dma_dom->domain, address, size);
 
 out:
 	return address;
@@ -1731,7 +1748,7 @@ static void __unmap_single(struct amd_iommu *iommu,
 	dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
 	if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-		iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size);
+		iommu_flush_pages(&dma_dom->domain, dma_addr, size);
 		dma_dom->need_flush = false;
 	}
 }
-- 
1.6.5.3



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

* [PATCH 07/34] x86/amd-iommu: Use __iommu_flush_pages for tlb flushes
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (5 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 06/34] x86/amd-iommu: Make iommu_flush_pages aware of multiple IOMMUs Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 08/34] x86/amd-iommu: Remove iommu_flush_domain function Joerg Roedel
                   ` (27 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch re-implements iommu_flush_tlb functions to use
the __iommu_flush_pages logic.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   22 +++++++---------------
 1 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 7c06e57..c55aa07 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -451,7 +451,7 @@ static void __iommu_flush_pages(struct protection_domain *domain,
 				u64 address, size_t size, int pde)
 {
 	int s = 0, i;
-	unsigned pages = iommu_num_pages(address, size, PAGE_SIZE);
+	unsigned long pages = iommu_num_pages(address, size, PAGE_SIZE);
 
 	address &= PAGE_MASK;
 
@@ -487,23 +487,15 @@ static void iommu_flush_pages(struct protection_domain *domain,
 }
 
 /* Flush the whole IO/TLB for a given protection domain */
-static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
+static void iommu_flush_tlb(struct protection_domain *domain)
 {
-	u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-
-	INC_STATS_COUNTER(domain_flush_single);
-
-	iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
+	__iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
 }
 
 /* Flush the whole IO/TLB for a given protection domain - including PDE */
-static void iommu_flush_tlb_pde(struct amd_iommu *iommu, u16 domid)
+static void iommu_flush_tlb_pde(struct protection_domain *domain)
 {
-       u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-
-       INC_STATS_COUNTER(domain_flush_single);
-
-       iommu_queue_inv_iommu_pages(iommu, address, domid, 1, 1);
+	__iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
 }
 
 /*
@@ -1236,7 +1228,7 @@ static void attach_device(struct amd_iommu *iommu,
 	 * here to evict all dirty stuff.
 	 */
 	iommu_queue_inv_dev_entry(iommu, devid);
-	iommu_flush_tlb_pde(iommu, domain->id);
+	iommu_flush_tlb_pde(domain);
 }
 
 /*
@@ -1697,7 +1689,7 @@ retry:
 	ADD_STATS_COUNTER(alloced_io_mem, size);
 
 	if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
-		iommu_flush_tlb(iommu, dma_dom->domain.id);
+		iommu_flush_tlb(&dma_dom->domain);
 		dma_dom->need_flush = false;
 	} else if (unlikely(iommu_has_npcache(iommu)))
 		iommu_flush_pages(&dma_dom->domain, address, size);
-- 
1.6.5.3



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

* [PATCH 08/34] x86/amd-iommu: Remove iommu_flush_domain function
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (6 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 07/34] x86/amd-iommu: Use __iommu_flush_pages for tlb flushes Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 09/34] x86/amd-iommu: Implement protection domain list Joerg Roedel
                   ` (26 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This iommu_flush_tlb_pde function does essentially the same.
So the iommu_flush_domain function is redundant and can be
removed.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   18 ++----------------
 1 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index c55aa07..b2c19f4 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -528,20 +528,6 @@ static void flush_all_domains_on_iommu(struct amd_iommu *iommu)
 
 }
 
-/*
- * This function is used to flush the IO/TLB for a given protection domain
- * on every IOMMU in the system
- */
-static void iommu_flush_domain(u16 domid)
-{
-	struct amd_iommu *iommu;
-
-	INC_STATS_COUNTER(domain_flush_all);
-
-	for_each_iommu(iommu)
-		flush_domain_on_iommu(iommu, domid);
-}
-
 void amd_iommu_flush_all_domains(void)
 {
 	struct amd_iommu *iommu;
@@ -1464,7 +1450,7 @@ static void update_domain(struct protection_domain *domain)
 
 	update_device_table(domain);
 	flush_devices_by_domain(domain);
-	iommu_flush_domain(domain->id);
+	iommu_flush_tlb_pde(domain);
 
 	domain->updated = false;
 }
@@ -2377,7 +2363,7 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom,
 		iova  += PAGE_SIZE;
 	}
 
-	iommu_flush_domain(domain->id);
+	iommu_flush_tlb_pde(domain);
 }
 
 static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
-- 
1.6.5.3



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

* [PATCH 09/34] x86/amd-iommu: Implement protection domain list
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (7 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 08/34] x86/amd-iommu: Remove iommu_flush_domain function Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 10/34] x86/amd-iommu: Reimplement amd_iommu_flush_all_domains() Joerg Roedel
                   ` (25 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch adds code to keep a global list of all protection
domains. This allows to simplify the resume code.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    7 ++++++
 arch/x86/kernel/amd_iommu.c            |   33 ++++++++++++++++++++++++++++++++
 arch/x86/kernel/amd_iommu_init.c       |    8 +++++++
 3 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index e68b148..b332b7f 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -231,6 +231,7 @@ extern bool amd_iommu_dump;
  * independent of their use.
  */
 struct protection_domain {
+	struct list_head list;  /* for list of all protection domains */
 	spinlock_t lock;	/* mostly used to lock the page table*/
 	u16 id;			/* the domain id written to the device table */
 	int mode;		/* paging mode (0-6 levels) */
@@ -376,6 +377,12 @@ extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
 extern int amd_iommus_present;
 
 /*
+ * Declarations for the global list of all protection domains
+ */
+extern spinlock_t amd_iommu_pd_lock;
+extern struct list_head amd_iommu_pd_list;
+
+/*
  * Structure defining one entry in the device table
  */
 struct dev_table_entry {
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index b2c19f4..0c4319b 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -985,6 +985,31 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom,
  *
  ****************************************************************************/
 
+/*
+ * This function adds a protection domain to the global protection domain list
+ */
+static void add_domain_to_list(struct protection_domain *domain)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+	list_add(&domain->list, &amd_iommu_pd_list);
+	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
+/*
+ * This function removes a protection domain to the global
+ * protection domain list
+ */
+static void del_domain_from_list(struct protection_domain *domain)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+	list_del(&domain->list);
+	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
 static u16 domain_id_alloc(void)
 {
 	unsigned long flags;
@@ -1073,6 +1098,8 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
 	if (!dom)
 		return;
 
+	del_domain_from_list(&dom->domain);
+
 	free_pagetable(&dom->domain);
 
 	for (i = 0; i < APERTURE_MAX_RANGES; ++i) {
@@ -1113,6 +1140,8 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
 	dma_dom->need_flush = false;
 	dma_dom->target_dev = 0xffff;
 
+	add_domain_to_list(&dma_dom->domain);
+
 	if (alloc_new_range(iommu, dma_dom, true, GFP_KERNEL))
 		goto free_dma_dom;
 
@@ -2188,6 +2217,8 @@ static void protection_domain_free(struct protection_domain *domain)
 	if (!domain)
 		return;
 
+	del_domain_from_list(domain);
+
 	if (domain->id)
 		domain_id_free(domain->id);
 
@@ -2207,6 +2238,8 @@ static struct protection_domain *protection_domain_alloc(void)
 	if (!domain->id)
 		goto out_err;
 
+	add_domain_to_list(domain);
+
 	return domain;
 
 out_err:
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 8567d16..73d5173 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -142,6 +142,12 @@ struct amd_iommu *amd_iommus[MAX_IOMMUS];
 int amd_iommus_present;
 
 /*
+ * List of protection domains - used during resume
+ */
+LIST_HEAD(amd_iommu_pd_list);
+spinlock_t amd_iommu_pd_lock;
+
+/*
  * Pointer to the device table which is shared by all AMD IOMMUs
  * it is indexed by the PCI device id or the HT unit id and contains
  * information about the domain the device belongs to as well as the
@@ -1263,6 +1269,8 @@ static int __init amd_iommu_init(void)
 	 */
 	amd_iommu_pd_alloc_bitmap[0] = 1;
 
+	spin_lock_init(&amd_iommu_pd_lock);
+
 	/*
 	 * now the data structures are allocated and basically initialized
 	 * start the real acpi table scan
-- 
1.6.5.3



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

* [PATCH 10/34] x86/amd-iommu: Reimplement amd_iommu_flush_all_domains()
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (8 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 09/34] x86/amd-iommu: Implement protection domain list Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 11/34] x86/amd-iommu: Reimplement flush_all_domains_on_iommu() Joerg Roedel
                   ` (24 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch reimplementes the amd_iommu_flush_all_domains
function to use the global protection domain list instead
of flushing every domain on every IOMMU.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0c4319b..5141f56 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -530,10 +530,12 @@ static void flush_all_domains_on_iommu(struct amd_iommu *iommu)
 
 void amd_iommu_flush_all_domains(void)
 {
-	struct amd_iommu *iommu;
+	struct protection_domain *domain;
 
-	for_each_iommu(iommu)
-		flush_all_domains_on_iommu(iommu);
+	list_for_each_entry(domain, &amd_iommu_pd_list, list) {
+		iommu_flush_tlb_pde(domain);
+		iommu_flush_complete(domain);
+	}
 }
 
 static void flush_all_devices_for_iommu(struct amd_iommu *iommu)
-- 
1.6.5.3



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

* [PATCH 11/34] x86/amd-iommu: Reimplement flush_all_domains_on_iommu()
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (9 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 10/34] x86/amd-iommu: Reimplement amd_iommu_flush_all_domains() Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 12/34] x86/amd-iommu: Make np-cache a global flag Joerg Roedel
                   ` (23 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch reimplements the function
flush_all_domains_on_iommu to use the global protection
domain list.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   43 ++++++++++++++++++++++++-------------------
 1 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 5141f56..a1bd99d 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -499,43 +499,48 @@ static void iommu_flush_tlb_pde(struct protection_domain *domain)
 }
 
 /*
- * This function flushes one domain on one IOMMU
+ * This function flushes all domains that have devices on the given IOMMU
  */
-static void flush_domain_on_iommu(struct amd_iommu *iommu, u16 domid)
+static void flush_all_domains_on_iommu(struct amd_iommu *iommu)
 {
-	struct iommu_cmd cmd;
+	u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+	struct protection_domain *domain;
 	unsigned long flags;
 
-	__iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
-				      domid, 1, 1);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	__iommu_queue_command(iommu, &cmd);
-	__iommu_completion_wait(iommu);
-	__iommu_wait_for_completion(iommu);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static void flush_all_domains_on_iommu(struct amd_iommu *iommu)
-{
-	int i;
+	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
 
-	for (i = 1; i < MAX_DOMAIN_ID; ++i) {
-		if (!test_bit(i, amd_iommu_pd_alloc_bitmap))
+	list_for_each_entry(domain, &amd_iommu_pd_list, list) {
+		if (domain->dev_iommu[iommu->index] == 0)
 			continue;
-		flush_domain_on_iommu(iommu, i);
+
+		spin_lock(&domain->lock);
+		iommu_queue_inv_iommu_pages(iommu, address, domain->id, 1, 1);
+		iommu_flush_complete(domain);
+		spin_unlock(&domain->lock);
 	}
 
+	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
 }
 
+/*
+ * This function uses heavy locking and may disable irqs for some time. But
+ * this is no issue because it is only called during resume.
+ */
 void amd_iommu_flush_all_domains(void)
 {
 	struct protection_domain *domain;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
 
 	list_for_each_entry(domain, &amd_iommu_pd_list, list) {
+		spin_lock(&domain->lock);
 		iommu_flush_tlb_pde(domain);
 		iommu_flush_complete(domain);
+		spin_unlock(&domain->lock);
 	}
+
+	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
 }
 
 static void flush_all_devices_for_iommu(struct amd_iommu *iommu)
-- 
1.6.5.3



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

* [PATCH 12/34] x86/amd-iommu: Make np-cache a global flag
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (10 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 11/34] x86/amd-iommu: Reimplement flush_all_domains_on_iommu() Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 13/34] x86/amd-iommu: Use check_device for amd_iommu_dma_supported Joerg Roedel
                   ` (22 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

The non-present cache flag was IOMMU local until now which
doesn't make sense. Make this a global flag so we can remove
the lase user of 'struct iommu' in the map/unmap path.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    3 +++
 arch/x86/kernel/amd_iommu.c            |    8 +-------
 arch/x86/kernel/amd_iommu_init.c       |    6 ++++++
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index b332b7f..4899f78 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -211,6 +211,9 @@ extern bool amd_iommu_dump;
 			printk(KERN_INFO "AMD-Vi: " format, ## arg);	\
 	} while(0);
 
+/* global flag if IOMMUs cache non-present entries */
+extern bool amd_iommu_np_cache;
+
 /*
  * Make iterating over all IOMMUs easier
  */
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index a1bd99d..5ebd24e 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -131,12 +131,6 @@ static void amd_iommu_stats_init(void)
 
 #endif
 
-/* returns !0 if the IOMMU is caching non-present entries in its TLB */
-static int iommu_has_npcache(struct amd_iommu *iommu)
-{
-	return iommu->cap & (1UL << IOMMU_CAP_NPCACHE);
-}
-
 /****************************************************************************
  *
  * Interrupt handling functions
@@ -1713,7 +1707,7 @@ retry:
 	if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
 		iommu_flush_tlb(&dma_dom->domain);
 		dma_dom->need_flush = false;
-	} else if (unlikely(iommu_has_npcache(iommu)))
+	} else if (unlikely(amd_iommu_np_cache))
 		iommu_flush_pages(&dma_dom->domain, address, size);
 
 out:
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 73d5173..fbe4c3c 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -141,6 +141,9 @@ LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
 struct amd_iommu *amd_iommus[MAX_IOMMUS];
 int amd_iommus_present;
 
+/* IOMMUs have a non-present cache? */
+bool amd_iommu_np_cache __read_mostly;
+
 /*
  * List of protection domains - used during resume
  */
@@ -891,6 +894,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 	init_iommu_from_acpi(iommu, h);
 	init_iommu_devices(iommu);
 
+	if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
+		amd_iommu_np_cache = true;
+
 	return pci_enable_device(iommu->dev);
 }
 
-- 
1.6.5.3



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

* [PATCH 13/34] x86/amd-iommu: Use check_device for amd_iommu_dma_supported
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (11 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 12/34] x86/amd-iommu: Make np-cache a global flag Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 14/34] x86/amd-iommu: Use check_device in get_device_resources Joerg Roedel
                   ` (21 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

The check_device logic needs to include the dma_supported
checks to be really sure. Merge the dma_supported logic into
check_device and use it to implement dma_supported.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   35 +++++++++++++++++++----------------
 1 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 5ebd24e..ac27b1d 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1375,9 +1375,27 @@ static struct notifier_block device_nb = {
  */
 static bool check_device(struct device *dev)
 {
+	u16 bdf;
+	struct pci_dev *pcidev;
+
 	if (!dev || !dev->dma_mask)
 		return false;
 
+	/* No device or no PCI device */
+	if (!dev || dev->bus != &pci_bus_type)
+		return false;
+
+	pcidev = to_pci_dev(dev);
+
+	bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
+
+	/* Out of our scope? */
+	if (bdf > amd_iommu_last_bdf)
+		return false;
+
+	if (amd_iommu_rlookup_table[bdf] == NULL)
+		return false;
+
 	return true;
 }
 
@@ -2065,22 +2083,7 @@ free_mem:
  */
 static int amd_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	u16 bdf;
-	struct pci_dev *pcidev;
-
-	/* No device or no PCI device */
-	if (!dev || dev->bus != &pci_bus_type)
-		return 0;
-
-	pcidev = to_pci_dev(dev);
-
-	bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
-
-	/* Out of our scope? */
-	if (bdf > amd_iommu_last_bdf)
-		return 0;
-
-	return 1;
+	return check_device(dev);
 }
 
 /*
-- 
1.6.5.3



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

* [PATCH 14/34] x86/amd-iommu: Use check_device in get_device_resources
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (12 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 13/34] x86/amd-iommu: Use check_device for amd_iommu_dma_supported Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 15/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_(un)map Joerg Roedel
                   ` (20 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

Every call-place of get_device_resources calls check_device
before it. So call it from get_device_resources directly and
simplify the code.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   86 ++++++++++++++-----------------------------
 1 files changed, 28 insertions(+), 58 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index ac27b1d..c5102eb 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1432,35 +1432,24 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
  * If the device is not yet associated with a domain this is also done
  * in this function.
  */
-static int get_device_resources(struct device *dev,
-				struct amd_iommu **iommu,
-				struct protection_domain **domain,
-				u16 *bdf)
+static bool get_device_resources(struct device *dev,
+				 struct amd_iommu **iommu,
+				 struct protection_domain **domain,
+				 u16 *bdf)
 {
 	struct dma_ops_domain *dma_dom;
 	struct pci_dev *pcidev;
 	u16 _bdf;
 
-	*iommu = NULL;
-	*domain = NULL;
-	*bdf = 0xffff;
-
-	if (dev->bus != &pci_bus_type)
-		return 0;
-
-	pcidev = to_pci_dev(dev);
-	_bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
-
-	/* device not translated by any IOMMU in the system? */
-	if (_bdf > amd_iommu_last_bdf)
-		return 0;
-
-	*bdf = amd_iommu_alias_table[_bdf];
+	if (!check_device(dev))
+		return false;
 
-	*iommu = amd_iommu_rlookup_table[*bdf];
-	if (*iommu == NULL)
-		return 0;
+	pcidev  = to_pci_dev(dev);
+	_bdf    = calc_devid(pcidev->bus->number, pcidev->devfn);
+	*bdf    = amd_iommu_alias_table[_bdf];
+	*iommu  = amd_iommu_rlookup_table[*bdf];
 	*domain = domain_for_device(*bdf);
+
 	if (*domain == NULL) {
 		dma_dom = find_protection_domain(*bdf);
 		if (!dma_dom)
@@ -1474,7 +1463,7 @@ static int get_device_resources(struct device *dev,
 	if (domain_for_device(_bdf) == NULL)
 		attach_device(*iommu, *domain, _bdf);
 
-	return 1;
+	return true;
 }
 
 static void update_device_table(struct protection_domain *domain)
@@ -1797,17 +1786,12 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
 
 	INC_STATS_COUNTER(cnt_map_single);
 
-	if (!check_device(dev))
-		return DMA_ERROR_CODE;
-
-	dma_mask = *dev->dma_mask;
-
-	get_device_resources(dev, &iommu, &domain, &devid);
-
-	if (iommu == NULL || domain == NULL)
+	if (!get_device_resources(dev, &iommu, &domain, &devid))
 		/* device not handled by any AMD IOMMU */
 		return (dma_addr_t)paddr;
 
+	dma_mask = *dev->dma_mask;
+
 	if (!dma_ops_domain(domain))
 		return DMA_ERROR_CODE;
 
@@ -1838,8 +1822,7 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 
 	INC_STATS_COUNTER(cnt_unmap_single);
 
-	if (!check_device(dev) ||
-	    !get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &iommu, &domain, &devid))
 		/* device not handled by any AMD IOMMU */
 		return;
 
@@ -1893,16 +1876,11 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 
 	INC_STATS_COUNTER(cnt_map_sg);
 
-	if (!check_device(dev))
-		return 0;
+	if (!get_device_resources(dev, &iommu, &domain, &devid))
+		return map_sg_no_iommu(dev, sglist, nelems, dir);
 
 	dma_mask = *dev->dma_mask;
 
-	get_device_resources(dev, &iommu, &domain, &devid);
-
-	if (!iommu || !domain)
-		return map_sg_no_iommu(dev, sglist, nelems, dir);
-
 	if (!dma_ops_domain(domain))
 		return 0;
 
@@ -1958,8 +1936,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 
 	INC_STATS_COUNTER(cnt_unmap_sg);
 
-	if (!check_device(dev) ||
-	    !get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &iommu, &domain, &devid))
 		return;
 
 	if (!dma_ops_domain(domain))
@@ -1994,24 +1971,22 @@ static void *alloc_coherent(struct device *dev, size_t size,
 
 	INC_STATS_COUNTER(cnt_alloc_coherent);
 
-	if (!check_device(dev))
-		return NULL;
+	if (!get_device_resources(dev, &iommu, &domain, &devid)) {
+		virt_addr = (void *)__get_free_pages(flag, get_order(size));
+		*dma_addr = __pa(virt_addr);
+		return virt_addr;
+	}
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid))
-		flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+	dma_mask  = dev->coherent_dma_mask;
+	flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+	flag     |= __GFP_ZERO;
 
-	flag |= __GFP_ZERO;
 	virt_addr = (void *)__get_free_pages(flag, get_order(size));
 	if (!virt_addr)
 		return NULL;
 
 	paddr = virt_to_phys(virt_addr);
 
-	if (!iommu || !domain) {
-		*dma_addr = (dma_addr_t)paddr;
-		return virt_addr;
-	}
-
 	if (!dma_ops_domain(domain))
 		goto out_free;
 
@@ -2054,12 +2029,7 @@ static void free_coherent(struct device *dev, size_t size,
 
 	INC_STATS_COUNTER(cnt_free_coherent);
 
-	if (!check_device(dev))
-		return;
-
-	get_device_resources(dev, &iommu, &domain, &devid);
-
-	if (!iommu || !domain)
+	if (!get_device_resources(dev, &iommu, &domain, &devid))
 		goto free_mem;
 
 	if (!dma_ops_domain(domain))
-- 
1.6.5.3



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

* [PATCH 15/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_(un)map
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (13 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 14/34] x86/amd-iommu: Use check_device in get_device_resources Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 16/34] x86/amd-iommu: Make alloc_new_range aware of multiple IOMMUs Joerg Roedel
                   ` (19 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

The parameter is unused in these function so remove it from
the parameter list.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index c5102eb..da3f9d8 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1585,8 +1585,7 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
  * This is the generic map function. It maps one 4kb page at paddr to
  * the given address in the DMA address space for the domain.
  */
-static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
-				     struct dma_ops_domain *dom,
+static dma_addr_t dma_ops_domain_map(struct dma_ops_domain *dom,
 				     unsigned long address,
 				     phys_addr_t paddr,
 				     int direction)
@@ -1620,8 +1619,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
 /*
  * The generic unmapping function for on page in the DMA address space.
  */
-static void dma_ops_domain_unmap(struct amd_iommu *iommu,
-				 struct dma_ops_domain *dom,
+static void dma_ops_domain_unmap(struct dma_ops_domain *dom,
 				 unsigned long address)
 {
 	struct aperture_range *aperture;
@@ -1700,7 +1698,7 @@ retry:
 
 	start = address;
 	for (i = 0; i < pages; ++i) {
-		ret = dma_ops_domain_map(iommu, dma_dom, start, paddr, dir);
+		ret = dma_ops_domain_map(dma_dom, start, paddr, dir);
 		if (ret == DMA_ERROR_CODE)
 			goto out_unmap;
 
@@ -1724,7 +1722,7 @@ out_unmap:
 
 	for (--i; i >= 0; --i) {
 		start -= PAGE_SIZE;
-		dma_ops_domain_unmap(iommu, dma_dom, start);
+		dma_ops_domain_unmap(dma_dom, start);
 	}
 
 	dma_ops_free_addresses(dma_dom, address, pages);
@@ -1754,7 +1752,7 @@ static void __unmap_single(struct amd_iommu *iommu,
 	start = dma_addr;
 
 	for (i = 0; i < pages; ++i) {
-		dma_ops_domain_unmap(iommu, dma_dom, start);
+		dma_ops_domain_unmap(dma_dom, start);
 		start += PAGE_SIZE;
 	}
 
-- 
1.6.5.3



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

* [PATCH 16/34] x86/amd-iommu: Make alloc_new_range aware of multiple IOMMUs
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (14 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 15/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_(un)map Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 17/34] x86/amd-iommu: Remove iommu parameter from __(un)map_single Joerg Roedel
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

Since the assumption that an dma_ops domain is only bound to
one IOMMU was given up we need to make alloc_new_range aware
of it.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   27 +++++++++++++++------------
 1 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index da3f9d8..687f617 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -788,11 +788,11 @@ static u64 *fetch_pte(struct protection_domain *domain,
  * aperture in case of dma_ops domain allocation or address allocation
  * failure.
  */
-static int alloc_new_range(struct amd_iommu *iommu,
-			   struct dma_ops_domain *dma_dom,
+static int alloc_new_range(struct dma_ops_domain *dma_dom,
 			   bool populate, gfp_t gfp)
 {
 	int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
+	struct amd_iommu *iommu;
 	int i;
 
 #ifdef CONFIG_IOMMU_STRESS
@@ -832,14 +832,17 @@ static int alloc_new_range(struct amd_iommu *iommu,
 	dma_dom->aperture_size += APERTURE_RANGE_SIZE;
 
 	/* Intialize the exclusion range if necessary */
-	if (iommu->exclusion_start &&
-	    iommu->exclusion_start >= dma_dom->aperture[index]->offset &&
-	    iommu->exclusion_start < dma_dom->aperture_size) {
-		unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
-		int pages = iommu_num_pages(iommu->exclusion_start,
-					    iommu->exclusion_length,
-					    PAGE_SIZE);
-		dma_ops_reserve_addresses(dma_dom, startpage, pages);
+	for_each_iommu(iommu) {
+		if (iommu->exclusion_start &&
+		    iommu->exclusion_start >= dma_dom->aperture[index]->offset
+		    && iommu->exclusion_start < dma_dom->aperture_size) {
+			unsigned long startpage;
+			int pages = iommu_num_pages(iommu->exclusion_start,
+						    iommu->exclusion_length,
+						    PAGE_SIZE);
+			startpage = iommu->exclusion_start >> PAGE_SHIFT;
+			dma_ops_reserve_addresses(dma_dom, startpage, pages);
+		}
 	}
 
 	/*
@@ -1143,7 +1146,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
 
 	add_domain_to_list(&dma_dom->domain);
 
-	if (alloc_new_range(iommu, dma_dom, true, GFP_KERNEL))
+	if (alloc_new_range(dma_dom, true, GFP_KERNEL))
 		goto free_dma_dom;
 
 	/*
@@ -1686,7 +1689,7 @@ retry:
 		 */
 		dma_dom->next_address = dma_dom->aperture_size;
 
-		if (alloc_new_range(iommu, dma_dom, false, GFP_ATOMIC))
+		if (alloc_new_range(dma_dom, false, GFP_ATOMIC))
 			goto out;
 
 		/*
-- 
1.6.5.3



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

* [PATCH 17/34] x86/amd-iommu: Remove iommu parameter from __(un)map_single
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (15 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 16/34] x86/amd-iommu: Make alloc_new_range aware of multiple IOMMUs Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 18/34] x86/amd-iommu: Remove iommu specific handling from dma_ops path Joerg Roedel
                   ` (17 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

With the prior changes this parameter is not longer
required. This patch removes it from the function and all
callers.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   18 ++++++++----------
 1 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 687f617..c04dcb7 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1653,7 +1653,6 @@ static void dma_ops_domain_unmap(struct dma_ops_domain *dom,
  * Must be called with the domain lock held.
  */
 static dma_addr_t __map_single(struct device *dev,
-			       struct amd_iommu *iommu,
 			       struct dma_ops_domain *dma_dom,
 			       phys_addr_t paddr,
 			       size_t size,
@@ -1737,8 +1736,7 @@ out_unmap:
  * Does the reverse of the __map_single function. Must be called with
  * the domain lock held too
  */
-static void __unmap_single(struct amd_iommu *iommu,
-			   struct dma_ops_domain *dma_dom,
+static void __unmap_single(struct dma_ops_domain *dma_dom,
 			   dma_addr_t dma_addr,
 			   size_t size,
 			   int dir)
@@ -1797,7 +1795,7 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
 		return DMA_ERROR_CODE;
 
 	spin_lock_irqsave(&domain->lock, flags);
-	addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false,
+	addr = __map_single(dev, domain->priv, paddr, size, dir, false,
 			    dma_mask);
 	if (addr == DMA_ERROR_CODE)
 		goto out;
@@ -1832,7 +1830,7 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 
 	spin_lock_irqsave(&domain->lock, flags);
 
-	__unmap_single(iommu, domain->priv, dma_addr, size, dir);
+	__unmap_single(domain->priv, dma_addr, size, dir);
 
 	iommu_flush_complete(domain);
 
@@ -1890,7 +1888,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 	for_each_sg(sglist, s, nelems, i) {
 		paddr = sg_phys(s);
 
-		s->dma_address = __map_single(dev, iommu, domain->priv,
+		s->dma_address = __map_single(dev, domain->priv,
 					      paddr, s->length, dir, false,
 					      dma_mask);
 
@@ -1910,7 +1908,7 @@ out:
 unmap:
 	for_each_sg(sglist, s, mapped_elems, i) {
 		if (s->dma_address)
-			__unmap_single(iommu, domain->priv, s->dma_address,
+			__unmap_single(domain->priv, s->dma_address,
 				       s->dma_length, dir);
 		s->dma_address = s->dma_length = 0;
 	}
@@ -1946,7 +1944,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 	spin_lock_irqsave(&domain->lock, flags);
 
 	for_each_sg(sglist, s, nelems, i) {
-		__unmap_single(iommu, domain->priv, s->dma_address,
+		__unmap_single(domain->priv, s->dma_address,
 			       s->dma_length, dir);
 		s->dma_address = s->dma_length = 0;
 	}
@@ -1996,7 +1994,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
 
 	spin_lock_irqsave(&domain->lock, flags);
 
-	*dma_addr = __map_single(dev, iommu, domain->priv, paddr,
+	*dma_addr = __map_single(dev, domain->priv, paddr,
 				 size, DMA_BIDIRECTIONAL, true, dma_mask);
 
 	if (*dma_addr == DMA_ERROR_CODE) {
@@ -2038,7 +2036,7 @@ static void free_coherent(struct device *dev, size_t size,
 
 	spin_lock_irqsave(&domain->lock, flags);
 
-	__unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
+	__unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
 
 	iommu_flush_complete(domain);
 
-- 
1.6.5.3



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

* [PATCH 18/34] x86/amd-iommu: Remove iommu specific handling from dma_ops path
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (16 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 17/34] x86/amd-iommu: Remove iommu parameter from __(un)map_single Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 19/34] x86/amd-iommu: Let domain_for_device handle aliases Joerg Roedel
                   ` (16 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch finishes the removal of all iommu specific
handling code in the dma_ops path.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   28 +++++++++++-----------------
 1 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index c04dcb7..2cd5800 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1436,11 +1436,11 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
  * in this function.
  */
 static bool get_device_resources(struct device *dev,
-				 struct amd_iommu **iommu,
 				 struct protection_domain **domain,
 				 u16 *bdf)
 {
 	struct dma_ops_domain *dma_dom;
+	struct amd_iommu *iommu;
 	struct pci_dev *pcidev;
 	u16 _bdf;
 
@@ -1450,21 +1450,21 @@ static bool get_device_resources(struct device *dev,
 	pcidev  = to_pci_dev(dev);
 	_bdf    = calc_devid(pcidev->bus->number, pcidev->devfn);
 	*bdf    = amd_iommu_alias_table[_bdf];
-	*iommu  = amd_iommu_rlookup_table[*bdf];
+	iommu   = amd_iommu_rlookup_table[*bdf];
 	*domain = domain_for_device(*bdf);
 
 	if (*domain == NULL) {
 		dma_dom = find_protection_domain(*bdf);
 		if (!dma_dom)
-			dma_dom = (*iommu)->default_dom;
+			dma_dom = iommu->default_dom;
 		*domain = &dma_dom->domain;
-		attach_device(*iommu, *domain, *bdf);
+		attach_device(iommu, *domain, *bdf);
 		DUMP_printk("Using protection domain %d for device %s\n",
 			    (*domain)->id, dev_name(dev));
 	}
 
 	if (domain_for_device(_bdf) == NULL)
-		attach_device(*iommu, *domain, _bdf);
+		attach_device(iommu, *domain, _bdf);
 
 	return true;
 }
@@ -1776,7 +1776,6 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
 			   struct dma_attrs *attrs)
 {
 	unsigned long flags;
-	struct amd_iommu *iommu;
 	struct protection_domain *domain;
 	u16 devid;
 	dma_addr_t addr;
@@ -1785,7 +1784,7 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
 
 	INC_STATS_COUNTER(cnt_map_single);
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &domain, &devid))
 		/* device not handled by any AMD IOMMU */
 		return (dma_addr_t)paddr;
 
@@ -1815,13 +1814,12 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 		       enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	unsigned long flags;
-	struct amd_iommu *iommu;
 	struct protection_domain *domain;
 	u16 devid;
 
 	INC_STATS_COUNTER(cnt_unmap_single);
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &domain, &devid))
 		/* device not handled by any AMD IOMMU */
 		return;
 
@@ -1864,7 +1862,6 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 		  struct dma_attrs *attrs)
 {
 	unsigned long flags;
-	struct amd_iommu *iommu;
 	struct protection_domain *domain;
 	u16 devid;
 	int i;
@@ -1875,7 +1872,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 
 	INC_STATS_COUNTER(cnt_map_sg);
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &domain, &devid))
 		return map_sg_no_iommu(dev, sglist, nelems, dir);
 
 	dma_mask = *dev->dma_mask;
@@ -1927,7 +1924,6 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 		     struct dma_attrs *attrs)
 {
 	unsigned long flags;
-	struct amd_iommu *iommu;
 	struct protection_domain *domain;
 	struct scatterlist *s;
 	u16 devid;
@@ -1935,7 +1931,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 
 	INC_STATS_COUNTER(cnt_unmap_sg);
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &domain, &devid))
 		return;
 
 	if (!dma_ops_domain(domain))
@@ -1962,7 +1958,6 @@ static void *alloc_coherent(struct device *dev, size_t size,
 {
 	unsigned long flags;
 	void *virt_addr;
-	struct amd_iommu *iommu;
 	struct protection_domain *domain;
 	u16 devid;
 	phys_addr_t paddr;
@@ -1970,7 +1965,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
 
 	INC_STATS_COUNTER(cnt_alloc_coherent);
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid)) {
+	if (!get_device_resources(dev, &domain, &devid)) {
 		virt_addr = (void *)__get_free_pages(flag, get_order(size));
 		*dma_addr = __pa(virt_addr);
 		return virt_addr;
@@ -2022,13 +2017,12 @@ static void free_coherent(struct device *dev, size_t size,
 			  void *virt_addr, dma_addr_t dma_addr)
 {
 	unsigned long flags;
-	struct amd_iommu *iommu;
 	struct protection_domain *domain;
 	u16 devid;
 
 	INC_STATS_COUNTER(cnt_free_coherent);
 
-	if (!get_device_resources(dev, &iommu, &domain, &devid))
+	if (!get_device_resources(dev, &domain, &devid))
 		goto free_mem;
 
 	if (!dma_ops_domain(domain))
-- 
1.6.5.3



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

* [PATCH 19/34] x86/amd-iommu: Let domain_for_device handle aliases
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (17 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 18/34] x86/amd-iommu: Remove iommu specific handling from dma_ops path Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 20/34] x86/amd-iommu: Simplify get_device_resources() Joerg Roedel
                   ` (15 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

If there is no domain associated to a device yet and the
device has an alias device which already has a domain, the
original device needs to have the same domain as the alias
device.
This patch changes domain_for_device to handle this
situation and directly assigns the alias device domain to
the device in this situation.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |  227 +++++++++++++++++++++++++-----------------
 1 files changed, 135 insertions(+), 92 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 2cd5800..75470ff 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -71,6 +71,19 @@ static u64 *fetch_pte(struct protection_domain *domain,
 		      unsigned long address, int map_size);
 static void update_domain(struct protection_domain *domain);
 
+/****************************************************************************
+ *
+ * Helper functions
+ *
+ ****************************************************************************/
+
+static inline u16 get_device_id(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	return calc_devid(pdev->bus->number, pdev->devfn);
+}
+
 #ifdef CONFIG_AMD_IOMMU_STATS
 
 /*
@@ -1174,26 +1187,13 @@ static bool dma_ops_domain(struct protection_domain *domain)
 	return domain->flags & PD_DMA_OPS_MASK;
 }
 
-/*
- * Find out the protection domain structure for a given PCI device. This
- * will give us the pointer to the page table root for example.
- */
-static struct protection_domain *domain_for_device(u16 devid)
-{
-	struct protection_domain *dom;
-	unsigned long flags;
-
-	read_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	dom = amd_iommu_pd_table[devid];
-	read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-
-	return dom;
-}
-
 static void set_dte_entry(u16 devid, struct protection_domain *domain)
 {
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 	u64 pte_root = virt_to_phys(domain->pt_root);
 
+	BUG_ON(amd_iommu_pd_table[devid] != NULL);
+
 	pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
 		    << DEV_ENTRY_MODE_SHIFT;
 	pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
@@ -1203,42 +1203,87 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain)
 	amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root);
 
 	amd_iommu_pd_table[devid] = domain;
+
+	/* Do reference counting */
+	domain->dev_iommu[iommu->index] += 1;
+	domain->dev_cnt                 += 1;
+
+	/* Flush the changes DTE entry */
+	iommu_queue_inv_dev_entry(iommu, devid);
+}
+
+static void clear_dte_entry(u16 devid)
+{
+	struct protection_domain *domain = amd_iommu_pd_table[devid];
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+	BUG_ON(domain == NULL);
+
+	/* remove domain from the lookup table */
+	amd_iommu_pd_table[devid] = NULL;
+
+	/* remove entry from the device table seen by the hardware */
+	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+	amd_iommu_dev_table[devid].data[1] = 0;
+	amd_iommu_dev_table[devid].data[2] = 0;
+
+	amd_iommu_apply_erratum_63(devid);
+
+	/* decrease reference counters */
+	domain->dev_iommu[iommu->index] -= 1;
+	domain->dev_cnt                 -= 1;
+
+	iommu_queue_inv_dev_entry(iommu, devid);
 }
 
 /*
  * If a device is not yet associated with a domain, this function does
  * assigns it visible for the hardware
  */
-static void __attach_device(struct amd_iommu *iommu,
-			    struct protection_domain *domain,
-			    u16 devid)
+static int __attach_device(struct device *dev,
+			   struct protection_domain *domain)
 {
+	u16 devid = get_device_id(dev);
+	u16 alias = amd_iommu_alias_table[devid];
+
 	/* lock domain */
 	spin_lock(&domain->lock);
 
-	/* update DTE entry */
-	set_dte_entry(devid, domain);
+	/* Some sanity checks */
+	if (amd_iommu_pd_table[alias] != NULL &&
+	    amd_iommu_pd_table[alias] != domain)
+		return -EBUSY;
 
-	/* Do reference counting */
-	domain->dev_iommu[iommu->index] += 1;
-	domain->dev_cnt                 += 1;
+	if (amd_iommu_pd_table[devid] != NULL &&
+	    amd_iommu_pd_table[devid] != domain)
+		return -EBUSY;
+
+	/* Do real assignment */
+	if (alias != devid &&
+	    amd_iommu_pd_table[alias] == NULL)
+		set_dte_entry(alias, domain);
+
+	if (amd_iommu_pd_table[devid] == NULL)
+		set_dte_entry(devid, domain);
 
 	/* ready */
 	spin_unlock(&domain->lock);
+
+	return 0;
 }
 
 /*
  * If a device is not yet associated with a domain, this function does
  * assigns it visible for the hardware
  */
-static void attach_device(struct amd_iommu *iommu,
-			  struct protection_domain *domain,
-			  u16 devid)
+static int attach_device(struct device *dev,
+			 struct protection_domain *domain)
 {
 	unsigned long flags;
+	int ret;
 
 	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	__attach_device(iommu, domain, devid);
+	ret = __attach_device(dev, domain);
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 
 	/*
@@ -1246,62 +1291,70 @@ static void attach_device(struct amd_iommu *iommu,
 	 * left the caches in the IOMMU dirty. So we have to flush
 	 * here to evict all dirty stuff.
 	 */
-	iommu_queue_inv_dev_entry(iommu, devid);
 	iommu_flush_tlb_pde(domain);
+
+	return ret;
 }
 
 /*
  * Removes a device from a protection domain (unlocked)
  */
-static void __detach_device(struct protection_domain *domain, u16 devid)
+static void __detach_device(struct device *dev)
 {
+	u16 devid = get_device_id(dev);
 	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 
 	BUG_ON(!iommu);
 
-	/* lock domain */
-	spin_lock(&domain->lock);
-
-	/* remove domain from the lookup table */
-	amd_iommu_pd_table[devid] = NULL;
-
-	/* remove entry from the device table seen by the hardware */
-	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
-	amd_iommu_dev_table[devid].data[1] = 0;
-	amd_iommu_dev_table[devid].data[2] = 0;
-
-	amd_iommu_apply_erratum_63(devid);
-
-	/* decrease reference counters */
-	domain->dev_iommu[iommu->index] -= 1;
-	domain->dev_cnt                 -= 1;
-
-	/* ready */
-	spin_unlock(&domain->lock);
+	clear_dte_entry(devid);
 
 	/*
 	 * If we run in passthrough mode the device must be assigned to the
 	 * passthrough domain if it is detached from any other domain
 	 */
-	if (iommu_pass_through) {
-		struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
-		__attach_device(iommu, pt_domain, devid);
-	}
+	if (iommu_pass_through)
+		__attach_device(dev, pt_domain);
 }
 
 /*
  * Removes a device from a protection domain (with devtable_lock held)
  */
-static void detach_device(struct protection_domain *domain, u16 devid)
+static void detach_device(struct device *dev)
 {
 	unsigned long flags;
 
 	/* lock device table */
 	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	__detach_device(domain, devid);
+	__detach_device(dev);
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
 
+/*
+ * Find out the protection domain structure for a given PCI device. This
+ * will give us the pointer to the page table root for example.
+ */
+static struct protection_domain *domain_for_device(struct device *dev)
+{
+	struct protection_domain *dom;
+	unsigned long flags;
+	u16 devid, alias;
+
+	devid = get_device_id(dev);
+	alias = amd_iommu_alias_table[devid];
+
+	read_lock_irqsave(&amd_iommu_devtable_lock, flags);
+	dom = amd_iommu_pd_table[devid];
+	if (dom == NULL &&
+	    amd_iommu_pd_table[alias] != NULL) {
+		__attach_device(dev, amd_iommu_pd_table[alias]);
+		dom = amd_iommu_pd_table[devid];
+	}
+
+	read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+
+	return dom;
+}
+
 static int device_change_notifier(struct notifier_block *nb,
 				  unsigned long action, void *data)
 {
@@ -1322,7 +1375,7 @@ static int device_change_notifier(struct notifier_block *nb,
 	if (iommu == NULL)
 		goto out;
 
-	domain = domain_for_device(devid);
+	domain = domain_for_device(dev);
 
 	if (domain && !dma_ops_domain(domain))
 		WARN_ONCE(1, "AMD IOMMU WARNING: device %s already bound "
@@ -1334,7 +1387,7 @@ static int device_change_notifier(struct notifier_block *nb,
 			goto out;
 		if (iommu_pass_through)
 			break;
-		detach_device(domain, devid);
+		detach_device(dev);
 		break;
 	case BUS_NOTIFY_ADD_DEVICE:
 		/* allocate a protection domain if a device is added */
@@ -1441,30 +1494,25 @@ static bool get_device_resources(struct device *dev,
 {
 	struct dma_ops_domain *dma_dom;
 	struct amd_iommu *iommu;
-	struct pci_dev *pcidev;
-	u16 _bdf;
 
 	if (!check_device(dev))
 		return false;
 
-	pcidev  = to_pci_dev(dev);
-	_bdf    = calc_devid(pcidev->bus->number, pcidev->devfn);
-	*bdf    = amd_iommu_alias_table[_bdf];
+	*bdf    = get_device_id(dev);
+	*domain = domain_for_device(dev);
 	iommu   = amd_iommu_rlookup_table[*bdf];
-	*domain = domain_for_device(*bdf);
 
-	if (*domain == NULL) {
-		dma_dom = find_protection_domain(*bdf);
-		if (!dma_dom)
-			dma_dom = iommu->default_dom;
-		*domain = &dma_dom->domain;
-		attach_device(iommu, *domain, *bdf);
-		DUMP_printk("Using protection domain %d for device %s\n",
-			    (*domain)->id, dev_name(dev));
-	}
+	if (*domain != NULL)
+		return true;
 
-	if (domain_for_device(_bdf) == NULL)
-		attach_device(iommu, *domain, _bdf);
+	/* Device not bount yet - bind it */
+	dma_dom = find_protection_domain(*bdf);
+	if (!dma_dom)
+		dma_dom = iommu->default_dom;
+	*domain = &dma_dom->domain;
+	attach_device(dev, *domain);
+	DUMP_printk("Using protection domain %d for device %s\n",
+		    (*domain)->id, dev_name(dev));
 
 	return true;
 }
@@ -2068,7 +2116,7 @@ static void prealloc_protection_domains(void)
 		if (devid > amd_iommu_last_bdf)
 			continue;
 		devid = amd_iommu_alias_table[devid];
-		if (domain_for_device(devid))
+		if (domain_for_device(&dev->dev))
 			continue;
 		iommu = amd_iommu_rlookup_table[devid];
 		if (!iommu)
@@ -2079,9 +2127,7 @@ static void prealloc_protection_domains(void)
 		init_unity_mappings_for_device(dma_dom, devid);
 		dma_dom->target_dev = devid;
 
-		attach_device(iommu, &dma_dom->domain, devid);
-		if (__devid != devid)
-			attach_device(iommu, &dma_dom->domain, __devid);
+		attach_device(&dev->dev, &dma_dom->domain);
 
 		list_add_tail(&dma_dom->list, &iommu_pd_list);
 	}
@@ -2174,7 +2220,7 @@ static void cleanup_domain(struct protection_domain *domain)
 
 	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid)
 		if (amd_iommu_pd_table[devid] == domain)
-			__detach_device(domain, devid);
+			clear_dte_entry(devid);
 
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
@@ -2262,7 +2308,6 @@ static void amd_iommu_domain_destroy(struct iommu_domain *dom)
 static void amd_iommu_detach_device(struct iommu_domain *dom,
 				    struct device *dev)
 {
-	struct protection_domain *domain = dom->priv;
 	struct amd_iommu *iommu;
 	struct pci_dev *pdev;
 	u16 devid;
@@ -2275,7 +2320,7 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
 	devid = calc_devid(pdev->bus->number, pdev->devfn);
 
 	if (devid > 0)
-		detach_device(domain, devid);
+		detach_device(dev);
 
 	iommu = amd_iommu_rlookup_table[devid];
 	if (!iommu)
@@ -2292,6 +2337,7 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 	struct protection_domain *old_domain;
 	struct amd_iommu *iommu;
 	struct pci_dev *pdev;
+	int ret;
 	u16 devid;
 
 	if (dev->bus != &pci_bus_type)
@@ -2309,15 +2355,15 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 	if (!iommu)
 		return -EINVAL;
 
-	old_domain = domain_for_device(devid);
+	old_domain = amd_iommu_pd_table[devid];
 	if (old_domain)
-		detach_device(old_domain, devid);
+		detach_device(dev);
 
-	attach_device(iommu, domain, devid);
+	ret = attach_device(dev, domain);
 
 	iommu_completion_wait(iommu);
 
-	return 0;
+	return ret;
 }
 
 static int amd_iommu_map_range(struct iommu_domain *dom,
@@ -2414,8 +2460,9 @@ static struct iommu_ops amd_iommu_ops = {
 
 int __init amd_iommu_init_passthrough(void)
 {
+	struct amd_iommu *iommu;
 	struct pci_dev *dev = NULL;
-	u16 devid, devid2;
+	u16 devid;
 
 	/* allocate passthroug domain */
 	pt_domain = protection_domain_alloc();
@@ -2425,20 +2472,16 @@ int __init amd_iommu_init_passthrough(void)
 	pt_domain->mode |= PAGE_MODE_NONE;
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		struct amd_iommu *iommu;
 
 		devid = calc_devid(dev->bus->number, dev->devfn);
 		if (devid > amd_iommu_last_bdf)
 			continue;
 
-		devid2 = amd_iommu_alias_table[devid];
-
-		iommu = amd_iommu_rlookup_table[devid2];
+		iommu = amd_iommu_rlookup_table[devid];
 		if (!iommu)
 			continue;
 
-		__attach_device(iommu, pt_domain, devid);
-		__attach_device(iommu, pt_domain, devid2);
+		attach_device(&dev->dev, pt_domain);
 	}
 
 	pr_info("AMD-Vi: Initialized for Passthrough Mode\n");
-- 
1.6.5.3



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

* [PATCH 20/34] x86/amd-iommu: Simplify get_device_resources()
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (18 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 19/34] x86/amd-iommu: Let domain_for_device handle aliases Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 21/34] x86/amd-iommu: Move find_protection_domain to helper functions Joerg Roedel
                   ` (14 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

With the previous changes the get_device_resources function
can be simplified even more. The only important information
for the callers is the protection domain.
This patch renames the function to get_domain() and let it
only return the protection domain for a device.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   86 ++++++++++++++++++-------------------------
 1 files changed, 36 insertions(+), 50 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 75470ff..e5bbe9a 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1463,6 +1463,7 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
 {
 	struct dma_ops_domain *entry, *ret = NULL;
 	unsigned long flags;
+	u16 alias = amd_iommu_alias_table[devid];
 
 	if (list_empty(&iommu_pd_list))
 		return NULL;
@@ -1470,7 +1471,8 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
 	spin_lock_irqsave(&iommu_pd_list_lock, flags);
 
 	list_for_each_entry(entry, &iommu_pd_list, list) {
-		if (entry->target_dev == devid) {
+		if (entry->target_dev == devid ||
+		    entry->target_dev == alias) {
 			ret = entry;
 			break;
 		}
@@ -1488,33 +1490,31 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
  * If the device is not yet associated with a domain this is also done
  * in this function.
  */
-static bool get_device_resources(struct device *dev,
-				 struct protection_domain **domain,
-				 u16 *bdf)
+static struct protection_domain *get_domain(struct device *dev)
 {
+	struct protection_domain *domain;
 	struct dma_ops_domain *dma_dom;
-	struct amd_iommu *iommu;
+	u16 devid = get_device_id(dev);
 
 	if (!check_device(dev))
-		return false;
+		return ERR_PTR(-EINVAL);
 
-	*bdf    = get_device_id(dev);
-	*domain = domain_for_device(dev);
-	iommu   = amd_iommu_rlookup_table[*bdf];
+	domain = domain_for_device(dev);
+	if (domain != NULL && !dma_ops_domain(domain))
+		return ERR_PTR(-EBUSY);
 
-	if (*domain != NULL)
-		return true;
+	if (domain != NULL)
+		return domain;
 
 	/* Device not bount yet - bind it */
-	dma_dom = find_protection_domain(*bdf);
+	dma_dom = find_protection_domain(devid);
 	if (!dma_dom)
-		dma_dom = iommu->default_dom;
-	*domain = &dma_dom->domain;
-	attach_device(dev, *domain);
+		dma_dom = amd_iommu_rlookup_table[devid]->default_dom;
+	attach_device(dev, &dma_dom->domain);
 	DUMP_printk("Using protection domain %d for device %s\n",
-		    (*domain)->id, dev_name(dev));
+		    dma_dom->domain.id, dev_name(dev));
 
-	return true;
+	return &dma_dom->domain;
 }
 
 static void update_device_table(struct protection_domain *domain)
@@ -1825,23 +1825,22 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
 {
 	unsigned long flags;
 	struct protection_domain *domain;
-	u16 devid;
 	dma_addr_t addr;
 	u64 dma_mask;
 	phys_addr_t paddr = page_to_phys(page) + offset;
 
 	INC_STATS_COUNTER(cnt_map_single);
 
-	if (!get_device_resources(dev, &domain, &devid))
-		/* device not handled by any AMD IOMMU */
+	domain = get_domain(dev);
+	if (PTR_ERR(domain) == -EINVAL)
 		return (dma_addr_t)paddr;
+	else if (IS_ERR(domain))
+		return DMA_ERROR_CODE;
 
 	dma_mask = *dev->dma_mask;
 
-	if (!dma_ops_domain(domain))
-		return DMA_ERROR_CODE;
-
 	spin_lock_irqsave(&domain->lock, flags);
+
 	addr = __map_single(dev, domain->priv, paddr, size, dir, false,
 			    dma_mask);
 	if (addr == DMA_ERROR_CODE)
@@ -1863,15 +1862,11 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 {
 	unsigned long flags;
 	struct protection_domain *domain;
-	u16 devid;
 
 	INC_STATS_COUNTER(cnt_unmap_single);
 
-	if (!get_device_resources(dev, &domain, &devid))
-		/* device not handled by any AMD IOMMU */
-		return;
-
-	if (!dma_ops_domain(domain))
+	domain = get_domain(dev);
+	if (IS_ERR(domain))
 		return;
 
 	spin_lock_irqsave(&domain->lock, flags);
@@ -1911,7 +1906,6 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 {
 	unsigned long flags;
 	struct protection_domain *domain;
-	u16 devid;
 	int i;
 	struct scatterlist *s;
 	phys_addr_t paddr;
@@ -1920,14 +1914,14 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 
 	INC_STATS_COUNTER(cnt_map_sg);
 
-	if (!get_device_resources(dev, &domain, &devid))
+	domain = get_domain(dev);
+	if (PTR_ERR(domain) == -EINVAL)
 		return map_sg_no_iommu(dev, sglist, nelems, dir);
+	else if (IS_ERR(domain))
+		return 0;
 
 	dma_mask = *dev->dma_mask;
 
-	if (!dma_ops_domain(domain))
-		return 0;
-
 	spin_lock_irqsave(&domain->lock, flags);
 
 	for_each_sg(sglist, s, nelems, i) {
@@ -1974,15 +1968,12 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 	unsigned long flags;
 	struct protection_domain *domain;
 	struct scatterlist *s;
-	u16 devid;
 	int i;
 
 	INC_STATS_COUNTER(cnt_unmap_sg);
 
-	if (!get_device_resources(dev, &domain, &devid))
-		return;
-
-	if (!dma_ops_domain(domain))
+	domain = get_domain(dev);
+	if (IS_ERR(domain))
 		return;
 
 	spin_lock_irqsave(&domain->lock, flags);
@@ -2007,17 +1998,18 @@ static void *alloc_coherent(struct device *dev, size_t size,
 	unsigned long flags;
 	void *virt_addr;
 	struct protection_domain *domain;
-	u16 devid;
 	phys_addr_t paddr;
 	u64 dma_mask = dev->coherent_dma_mask;
 
 	INC_STATS_COUNTER(cnt_alloc_coherent);
 
-	if (!get_device_resources(dev, &domain, &devid)) {
+	domain = get_domain(dev);
+	if (PTR_ERR(domain) == -EINVAL) {
 		virt_addr = (void *)__get_free_pages(flag, get_order(size));
 		*dma_addr = __pa(virt_addr);
 		return virt_addr;
-	}
+	} else if (IS_ERR(domain))
+		return NULL;
 
 	dma_mask  = dev->coherent_dma_mask;
 	flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
@@ -2029,9 +2021,6 @@ static void *alloc_coherent(struct device *dev, size_t size,
 
 	paddr = virt_to_phys(virt_addr);
 
-	if (!dma_ops_domain(domain))
-		goto out_free;
-
 	if (!dma_mask)
 		dma_mask = *dev->dma_mask;
 
@@ -2066,14 +2055,11 @@ static void free_coherent(struct device *dev, size_t size,
 {
 	unsigned long flags;
 	struct protection_domain *domain;
-	u16 devid;
 
 	INC_STATS_COUNTER(cnt_free_coherent);
 
-	if (!get_device_resources(dev, &domain, &devid))
-		goto free_mem;
-
-	if (!dma_ops_domain(domain))
+	domain = get_domain(dev);
+	if (IS_ERR(domain))
 		goto free_mem;
 
 	spin_lock_irqsave(&domain->lock, flags);
-- 
1.6.5.3



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

* [PATCH 21/34] x86/amd-iommu: Move find_protection_domain to helper functions
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (19 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 20/34] x86/amd-iommu: Simplify get_device_resources() Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 22/34] x86/amd-iommu: Use get_device_id and check_device where appropriate Joerg Roedel
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This is a helper function and when its placed in the helper
function section we can remove its forward declaration.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   57 +++++++++++++++++++++----------------------
 1 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index e5bbe9a..405f8da 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -59,7 +59,6 @@ struct iommu_cmd {
 
 static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 			     struct unity_map_entry *e);
-static struct dma_ops_domain *find_protection_domain(u16 devid);
 static u64 *alloc_pte(struct protection_domain *domain,
 		      unsigned long address, int end_lvl,
 		      u64 **pte_page, gfp_t gfp);
@@ -84,6 +83,34 @@ static inline u16 get_device_id(struct device *dev)
 	return calc_devid(pdev->bus->number, pdev->devfn);
 }
 
+/*
+ * In this function the list of preallocated protection domains is traversed to
+ * find the domain for a specific device
+ */
+static struct dma_ops_domain *find_protection_domain(u16 devid)
+{
+	struct dma_ops_domain *entry, *ret = NULL;
+	unsigned long flags;
+	u16 alias = amd_iommu_alias_table[devid];
+
+	if (list_empty(&iommu_pd_list))
+		return NULL;
+
+	spin_lock_irqsave(&iommu_pd_list_lock, flags);
+
+	list_for_each_entry(entry, &iommu_pd_list, list) {
+		if (entry->target_dev == devid ||
+		    entry->target_dev == alias) {
+			ret = entry;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+	return ret;
+}
+
 #ifdef CONFIG_AMD_IOMMU_STATS
 
 /*
@@ -1456,34 +1483,6 @@ static bool check_device(struct device *dev)
 }
 
 /*
- * In this function the list of preallocated protection domains is traversed to
- * find the domain for a specific device
- */
-static struct dma_ops_domain *find_protection_domain(u16 devid)
-{
-	struct dma_ops_domain *entry, *ret = NULL;
-	unsigned long flags;
-	u16 alias = amd_iommu_alias_table[devid];
-
-	if (list_empty(&iommu_pd_list))
-		return NULL;
-
-	spin_lock_irqsave(&iommu_pd_list_lock, flags);
-
-	list_for_each_entry(entry, &iommu_pd_list, list) {
-		if (entry->target_dev == devid ||
-		    entry->target_dev == alias) {
-			ret = entry;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
-
-	return ret;
-}
-
-/*
  * In the dma_ops path we only have the struct device. This function
  * finds the corresponding IOMMU, the protection domain and the
  * requestor id for a given device.
-- 
1.6.5.3



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

* [PATCH 22/34] x86/amd-iommu: Use get_device_id and check_device where appropriate
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (20 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 21/34] x86/amd-iommu: Move find_protection_domain to helper functions Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 23/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_alloc Joerg Roedel
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

The logic of these two functions is reimplemented (at least
in parts) in places in the code. This patch removes these
code duplications and uses the functions instead. As a side
effect it moves check_device() to the helper function code
section.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |  110 +++++++++++++++++++------------------------
 1 files changed, 49 insertions(+), 61 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 405f8da..d10195b 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -111,6 +111,33 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
 	return ret;
 }
 
+/*
+ * This function checks if the driver got a valid device from the caller to
+ * avoid dereferencing invalid pointers.
+ */
+static bool check_device(struct device *dev)
+{
+	u16 devid;
+
+	if (!dev || !dev->dma_mask)
+		return false;
+
+	/* No device or no PCI device */
+	if (!dev || dev->bus != &pci_bus_type)
+		return false;
+
+	devid = get_device_id(dev);
+
+	/* Out of our scope? */
+	if (devid > amd_iommu_last_bdf)
+		return false;
+
+	if (amd_iommu_rlookup_table[devid] == NULL)
+		return false;
+
+	return true;
+}
+
 #ifdef CONFIG_AMD_IOMMU_STATS
 
 /*
@@ -1386,22 +1413,17 @@ static int device_change_notifier(struct notifier_block *nb,
 				  unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct pci_dev *pdev = to_pci_dev(dev);
-	u16 devid = calc_devid(pdev->bus->number, pdev->devfn);
+	u16 devid;
 	struct protection_domain *domain;
 	struct dma_ops_domain *dma_domain;
 	struct amd_iommu *iommu;
 	unsigned long flags;
 
-	if (devid > amd_iommu_last_bdf)
-		goto out;
-
-	devid = amd_iommu_alias_table[devid];
-
-	iommu = amd_iommu_rlookup_table[devid];
-	if (iommu == NULL)
-		goto out;
+	if (!check_device(dev))
+		return 0;
 
+	devid  = get_device_id(dev);
+	iommu  = amd_iommu_rlookup_table[devid];
 	domain = domain_for_device(dev);
 
 	if (domain && !dma_ops_domain(domain))
@@ -1453,36 +1475,6 @@ static struct notifier_block device_nb = {
  *****************************************************************************/
 
 /*
- * This function checks if the driver got a valid device from the caller to
- * avoid dereferencing invalid pointers.
- */
-static bool check_device(struct device *dev)
-{
-	u16 bdf;
-	struct pci_dev *pcidev;
-
-	if (!dev || !dev->dma_mask)
-		return false;
-
-	/* No device or no PCI device */
-	if (!dev || dev->bus != &pci_bus_type)
-		return false;
-
-	pcidev = to_pci_dev(dev);
-
-	bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
-
-	/* Out of our scope? */
-	if (bdf > amd_iommu_last_bdf)
-		return false;
-
-	if (amd_iommu_rlookup_table[bdf] == NULL)
-		return false;
-
-	return true;
-}
-
-/*
  * In the dma_ops path we only have the struct device. This function
  * finds the corresponding IOMMU, the protection domain and the
  * requestor id for a given device.
@@ -2094,15 +2086,20 @@ static void prealloc_protection_domains(void)
 	struct pci_dev *dev = NULL;
 	struct dma_ops_domain *dma_dom;
 	struct amd_iommu *iommu;
-	u16 devid, __devid;
+	u16 devid;
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		__devid = devid = calc_devid(dev->bus->number, dev->devfn);
-		if (devid > amd_iommu_last_bdf)
+
+		/* Do we handle this device? */
+		if (!check_device(&dev->dev))
 			continue;
-		devid = amd_iommu_alias_table[devid];
+
+		/* Is there already any domain for it? */
 		if (domain_for_device(&dev->dev))
 			continue;
+
+		devid = get_device_id(&dev->dev);
+
 		iommu = amd_iommu_rlookup_table[devid];
 		if (!iommu)
 			continue;
@@ -2294,17 +2291,14 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
 				    struct device *dev)
 {
 	struct amd_iommu *iommu;
-	struct pci_dev *pdev;
 	u16 devid;
 
-	if (dev->bus != &pci_bus_type)
+	if (!check_device(dev))
 		return;
 
-	pdev = to_pci_dev(dev);
-
-	devid = calc_devid(pdev->bus->number, pdev->devfn);
+	devid = get_device_id(dev);
 
-	if (devid > 0)
+	if (amd_iommu_pd_table[devid] != NULL)
 		detach_device(dev);
 
 	iommu = amd_iommu_rlookup_table[devid];
@@ -2321,20 +2315,13 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 	struct protection_domain *domain = dom->priv;
 	struct protection_domain *old_domain;
 	struct amd_iommu *iommu;
-	struct pci_dev *pdev;
 	int ret;
 	u16 devid;
 
-	if (dev->bus != &pci_bus_type)
+	if (!check_device(dev))
 		return -EINVAL;
 
-	pdev = to_pci_dev(dev);
-
-	devid = calc_devid(pdev->bus->number, pdev->devfn);
-
-	if (devid >= amd_iommu_last_bdf ||
-			devid != amd_iommu_alias_table[devid])
-		return -EINVAL;
+	devid = get_device_id(dev);
 
 	iommu = amd_iommu_rlookup_table[devid];
 	if (!iommu)
@@ -2458,10 +2445,11 @@ int __init amd_iommu_init_passthrough(void)
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 
-		devid = calc_devid(dev->bus->number, dev->devfn);
-		if (devid > amd_iommu_last_bdf)
+		if (!check_device(&dev->dev))
 			continue;
 
+		devid = get_device_id(&dev->dev);
+
 		iommu = amd_iommu_rlookup_table[devid];
 		if (!iommu)
 			continue;
-- 
1.6.5.3



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

* [PATCH 23/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_alloc
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (21 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 22/34] x86/amd-iommu: Use get_device_id and check_device where appropriate Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 24/34] x86/amd-iommu: Move some pte allocation functions in the right section Joerg Roedel
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This function doesn't use the parameter anymore so it can be
removed.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index d10195b..17e83ec 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1188,7 +1188,7 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
  * It also intializes the page table and the address allocator data
  * structures required for the dma_ops interface
  */
-static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
+static struct dma_ops_domain *dma_ops_domain_alloc(void)
 {
 	struct dma_ops_domain *dma_dom;
 
@@ -1443,7 +1443,7 @@ static int device_change_notifier(struct notifier_block *nb,
 		dma_domain = find_protection_domain(devid);
 		if (dma_domain)
 			goto out;
-		dma_domain = dma_ops_domain_alloc(iommu);
+		dma_domain = dma_ops_domain_alloc();
 		if (!dma_domain)
 			goto out;
 		dma_domain->target_dev = devid;
@@ -2085,7 +2085,6 @@ static void prealloc_protection_domains(void)
 {
 	struct pci_dev *dev = NULL;
 	struct dma_ops_domain *dma_dom;
-	struct amd_iommu *iommu;
 	u16 devid;
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
@@ -2100,10 +2099,7 @@ static void prealloc_protection_domains(void)
 
 		devid = get_device_id(&dev->dev);
 
-		iommu = amd_iommu_rlookup_table[devid];
-		if (!iommu)
-			continue;
-		dma_dom = dma_ops_domain_alloc(iommu);
+		dma_dom = dma_ops_domain_alloc();
 		if (!dma_dom)
 			continue;
 		init_unity_mappings_for_device(dma_dom, devid);
@@ -2139,7 +2135,7 @@ int __init amd_iommu_init_dma_ops(void)
 	 * protection domain will be assigned to the default one.
 	 */
 	for_each_iommu(iommu) {
-		iommu->default_dom = dma_ops_domain_alloc(iommu);
+		iommu->default_dom = dma_ops_domain_alloc();
 		if (iommu->default_dom == NULL)
 			return -ENOMEM;
 		iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
-- 
1.6.5.3



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

* [PATCH 24/34] x86/amd-iommu: Move some pte allocation functions in the right section
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (22 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 23/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_alloc Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 25/34] x86/amd-iommu: Rearrange dma_ops related functions Joerg Roedel
                   ` (10 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch moves alloc_pte() and fetch_pte() into the page
table handling code section so that the forward declarations
for them could be removed.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |  193 +++++++++++++++++++++----------------------
 1 files changed, 94 insertions(+), 99 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 17e83ec..90b3650 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -59,15 +59,10 @@ struct iommu_cmd {
 
 static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 			     struct unity_map_entry *e);
-static u64 *alloc_pte(struct protection_domain *domain,
-		      unsigned long address, int end_lvl,
-		      u64 **pte_page, gfp_t gfp);
 static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
 				      unsigned long start_page,
 				      unsigned int pages);
 static void reset_iommu_command_buffer(struct amd_iommu *iommu);
-static u64 *fetch_pte(struct protection_domain *domain,
-		      unsigned long address, int map_size);
 static void update_domain(struct protection_domain *domain);
 
 /****************************************************************************
@@ -665,6 +660,100 @@ void amd_iommu_flush_all_devices(void)
  ****************************************************************************/
 
 /*
+ * This function is used to add another level to an IO page table. Adding
+ * another level increases the size of the address space by 9 bits to a size up
+ * to 64 bits.
+ */
+static bool increase_address_space(struct protection_domain *domain,
+				   gfp_t gfp)
+{
+	u64 *pte;
+
+	if (domain->mode == PAGE_MODE_6_LEVEL)
+		/* address space already 64 bit large */
+		return false;
+
+	pte = (void *)get_zeroed_page(gfp);
+	if (!pte)
+		return false;
+
+	*pte             = PM_LEVEL_PDE(domain->mode,
+					virt_to_phys(domain->pt_root));
+	domain->pt_root  = pte;
+	domain->mode    += 1;
+	domain->updated  = true;
+
+	return true;
+}
+
+static u64 *alloc_pte(struct protection_domain *domain,
+		      unsigned long address,
+		      int end_lvl,
+		      u64 **pte_page,
+		      gfp_t gfp)
+{
+	u64 *pte, *page;
+	int level;
+
+	while (address > PM_LEVEL_SIZE(domain->mode))
+		increase_address_space(domain, gfp);
+
+	level =  domain->mode - 1;
+	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+
+	while (level > end_lvl) {
+		if (!IOMMU_PTE_PRESENT(*pte)) {
+			page = (u64 *)get_zeroed_page(gfp);
+			if (!page)
+				return NULL;
+			*pte = PM_LEVEL_PDE(level, virt_to_phys(page));
+		}
+
+		level -= 1;
+
+		pte = IOMMU_PTE_PAGE(*pte);
+
+		if (pte_page && level == end_lvl)
+			*pte_page = pte;
+
+		pte = &pte[PM_LEVEL_INDEX(level, address)];
+	}
+
+	return pte;
+}
+
+/*
+ * This function checks if there is a PTE for a given dma address. If
+ * there is one, it returns the pointer to it.
+ */
+static u64 *fetch_pte(struct protection_domain *domain,
+		      unsigned long address, int map_size)
+{
+	int level;
+	u64 *pte;
+
+	level =  domain->mode - 1;
+	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+
+	while (level > map_size) {
+		if (!IOMMU_PTE_PRESENT(*pte))
+			return NULL;
+
+		level -= 1;
+
+		pte = IOMMU_PTE_PAGE(*pte);
+		pte = &pte[PM_LEVEL_INDEX(level, address)];
+
+		if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) {
+			pte = NULL;
+			break;
+		}
+	}
+
+	return pte;
+}
+
+/*
  * Generic mapping functions. It maps a physical address into a DMA
  * address space. It allocates the page table pages if necessary.
  * In the future it can be extended to a generic mapping function
@@ -820,37 +909,6 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
  */
 
 /*
- * This function checks if there is a PTE for a given dma address. If
- * there is one, it returns the pointer to it.
- */
-static u64 *fetch_pte(struct protection_domain *domain,
-		      unsigned long address, int map_size)
-{
-	int level;
-	u64 *pte;
-
-	level =  domain->mode - 1;
-	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
-
-	while (level > map_size) {
-		if (!IOMMU_PTE_PRESENT(*pte))
-			return NULL;
-
-		level -= 1;
-
-		pte = IOMMU_PTE_PAGE(*pte);
-		pte = &pte[PM_LEVEL_INDEX(level, address)];
-
-		if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) {
-			pte = NULL;
-			break;
-		}
-	}
-
-	return pte;
-}
-
-/*
  * This function is used to add a new aperture range to an existing
  * aperture in case of dma_ops domain allocation or address allocation
  * failure.
@@ -1535,69 +1593,6 @@ static void update_domain(struct protection_domain *domain)
 }
 
 /*
- * This function is used to add another level to an IO page table. Adding
- * another level increases the size of the address space by 9 bits to a size up
- * to 64 bits.
- */
-static bool increase_address_space(struct protection_domain *domain,
-				   gfp_t gfp)
-{
-	u64 *pte;
-
-	if (domain->mode == PAGE_MODE_6_LEVEL)
-		/* address space already 64 bit large */
-		return false;
-
-	pte = (void *)get_zeroed_page(gfp);
-	if (!pte)
-		return false;
-
-	*pte             = PM_LEVEL_PDE(domain->mode,
-					virt_to_phys(domain->pt_root));
-	domain->pt_root  = pte;
-	domain->mode    += 1;
-	domain->updated  = true;
-
-	return true;
-}
-
-static u64 *alloc_pte(struct protection_domain *domain,
-		      unsigned long address,
-		      int end_lvl,
-		      u64 **pte_page,
-		      gfp_t gfp)
-{
-	u64 *pte, *page;
-	int level;
-
-	while (address > PM_LEVEL_SIZE(domain->mode))
-		increase_address_space(domain, gfp);
-
-	level =  domain->mode - 1;
-	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
-
-	while (level > end_lvl) {
-		if (!IOMMU_PTE_PRESENT(*pte)) {
-			page = (u64 *)get_zeroed_page(gfp);
-			if (!page)
-				return NULL;
-			*pte = PM_LEVEL_PDE(level, virt_to_phys(page));
-		}
-
-		level -= 1;
-
-		pte = IOMMU_PTE_PAGE(*pte);
-
-		if (pte_page && level == end_lvl)
-			*pte_page = pte;
-
-		pte = &pte[PM_LEVEL_INDEX(level, address)];
-	}
-
-	return pte;
-}
-
-/*
  * This function fetches the PTE for a given address in the aperture
  */
 static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
-- 
1.6.5.3



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

* [PATCH 25/34] x86/amd-iommu: Rearrange dma_ops related functions
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (23 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 24/34] x86/amd-iommu: Move some pte allocation functions in the right section Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 26/34] x86/amd-iommu: Remove support for domain sharing Joerg Roedel
                   ` (9 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch rearranges two dma_ops related functions so that
their forward declarations are not longer necessary.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   89 ++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 47 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 90b3650..14b60c0 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -57,11 +57,6 @@ struct iommu_cmd {
 	u32 data[4];
 };
 
-static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
-			     struct unity_map_entry *e);
-static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
-				      unsigned long start_page,
-				      unsigned int pages);
 static void reset_iommu_command_buffer(struct amd_iommu *iommu);
 static void update_domain(struct protection_domain *domain);
 
@@ -823,28 +818,6 @@ static int iommu_for_unity_map(struct amd_iommu *iommu,
 }
 
 /*
- * Init the unity mappings for a specific IOMMU in the system
- *
- * Basically iterates over all unity mapping entries and applies them to
- * the default domain DMA of that IOMMU if necessary.
- */
-static int iommu_init_unity_mappings(struct amd_iommu *iommu)
-{
-	struct unity_map_entry *entry;
-	int ret;
-
-	list_for_each_entry(entry, &amd_iommu_unity_map, list) {
-		if (!iommu_for_unity_map(iommu, entry))
-			continue;
-		ret = dma_ops_unity_map(iommu->default_dom, entry);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-/*
  * This function actually applies the mapping to the page table of the
  * dma_ops domain.
  */
@@ -873,6 +846,28 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 }
 
 /*
+ * Init the unity mappings for a specific IOMMU in the system
+ *
+ * Basically iterates over all unity mapping entries and applies them to
+ * the default domain DMA of that IOMMU if necessary.
+ */
+static int iommu_init_unity_mappings(struct amd_iommu *iommu)
+{
+	struct unity_map_entry *entry;
+	int ret;
+
+	list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+		if (!iommu_for_unity_map(iommu, entry))
+			continue;
+		ret = dma_ops_unity_map(iommu->default_dom, entry);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/*
  * Inits the unity mappings required for a specific device
  */
 static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
@@ -909,6 +904,26 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
  */
 
 /*
+ * Used to reserve address ranges in the aperture (e.g. for exclusion
+ * ranges.
+ */
+static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
+				      unsigned long start_page,
+				      unsigned int pages)
+{
+	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
+
+	if (start_page + pages > last_page)
+		pages = last_page - start_page;
+
+	for (i = start_page; i < start_page + pages; ++i) {
+		int index = i / APERTURE_RANGE_PAGES;
+		int page  = i % APERTURE_RANGE_PAGES;
+		__set_bit(page, dom->aperture[index]->bitmap);
+	}
+}
+
+/*
  * This function is used to add a new aperture range to an existing
  * aperture in case of dma_ops domain allocation or address allocation
  * failure.
@@ -1166,26 +1181,6 @@ static void domain_id_free(int id)
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
 
-/*
- * Used to reserve address ranges in the aperture (e.g. for exclusion
- * ranges.
- */
-static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
-				      unsigned long start_page,
-				      unsigned int pages)
-{
-	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
-
-	if (start_page + pages > last_page)
-		pages = last_page - start_page;
-
-	for (i = start_page; i < start_page + pages; ++i) {
-		int index = i / APERTURE_RANGE_PAGES;
-		int page  = i % APERTURE_RANGE_PAGES;
-		__set_bit(page, dom->aperture[index]->bitmap);
-	}
-}
-
 static void free_pagetable(struct protection_domain *domain)
 {
 	int i, j;
-- 
1.6.5.3



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

* [PATCH 26/34] x86/amd-iommu: Remove support for domain sharing
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (24 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 25/34] x86/amd-iommu: Rearrange dma_ops related functions Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 27/34] x86/amd-iommu: Use dev->arch->iommu to store iommu related information Joerg Roedel
                   ` (8 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch makes device isolation mandatory and removes
support for the amd_iommu=share option. This simplifies the
code in several places.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    3 ---
 arch/x86/kernel/amd_iommu.c            |   10 ++--------
 arch/x86/kernel/amd_iommu_init.c       |   17 -----------------
 3 files changed, 2 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 4899f78..02b6a0f 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -451,9 +451,6 @@ extern struct protection_domain **amd_iommu_pd_table;
 /* allocation bitmap for domain ids */
 extern unsigned long *amd_iommu_pd_alloc_bitmap;
 
-/* will be 1 if device isolation is enabled */
-extern bool amd_iommu_isolate;
-
 /*
  * If true, the addresses will be flushed on unmap time, not when
  * they are reused
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 14b60c0..ed58a16 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -148,7 +148,6 @@ DECLARE_STATS_COUNTER(alloced_io_mem);
 DECLARE_STATS_COUNTER(total_map_requests);
 
 static struct dentry *stats_dir;
-static struct dentry *de_isolate;
 static struct dentry *de_fflush;
 
 static void amd_iommu_stats_add(struct __iommu_counter *cnt)
@@ -166,9 +165,6 @@ static void amd_iommu_stats_init(void)
 	if (stats_dir == NULL)
 		return;
 
-	de_isolate = debugfs_create_bool("isolation", 0444, stats_dir,
-					 (u32 *)&amd_iommu_isolate);
-
 	de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
 					 (u32 *)&amd_iommu_unmap_flush);
 
@@ -2135,11 +2131,9 @@ int __init amd_iommu_init_dma_ops(void)
 	}
 
 	/*
-	 * If device isolation is enabled, pre-allocate the protection
-	 * domains for each device.
+	 * Pre-allocate the protection domains for each device.
 	 */
-	if (amd_iommu_isolate)
-		prealloc_protection_domains();
+	prealloc_protection_domains();
 
 	iommu_detected = 1;
 	swiotlb = 0;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index fbe4c3c..fe1686f 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -125,13 +125,6 @@ u16 amd_iommu_last_bdf;			/* largest PCI device id we have
 					   to handle */
 LIST_HEAD(amd_iommu_unity_map);		/* a list of required unity mappings
 					   we find in ACPI */
-#ifdef CONFIG_IOMMU_STRESS
-bool amd_iommu_isolate = false;
-#else
-bool amd_iommu_isolate = true;		/* if true, device isolation is
-					   enabled */
-#endif
-
 bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
@@ -1308,12 +1301,6 @@ static int __init amd_iommu_init(void)
 	if (iommu_pass_through)
 		goto out;
 
-	printk(KERN_INFO "AMD-Vi: device isolation ");
-	if (amd_iommu_isolate)
-		printk("enabled\n");
-	else
-		printk("disabled\n");
-
 	if (amd_iommu_unmap_flush)
 		printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n");
 	else
@@ -1387,10 +1374,6 @@ static int __init parse_amd_iommu_dump(char *str)
 static int __init parse_amd_iommu_options(char *str)
 {
 	for (; *str; ++str) {
-		if (strncmp(str, "isolate", 7) == 0)
-			amd_iommu_isolate = true;
-		if (strncmp(str, "share", 5) == 0)
-			amd_iommu_isolate = false;
 		if (strncmp(str, "fullflush", 9) == 0)
 			amd_iommu_unmap_flush = true;
 	}
-- 
1.6.5.3



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

* [PATCH 27/34] x86/amd-iommu: Use dev->arch->iommu to store iommu related information
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (25 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 26/34] x86/amd-iommu: Remove support for domain sharing Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 28/34] x86/amd-iommu: Add device bind reference counting Joerg Roedel
                   ` (7 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch changes IOMMU code to use dev->archdata->iommu to
store information about the alias device and the domain the
device is attached to.
This allows the driver to get rid of the amd_iommu_pd_table
in the future.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    8 +++
 arch/x86/include/asm/device.h          |    2 +-
 arch/x86/kernel/amd_iommu.c            |  109 +++++++++++++++++++++++++-------
 3 files changed, 95 insertions(+), 24 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 02b6a0f..9eaa27b 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -248,6 +248,14 @@ struct protection_domain {
 };
 
 /*
+ * This struct contains device specific data for the IOMMU
+ */
+struct iommu_dev_data {
+	struct device *alias;		  /* The Alias Device */
+	struct protection_domain *domain; /* Domain the device is bound to */
+};
+
+/*
  * For dynamic growth the aperture size is split into ranges of 128MB of
  * DMA address space each. This struct represents one such range.
  */
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
index cee34e9..029f230 100644
--- a/arch/x86/include/asm/device.h
+++ b/arch/x86/include/asm/device.h
@@ -8,7 +8,7 @@ struct dev_archdata {
 #ifdef CONFIG_X86_64
 struct dma_map_ops *dma_ops;
 #endif
-#ifdef CONFIG_DMAR
+#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
 	void *iommu; /* hook for IOMMU specific extension */
 #endif
 };
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index ed58a16..3214e88 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -73,6 +73,11 @@ static inline u16 get_device_id(struct device *dev)
 	return calc_devid(pdev->bus->number, pdev->devfn);
 }
 
+static struct iommu_dev_data *get_dev_data(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
+
 /*
  * In this function the list of preallocated protection domains is traversed to
  * find the domain for a specific device
@@ -128,6 +133,35 @@ static bool check_device(struct device *dev)
 	return true;
 }
 
+static int iommu_init_device(struct device *dev)
+{
+	struct iommu_dev_data *dev_data;
+	struct pci_dev *pdev;
+	u16 devid, alias;
+
+	if (dev->archdata.iommu)
+		return 0;
+
+	dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return -ENOMEM;
+
+	devid = get_device_id(dev);
+	alias = amd_iommu_alias_table[devid];
+	pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
+	if (pdev)
+		dev_data->alias = &pdev->dev;
+
+	dev->archdata.iommu = dev_data;
+
+
+	return 0;
+}
+
+static void iommu_uninit_device(struct device *dev)
+{
+	kfree(dev->archdata.iommu);
+}
 #ifdef CONFIG_AMD_IOMMU_STATS
 
 /*
@@ -1346,28 +1380,39 @@ static void clear_dte_entry(u16 devid)
 static int __attach_device(struct device *dev,
 			   struct protection_domain *domain)
 {
-	u16 devid = get_device_id(dev);
-	u16 alias = amd_iommu_alias_table[devid];
+	struct iommu_dev_data *dev_data, *alias_data;
+	u16 devid, alias;
+
+	devid      = get_device_id(dev);
+	alias      = amd_iommu_alias_table[devid];
+	dev_data   = get_dev_data(dev);
+	alias_data = get_dev_data(dev_data->alias);
+	if (!alias_data)
+		return -EINVAL;
 
 	/* lock domain */
 	spin_lock(&domain->lock);
 
 	/* Some sanity checks */
-	if (amd_iommu_pd_table[alias] != NULL &&
-	    amd_iommu_pd_table[alias] != domain)
+	if (alias_data->domain != NULL &&
+	    alias_data->domain != domain)
 		return -EBUSY;
 
-	if (amd_iommu_pd_table[devid] != NULL &&
-	    amd_iommu_pd_table[devid] != domain)
+	if (dev_data->domain != NULL &&
+	    dev_data->domain != domain)
 		return -EBUSY;
 
 	/* Do real assignment */
 	if (alias != devid &&
-	    amd_iommu_pd_table[alias] == NULL)
+	    alias_data->domain == NULL) {
+		alias_data->domain = domain;
 		set_dte_entry(alias, domain);
+	}
 
-	if (amd_iommu_pd_table[devid] == NULL)
+	if (dev_data->domain == NULL) {
+		dev_data->domain = domain;
 		set_dte_entry(devid, domain);
+	}
 
 	/* ready */
 	spin_unlock(&domain->lock);
@@ -1406,10 +1451,12 @@ static void __detach_device(struct device *dev)
 {
 	u16 devid = get_device_id(dev);
 	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+	struct iommu_dev_data *dev_data = get_dev_data(dev);
 
 	BUG_ON(!iommu);
 
 	clear_dte_entry(devid);
+	dev_data->domain = NULL;
 
 	/*
 	 * If we run in passthrough mode the device must be assigned to the
@@ -1439,18 +1486,23 @@ static void detach_device(struct device *dev)
 static struct protection_domain *domain_for_device(struct device *dev)
 {
 	struct protection_domain *dom;
+	struct iommu_dev_data *dev_data, *alias_data;
 	unsigned long flags;
 	u16 devid, alias;
 
-	devid = get_device_id(dev);
-	alias = amd_iommu_alias_table[devid];
+	devid      = get_device_id(dev);
+	alias      = amd_iommu_alias_table[devid];
+	dev_data   = get_dev_data(dev);
+	alias_data = get_dev_data(dev_data->alias);
+	if (!alias_data)
+		return NULL;
 
 	read_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	dom = amd_iommu_pd_table[devid];
+	dom = dev_data->domain;
 	if (dom == NULL &&
-	    amd_iommu_pd_table[alias] != NULL) {
-		__attach_device(dev, amd_iommu_pd_table[alias]);
-		dom = amd_iommu_pd_table[devid];
+	    alias_data->domain != NULL) {
+		__attach_device(dev, alias_data->domain);
+		dom = alias_data->domain;
 	}
 
 	read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
@@ -1473,14 +1525,12 @@ static int device_change_notifier(struct notifier_block *nb,
 
 	devid  = get_device_id(dev);
 	iommu  = amd_iommu_rlookup_table[devid];
-	domain = domain_for_device(dev);
-
-	if (domain && !dma_ops_domain(domain))
-		WARN_ONCE(1, "AMD IOMMU WARNING: device %s already bound "
-			  "to a non-dma-ops domain\n", dev_name(dev));
 
 	switch (action) {
 	case BUS_NOTIFY_UNBOUND_DRIVER:
+
+		domain = domain_for_device(dev);
+
 		if (!domain)
 			goto out;
 		if (iommu_pass_through)
@@ -1488,6 +1538,11 @@ static int device_change_notifier(struct notifier_block *nb,
 		detach_device(dev);
 		break;
 	case BUS_NOTIFY_ADD_DEVICE:
+
+		iommu_init_device(dev);
+
+		domain = domain_for_device(dev);
+
 		/* allocate a protection domain if a device is added */
 		dma_domain = find_protection_domain(devid);
 		if (dma_domain)
@@ -1502,6 +1557,10 @@ static int device_change_notifier(struct notifier_block *nb,
 		spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
 
 		break;
+	case BUS_NOTIFY_DEL_DEVICE:
+
+		iommu_uninit_device(dev);
+
 	default:
 		goto out;
 	}
@@ -2079,6 +2138,8 @@ static void prealloc_protection_domains(void)
 		if (!check_device(&dev->dev))
 			continue;
 
+		iommu_init_device(&dev->dev);
+
 		/* Is there already any domain for it? */
 		if (domain_for_device(&dev->dev))
 			continue;
@@ -2270,6 +2331,7 @@ static void amd_iommu_domain_destroy(struct iommu_domain *dom)
 static void amd_iommu_detach_device(struct iommu_domain *dom,
 				    struct device *dev)
 {
+	struct iommu_dev_data *dev_data = dev->archdata.iommu;
 	struct amd_iommu *iommu;
 	u16 devid;
 
@@ -2278,7 +2340,7 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
 
 	devid = get_device_id(dev);
 
-	if (amd_iommu_pd_table[devid] != NULL)
+	if (dev_data->domain != NULL)
 		detach_device(dev);
 
 	iommu = amd_iommu_rlookup_table[devid];
@@ -2293,7 +2355,7 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 				   struct device *dev)
 {
 	struct protection_domain *domain = dom->priv;
-	struct protection_domain *old_domain;
+	struct iommu_dev_data *dev_data;
 	struct amd_iommu *iommu;
 	int ret;
 	u16 devid;
@@ -2301,14 +2363,15 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 	if (!check_device(dev))
 		return -EINVAL;
 
+	dev_data = dev->archdata.iommu;
+
 	devid = get_device_id(dev);
 
 	iommu = amd_iommu_rlookup_table[devid];
 	if (!iommu)
 		return -EINVAL;
 
-	old_domain = amd_iommu_pd_table[devid];
-	if (old_domain)
+	if (dev_data->domain)
 		detach_device(dev);
 
 	ret = attach_device(dev, domain);
-- 
1.6.5.3



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

* [PATCH 28/34] x86/amd-iommu: Add device bind reference counting
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (26 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 27/34] x86/amd-iommu: Use dev->arch->iommu to store iommu related information Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 29/34] x86/amd-iommu: Keep devices per domain in a list Joerg Roedel
                   ` (6 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch adds a reference count to each device to count
how often the device was bound to that domain. This is
important for single devices that act as an alias for a
number of others. These devices must stay bound to their
domains until all devices that alias to it are unbound from
the same domain.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    1 +
 arch/x86/kernel/amd_iommu.c            |   37 +++++++++++++++++++++++++-------
 2 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 9eaa27b..434e90e 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -253,6 +253,7 @@ struct protection_domain {
 struct iommu_dev_data {
 	struct device *alias;		  /* The Alias Device */
 	struct protection_domain *domain; /* Domain the device is bound to */
+	atomic_t bind;			  /* Domain attach reverent count */
 };
 
 /*
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 3214e88..f5db7d5 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -152,6 +152,8 @@ static int iommu_init_device(struct device *dev)
 	if (pdev)
 		dev_data->alias = &pdev->dev;
 
+	atomic_set(&dev_data->bind, 0);
+
 	dev->archdata.iommu = dev_data;
 
 
@@ -1403,10 +1405,13 @@ static int __attach_device(struct device *dev,
 		return -EBUSY;
 
 	/* Do real assignment */
-	if (alias != devid &&
-	    alias_data->domain == NULL) {
-		alias_data->domain = domain;
-		set_dte_entry(alias, domain);
+	if (alias != devid) {
+		if (alias_data->domain == NULL) {
+			alias_data->domain = domain;
+			set_dte_entry(alias, domain);
+		}
+
+		atomic_inc(&alias_data->bind);
 	}
 
 	if (dev_data->domain == NULL) {
@@ -1414,6 +1419,8 @@ static int __attach_device(struct device *dev,
 		set_dte_entry(devid, domain);
 	}
 
+	atomic_inc(&dev_data->bind);
+
 	/* ready */
 	spin_unlock(&domain->lock);
 
@@ -1449,20 +1456,34 @@ static int attach_device(struct device *dev,
  */
 static void __detach_device(struct device *dev)
 {
-	u16 devid = get_device_id(dev);
+	u16 devid = get_device_id(dev), alias;
 	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 	struct iommu_dev_data *dev_data = get_dev_data(dev);
+	struct iommu_dev_data *alias_data;
 
 	BUG_ON(!iommu);
 
-	clear_dte_entry(devid);
-	dev_data->domain = NULL;
+	devid = get_device_id(dev);
+	alias = get_device_id(dev_data->alias);
+
+	if (devid != alias) {
+		alias_data = get_dev_data(dev_data->alias);
+		if (atomic_dec_and_test(&alias_data->bind)) {
+			clear_dte_entry(alias);
+			alias_data->domain = NULL;
+		}
+	}
+
+	if (atomic_dec_and_test(&dev_data->bind)) {
+		clear_dte_entry(devid);
+		dev_data->domain = NULL;
+	}
 
 	/*
 	 * If we run in passthrough mode the device must be assigned to the
 	 * passthrough domain if it is detached from any other domain
 	 */
-	if (iommu_pass_through)
+	if (iommu_pass_through && dev_data->domain == NULL)
 		__attach_device(dev, pt_domain);
 }
 
-- 
1.6.5.3



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

* [PATCH 29/34] x86/amd-iommu: Keep devices per domain in a list
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (27 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 28/34] x86/amd-iommu: Add device bind reference counting Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 30/34] x86/amd-iommu: Cleanup attach/detach_device code Joerg Roedel
                   ` (5 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch introduces a list to each protection domain which
keeps all devices associated with the domain. This can be
used later to optimize certain functions and to completly
remove the amd_iommu_pd_table.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    2 ++
 arch/x86/kernel/amd_iommu.c            |   11 +++++++++++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 434e90e..93953d1 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -235,6 +235,7 @@ extern bool amd_iommu_np_cache;
  */
 struct protection_domain {
 	struct list_head list;  /* for list of all protection domains */
+	struct list_head dev_list; /* List of all devices in this domain */
 	spinlock_t lock;	/* mostly used to lock the page table*/
 	u16 id;			/* the domain id written to the device table */
 	int mode;		/* paging mode (0-6 levels) */
@@ -251,6 +252,7 @@ struct protection_domain {
  * This struct contains device specific data for the IOMMU
  */
 struct iommu_dev_data {
+	struct list_head list;		  /* For domain->dev_list */
 	struct device *alias;		  /* The Alias Device */
 	struct protection_domain *domain; /* Domain the device is bound to */
 	atomic_t bind;			  /* Domain attach reverent count */
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index f5db7d5..530d608 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1286,6 +1286,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void)
 	dma_dom->domain.id = domain_id_alloc();
 	if (dma_dom->domain.id == 0)
 		goto free_dma_dom;
+	INIT_LIST_HEAD(&dma_dom->domain.dev_list);
 	dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
 	dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
 	dma_dom->domain.flags = PD_DMA_OPS_MASK;
@@ -1408,6 +1409,7 @@ static int __attach_device(struct device *dev,
 	if (alias != devid) {
 		if (alias_data->domain == NULL) {
 			alias_data->domain = domain;
+			list_add(&alias_data->list, &domain->dev_list);
 			set_dte_entry(alias, domain);
 		}
 
@@ -1416,6 +1418,7 @@ static int __attach_device(struct device *dev,
 
 	if (dev_data->domain == NULL) {
 		dev_data->domain = domain;
+		list_add(&dev_data->list, &domain->dev_list);
 		set_dte_entry(devid, domain);
 	}
 
@@ -1460,6 +1463,7 @@ static void __detach_device(struct device *dev)
 	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 	struct iommu_dev_data *dev_data = get_dev_data(dev);
 	struct iommu_dev_data *alias_data;
+	unsigned long flags;
 
 	BUG_ON(!iommu);
 
@@ -1469,13 +1473,19 @@ static void __detach_device(struct device *dev)
 	if (devid != alias) {
 		alias_data = get_dev_data(dev_data->alias);
 		if (atomic_dec_and_test(&alias_data->bind)) {
+			spin_lock_irqsave(&alias_data->domain->lock, flags);
 			clear_dte_entry(alias);
+			list_del(&alias_data->list);
+			spin_unlock_irqrestore(&alias_data->domain->lock, flags);
 			alias_data->domain = NULL;
 		}
 	}
 
 	if (atomic_dec_and_test(&dev_data->bind)) {
+		spin_lock_irqsave(&dev_data->domain->lock, flags);
 		clear_dte_entry(devid);
+		list_del(&dev_data->list);
+		spin_unlock_irqrestore(&dev_data->domain->lock, flags);
 		dev_data->domain = NULL;
 	}
 
@@ -2294,6 +2304,7 @@ static struct protection_domain *protection_domain_alloc(void)
 	domain->id = domain_id_alloc();
 	if (!domain->id)
 		goto out_err;
+	INIT_LIST_HEAD(&domain->dev_list);
 
 	add_domain_to_list(domain);
 
-- 
1.6.5.3



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

* [PATCH 30/34] x86/amd-iommu: Cleanup attach/detach_device code
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (28 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 29/34] x86/amd-iommu: Keep devices per domain in a list Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 31/34] x86/amd-iommu: Introduce iommu_flush_device() function Joerg Roedel
                   ` (4 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch cleans up the attach_device and detach_device
paths and fixes reference counting while at it.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |  102 ++++++++++++++++++++++++------------------
 1 files changed, 58 insertions(+), 44 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 530d608..e3363fd 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1329,7 +1329,6 @@ static bool dma_ops_domain(struct protection_domain *domain)
 
 static void set_dte_entry(u16 devid, struct protection_domain *domain)
 {
-	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 	u64 pte_root = virt_to_phys(domain->pt_root);
 
 	BUG_ON(amd_iommu_pd_table[devid] != NULL);
@@ -1344,18 +1343,11 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain)
 
 	amd_iommu_pd_table[devid] = domain;
 
-	/* Do reference counting */
-	domain->dev_iommu[iommu->index] += 1;
-	domain->dev_cnt                 += 1;
-
-	/* Flush the changes DTE entry */
-	iommu_queue_inv_dev_entry(iommu, devid);
 }
 
 static void clear_dte_entry(u16 devid)
 {
 	struct protection_domain *domain = amd_iommu_pd_table[devid];
-	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 
 	BUG_ON(domain == NULL);
 
@@ -1368,11 +1360,51 @@ static void clear_dte_entry(u16 devid)
 	amd_iommu_dev_table[devid].data[2] = 0;
 
 	amd_iommu_apply_erratum_63(devid);
+}
+
+static void do_attach(struct device *dev, struct protection_domain *domain)
+{
+	struct iommu_dev_data *dev_data;
+	struct amd_iommu *iommu;
+	u16 devid;
+
+	devid    = get_device_id(dev);
+	iommu    = amd_iommu_rlookup_table[devid];
+	dev_data = get_dev_data(dev);
+
+	/* Update data structures */
+	dev_data->domain = domain;
+	list_add(&dev_data->list, &domain->dev_list);
+	set_dte_entry(devid, domain);
+
+	/* Do reference counting */
+	domain->dev_iommu[iommu->index] += 1;
+	domain->dev_cnt                 += 1;
+
+	/* Flush the DTE entry */
+	iommu_queue_inv_dev_entry(iommu, devid);
+}
+
+static void do_detach(struct device *dev)
+{
+	struct iommu_dev_data *dev_data;
+	struct amd_iommu *iommu;
+	u16 devid;
+
+	devid    = get_device_id(dev);
+	iommu    = amd_iommu_rlookup_table[devid];
+	dev_data = get_dev_data(dev);
 
 	/* decrease reference counters */
-	domain->dev_iommu[iommu->index] -= 1;
-	domain->dev_cnt                 -= 1;
+	dev_data->domain->dev_iommu[iommu->index] -= 1;
+	dev_data->domain->dev_cnt                 -= 1;
+
+	/* Update data structures */
+	dev_data->domain = NULL;
+	list_del(&dev_data->list);
+	clear_dte_entry(devid);
 
+	/* Flush the DTE entry */
 	iommu_queue_inv_dev_entry(iommu, devid);
 }
 
@@ -1384,12 +1416,10 @@ static int __attach_device(struct device *dev,
 			   struct protection_domain *domain)
 {
 	struct iommu_dev_data *dev_data, *alias_data;
-	u16 devid, alias;
 
-	devid      = get_device_id(dev);
-	alias      = amd_iommu_alias_table[devid];
 	dev_data   = get_dev_data(dev);
 	alias_data = get_dev_data(dev_data->alias);
+
 	if (!alias_data)
 		return -EINVAL;
 
@@ -1406,21 +1436,16 @@ static int __attach_device(struct device *dev,
 		return -EBUSY;
 
 	/* Do real assignment */
-	if (alias != devid) {
-		if (alias_data->domain == NULL) {
-			alias_data->domain = domain;
-			list_add(&alias_data->list, &domain->dev_list);
-			set_dte_entry(alias, domain);
-		}
+	if (dev_data->alias != dev) {
+		alias_data = get_dev_data(dev_data->alias);
+		if (alias_data->domain == NULL)
+			do_attach(dev_data->alias, domain);
 
 		atomic_inc(&alias_data->bind);
 	}
 
-	if (dev_data->domain == NULL) {
-		dev_data->domain = domain;
-		list_add(&dev_data->list, &domain->dev_list);
-		set_dte_entry(devid, domain);
-	}
+	if (dev_data->domain == NULL)
+		do_attach(dev, domain);
 
 	atomic_inc(&dev_data->bind);
 
@@ -1459,35 +1484,24 @@ static int attach_device(struct device *dev,
  */
 static void __detach_device(struct device *dev)
 {
-	u16 devid = get_device_id(dev), alias;
-	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 	struct iommu_dev_data *dev_data = get_dev_data(dev);
 	struct iommu_dev_data *alias_data;
 	unsigned long flags;
 
-	BUG_ON(!iommu);
+	BUG_ON(!dev_data->domain);
 
-	devid = get_device_id(dev);
-	alias = get_device_id(dev_data->alias);
+	spin_lock_irqsave(&dev_data->domain->lock, flags);
 
-	if (devid != alias) {
+	if (dev_data->alias != dev) {
 		alias_data = get_dev_data(dev_data->alias);
-		if (atomic_dec_and_test(&alias_data->bind)) {
-			spin_lock_irqsave(&alias_data->domain->lock, flags);
-			clear_dte_entry(alias);
-			list_del(&alias_data->list);
-			spin_unlock_irqrestore(&alias_data->domain->lock, flags);
-			alias_data->domain = NULL;
-		}
+		if (atomic_dec_and_test(&alias_data->bind))
+			do_detach(dev_data->alias);
 	}
 
-	if (atomic_dec_and_test(&dev_data->bind)) {
-		spin_lock_irqsave(&dev_data->domain->lock, flags);
-		clear_dte_entry(devid);
-		list_del(&dev_data->list);
-		spin_unlock_irqrestore(&dev_data->domain->lock, flags);
-		dev_data->domain = NULL;
-	}
+	if (atomic_dec_and_test(&dev_data->bind))
+		do_detach(dev);
+
+	spin_unlock_irqrestore(&dev_data->domain->lock, flags);
 
 	/*
 	 * If we run in passthrough mode the device must be assigned to the
-- 
1.6.5.3



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

* [PATCH 31/34] x86/amd-iommu: Introduce iommu_flush_device() function
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (29 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 30/34] x86/amd-iommu: Cleanup attach/detach_device code Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 32/34] x86/amd-iommu: Cleanup DTE flushing code Joerg Roedel
                   ` (3 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch adds a function to flush a DTE entry for a given
struct device and replaces iommu_queue_inv_dev_entry calls
with this function where appropriate.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index e3363fd..41c4ebe 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -494,6 +494,17 @@ static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
 	return ret;
 }
 
+static int iommu_flush_device(struct device *dev)
+{
+	struct amd_iommu *iommu;
+	u16 devid;
+
+	devid = get_device_id(dev);
+	iommu = amd_iommu_rlookup_table[devid];
+
+	return iommu_queue_inv_dev_entry(iommu, devid);
+}
+
 static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
 					  u16 domid, int pde, int s)
 {
@@ -1382,7 +1393,7 @@ static void do_attach(struct device *dev, struct protection_domain *domain)
 	domain->dev_cnt                 += 1;
 
 	/* Flush the DTE entry */
-	iommu_queue_inv_dev_entry(iommu, devid);
+	iommu_flush_device(dev);
 }
 
 static void do_detach(struct device *dev)
@@ -1405,7 +1416,7 @@ static void do_detach(struct device *dev)
 	clear_dte_entry(devid);
 
 	/* Flush the DTE entry */
-	iommu_queue_inv_dev_entry(iommu, devid);
+	iommu_flush_device(dev);
 }
 
 /*
@@ -1610,7 +1621,7 @@ static int device_change_notifier(struct notifier_block *nb,
 		goto out;
 	}
 
-	iommu_queue_inv_dev_entry(iommu, devid);
+	iommu_flush_device(dev);
 	iommu_completion_wait(iommu);
 
 out:
@@ -2393,7 +2404,7 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
 	if (!iommu)
 		return;
 
-	iommu_queue_inv_dev_entry(iommu, devid);
+	iommu_flush_device(dev);
 	iommu_completion_wait(iommu);
 }
 
-- 
1.6.5.3



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

* [PATCH 32/34] x86/amd-iommu: Cleanup DTE flushing code
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (30 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 31/34] x86/amd-iommu: Introduce iommu_flush_device() function Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 33/34] x86/amd-iommu: Move reset_iommu_command_buffer out of locked code Joerg Roedel
                   ` (2 subsequent siblings)
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch cleans up the code to flush device table entries
in the IOMMU. With this chance the driver can get rid of the
iommu_queue_inv_dev_entry() function.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    1 +
 arch/x86/kernel/amd_iommu.c            |  100 +++++++++++---------------------
 2 files changed, 35 insertions(+), 66 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 93953d1..f92d1b3 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -253,6 +253,7 @@ struct protection_domain {
  */
 struct iommu_dev_data {
 	struct list_head list;		  /* For domain->dev_list */
+	struct device *dev;		  /* Device this data belong to */
 	struct device *alias;		  /* The Alias Device */
 	struct protection_domain *domain; /* Domain the device is bound to */
 	atomic_t bind;			  /* Domain attach reverent count */
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 41c4ebe..0eafca5 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -146,6 +146,8 @@ static int iommu_init_device(struct device *dev)
 	if (!dev_data)
 		return -ENOMEM;
 
+	dev_data->dev = dev;
+
 	devid = get_device_id(dev);
 	alias = amd_iommu_alias_table[devid];
 	pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
@@ -478,31 +480,21 @@ static void iommu_flush_complete(struct protection_domain *domain)
 /*
  * Command send function for invalidating a device table entry
  */
-static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
-{
-	struct iommu_cmd cmd;
-	int ret;
-
-	BUG_ON(iommu == NULL);
-
-	memset(&cmd, 0, sizeof(cmd));
-	CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY);
-	cmd.data[0] = devid;
-
-	ret = iommu_queue_command(iommu, &cmd);
-
-	return ret;
-}
-
 static int iommu_flush_device(struct device *dev)
 {
 	struct amd_iommu *iommu;
+	struct iommu_cmd cmd;
 	u16 devid;
 
 	devid = get_device_id(dev);
 	iommu = amd_iommu_rlookup_table[devid];
 
-	return iommu_queue_inv_dev_entry(iommu, devid);
+	/* Build command */
+	memset(&cmd, 0, sizeof(cmd));
+	CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY);
+	cmd.data[0] = devid;
+
+	return iommu_queue_command(iommu, &cmd);
 }
 
 static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
@@ -592,30 +584,43 @@ static void iommu_flush_tlb_pde(struct protection_domain *domain)
 	__iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
 }
 
+
 /*
- * This function flushes all domains that have devices on the given IOMMU
+ * This function flushes the DTEs for all devices in domain
  */
-static void flush_all_domains_on_iommu(struct amd_iommu *iommu)
+static void iommu_flush_domain_devices(struct protection_domain *domain)
+{
+	struct iommu_dev_data *dev_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	list_for_each_entry(dev_data, &domain->dev_list, list)
+		iommu_flush_device(dev_data->dev);
+
+	spin_unlock_irqrestore(&domain->lock, flags);
+}
+
+static void iommu_flush_all_domain_devices(void)
 {
-	u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
 	struct protection_domain *domain;
 	unsigned long flags;
 
 	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
 
 	list_for_each_entry(domain, &amd_iommu_pd_list, list) {
-		if (domain->dev_iommu[iommu->index] == 0)
-			continue;
-
-		spin_lock(&domain->lock);
-		iommu_queue_inv_iommu_pages(iommu, address, domain->id, 1, 1);
+		iommu_flush_domain_devices(domain);
 		iommu_flush_complete(domain);
-		spin_unlock(&domain->lock);
 	}
 
 	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
 }
 
+void amd_iommu_flush_all_devices(void)
+{
+	iommu_flush_all_domain_devices();
+}
+
 /*
  * This function uses heavy locking and may disable irqs for some time. But
  * this is no issue because it is only called during resume.
@@ -637,38 +642,6 @@ void amd_iommu_flush_all_domains(void)
 	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
 }
 
-static void flush_all_devices_for_iommu(struct amd_iommu *iommu)
-{
-	int i;
-
-	for (i = 0; i <= amd_iommu_last_bdf; ++i) {
-		if (iommu != amd_iommu_rlookup_table[i])
-			continue;
-
-		iommu_queue_inv_dev_entry(iommu, i);
-		iommu_completion_wait(iommu);
-	}
-}
-
-static void flush_devices_by_domain(struct protection_domain *domain)
-{
-	struct amd_iommu *iommu;
-	int i;
-
-	for (i = 0; i <= amd_iommu_last_bdf; ++i) {
-		if ((domain == NULL && amd_iommu_pd_table[i] == NULL) ||
-		    (amd_iommu_pd_table[i] != domain))
-			continue;
-
-		iommu = amd_iommu_rlookup_table[i];
-		if (!iommu)
-			continue;
-
-		iommu_queue_inv_dev_entry(iommu, i);
-		iommu_completion_wait(iommu);
-	}
-}
-
 static void reset_iommu_command_buffer(struct amd_iommu *iommu)
 {
 	pr_err("AMD-Vi: Resetting IOMMU command buffer\n");
@@ -679,17 +652,12 @@ static void reset_iommu_command_buffer(struct amd_iommu *iommu)
 	iommu->reset_in_progress = true;
 
 	amd_iommu_reset_cmd_buffer(iommu);
-	flush_all_devices_for_iommu(iommu);
-	flush_all_domains_on_iommu(iommu);
+	amd_iommu_flush_all_devices();
+	amd_iommu_flush_all_domains();
 
 	iommu->reset_in_progress = false;
 }
 
-void amd_iommu_flush_all_devices(void)
-{
-	flush_devices_by_domain(NULL);
-}
-
 /****************************************************************************
  *
  * The functions below are used the create the page table mappings for
@@ -1692,7 +1660,7 @@ static void update_domain(struct protection_domain *domain)
 		return;
 
 	update_device_table(domain);
-	flush_devices_by_domain(domain);
+	iommu_flush_domain_devices(domain);
 	iommu_flush_tlb_pde(domain);
 
 	domain->updated = false;
-- 
1.6.5.3



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

* [PATCH 33/34] x86/amd-iommu: Move reset_iommu_command_buffer out of locked code
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (31 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 32/34] x86/amd-iommu: Cleanup DTE flushing code Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 13:55 ` [PATCH 34/34] x86/amd-iommu: Remove amd_iommu_pd_table Joerg Roedel
  2009-11-27 19:27 ` [git pull] IOMMU updates for 2.6.33 Ingo Molnar
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

This patch removes the ugly contruct where the
iommu->lock must be released while before calling the
reset_iommu_command_buffer function.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0eafca5..b75fcd9 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -285,6 +285,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
 		break;
 	case EVENT_TYPE_ILL_CMD:
 		printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
+		iommu->reset_in_progress = true;
 		reset_iommu_command_buffer(iommu);
 		dump_command(address);
 		break;
@@ -407,11 +408,8 @@ static void __iommu_wait_for_completion(struct amd_iommu *iommu)
 	status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
 	writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
 
-	if (unlikely(i == EXIT_LOOP_COUNT)) {
-		spin_unlock(&iommu->lock);
-		reset_iommu_command_buffer(iommu);
-		spin_lock(&iommu->lock);
-	}
+	if (unlikely(i == EXIT_LOOP_COUNT))
+		iommu->reset_in_progress = true;
 }
 
 /*
@@ -458,6 +456,9 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
 out:
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
+	if (iommu->reset_in_progress)
+		reset_iommu_command_buffer(iommu);
+
 	return 0;
 }
 
@@ -649,8 +650,6 @@ static void reset_iommu_command_buffer(struct amd_iommu *iommu)
 	if (iommu->reset_in_progress)
 		panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n");
 
-	iommu->reset_in_progress = true;
-
 	amd_iommu_reset_cmd_buffer(iommu);
 	amd_iommu_flush_all_devices();
 	amd_iommu_flush_all_domains();
-- 
1.6.5.3



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

* [PATCH 34/34] x86/amd-iommu: Remove amd_iommu_pd_table
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (32 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 33/34] x86/amd-iommu: Move reset_iommu_command_buffer out of locked code Joerg Roedel
@ 2009-11-27 13:55 ` Joerg Roedel
  2009-11-27 19:27 ` [git pull] IOMMU updates for 2.6.33 Ingo Molnar
  34 siblings, 0 replies; 36+ messages in thread
From: Joerg Roedel @ 2009-11-27 13:55 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: iommu, linux-kernel, Joerg Roedel

The data that was stored in this table is now available in
dev->archdata.iommu. So this table is not longer necessary.
This patch removes the remaining uses of that variable and
removes it from the code.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/include/asm/amd_iommu_types.h |    3 --
 arch/x86/kernel/amd_iommu.c            |   35 ++++++++++---------------------
 arch/x86/kernel/amd_iommu_init.c       |   18 ----------------
 3 files changed, 11 insertions(+), 45 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index f92d1b3..ba19ad4 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -457,9 +457,6 @@ extern unsigned amd_iommu_aperture_order;
 /* largest PCI device id we expect translation requests for */
 extern u16 amd_iommu_last_bdf;
 
-/* data structures for protection domain handling */
-extern struct protection_domain **amd_iommu_pd_table;
-
 /* allocation bitmap for domain ids */
 extern unsigned long *amd_iommu_pd_alloc_bitmap;
 
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index b75fcd9..32fb091 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1309,8 +1309,6 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain)
 {
 	u64 pte_root = virt_to_phys(domain->pt_root);
 
-	BUG_ON(amd_iommu_pd_table[devid] != NULL);
-
 	pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
 		    << DEV_ENTRY_MODE_SHIFT;
 	pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
@@ -1318,20 +1316,10 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain)
 	amd_iommu_dev_table[devid].data[2] = domain->id;
 	amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root);
 	amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root);
-
-	amd_iommu_pd_table[devid] = domain;
-
 }
 
 static void clear_dte_entry(u16 devid)
 {
-	struct protection_domain *domain = amd_iommu_pd_table[devid];
-
-	BUG_ON(domain == NULL);
-
-	/* remove domain from the lookup table */
-	amd_iommu_pd_table[devid] = NULL;
-
 	/* remove entry from the device table seen by the hardware */
 	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
 	amd_iommu_dev_table[devid].data[1] = 0;
@@ -1641,15 +1629,11 @@ static struct protection_domain *get_domain(struct device *dev)
 
 static void update_device_table(struct protection_domain *domain)
 {
-	unsigned long flags;
-	int i;
+	struct iommu_dev_data *dev_data;
 
-	for (i = 0; i <= amd_iommu_last_bdf; ++i) {
-		if (amd_iommu_pd_table[i] != domain)
-			continue;
-		write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-		set_dte_entry(i, domain);
-		write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+	list_for_each_entry(dev_data, &domain->dev_list, list) {
+		u16 devid = get_device_id(dev_data->dev);
+		set_dte_entry(devid, domain);
 	}
 }
 
@@ -2259,14 +2243,17 @@ free_domains:
 
 static void cleanup_domain(struct protection_domain *domain)
 {
+	struct iommu_dev_data *dev_data, *next;
 	unsigned long flags;
-	u16 devid;
 
 	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
 
-	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid)
-		if (amd_iommu_pd_table[devid] == domain)
-			clear_dte_entry(devid);
+	list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
+		struct device *dev = dev_data->dev;
+
+		do_detach(dev);
+		atomic_set(&dev_data->bind, 0);
+	}
 
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index fe1686f..7ffc399 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -165,12 +165,6 @@ u16 *amd_iommu_alias_table;
 struct amd_iommu **amd_iommu_rlookup_table;
 
 /*
- * The pd table (protection domain table) is used to find the protection domain
- * data structure a device belongs to. Indexed with the PCI device id too.
- */
-struct protection_domain **amd_iommu_pd_table;
-
-/*
  * AMD IOMMU allows up to 2^16 differend protection domains. This is a bitmap
  * to know which ones are already in use.
  */
@@ -1238,15 +1232,6 @@ static int __init amd_iommu_init(void)
 	if (amd_iommu_rlookup_table == NULL)
 		goto free;
 
-	/*
-	 * Protection Domain table - maps devices to protection domains
-	 * This table has the same size as the rlookup_table
-	 */
-	amd_iommu_pd_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-				     get_order(rlookup_table_size));
-	if (amd_iommu_pd_table == NULL)
-		goto free;
-
 	amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(
 					    GFP_KERNEL | __GFP_ZERO,
 					    get_order(MAX_DOMAIN_ID/8));
@@ -1314,9 +1299,6 @@ free:
 	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
 		   get_order(MAX_DOMAIN_ID/8));
 
-	free_pages((unsigned long)amd_iommu_pd_table,
-		   get_order(rlookup_table_size));
-
 	free_pages((unsigned long)amd_iommu_rlookup_table,
 		   get_order(rlookup_table_size));
 
-- 
1.6.5.3



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

* Re: [git pull] IOMMU updates for 2.6.33
  2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
                   ` (33 preceding siblings ...)
  2009-11-27 13:55 ` [PATCH 34/34] x86/amd-iommu: Remove amd_iommu_pd_table Joerg Roedel
@ 2009-11-27 19:27 ` Ingo Molnar
  34 siblings, 0 replies; 36+ messages in thread
From: Ingo Molnar @ 2009-11-27 19:27 UTC (permalink / raw)
  To: Joerg Roedel; +Cc: iommu, linux-kernel


* Joerg Roedel <joerg.roedel@amd.com> wrote:

> Hi Ingo,
> 
> 
> The following changes since commit 273bee27fa9f79d94b78c83506016f2e41e78983:
>   FUJITA Tomonori (1):
>         x86: Fix iommu=soft boot option
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git amd-iommu/2.6.33
> 
> Joerg Roedel (35):
>       x86/amd-iommu: Separate internal interface definitions
>       x86/amd-iommu: Update copyright headers
>       x86/amd-iommu: Add an index field to struct amd_iommu
>       x86/amd-iommu: Add per IOMMU reference counting
>       x86/amd-iommu: Add function to complete a tlb flush
>       x86/amd-iommu: Make iommu_flush_pages aware of multiple IOMMUs
>       x86/amd-iommu: Use __iommu_flush_pages for tlb flushes
>       x86/amd-iommu: Remove iommu_flush_domain function
>       x86/amd-iommu: Implement protection domain list
>       x86/amd-iommu: Reimplement amd_iommu_flush_all_domains()
>       x86/amd-iommu: Reimplement flush_all_domains_on_iommu()
>       x86/amd-iommu: Make np-cache a global flag
>       x86/amd-iommu: Use check_device for amd_iommu_dma_supported
>       x86/amd-iommu: Use check_device in get_device_resources
>       x86/amd-iommu: Remove iommu parameter from dma_ops_domain_(un)map
>       x86/amd-iommu: Make alloc_new_range aware of multiple IOMMUs
>       x86/amd-iommu: Remove iommu parameter from __(un)map_single
>       x86/amd-iommu: Remove iommu specific handling from dma_ops path
>       x86/amd-iommu: Let domain_for_device handle aliases
>       x86/amd-iommu: Simplify get_device_resources()
>       x86/amd-iommu: Move find_protection_domain to helper functions
>       x86/amd-iommu: Use get_device_id and check_device where appropriate
>       x86/amd-iommu: Remove iommu parameter from dma_ops_domain_alloc
>       x86/amd-iommu: Move some pte allocation functions in the right section
>       x86/amd-iommu: Rearrange dma_ops related functions
>       x86/amd-iommu: Remove support for domain sharing
>       x86/amd-iommu: Use dev->arch->iommu to store iommu related information
>       x86/amd-iommu: Add device bind reference counting
>       x86/amd-iommu: Keep devices per domain in a list
>       x86/amd-iommu: Cleanup attach/detach_device code
>       x86/amd-iommu: Introduce iommu_flush_device() function
>       x86/amd-iommu: Cleanup DTE flushing code
>       x86/amd-iommu: Move reset_iommu_command_buffer out of locked code
>       x86/amd-iommu: Remove amd_iommu_pd_table
>       Merge branch 'gart/fixes' into amd-iommu/2.6.33
> 
> Pavel Vasilyev (1):
>       agp/amd64: Remove GART dependency on AGP_AMD64
> 
>  arch/x86/include/asm/amd_iommu.h       |   12 +-
>  arch/x86/include/asm/amd_iommu_proto.h |   38 +
>  arch/x86/include/asm/amd_iommu_types.h |   54 ++-
>  arch/x86/include/asm/device.h          |    2 +-
>  arch/x86/kernel/amd_iommu.c            | 1230 +++++++++++++++++---------------
>  arch/x86/kernel/amd_iommu_init.c       |   67 +-
>  drivers/char/agp/Kconfig               |    3 +-
>  7 files changed, 777 insertions(+), 629 deletions(-)
>  create mode 100644 arch/x86/include/asm/amd_iommu_proto.h
> 
> Most of the changes are for AMD IOMMU driver. The changes there are 
> bigger than usual because I did a lot of changes to the data 
> structures storing the relations between devices, protection domains 
> and iommus. A major change is that the amd_iommu_pd_table is now gone 
> and replaced by a struct iommu_dev_data for each device stored in 
> dev->archdata->iommu. These changes result in a more robust reference 
> counting, especially for devices with an alias and simplified code in 
> many places. Also included are some related cleanups which separated 
> the internal function prototypes to a several header and code movement 
> to get rid of most function forward declarations. Please pull.

Pulled into tip:core/iommu - thanks a lot Joerg!

	Ingo

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

end of thread, other threads:[~2009-11-27 19:27 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-27 13:55 [git pull] IOMMU updates for 2.6.33 Joerg Roedel
2009-11-27 13:55 ` [PATCH 01/34] x86/amd-iommu: Separate internal interface definitions Joerg Roedel
2009-11-27 13:55 ` [PATCH 02/34] x86/amd-iommu: Update copyright headers Joerg Roedel
2009-11-27 13:55 ` [PATCH 03/34] x86/amd-iommu: Add an index field to struct amd_iommu Joerg Roedel
2009-11-27 13:55 ` [PATCH 04/34] x86/amd-iommu: Add per IOMMU reference counting Joerg Roedel
2009-11-27 13:55 ` [PATCH 05/34] x86/amd-iommu: Add function to complete a tlb flush Joerg Roedel
2009-11-27 13:55 ` [PATCH 06/34] x86/amd-iommu: Make iommu_flush_pages aware of multiple IOMMUs Joerg Roedel
2009-11-27 13:55 ` [PATCH 07/34] x86/amd-iommu: Use __iommu_flush_pages for tlb flushes Joerg Roedel
2009-11-27 13:55 ` [PATCH 08/34] x86/amd-iommu: Remove iommu_flush_domain function Joerg Roedel
2009-11-27 13:55 ` [PATCH 09/34] x86/amd-iommu: Implement protection domain list Joerg Roedel
2009-11-27 13:55 ` [PATCH 10/34] x86/amd-iommu: Reimplement amd_iommu_flush_all_domains() Joerg Roedel
2009-11-27 13:55 ` [PATCH 11/34] x86/amd-iommu: Reimplement flush_all_domains_on_iommu() Joerg Roedel
2009-11-27 13:55 ` [PATCH 12/34] x86/amd-iommu: Make np-cache a global flag Joerg Roedel
2009-11-27 13:55 ` [PATCH 13/34] x86/amd-iommu: Use check_device for amd_iommu_dma_supported Joerg Roedel
2009-11-27 13:55 ` [PATCH 14/34] x86/amd-iommu: Use check_device in get_device_resources Joerg Roedel
2009-11-27 13:55 ` [PATCH 15/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_(un)map Joerg Roedel
2009-11-27 13:55 ` [PATCH 16/34] x86/amd-iommu: Make alloc_new_range aware of multiple IOMMUs Joerg Roedel
2009-11-27 13:55 ` [PATCH 17/34] x86/amd-iommu: Remove iommu parameter from __(un)map_single Joerg Roedel
2009-11-27 13:55 ` [PATCH 18/34] x86/amd-iommu: Remove iommu specific handling from dma_ops path Joerg Roedel
2009-11-27 13:55 ` [PATCH 19/34] x86/amd-iommu: Let domain_for_device handle aliases Joerg Roedel
2009-11-27 13:55 ` [PATCH 20/34] x86/amd-iommu: Simplify get_device_resources() Joerg Roedel
2009-11-27 13:55 ` [PATCH 21/34] x86/amd-iommu: Move find_protection_domain to helper functions Joerg Roedel
2009-11-27 13:55 ` [PATCH 22/34] x86/amd-iommu: Use get_device_id and check_device where appropriate Joerg Roedel
2009-11-27 13:55 ` [PATCH 23/34] x86/amd-iommu: Remove iommu parameter from dma_ops_domain_alloc Joerg Roedel
2009-11-27 13:55 ` [PATCH 24/34] x86/amd-iommu: Move some pte allocation functions in the right section Joerg Roedel
2009-11-27 13:55 ` [PATCH 25/34] x86/amd-iommu: Rearrange dma_ops related functions Joerg Roedel
2009-11-27 13:55 ` [PATCH 26/34] x86/amd-iommu: Remove support for domain sharing Joerg Roedel
2009-11-27 13:55 ` [PATCH 27/34] x86/amd-iommu: Use dev->arch->iommu to store iommu related information Joerg Roedel
2009-11-27 13:55 ` [PATCH 28/34] x86/amd-iommu: Add device bind reference counting Joerg Roedel
2009-11-27 13:55 ` [PATCH 29/34] x86/amd-iommu: Keep devices per domain in a list Joerg Roedel
2009-11-27 13:55 ` [PATCH 30/34] x86/amd-iommu: Cleanup attach/detach_device code Joerg Roedel
2009-11-27 13:55 ` [PATCH 31/34] x86/amd-iommu: Introduce iommu_flush_device() function Joerg Roedel
2009-11-27 13:55 ` [PATCH 32/34] x86/amd-iommu: Cleanup DTE flushing code Joerg Roedel
2009-11-27 13:55 ` [PATCH 33/34] x86/amd-iommu: Move reset_iommu_command_buffer out of locked code Joerg Roedel
2009-11-27 13:55 ` [PATCH 34/34] x86/amd-iommu: Remove amd_iommu_pd_table Joerg Roedel
2009-11-27 19:27 ` [git pull] IOMMU updates for 2.6.33 Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox