@@ -2376,11 +2376,11 @@ phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
2376
2376
EXPORT_SYMBOL_GPL (iommu_iova_to_phys );
2377
2377
2378
2378
static size_t iommu_pgsize (struct iommu_domain * domain , unsigned long iova ,
2379
- phys_addr_t paddr , size_t size )
2379
+ phys_addr_t paddr , size_t size , size_t * count )
2380
2380
{
2381
- unsigned int pgsize_idx ;
2381
+ unsigned int pgsize_idx , pgsize_idx_next ;
2382
2382
unsigned long pgsizes ;
2383
- size_t pgsize ;
2383
+ size_t offset , pgsize , pgsize_next ;
2384
2384
unsigned long addr_merge = paddr | iova ;
2385
2385
2386
2386
/* Page sizes supported by the hardware and small enough for @size */
@@ -2396,7 +2396,36 @@ static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova,
2396
2396
/* Pick the biggest page size remaining */
2397
2397
pgsize_idx = __fls (pgsizes );
2398
2398
pgsize = BIT (pgsize_idx );
2399
+ if (!count )
2400
+ return pgsize ;
2399
2401
2402
+ /* Find the next biggest support page size, if it exists */
2403
+ pgsizes = domain -> pgsize_bitmap & ~GENMASK (pgsize_idx , 0 );
2404
+ if (!pgsizes )
2405
+ goto out_set_count ;
2406
+
2407
+ pgsize_idx_next = __ffs (pgsizes );
2408
+ pgsize_next = BIT (pgsize_idx_next );
2409
+
2410
+ /*
2411
+ * There's no point trying a bigger page size unless the virtual
2412
+ * and physical addresses are similarly offset within the larger page.
2413
+ */
2414
+ if ((iova ^ paddr ) & (pgsize_next - 1 ))
2415
+ goto out_set_count ;
2416
+
2417
+ /* Calculate the offset to the next page size alignment boundary */
2418
+ offset = pgsize_next - (addr_merge & (pgsize_next - 1 ));
2419
+
2420
+ /*
2421
+ * If size is big enough to accommodate the larger page, reduce
2422
+ * the number of smaller pages.
2423
+ */
2424
+ if (offset + pgsize_next <= size )
2425
+ size = offset ;
2426
+
2427
+ out_set_count :
2428
+ * count = size >> pgsize_idx ;
2400
2429
return pgsize ;
2401
2430
}
2402
2431
@@ -2434,7 +2463,7 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
2434
2463
pr_debug ("map: iova 0x%lx pa %pa size 0x%zx\n" , iova , & paddr , size );
2435
2464
2436
2465
while (size ) {
2437
- size_t pgsize = iommu_pgsize (domain , iova , paddr , size );
2466
+ size_t pgsize = iommu_pgsize (domain , iova , paddr , size , NULL );
2438
2467
2439
2468
pr_debug ("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n" ,
2440
2469
iova , & paddr , pgsize );
@@ -2485,6 +2514,19 @@ int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova,
2485
2514
}
2486
2515
EXPORT_SYMBOL_GPL (iommu_map_atomic );
2487
2516
2517
+ static size_t __iommu_unmap_pages (struct iommu_domain * domain ,
2518
+ unsigned long iova , size_t size ,
2519
+ struct iommu_iotlb_gather * iotlb_gather )
2520
+ {
2521
+ const struct iommu_ops * ops = domain -> ops ;
2522
+ size_t pgsize , count ;
2523
+
2524
+ pgsize = iommu_pgsize (domain , iova , iova , size , & count );
2525
+ return ops -> unmap_pages ?
2526
+ ops -> unmap_pages (domain , iova , pgsize , count , iotlb_gather ) :
2527
+ ops -> unmap (domain , iova , pgsize , iotlb_gather );
2528
+ }
2529
+
2488
2530
static size_t __iommu_unmap (struct iommu_domain * domain ,
2489
2531
unsigned long iova , size_t size ,
2490
2532
struct iommu_iotlb_gather * iotlb_gather )
@@ -2494,7 +2536,7 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
2494
2536
unsigned long orig_iova = iova ;
2495
2537
unsigned int min_pagesz ;
2496
2538
2497
- if (unlikely (ops -> unmap == NULL ||
2539
+ if (unlikely (!( ops -> unmap || ops -> unmap_pages ) ||
2498
2540
domain -> pgsize_bitmap == 0UL ))
2499
2541
return 0 ;
2500
2542
@@ -2522,10 +2564,9 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
2522
2564
* or we hit an area that isn't mapped.
2523
2565
*/
2524
2566
while (unmapped < size ) {
2525
- size_t pgsize ;
2526
-
2527
- pgsize = iommu_pgsize (domain , iova , iova , size - unmapped );
2528
- unmapped_page = ops -> unmap (domain , iova , pgsize , iotlb_gather );
2567
+ unmapped_page = __iommu_unmap_pages (domain , iova ,
2568
+ size - unmapped ,
2569
+ iotlb_gather );
2529
2570
if (!unmapped_page )
2530
2571
break ;
2531
2572
0 commit comments