2008-08-04 16:08:37

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 0/10] introduce generic iommu_num_pages function

Hi,

this series of patches re-introduces the iommu_num_pages function so that it
can be used by each architecture specific IOMMU implementations. The series
also changes IOMMU implementations for X86, Alpha, PowerPC and UltraSparc. The
other implementations are not yet changed because the modifications required
are not obvious and I can't test them on real hardware.

The first three patches are to make this series bisectable. The changes are
compile-tested on the architectures changed and runtime tested in X86 only. The
patches apply cleanly to latest linus/master tree.

Joerg

git diff --stat linus/master:

arch/alpha/kernel/pci_iommu.c | 17 +++++------------
arch/powerpc/kernel/iommu.c | 23 +++++++----------------
arch/sparc64/kernel/iommu.c | 7 ++++---
arch/sparc64/kernel/iommu_common.h | 14 ++------------
arch/sparc64/kernel/pci_sun4v.c | 7 ++++---
arch/x86/kernel/amd_iommu.c | 9 +++++----
arch/x86/kernel/pci-calgary_64.c | 18 ++++--------------
arch/x86/kernel/pci-dma.c | 4 ++--
arch/x86/kernel/pci-gart_64.c | 8 ++++----
include/asm-x86/iommu.h | 2 +-
include/linux/iommu-helper.h | 2 ++
lib/iommu-helper.c | 9 +++++++++
12 files changed, 49 insertions(+), 71 deletions(-)



2008-08-04 16:05:20

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 04/10] introduce generic iommu_num_pages function

This patch introduces the generic iommu_num_pages function. It can be used by
different architectures to calculate the number of IOMMU pages required to map
a given memory area.

Signed-off-by: Joerg Roedel <[email protected]>
---
include/linux/iommu-helper.h | 2 ++
lib/iommu-helper.c | 9 +++++++++
2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h
index c975caf..cb659aa 100644
--- a/include/linux/iommu-helper.h
+++ b/include/linux/iommu-helper.h
@@ -8,3 +8,5 @@ extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
unsigned long align_mask);
extern void iommu_area_free(unsigned long *map, unsigned long start,
unsigned int nr);
+extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
+ unsigned long io_page_size);
diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c
index a3b8d4c..ca4a963 100644
--- a/lib/iommu-helper.c
+++ b/lib/iommu-helper.c
@@ -80,3 +80,12 @@ void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
}
}
EXPORT_SYMBOL(iommu_area_free);
+
+unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
+ unsigned long io_page_size)
+{
+ unsigned long size = (addr & (io_page_size - 1)) + len;
+
+ return DIV_ROUND_UP(size, io_page_size);
+}
+EXPORT_SYMBOL(iommu_num_pages);
--
1.5.3.7

2008-08-04 16:05:40

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 05/10] x86: convert GART driver to generic iommu_num_pages function

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

diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index cdf1c00..fa313d4 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -238,7 +238,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir)
{
- unsigned long npages = iommu_nr_pages(phys_mem, size);
+ unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
unsigned long iommu_page = alloc_iommu(dev, npages);
int i;

@@ -301,7 +301,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
return;

iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
- npages = iommu_nr_pages(dma_addr, size);
+ npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
CLEAR_LEAK(iommu_page + i);
@@ -384,7 +384,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
}

addr = phys_addr;
- pages = iommu_nr_pages(s->offset, s->length);
+ pages = iommu_num_pages(s->offset, s->length, PAGE_SIZE);
while (pages--) {
iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
SET_LEAK(iommu_page);
@@ -467,7 +467,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)

seg_size += s->length;
need = nextneed;
- pages += iommu_nr_pages(s->offset, s->length);
+ pages += iommu_num_pages(s->offset, s->length, PAGE_SIZE);
ps = s;
}
if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
--
1.5.3.7

2008-08-04 16:05:55

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 08/10] powerpc: use iommu_num_pages function in IOMMU code

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/powerpc/kernel/iommu.c | 23 +++++++----------------
1 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index e2cf632..ea1ba89 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -51,17 +51,6 @@ static int protect4gb = 1;

static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int);

-static inline unsigned long iommu_nr_pages(unsigned long vaddr,
- unsigned long slen)
-{
- unsigned long npages;
-
- npages = IOMMU_PAGE_ALIGN(vaddr + slen) - (vaddr & IOMMU_PAGE_MASK);
- npages >>= IOMMU_PAGE_SHIFT;
-
- return npages;
-}
-
static int __init setup_protect4gb(char *str)
{
if (strcmp(str, "on") == 0)
@@ -325,7 +314,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
}
/* Allocate iommu entries for that segment */
vaddr = (unsigned long) sg_virt(s);
- npages = iommu_nr_pages(vaddr, slen);
+ npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE);
align = 0;
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
(vaddr & ~PAGE_MASK) == 0)
@@ -418,7 +407,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
unsigned long vaddr, npages;

vaddr = s->dma_address & IOMMU_PAGE_MASK;
- npages = iommu_nr_pages(s->dma_address, s->dma_length);
+ npages = iommu_num_pages(s->dma_address, s->dma_length,
+ IOMMU_PAGE_SIZE);
__iommu_free(tbl, vaddr, npages);
s->dma_address = DMA_ERROR_CODE;
s->dma_length = 0;
@@ -452,7 +442,8 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,

if (sg->dma_length == 0)
break;
- npages = iommu_nr_pages(dma_handle, sg->dma_length);
+ npages = iommu_num_pages(dma_handle, sg->dma_length,
+ IOMMU_PAGE_SIZE);
__iommu_free(tbl, dma_handle, npages);
sg = sg_next(sg);
}
@@ -584,7 +575,7 @@ dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
BUG_ON(direction == DMA_NONE);

uaddr = (unsigned long)vaddr;
- npages = iommu_nr_pages(uaddr, size);
+ npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE);

if (tbl) {
align = 0;
@@ -617,7 +608,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
BUG_ON(direction == DMA_NONE);

if (tbl) {
- npages = iommu_nr_pages(dma_handle, size);
+ npages = iommu_num_pages(dma_handle, size, IOMMU_PAGE_SIZE);
iommu_free(tbl, dma_handle, npages);
}
}
--
1.5.3.7

2008-08-04 16:06:16

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 09/10] alpha: use iommu_num_pages function in IOMMU code

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

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 2179c60..b9094da 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -41,13 +41,6 @@ mk_iommu_pte(unsigned long paddr)
return (paddr >> (PAGE_SHIFT-1)) | 1;
}

-static inline long
-calc_npages(long bytes)
-{
- return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
-}
-
-
/* Return the minimum of MAX or the first power of two larger
than main memory. */

@@ -287,7 +280,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;

- npages = calc_npages((paddr & ~PAGE_MASK) + size);
+ npages = iommu_num_pages(paddr, size, PAGE_SIZE);

/* Force allocation to 64KB boundary for ISA bridges. */
if (pdev && pdev == isa_bridge)
@@ -387,7 +380,7 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
BUG();
}

- npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
+ npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);

spin_lock_irqsave(&arena->lock, flags);

@@ -580,7 +573,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
contiguous. */

paddr &= ~PAGE_MASK;
- npages = calc_npages(paddr + size);
+ npages = iommu_num_pages(paddr, size, PAGE_SIZE);
dma_ofs = iommu_arena_alloc(dev, arena, npages, 0);
if (dma_ofs < 0) {
/* If we attempted a direct map above but failed, die. */
@@ -616,7 +609,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
sg++;
}

- npages = calc_npages((paddr & ~PAGE_MASK) + size);
+ npages = iommu_num_pages(paddr, size, PAGE_SIZE);

paddr &= PAGE_MASK;
for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
@@ -775,7 +768,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
DBGA(" (%ld) sg [%lx,%lx]\n",
sg - end + nents, addr, size);

- npages = calc_npages((addr & ~PAGE_MASK) + size);
+ npages = iommu_num_pages(addr, size, PAGE_SIZE);
ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
iommu_arena_free(arena, ofs, npages);

--
1.5.3.7

2008-08-04 16:06:49

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 01/10] x86: rename iommu_num_pages function to iommu_nr_pages

This is a preparation patch for introducing a generic iommu_num_pages function.

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

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 22d7d05..f211341 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -182,7 +182,7 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
u64 address, size_t size)
{
int s = 0;
- unsigned pages = iommu_num_pages(address, size);
+ unsigned pages = iommu_nr_pages(address, size);

address &= PAGE_MASK;

@@ -554,7 +554,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
if (iommu->exclusion_start &&
iommu->exclusion_start < dma_dom->aperture_size) {
unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
- int pages = iommu_num_pages(iommu->exclusion_start,
+ int pages = iommu_nr_pages(iommu->exclusion_start,
iommu->exclusion_length);
dma_ops_reserve_addresses(dma_dom, startpage, pages);
}
@@ -764,7 +764,7 @@ static dma_addr_t __map_single(struct device *dev,
unsigned int pages;
int i;

- pages = iommu_num_pages(paddr, size);
+ pages = iommu_nr_pages(paddr, size);
paddr &= PAGE_MASK;

address = dma_ops_alloc_addresses(dev, dma_dom, pages);
@@ -799,7 +799,7 @@ static void __unmap_single(struct amd_iommu *iommu,
if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size))
return;

- pages = iommu_num_pages(dma_addr, size);
+ pages = iommu_nr_pages(dma_addr, size);
dma_addr &= PAGE_MASK;
start = dma_addr;

diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 87d4d69..9e46c71 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -124,13 +124,13 @@ void __init pci_iommu_alloc(void)
pci_swiotlb_init();
}

-unsigned long iommu_num_pages(unsigned long addr, unsigned long len)
+unsigned long iommu_nr_pages(unsigned long addr, unsigned long len)
{
unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);

return size >> PAGE_SHIFT;
}
-EXPORT_SYMBOL(iommu_num_pages);
+EXPORT_SYMBOL(iommu_nr_pages);
#endif

/*
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 49285f8..cdf1c00 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -238,7 +238,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir)
{
- unsigned long npages = iommu_num_pages(phys_mem, size);
+ unsigned long npages = iommu_nr_pages(phys_mem, size);
unsigned long iommu_page = alloc_iommu(dev, npages);
int i;

@@ -301,7 +301,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
return;

iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
- npages = iommu_num_pages(dma_addr, size);
+ npages = iommu_nr_pages(dma_addr, size);
for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
CLEAR_LEAK(iommu_page + i);
@@ -384,7 +384,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
}

addr = phys_addr;
- pages = iommu_num_pages(s->offset, s->length);
+ pages = iommu_nr_pages(s->offset, s->length);
while (pages--) {
iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
SET_LEAK(iommu_page);
@@ -467,7 +467,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)

seg_size += s->length;
need = nextneed;
- pages += iommu_num_pages(s->offset, s->length);
+ pages += iommu_nr_pages(s->offset, s->length);
ps = s;
}
if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h
index 5f888cc..61d64e4 100644
--- a/include/asm-x86/iommu.h
+++ b/include/asm-x86/iommu.h
@@ -7,7 +7,7 @@ extern struct dma_mapping_ops nommu_dma_ops;
extern int force_iommu, no_iommu;
extern int iommu_detected;

-extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len);
+extern unsigned long iommu_nr_pages(unsigned long addr, unsigned long len);

#ifdef CONFIG_GART_IOMMU
extern int gart_iommu_aperture;
--
1.5.3.7

2008-08-04 16:06:32

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 07/10] x86: convert Calgary IOMMU driver to generic iommu_num_pages function

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

diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index b67a4b1..1fbba8a 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -217,16 +217,6 @@ static inline unsigned long verify_bit_range(unsigned long* bitmap,

#endif /* CONFIG_IOMMU_DEBUG */

-static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
-{
- unsigned int npages;
-
- npages = PAGE_ALIGN(dma + dmalen) - (dma & PAGE_MASK);
- npages >>= PAGE_SHIFT;
-
- return npages;
-}
-
static inline int translation_enabled(struct iommu_table *tbl)
{
/* only PHBs with translation enabled have an IOMMU table */
@@ -409,7 +399,7 @@ static void calgary_unmap_sg(struct device *dev,
if (dmalen == 0)
break;

- npages = num_dma_pages(dma, dmalen);
+ npages = iommu_num_pages(dma, dmalen, PAGE_SIZE);
iommu_free(tbl, dma, npages);
}
}
@@ -428,7 +418,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
BUG_ON(!sg_page(s));

vaddr = (unsigned long) sg_virt(s);
- npages = num_dma_pages(vaddr, s->length);
+ npages = iommu_num_pages(vaddr, s->length, PAGE_SIZE);

entry = iommu_range_alloc(dev, tbl, npages);
if (entry == bad_dma_address) {
@@ -465,7 +455,7 @@ static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
struct iommu_table *tbl = find_iommu_table(dev);

uaddr = (unsigned long)vaddr;
- npages = num_dma_pages(uaddr, size);
+ npages = iommu_num_pages(uaddr, size, PAGE_SIZE);

return iommu_alloc(dev, tbl, vaddr, npages, direction);
}
@@ -476,7 +466,7 @@ static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
struct iommu_table *tbl = find_iommu_table(dev);
unsigned int npages;

- npages = num_dma_pages(dma_handle, size);
+ npages = iommu_num_pages(dma_handle, size, PAGE_SIZE);
iommu_free(tbl, dma_handle, npages);
}

--
1.5.3.7

2008-08-04 16:07:16

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 02/10] sparc64: rename iommu_num_pages function to iommu_nr_pages

This is a preparation patch for introducing a generic iommu_num_pages function.

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/sparc64/kernel/iommu.c | 6 +++---
arch/sparc64/kernel/iommu_common.h | 4 ++--
arch/sparc64/kernel/pci_sun4v.c | 6 +++---
3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 2a37a6c..f73b238 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -575,7 +575,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
}
/* Allocate iommu entries for that segment */
paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
- npages = iommu_num_pages(paddr, slen);
+ npages = iommu_nr_pages(paddr, slen);
entry = iommu_range_alloc(dev, iommu, npages, &handle);

/* Handle failure */
@@ -647,7 +647,7 @@ iommu_map_failed:
iopte_t *base;

vaddr = s->dma_address & IO_PAGE_MASK;
- npages = iommu_num_pages(s->dma_address, s->dma_length);
+ npages = iommu_nr_pages(s->dma_address, s->dma_length);
iommu_range_free(iommu, vaddr, npages);

entry = (vaddr - iommu->page_table_map_base)
@@ -715,7 +715,7 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,

if (!len)
break;
- npages = iommu_num_pages(dma_handle, len);
+ npages = iommu_nr_pages(dma_handle, len);
iommu_range_free(iommu, dma_handle, npages);

entry = ((dma_handle - iommu->page_table_map_base)
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 53b19c8..202d8ae 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -35,7 +35,7 @@

#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))

-static inline unsigned long iommu_num_pages(unsigned long vaddr,
+static inline unsigned long iommu_nr_pages(unsigned long vaddr,
unsigned long slen)
{
unsigned long npages;
@@ -53,7 +53,7 @@ static inline int is_span_boundary(unsigned long entry,
struct scatterlist *sg)
{
unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs);
- int nr = iommu_num_pages(paddr, outs->dma_length + sg->length);
+ int nr = iommu_nr_pages(paddr, outs->dma_length + sg->length);

return iommu_is_span_boundary(entry, nr, shift, boundary_size);
}
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index a104c80..6a53c31 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -382,7 +382,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
}
/* Allocate iommu entries for that segment */
paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
- npages = iommu_num_pages(paddr, slen);
+ npages = iommu_nr_pages(paddr, slen);
entry = iommu_range_alloc(dev, iommu, npages, &handle);

/* Handle failure */
@@ -459,7 +459,7 @@ iommu_map_failed:
unsigned long vaddr, npages;

vaddr = s->dma_address & IO_PAGE_MASK;
- npages = iommu_num_pages(s->dma_address, s->dma_length);
+ npages = iommu_nr_pages(s->dma_address, s->dma_length);
iommu_range_free(iommu, vaddr, npages);
/* XXX demap? XXX */
s->dma_address = DMA_ERROR_CODE;
@@ -498,7 +498,7 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,

if (!len)
break;
- npages = iommu_num_pages(dma_handle, len);
+ npages = iommu_nr_pages(dma_handle, len);
iommu_range_free(iommu, dma_handle, npages);

entry = ((dma_handle - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
--
1.5.3.7

2008-08-04 16:07:57

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 10/10] sparc64: use iommu_num_pages function in IOMMU code

Signed-off-by: Joerg Roedel <[email protected]>
---
arch/sparc64/kernel/iommu.c | 7 ++++---
arch/sparc64/kernel/iommu_common.h | 14 ++------------
arch/sparc64/kernel/pci_sun4v.c | 7 ++++---
3 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index f73b238..1cc1995 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -575,7 +575,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
}
/* Allocate iommu entries for that segment */
paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
- npages = iommu_nr_pages(paddr, slen);
+ npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
entry = iommu_range_alloc(dev, iommu, npages, &handle);

/* Handle failure */
@@ -647,7 +647,8 @@ iommu_map_failed:
iopte_t *base;

vaddr = s->dma_address & IO_PAGE_MASK;
- npages = iommu_nr_pages(s->dma_address, s->dma_length);
+ npages = iommu_num_pages(s->dma_address, s->dma_length,
+ IO_PAGE_SIZE);
iommu_range_free(iommu, vaddr, npages);

entry = (vaddr - iommu->page_table_map_base)
@@ -715,7 +716,7 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,

if (!len)
break;
- npages = iommu_nr_pages(dma_handle, len);
+ npages = iommu_num_pages(dma_handle, len, IO_PAGE_SIZE);
iommu_range_free(iommu, dma_handle, npages);

entry = ((dma_handle - iommu->page_table_map_base)
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 202d8ae..591f587 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -35,17 +35,6 @@

#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))

-static inline unsigned long iommu_nr_pages(unsigned long vaddr,
- unsigned long slen)
-{
- unsigned long npages;
-
- npages = IO_PAGE_ALIGN(vaddr + slen) - (vaddr & IO_PAGE_MASK);
- npages >>= IO_PAGE_SHIFT;
-
- return npages;
-}
-
static inline int is_span_boundary(unsigned long entry,
unsigned long shift,
unsigned long boundary_size,
@@ -53,7 +42,8 @@ static inline int is_span_boundary(unsigned long entry,
struct scatterlist *sg)
{
unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs);
- int nr = iommu_nr_pages(paddr, outs->dma_length + sg->length);
+ int nr = iommu_num_pages(paddr, outs->dma_length + sg->length,
+ IO_PAGE_SIZE);

return iommu_is_span_boundary(entry, nr, shift, boundary_size);
}
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 6a53c31..2e2a03c 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -382,7 +382,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
}
/* Allocate iommu entries for that segment */
paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
- npages = iommu_nr_pages(paddr, slen);
+ npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
entry = iommu_range_alloc(dev, iommu, npages, &handle);

/* Handle failure */
@@ -459,7 +459,8 @@ iommu_map_failed:
unsigned long vaddr, npages;

vaddr = s->dma_address & IO_PAGE_MASK;
- npages = iommu_nr_pages(s->dma_address, s->dma_length);
+ npages = iommu_num_pages(s->dma_address, s->dma_length,
+ IO_PAGE_SIZE);
iommu_range_free(iommu, vaddr, npages);
/* XXX demap? XXX */
s->dma_address = DMA_ERROR_CODE;
@@ -498,7 +499,7 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,

if (!len)
break;
- npages = iommu_nr_pages(dma_handle, len);
+ npages = iommu_num_pages(dma_handle, len, IO_PAGE_SIZE);
iommu_range_free(iommu, dma_handle, npages);

entry = ((dma_handle - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
--
1.5.3.7

2008-08-04 16:07:42

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 06/10] x86, AMD IOMMU: convert driver to generic iommu_num_pages function

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

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index f211341..108e003 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -182,7 +182,7 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
u64 address, size_t size)
{
int s = 0;
- unsigned pages = iommu_nr_pages(address, size);
+ unsigned pages = iommu_num_pages(address, size, PAGE_SIZE);

address &= PAGE_MASK;

@@ -554,8 +554,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
if (iommu->exclusion_start &&
iommu->exclusion_start < dma_dom->aperture_size) {
unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
- int pages = iommu_nr_pages(iommu->exclusion_start,
- iommu->exclusion_length);
+ int pages = iommu_num_pages(iommu->exclusion_start,
+ iommu->exclusion_length,
+ PAGE_SIZE);
dma_ops_reserve_addresses(dma_dom, startpage, pages);
}

@@ -764,7 +765,7 @@ static dma_addr_t __map_single(struct device *dev,
unsigned int pages;
int i;

- pages = iommu_nr_pages(paddr, size);
+ pages = iommu_num_pages(paddr, size, PAGE_SIZE);
paddr &= PAGE_MASK;

address = dma_ops_alloc_addresses(dev, dma_dom, pages);
@@ -799,7 +800,7 @@ static void __unmap_single(struct amd_iommu *iommu,
if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size))
return;

- pages = iommu_nr_pages(dma_addr, size);
+ pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
dma_addr &= PAGE_MASK;
start = dma_addr;

--
1.5.3.7

2008-08-04 16:08:20

by Joerg Roedel

[permalink] [raw]
Subject: [PATCH 03/10] powerpc: rename iommu_num_pages function to iommu_nr_pages

This is a preparation patch for introducing a generic iommu_num_pages function.

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

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 550a193..e2cf632 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -51,7 +51,7 @@ static int protect4gb = 1;

static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int);

-static inline unsigned long iommu_num_pages(unsigned long vaddr,
+static inline unsigned long iommu_nr_pages(unsigned long vaddr,
unsigned long slen)
{
unsigned long npages;
@@ -325,7 +325,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
}
/* Allocate iommu entries for that segment */
vaddr = (unsigned long) sg_virt(s);
- npages = iommu_num_pages(vaddr, slen);
+ npages = iommu_nr_pages(vaddr, slen);
align = 0;
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
(vaddr & ~PAGE_MASK) == 0)
@@ -418,7 +418,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
unsigned long vaddr, npages;

vaddr = s->dma_address & IOMMU_PAGE_MASK;
- npages = iommu_num_pages(s->dma_address, s->dma_length);
+ npages = iommu_nr_pages(s->dma_address, s->dma_length);
__iommu_free(tbl, vaddr, npages);
s->dma_address = DMA_ERROR_CODE;
s->dma_length = 0;
@@ -452,7 +452,7 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,

if (sg->dma_length == 0)
break;
- npages = iommu_num_pages(dma_handle, sg->dma_length);
+ npages = iommu_nr_pages(dma_handle, sg->dma_length);
__iommu_free(tbl, dma_handle, npages);
sg = sg_next(sg);
}
@@ -584,7 +584,7 @@ dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
BUG_ON(direction == DMA_NONE);

uaddr = (unsigned long)vaddr;
- npages = iommu_num_pages(uaddr, size);
+ npages = iommu_nr_pages(uaddr, size);

if (tbl) {
align = 0;
@@ -617,7 +617,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
BUG_ON(direction == DMA_NONE);

if (tbl) {
- npages = iommu_num_pages(dma_handle, size);
+ npages = iommu_nr_pages(dma_handle, size);
iommu_free(tbl, dma_handle, npages);
}
}
--
1.5.3.7

2008-08-04 16:11:25

by Muli Ben-Yehuda

[permalink] [raw]
Subject: Re: [PATCH 07/10] x86: convert Calgary IOMMU driver to generic iommu_num_pages function

On Mon, Aug 04, 2008 at 06:04:47PM +0200, Joerg Roedel wrote:

> Signed-off-by: Joerg Roedel <[email protected]>

Acked-by: Muli Ben-Yehdua <[email protected]>

Cheers,
Muli

2008-08-04 21:27:56

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 02/10] sparc64: rename iommu_num_pages function to iommu_nr_pages

From: Joerg Roedel <[email protected]>
Date: Mon, 4 Aug 2008 18:04:42 +0200

> @@ -35,7 +35,7 @@
>
> #define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
>
> -static inline unsigned long iommu_num_pages(unsigned long vaddr,
> +static inline unsigned long iommu_nr_pages(unsigned long vaddr,
> unsigned long slen)

Please, when you change the name of a function, fix up the indentation
of the arguments in the following lines of the declaration so that they
still line up properly.

2008-08-04 21:28:45

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 10/10] sparc64: use iommu_num_pages function in IOMMU code

From: Joerg Roedel <[email protected]>
Date: Mon, 4 Aug 2008 18:04:50 +0200

> Signed-off-by: Joerg Roedel <[email protected]>

So we rename, then convert everything back.

This seems like a lot of commit masterbation for what is
clearly one single change.

2008-08-05 01:29:40

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 0/10] introduce generic iommu_num_pages function

On Mon, 2008-08-04 at 18:04 +0200, Joerg Roedel wrote:
> Hi,
>
> this series of patches re-introduces the iommu_num_pages function so that it
> can be used by each architecture specific IOMMU implementations. The series
> also changes IOMMU implementations for X86, Alpha, PowerPC and UltraSparc. The
> other implementations are not yet changed because the modifications required
> are not obvious and I can't test them on real hardware.
>
> The first three patches are to make this series bisectable. The changes are
> compile-tested on the architectures changed and runtime tested in X86 only. The
> patches apply cleanly to latest linus/master tree.

Had a quick look, it seems allright to me.

Ben.

> Joerg
>
> git diff --stat linus/master:
>
> arch/alpha/kernel/pci_iommu.c | 17 +++++------------
> arch/powerpc/kernel/iommu.c | 23 +++++++----------------
> arch/sparc64/kernel/iommu.c | 7 ++++---
> arch/sparc64/kernel/iommu_common.h | 14 ++------------
> arch/sparc64/kernel/pci_sun4v.c | 7 ++++---
> arch/x86/kernel/amd_iommu.c | 9 +++++----
> arch/x86/kernel/pci-calgary_64.c | 18 ++++--------------
> arch/x86/kernel/pci-dma.c | 4 ++--
> arch/x86/kernel/pci-gart_64.c | 8 ++++----
> include/asm-x86/iommu.h | 2 +-
> include/linux/iommu-helper.h | 2 ++
> lib/iommu-helper.c | 9 +++++++++
> 12 files changed, 49 insertions(+), 71 deletions(-)
>
>

2008-08-05 01:35:45

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 10/10] sparc64: use iommu_num_pages function in IOMMU code

On Mon, 2008-08-04 at 14:28 -0700, David Miller wrote:
> From: Joerg Roedel <[email protected]>
> Date: Mon, 4 Aug 2008 18:04:50 +0200
>
> > Signed-off-by: Joerg Roedel <[email protected]>
>
> So we rename, then convert everything back.
>
> This seems like a lot of commit masterbation for what is
> clearly one single change.

Yup, I wouldn't mind a single patch doing the whole thing at once.

Ben.

2008-08-05 02:10:33

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 10/10] sparc64: use iommu_num_pages function in IOMMU code

On Mon, 04 Aug 2008 14:28:34 -0700 (PDT)
David Miller <[email protected]> wrote:

> From: Joerg Roedel <[email protected]>
> Date: Mon, 4 Aug 2008 18:04:50 +0200
>
> > Signed-off-by: Joerg Roedel <[email protected]>
>
> So we rename, then convert everything back.
>
> This seems like a lot of commit masterbation for what is
> clearly one single change.

The first patch adds a helper function, iommu_nr_pages(). Then the
following patches (or a single patch) convert all the IOMMUs to use
it.

If we really like 'iommu_num_pages' function name, then a single patch
can replace all iommu_nr_pages().

2008-08-05 08:06:20

by Joerg Roedel

[permalink] [raw]
Subject: Re: [PATCH 10/10] sparc64: use iommu_num_pages function in IOMMU code

On Mon, Aug 04, 2008 at 02:28:34PM -0700, David Miller wrote:
> From: Joerg Roedel <[email protected]>
> Date: Mon, 4 Aug 2008 18:04:50 +0200
>
> > Signed-off-by: Joerg Roedel <[email protected]>
>
> So we rename, then convert everything back.
>
> This seems like a lot of commit masterbation for what is
> clearly one single change.

I didn't want to change multiple architectures with a single patch so I
splitted it up. The whole renaming in the beginning is to make the patch
series bisectable. But if its no problem to change multiple
architectures with one patch I will those changes in a single patch next
time.

Joerg

--
| 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

2008-08-05 08:26:40

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 10/10] sparc64: use iommu_num_pages function in IOMMU code


> I didn't want to change multiple architectures with a single patch so I
> splitted it up. The whole renaming in the beginning is to make the patch
> series bisectable. But if its no problem to change multiple
> architectures with one patch I will those changes in a single patch next
> time.

I wouldn't say there's a strict rule. It's a balance to find between
the complexity of the patch, the risk of breaking archs, etc...

In your case, the added churn of going through a temporary renamed
helper represents more, imho, than the risk of breakage of what is
a fairly trivial patch in the first place. Also, it only affects a few
archs. So it's simpler or everybody to deal with a single patch even if
that means it -might- need a rev or two in case it does indeed break
something...

Ben.