Skip to content

Commit

Permalink
iommu/core: stop converting bytes to page order back and forth
Browse files Browse the repository at this point in the history
Express sizes in bytes rather than in page order, to eliminate the
size->order->size conversions we have whenever the IOMMU API is calling
the low level drivers' map/unmap methods.

Adopt all existing drivers.

Signed-off-by: Ohad Ben-Cohen <[email protected]>
Cc: David Brown <[email protected]>
Cc: David Woodhouse <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Stepan Moskovchenko <[email protected]>
Cc: KyongHo Cho <[email protected]>
Cc: Hiroshi DOYU <[email protected]>
Cc: Laurent Pinchart <[email protected]>
Signed-off-by: Joerg Roedel <[email protected]>
  • Loading branch information
ohadbc authored and Joerg Roedel committed Nov 10, 2011
1 parent 1ea6b8f commit 5009065
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 42 deletions.
13 changes: 5 additions & 8 deletions drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2702,9 +2702,8 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
}

static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
phys_addr_t paddr, int gfp_order, int iommu_prot)
phys_addr_t paddr, size_t page_size, int iommu_prot)
{
unsigned long page_size = 0x1000UL << gfp_order;
struct protection_domain *domain = dom->priv;
int prot = 0;
int ret;
Expand All @@ -2721,21 +2720,19 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
return ret;
}

static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
int gfp_order)
static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
size_t page_size)
{
struct protection_domain *domain = dom->priv;
unsigned long page_size, unmap_size;

page_size = 0x1000UL << gfp_order;
size_t unmap_size;

mutex_lock(&domain->api_lock);
unmap_size = iommu_unmap_page(domain, iova, page_size);
mutex_unlock(&domain->api_lock);

domain_flush_tlb_pde(domain);

return get_order(unmap_size);
return unmap_size;
}

static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
Expand Down
11 changes: 4 additions & 7 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3979,12 +3979,11 @@ static void intel_iommu_detach_device(struct iommu_domain *domain,

static int intel_iommu_map(struct iommu_domain *domain,
unsigned long iova, phys_addr_t hpa,
int gfp_order, int iommu_prot)
size_t size, int iommu_prot)
{
struct dmar_domain *dmar_domain = domain->priv;
u64 max_addr;
int prot = 0;
size_t size;
int ret;

if (iommu_prot & IOMMU_READ)
Expand All @@ -3994,7 +3993,6 @@ static int intel_iommu_map(struct iommu_domain *domain,
if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
prot |= DMA_PTE_SNP;

size = PAGE_SIZE << gfp_order;
max_addr = iova + size;
if (dmar_domain->max_addr < max_addr) {
u64 end;
Expand All @@ -4017,11 +4015,10 @@ static int intel_iommu_map(struct iommu_domain *domain,
return ret;
}

static int intel_iommu_unmap(struct iommu_domain *domain,
unsigned long iova, int gfp_order)
static size_t intel_iommu_unmap(struct iommu_domain *domain,
unsigned long iova, size_t size)
{
struct dmar_domain *dmar_domain = domain->priv;
size_t size = PAGE_SIZE << gfp_order;
int order;

order = dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
Expand All @@ -4030,7 +4027,7 @@ static int intel_iommu_unmap(struct iommu_domain *domain,
if (dmar_domain->max_addr == iova + size)
dmar_domain->max_addr = iova;

return order;
return PAGE_SIZE << order;
}

static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Expand Down
8 changes: 5 additions & 3 deletions drivers/iommu/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,13 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,

BUG_ON(!IS_ALIGNED(iova | paddr, size));

return domain->ops->map(domain, iova, paddr, gfp_order, prot);
return domain->ops->map(domain, iova, paddr, size, prot);
}
EXPORT_SYMBOL_GPL(iommu_map);

int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
{
size_t size;
size_t size, unmapped;

if (unlikely(domain->ops->unmap == NULL))
return -ENODEV;
Expand All @@ -183,6 +183,8 @@ int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)

BUG_ON(!IS_ALIGNED(iova, size));

return domain->ops->unmap(domain, iova, gfp_order);
unmapped = domain->ops->unmap(domain, iova, size);

return get_order(unmapped);
}
EXPORT_SYMBOL_GPL(iommu_unmap);
19 changes: 7 additions & 12 deletions drivers/iommu/msm_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
}

static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
phys_addr_t pa, int order, int prot)
phys_addr_t pa, size_t len, int prot)
{
struct msm_priv *priv;
unsigned long flags;
Expand All @@ -363,7 +363,6 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
unsigned long *sl_pte;
unsigned long sl_offset;
unsigned int pgprot;
size_t len = 0x1000UL << order;
int ret = 0, tex, sh;

spin_lock_irqsave(&msm_iommu_lock, flags);
Expand Down Expand Up @@ -463,8 +462,8 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
return ret;
}

static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
int order)
static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
size_t len)
{
struct msm_priv *priv;
unsigned long flags;
Expand All @@ -474,7 +473,6 @@ static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
unsigned long *sl_table;
unsigned long *sl_pte;
unsigned long sl_offset;
size_t len = 0x1000UL << order;
int i, ret = 0;

spin_lock_irqsave(&msm_iommu_lock, flags);
Expand Down Expand Up @@ -544,15 +542,12 @@ static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,

ret = __flush_iotlb(domain);

/*
* the IOMMU API requires us to return the order of the unmapped
* page (on success).
*/
if (!ret)
ret = order;
fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret;

/* the IOMMU API requires us to return how many bytes were unmapped */
len = ret ? 0 : len;
return len;
}

static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
Expand Down
14 changes: 5 additions & 9 deletions drivers/iommu/omap-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1019,12 +1019,11 @@ static void iopte_cachep_ctor(void *iopte)
}

static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
phys_addr_t pa, int order, int prot)
phys_addr_t pa, size_t bytes, int prot)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct omap_iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
size_t bytes = PAGE_SIZE << order;
struct iotlb_entry e;
int omap_pgsz;
u32 ret, flags;
Expand All @@ -1049,19 +1048,16 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
return ret;
}

static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
int order)
static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
size_t size)
{
struct omap_iommu_domain *omap_domain = domain->priv;
struct omap_iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
size_t unmap_size;

dev_dbg(dev, "unmapping da 0x%lx order %d\n", da, order);
dev_dbg(dev, "unmapping da 0x%lx size %u\n", da, size);

unmap_size = iopgtable_clear_entry(oiommu, da);

return unmap_size ? get_order(unmap_size) : -EINVAL;
return iopgtable_clear_entry(oiommu, da);
}

static int
Expand Down
6 changes: 3 additions & 3 deletions include/linux/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ struct iommu_ops {
int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
int (*map)(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, int gfp_order, int prot);
int (*unmap)(struct iommu_domain *domain, unsigned long iova,
int gfp_order);
phys_addr_t paddr, size_t size, int prot);
size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
size_t size);
phys_addr_t (*iova_to_phys)(struct iommu_domain *domain,
unsigned long iova);
int (*domain_has_cap)(struct iommu_domain *domain,
Expand Down

0 comments on commit 5009065

Please sign in to comment.