Skip to content

Commit f3cc4f8

Browse files
niklas88joergroedel
authored andcommitted
iommu/s390: Implement map_pages()/unmap_pages() instead of map()/unmap()
While s390-iommu currently implements the map_page()/unmap_page() operations which only map/unmap a single page at a time the internal s390_iommu_update_trans() API already supports mapping/unmapping a range of pages at once. Take advantage of this by implementing the map_pages()/unmap_pages() operations instead thus allowing users of the IOMMU drivers to map multiple pages in a single call followed by a single I/O TLB flush if needed. Reviewed-by: Matthew Rosato <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Niklas Schnelle <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent b4d8ae0 commit f3cc4f8

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

drivers/iommu/s390-iommu.c

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,15 @@ static void s390_iommu_release_device(struct device *dev)
196196

197197
static int s390_iommu_update_trans(struct s390_domain *s390_domain,
198198
phys_addr_t pa, dma_addr_t dma_addr,
199-
size_t size, int flags)
199+
unsigned long nr_pages, int flags)
200200
{
201201
phys_addr_t page_addr = pa & PAGE_MASK;
202202
dma_addr_t start_dma_addr = dma_addr;
203-
unsigned long irq_flags, nr_pages, i;
203+
unsigned long irq_flags, i;
204204
struct zpci_dev *zdev;
205205
unsigned long *entry;
206206
int rc = 0;
207207

208-
if (dma_addr < s390_domain->domain.geometry.aperture_start ||
209-
(dma_addr + size - 1) > s390_domain->domain.geometry.aperture_end)
210-
return -EINVAL;
211-
212-
nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
213208
if (!nr_pages)
214209
return 0;
215210

@@ -252,11 +247,24 @@ static int s390_iommu_update_trans(struct s390_domain *s390_domain,
252247
return rc;
253248
}
254249

255-
static int s390_iommu_map(struct iommu_domain *domain, unsigned long iova,
256-
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
250+
static int s390_iommu_map_pages(struct iommu_domain *domain,
251+
unsigned long iova, phys_addr_t paddr,
252+
size_t pgsize, size_t pgcount,
253+
int prot, gfp_t gfp, size_t *mapped)
257254
{
258255
struct s390_domain *s390_domain = to_s390_domain(domain);
259256
int flags = ZPCI_PTE_VALID, rc = 0;
257+
size_t size = pgcount << __ffs(pgsize);
258+
259+
if (pgsize != SZ_4K)
260+
return -EINVAL;
261+
262+
if (iova < s390_domain->domain.geometry.aperture_start ||
263+
(iova + size - 1) > s390_domain->domain.geometry.aperture_end)
264+
return -EINVAL;
265+
266+
if (!IS_ALIGNED(iova | paddr, pgsize))
267+
return -EINVAL;
260268

261269
if (!(prot & IOMMU_READ))
262270
return -EINVAL;
@@ -265,7 +273,9 @@ static int s390_iommu_map(struct iommu_domain *domain, unsigned long iova,
265273
flags |= ZPCI_TABLE_PROTECTED;
266274

267275
rc = s390_iommu_update_trans(s390_domain, paddr, iova,
268-
size, flags);
276+
pgcount, flags);
277+
if (!rc)
278+
*mapped = size;
269279

270280
return rc;
271281
}
@@ -301,21 +311,27 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
301311
return phys;
302312
}
303313

304-
static size_t s390_iommu_unmap(struct iommu_domain *domain,
305-
unsigned long iova, size_t size,
306-
struct iommu_iotlb_gather *gather)
314+
static size_t s390_iommu_unmap_pages(struct iommu_domain *domain,
315+
unsigned long iova,
316+
size_t pgsize, size_t pgcount,
317+
struct iommu_iotlb_gather *gather)
307318
{
308319
struct s390_domain *s390_domain = to_s390_domain(domain);
320+
size_t size = pgcount << __ffs(pgsize);
309321
int flags = ZPCI_PTE_INVALID;
310322
phys_addr_t paddr;
311323
int rc;
312324

325+
if (WARN_ON(iova < s390_domain->domain.geometry.aperture_start ||
326+
(iova + size - 1) > s390_domain->domain.geometry.aperture_end))
327+
return 0;
328+
313329
paddr = s390_iommu_iova_to_phys(domain, iova);
314330
if (!paddr)
315331
return 0;
316332

317333
rc = s390_iommu_update_trans(s390_domain, paddr, iova,
318-
size, flags);
334+
pgcount, flags);
319335
if (rc)
320336
return 0;
321337

@@ -361,8 +377,8 @@ static const struct iommu_ops s390_iommu_ops = {
361377
.default_domain_ops = &(const struct iommu_domain_ops) {
362378
.attach_dev = s390_iommu_attach_device,
363379
.detach_dev = s390_iommu_detach_device,
364-
.map = s390_iommu_map,
365-
.unmap = s390_iommu_unmap,
380+
.map_pages = s390_iommu_map_pages,
381+
.unmap_pages = s390_iommu_unmap_pages,
366382
.iova_to_phys = s390_iommu_iova_to_phys,
367383
.free = s390_domain_free,
368384
}

0 commit comments

Comments
 (0)