2008-12-15 14:19:37

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 0/22] more AMD IOMMU updates for 2.6.29

Hi,

this is the rest of AMD IOMMU updates for the 2.6.29 merge window (the
other part is contained in the KVM device passthrough patchsets posted
before).
These patches include some cleanups and improvements for PCI device
hotplug. The most interesting part is the new stats collection facility.
Once enabled, the user can see various high-level statistics about what
the IOMMU code (mostly limited to DMA-API) is doing in debugfs. This can
be used to optimize this and other code (e.g. pv-dma in KVM) in the
future.

Joerg

diffstat:

arch/x86/Kconfig | 10 +++
arch/x86/include/asm/amd_iommu_types.h | 46 +++++++++----
arch/x86/kernel/amd_iommu.c | 117 ++++++++++++++++++++++++++++++--
arch/x86/kernel/amd_iommu_init.c | 15 ++---
4 files changed, 160 insertions(+), 28 deletions(-)



2008-12-15 14:18:25

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 05/22] AMD IOMMU: convert amd_iommu_isolate to bool

Impact: cleanup

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/include/asm/amd_iommu_types.h | 2 +-
arch/x86/kernel/amd_iommu_init.c | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index c4b144e..7abf9cf 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -381,7 +381,7 @@ extern struct protection_domain **amd_iommu_pd_table;
extern unsigned long *amd_iommu_pd_alloc_bitmap;

/* will be 1 if device isolation is enabled */
-extern int amd_iommu_isolate;
+extern bool amd_iommu_isolate;

/*
* If true, the addresses will be flushed on unmap time, not when
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 30ae270..b53152b 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -121,7 +121,8 @@ u16 amd_iommu_last_bdf; /* largest PCI device id we have
LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings
we find in ACPI */
unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
-int amd_iommu_isolate = 1; /* if 1, device isolation is enabled */
+bool amd_iommu_isolate = true; /* if true, device isolation is
+ enabled */
bool amd_iommu_unmap_flush; /* if true, flush on every unmap */

LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
@@ -1212,9 +1213,9 @@ static int __init parse_amd_iommu_options(char *str)
{
for (; *str; ++str) {
if (strncmp(str, "isolate", 7) == 0)
- amd_iommu_isolate = 1;
+ amd_iommu_isolate = true;
if (strncmp(str, "share", 5) == 0)
- amd_iommu_isolate = 0;
+ amd_iommu_isolate = false;
if (strncmp(str, "fullflush", 9) == 0)
amd_iommu_unmap_flush = true;
}
--
1.5.6.4

2008-12-15 14:18:42

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 02/22] AMD IOMMU: allocate a new protection for hotplugged devices

Impact: also hotplug devices benefit from device isolation

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 1694415..cebbf58 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -922,6 +922,8 @@ static int device_change_notifier(struct notifier_block *nb,
struct protection_domain *domain;
struct dma_ops_domain *dma_domain;
struct amd_iommu *iommu;
+ int order = amd_iommu_aperture_order;
+ unsigned long flags;

if (devid > amd_iommu_last_bdf)
goto out;
@@ -954,6 +956,21 @@ static int device_change_notifier(struct notifier_block *nb,
goto out;
detach_device(domain, devid);
break;
+ case BUS_NOTIFY_ADD_DEVICE:
+ /* allocate a protection domain if a device is added */
+ dma_domain = find_protection_domain(devid);
+ if (dma_domain)
+ goto out;
+ dma_domain = dma_ops_domain_alloc(iommu, order);
+ if (!dma_domain)
+ goto out;
+ dma_domain->target_dev = devid;
+
+ spin_lock_irqsave(&iommu_pd_list_lock, flags);
+ list_add_tail(&dma_domain->list, &iommu_pd_list);
+ spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+ break;
default:
goto out;
}
--
1.5.6.4

2008-12-15 14:18:55

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 01/22] AMD IOMMU: add a domain flag for default domains

Impact: adds a new protection domain flag

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/include/asm/amd_iommu_types.h | 2 ++
arch/x86/kernel/amd_iommu.c | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 1c769f4..6adc702 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -192,6 +192,8 @@

/* Protection domain flags */
#define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */
+#define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops
+ domain for an IOMMU */

/*
* This structure contains generic data for IOMMU protection domains
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index cc78834..1694415 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1573,6 +1573,7 @@ int __init amd_iommu_init_dma_ops(void)
iommu->default_dom = dma_ops_domain_alloc(iommu, order);
if (iommu->default_dom == NULL)
return -ENOMEM;
+ iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
ret = iommu_init_unity_mappings(iommu);
if (ret)
goto free_domains;
--
1.5.6.4

2008-12-15 14:19:19

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 09/22] AMD IOMMU: add necessary header defines for stats counting

Impact: add defines to make iommu stats collection configurable

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/include/asm/amd_iommu_types.h | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 7abf9cf..1379c5f 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -396,4 +396,30 @@ static inline u16 calc_devid(u8 bus, u8 devfn)
return (((u16)bus) << 8) | devfn;
}

+#ifdef CONFIG_AMD_IOMMU_STATS
+
+struct __iommu_counter {
+ char *name;
+ struct dentry *dent;
+ u64 value;
+};
+
+#define DECLARE_STATS_COUNTER(nm) \
+ static struct __iommu_counter nm = { \
+ .name = #nm, \
+ }
+
+#define INC_STATS_COUNTER(name) name.value += 1
+#define ADD_STATS_COUNTER(name, x) name.value += (x)
+#define SUB_STATS_COUNTER(name, x) name.value -= (x)
+
+#else /* CONFIG_AMD_IOMMU_STATS */
+
+#define DECLARE_STATS_COUNTER(name)
+#define INC_STATS_COUNTER(name)
+#define ADD_STATS_COUNTER(name, x)
+#define SUB_STATS_COUNTER(name, x)
+
+#endif /* CONFIG_AMD_IOMMU_STATS */
+
#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
--
1.5.6.4

2008-12-15 14:19:55

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 03/22] AMD IOMMU: use dev_name instead of self-build print_devid

Impact: use generic dev_name instead of own function

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/include/asm/amd_iommu_types.h | 12 ------------
arch/x86/kernel/amd_iommu.c | 3 +--
2 files changed, 1 insertions(+), 14 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 6adc702..ee8cfa0 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -389,18 +389,6 @@ extern int amd_iommu_isolate;
*/
extern bool amd_iommu_unmap_flush;

-/* takes a PCI device id and prints it out in a readable form */
-static inline void print_devid(u16 devid, int nl)
-{
- int bus = devid >> 8;
- int dev = devid >> 3 & 0x1f;
- int fn = devid & 0x07;
-
- printk("%02x:%02x.%x", bus, dev, fn);
- if (nl)
- printk("\n");
-}
-
/* takes bus and device/function and returns the device id
* FIXME: should that be in generic PCI code? */
static inline u16 calc_devid(u8 bus, u8 devfn)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index cebbf58..dc7cef3 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1073,8 +1073,7 @@ static int get_device_resources(struct device *dev,
*domain = &dma_dom->domain;
attach_device(*iommu, *domain, *bdf);
printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
- "device ", (*domain)->id);
- print_devid(_bdf, 1);
+ "device %s\n", (*domain)->id, dev_name(dev));
}

if (domain_for_device(_bdf) == NULL)
--
1.5.6.4

2008-12-15 14:20:22

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 18/22] AMD IOMMU: add stats counter for cross-page request

Impact: see number of requests for more than one page in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index a00d20c..02e8c18 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -70,6 +70,7 @@ DECLARE_STATS_COUNTER(cnt_map_sg);
DECLARE_STATS_COUNTER(cnt_unmap_sg);
DECLARE_STATS_COUNTER(cnt_alloc_coherent);
DECLARE_STATS_COUNTER(cnt_free_coherent);
+DECLARE_STATS_COUNTER(cross_page);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -103,6 +104,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cnt_unmap_sg);
amd_iommu_stats_add(&cnt_alloc_coherent);
amd_iommu_stats_add(&cnt_free_coherent);
+ amd_iommu_stats_add(&cross_page);
}

#endif
@@ -1216,6 +1218,9 @@ static dma_addr_t __map_single(struct device *dev,
pages = iommu_num_pages(paddr, size, PAGE_SIZE);
paddr &= PAGE_MASK;

+ if (pages > 1)
+ INC_STATS_COUNTER(cross_page);
+
if (align)
align_mask = (1UL << get_order(size)) - 1;

--
1.5.6.4

2008-12-15 14:20:43

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 13/22] AMD IOMMU: add stats counter for unmap_single requests

Impact: see number of unmap_single requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 4b23879..18f26eb 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -65,6 +65,7 @@ static struct dma_ops_domain *find_protection_domain(u16 devid);

DECLARE_STATS_COUNTER(compl_wait);
DECLARE_STATS_COUNTER(cnt_map_single);
+DECLARE_STATS_COUNTER(cnt_unmap_single);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -93,6 +94,7 @@ static void amd_iommu_stats_init(void)

amd_iommu_stats_add(&compl_wait);
amd_iommu_stats_add(&cnt_map_single);
+ amd_iommu_stats_add(&cnt_unmap_single);
}

#endif
@@ -1320,6 +1322,8 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
struct protection_domain *domain;
u16 devid;

+ INC_STATS_COUNTER(cnt_unmap_single);
+
if (!check_device(dev) ||
!get_device_resources(dev, &iommu, &domain, &devid))
/* device not handled by any AMD IOMMU */
--
1.5.6.4

2008-12-15 14:21:24

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 17/22] AMD IOMMU: add stats counter for free_coherent requests

Impact: see number of free_coherent requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index e7180e9..a00d20c 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -69,6 +69,7 @@ DECLARE_STATS_COUNTER(cnt_unmap_single);
DECLARE_STATS_COUNTER(cnt_map_sg);
DECLARE_STATS_COUNTER(cnt_unmap_sg);
DECLARE_STATS_COUNTER(cnt_alloc_coherent);
+DECLARE_STATS_COUNTER(cnt_free_coherent);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -101,6 +102,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cnt_map_sg);
amd_iommu_stats_add(&cnt_unmap_sg);
amd_iommu_stats_add(&cnt_alloc_coherent);
+ amd_iommu_stats_add(&cnt_free_coherent);
}

#endif
@@ -1540,6 +1542,8 @@ static void free_coherent(struct device *dev, size_t size,
struct protection_domain *domain;
u16 devid;

+ INC_STATS_COUNTER(cnt_free_coherent);
+
if (!check_device(dev))
return;

--
1.5.6.4

2008-12-15 14:20:58

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 07/22] AMD IOMMU: use dev_name in iommu_enable function

Impact: cleanup

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu_init.c | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index b53152b..0f36753 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -245,12 +245,8 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
/* Function to enable the hardware */
void __init iommu_enable(struct amd_iommu *iommu)
{
- printk(KERN_INFO "AMD IOMMU: Enabling IOMMU "
- "at %02x:%02x.%x cap 0x%hx\n",
- iommu->dev->bus->number,
- PCI_SLOT(iommu->dev->devfn),
- PCI_FUNC(iommu->dev->devfn),
- iommu->cap_ptr);
+ printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at %s cap 0x%hx\n",
+ dev_name(&iommu->dev->dev), iommu->cap_ptr);

iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
}
--
1.5.6.4

2008-12-15 14:21:40

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 12/22] AMD IOMMU: add stats counter for map_single requests

Impact: see number of map_single requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index a494a98..4b23879 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -64,6 +64,7 @@ static struct dma_ops_domain *find_protection_domain(u16 devid);
*/

DECLARE_STATS_COUNTER(compl_wait);
+DECLARE_STATS_COUNTER(cnt_map_single);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -91,6 +92,7 @@ static void amd_iommu_stats_init(void)
(u32 *)&amd_iommu_unmap_flush);

amd_iommu_stats_add(&compl_wait);
+ amd_iommu_stats_add(&cnt_map_single);
}

#endif
@@ -1277,6 +1279,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
dma_addr_t addr;
u64 dma_mask;

+ INC_STATS_COUNTER(cnt_map_single);
+
if (!check_device(dev))
return bad_dma_address;

--
1.5.6.4

2008-12-15 14:21:58

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 16/22] AMD IOMMU: add stats counter for alloc_coherent requests

Impact: see number of alloc_coherent requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index a2022de..e7180e9 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -68,6 +68,7 @@ DECLARE_STATS_COUNTER(cnt_map_single);
DECLARE_STATS_COUNTER(cnt_unmap_single);
DECLARE_STATS_COUNTER(cnt_map_sg);
DECLARE_STATS_COUNTER(cnt_unmap_sg);
+DECLARE_STATS_COUNTER(cnt_alloc_coherent);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -99,6 +100,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cnt_unmap_single);
amd_iommu_stats_add(&cnt_map_sg);
amd_iommu_stats_add(&cnt_unmap_sg);
+ amd_iommu_stats_add(&cnt_alloc_coherent);
}

#endif
@@ -1480,6 +1482,8 @@ static void *alloc_coherent(struct device *dev, size_t size,
phys_addr_t paddr;
u64 dma_mask = dev->coherent_dma_mask;

+ INC_STATS_COUNTER(cnt_alloc_coherent);
+
if (!check_device(dev))
return NULL;

--
1.5.6.4

2008-12-15 14:22:25

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 22/22] AMD IOMMU: add statistics about total number of map requests

Impact: see total number of map requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 9c34902..c8d4301 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -74,6 +74,7 @@ DECLARE_STATS_COUNTER(cross_page);
DECLARE_STATS_COUNTER(domain_flush_single);
DECLARE_STATS_COUNTER(domain_flush_all);
DECLARE_STATS_COUNTER(alloced_io_mem);
+DECLARE_STATS_COUNTER(total_map_requests);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -111,6 +112,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&domain_flush_single);
amd_iommu_stats_add(&domain_flush_all);
amd_iommu_stats_add(&alloced_io_mem);
+ amd_iommu_stats_add(&total_map_requests);
}

#endif
@@ -1228,6 +1230,8 @@ static dma_addr_t __map_single(struct device *dev,
pages = iommu_num_pages(paddr, size, PAGE_SIZE);
paddr &= PAGE_MASK;

+ INC_STATS_COUNTER(total_map_requests);
+
if (pages > 1)
INC_STATS_COUNTER(cross_page);

--
1.5.6.4

2008-12-15 14:22:40

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 15/22] AMD IOMMU: add stats counter for unmap_sg requests

Impact: see number of unmap_sg requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index bb0e03e..a2022de 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -67,6 +67,7 @@ DECLARE_STATS_COUNTER(compl_wait);
DECLARE_STATS_COUNTER(cnt_map_single);
DECLARE_STATS_COUNTER(cnt_unmap_single);
DECLARE_STATS_COUNTER(cnt_map_sg);
+DECLARE_STATS_COUNTER(cnt_unmap_sg);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -97,6 +98,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cnt_map_single);
amd_iommu_stats_add(&cnt_unmap_single);
amd_iommu_stats_add(&cnt_map_sg);
+ amd_iommu_stats_add(&cnt_unmap_sg);
}

#endif
@@ -1442,6 +1444,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
u16 devid;
int i;

+ INC_STATS_COUNTER(cnt_unmap_sg);
+
if (!check_device(dev) ||
!get_device_resources(dev, &iommu, &domain, &devid))
return;
--
1.5.6.4

2008-12-15 14:22:57

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 14/22] AMD IOMMU: add stats counter for map_sg requests

Impact: see number of map_sg requests in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 18f26eb..bb0e03e 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -66,6 +66,7 @@ static struct dma_ops_domain *find_protection_domain(u16 devid);
DECLARE_STATS_COUNTER(compl_wait);
DECLARE_STATS_COUNTER(cnt_map_single);
DECLARE_STATS_COUNTER(cnt_unmap_single);
+DECLARE_STATS_COUNTER(cnt_map_sg);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -95,6 +96,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&compl_wait);
amd_iommu_stats_add(&cnt_map_single);
amd_iommu_stats_add(&cnt_unmap_single);
+ amd_iommu_stats_add(&cnt_map_sg);
}

#endif
@@ -1376,6 +1378,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
int mapped_elems = 0;
u64 dma_mask;

+ INC_STATS_COUNTER(cnt_map_sg);
+
if (!check_device(dev))
return 0;

--
1.5.6.4

2008-12-15 14:23:29

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 04/22] AMD IOMMU: convert iommu->need_sync to bool

Impact: use bool instead of int for iommu->need_sync

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/include/asm/amd_iommu_types.h | 2 +-
arch/x86/kernel/amd_iommu.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index ee8cfa0..c4b144e 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -302,7 +302,7 @@ struct amd_iommu {
bool int_enabled;

/* if one, we need to send a completion wait command */
- int need_sync;
+ bool need_sync;

/* default dma_ops domain for that IOMMU */
struct dma_ops_domain *default_dom;
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index dc7cef3..8363731 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -197,7 +197,7 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
spin_lock_irqsave(&iommu->lock, flags);
ret = __iommu_queue_command(iommu, cmd);
if (!ret)
- iommu->need_sync = 1;
+ iommu->need_sync = true;
spin_unlock_irqrestore(&iommu->lock, flags);

return ret;
@@ -260,7 +260,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
if (!iommu->need_sync)
goto out;

- iommu->need_sync = 0;
+ iommu->need_sync = false;

ret = __iommu_completion_wait(iommu);

--
1.5.6.4

2008-12-15 14:23:46

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 21/22] AMD IOMMU: add statistics about allocated io memory

Impact: see amount of allocated io memory in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index be6d107..9c34902 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -73,6 +73,7 @@ DECLARE_STATS_COUNTER(cnt_free_coherent);
DECLARE_STATS_COUNTER(cross_page);
DECLARE_STATS_COUNTER(domain_flush_single);
DECLARE_STATS_COUNTER(domain_flush_all);
+DECLARE_STATS_COUNTER(alloced_io_mem);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -109,6 +110,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cross_page);
amd_iommu_stats_add(&domain_flush_single);
amd_iommu_stats_add(&domain_flush_all);
+ amd_iommu_stats_add(&alloced_io_mem);
}

#endif
@@ -1245,6 +1247,8 @@ static dma_addr_t __map_single(struct device *dev,
}
address += offset;

+ 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);
dma_dom->need_flush = false;
@@ -1281,6 +1285,8 @@ static void __unmap_single(struct amd_iommu *iommu,
start += PAGE_SIZE;
}

+ SUB_STATS_COUNTER(alloced_io_mem, size);
+
dma_ops_free_addresses(dma_dom, dma_addr, pages);

if (amd_iommu_unmap_flush || dma_dom->need_flush) {
--
1.5.6.4

2008-12-15 14:24:29

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 11/22] AMD IOMMU: add stats counter for completion wait events

Impact: see number of completion wait events in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index be1ddca..a494a98 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -63,6 +63,8 @@ static struct dma_ops_domain *find_protection_domain(u16 devid);
* Initialization code for statistics collection
*/

+DECLARE_STATS_COUNTER(compl_wait);
+
static struct dentry *stats_dir;
static struct dentry *de_isolate;
static struct dentry *de_fflush;
@@ -87,6 +89,8 @@ static void amd_iommu_stats_init(void)

de_fflush = debugfs_create_bool("fullflush", 0444, stats_dir,
(u32 *)&amd_iommu_unmap_flush);
+
+ amd_iommu_stats_add(&compl_wait);
}

#endif
@@ -248,6 +252,8 @@ static void __iommu_wait_for_completion(struct amd_iommu *iommu)
unsigned status = 0;
unsigned long i = 0;

+ INC_STATS_COUNTER(compl_wait);
+
while (!ready && (i < EXIT_LOOP_COUNT)) {
++i;
/* wait for the bit to become one */
--
1.5.6.4

2008-12-15 14:24:00

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 08/22] AMD IOMMU: add Kconfig entry for statistic collection code

Impact: adds new Kconfig entry

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/Kconfig | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b9f7187..de65e30 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -567,6 +567,16 @@ config AMD_IOMMU
your BIOS for an option to enable it or if you have an IVRS ACPI
table.

+config AMD_IOMMU_STATS
+ bool "Export AMD IOMMU statistics to debugfs"
+ depends on AMD_IOMMU
+ select DEBUG_FS
+ help
+ This option enables code in the AMD IOMMU driver to collect various
+ statistics about whats happening in the driver and exports that
+ information to userspace via debugfs.
+ If unsure, say N.
+
# need this always selected by IOMMU for the VIA workaround
config SWIOTLB
bool
--
1.5.6.4

2008-12-15 14:24:44

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 20/22] AMD IOMMU: add stats counter for domain tlb flushes

Impact: see number of domain tlb flushes in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 8490a06..be6d107 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -72,6 +72,7 @@ DECLARE_STATS_COUNTER(cnt_alloc_coherent);
DECLARE_STATS_COUNTER(cnt_free_coherent);
DECLARE_STATS_COUNTER(cross_page);
DECLARE_STATS_COUNTER(domain_flush_single);
+DECLARE_STATS_COUNTER(domain_flush_all);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -107,6 +108,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cnt_free_coherent);
amd_iommu_stats_add(&cross_page);
amd_iommu_stats_add(&domain_flush_single);
+ amd_iommu_stats_add(&domain_flush_all);
}

#endif
@@ -430,6 +432,8 @@ static void iommu_flush_domain(u16 domid)
struct amd_iommu *iommu;
struct iommu_cmd cmd;

+ INC_STATS_COUNTER(domain_flush_all);
+
__iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
domid, 1, 1);

--
1.5.6.4

2008-12-15 14:25:04

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 06/22] AMD IOMMU: use calc_devid in prealloc_protection_domains

Impact: cleanup

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 8363731..0734ae9 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1542,7 +1542,7 @@ void prealloc_protection_domains(void)
u16 devid;

while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- devid = (dev->bus->number << 8) | dev->devfn;
+ devid = calc_devid(dev->bus->number, dev->devfn);
if (devid > amd_iommu_last_bdf)
continue;
devid = amd_iommu_alias_table[devid];
--
1.5.6.4

2008-12-15 14:25:34

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 19/22] AMD IOMMU: add stats counter for single iommu domain tlb flushes

Impact: see number of single iommu domain tlb flushes in debugfs

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/kernel/amd_iommu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 02e8c18..8490a06 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -71,6 +71,7 @@ DECLARE_STATS_COUNTER(cnt_unmap_sg);
DECLARE_STATS_COUNTER(cnt_alloc_coherent);
DECLARE_STATS_COUNTER(cnt_free_coherent);
DECLARE_STATS_COUNTER(cross_page);
+DECLARE_STATS_COUNTER(domain_flush_single);

static struct dentry *stats_dir;
static struct dentry *de_isolate;
@@ -105,6 +106,7 @@ static void amd_iommu_stats_init(void)
amd_iommu_stats_add(&cnt_alloc_coherent);
amd_iommu_stats_add(&cnt_free_coherent);
amd_iommu_stats_add(&cross_page);
+ amd_iommu_stats_add(&domain_flush_single);
}

#endif
@@ -412,6 +414,8 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
{
u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;

+ INC_STATS_COUNTER(domain_flush_single);
+
iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
}

--
1.5.6.4

2008-12-15 14:25:50

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 10/22] AMD IOMMU: add init code for statistic collection

Impact: create a new debugfs directory

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/x86/include/asm/amd_iommu_types.h | 2 +
arch/x86/kernel/amd_iommu.c | 37 ++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 1379c5f..95c8cd9 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -420,6 +420,8 @@ 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 */

#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0734ae9..be1ddca 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -20,6 +20,7 @@
#include <linux/pci.h>
#include <linux/gfp.h>
#include <linux/bitops.h>
+#include <linux/debugfs.h>
#include <linux/scatterlist.h>
#include <linux/iommu-helper.h>
#ifdef CONFIG_IOMMU_API
@@ -56,6 +57,40 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
static struct dma_ops_domain *find_protection_domain(u16 devid);


+#ifdef CONFIG_AMD_IOMMU_STATS
+
+/*
+ * Initialization code for statistics collection
+ */
+
+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)
+{
+ if (stats_dir == NULL)
+ return;
+
+ cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
+ &cnt->value);
+}
+
+static void amd_iommu_stats_init(void)
+{
+ stats_dir = debugfs_create_dir("amd-iommu", NULL);
+ 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);
+}
+
+#endif
+
/* returns !0 if the IOMMU is caching non-present entries in its TLB */
static int iommu_has_npcache(struct amd_iommu *iommu)
{
@@ -1619,6 +1654,8 @@ int __init amd_iommu_init_dma_ops(void)

bus_register_notifier(&pci_bus_type, &device_nb);

+ amd_iommu_stats_init();
+
return 0;

free_domains:
--
1.5.6.4

2008-12-15 15:18:17

by David Vrabel

[permalink] [raw]
Subject: Re: [PATCH 03/22] AMD IOMMU: use dev_name instead of self-build print_devid

Joerg Roedel wrote:
> Impact: use generic dev_name instead of own function
^^^^^^
This has been bugging me for a while. This word is redundant.

David
--
David Vrabel, Senior Software Engineer, Drivers
CSR, Churchill House, Cambridge Business Park, Tel: +44 (0)1223 692562
Cowley Road, Cambridge, CB4 0WZ http://www.csr.com/

2008-12-15 15:27:19

by Joerg Roedel

[permalink] [raw]
Subject: Re: [PATCH 03/22] AMD IOMMU: use dev_name instead of self-build print_devid

On Mon, Dec 15, 2008 at 03:16:50PM +0000, David Vrabel wrote:
> Joerg Roedel wrote:
> > Impact: use generic dev_name instead of own function
> ^^^^^^
> This has been bugging me for a while. This word is redundant.

The x86 maintainers want it. I guess it is a grep-pointer or something.

--
| AMD Saxony Limited Liability Company & Co. KG
Operating | Wilschdorfer Landstr. 101, 01109 Dresden, Germany
System | Register Court Dresden: HRA 4896
Research | General Partner authorized to represent:
Center | AMD Saxony LLC (Wilmington, Delaware, US)
| General Manager of AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy