@@ -2396,50 +2396,110 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
2396
2396
__unmap_single (domain -> priv , dma_addr , size , dir );
2397
2397
}
2398
2398
2399
+ static int sg_num_pages (struct device * dev ,
2400
+ struct scatterlist * sglist ,
2401
+ int nelems )
2402
+ {
2403
+ unsigned long mask , boundary_size ;
2404
+ struct scatterlist * s ;
2405
+ int i , npages = 0 ;
2406
+
2407
+ mask = dma_get_seg_boundary (dev );
2408
+ boundary_size = mask + 1 ? ALIGN (mask + 1 , PAGE_SIZE ) >> PAGE_SHIFT :
2409
+ 1UL << (BITS_PER_LONG - PAGE_SHIFT );
2410
+
2411
+ for_each_sg (sglist , s , nelems , i ) {
2412
+ int p , n ;
2413
+
2414
+ s -> dma_address = npages << PAGE_SHIFT ;
2415
+ p = npages % boundary_size ;
2416
+ n = iommu_num_pages (sg_phys (s ), s -> length , PAGE_SIZE );
2417
+ if (p + n > boundary_size )
2418
+ npages += boundary_size - p ;
2419
+ npages += n ;
2420
+ }
2421
+
2422
+ return npages ;
2423
+ }
2424
+
2399
2425
/*
2400
2426
* The exported map_sg function for dma_ops (handles scatter-gather
2401
2427
* lists).
2402
2428
*/
2403
2429
static int map_sg (struct device * dev , struct scatterlist * sglist ,
2404
- int nelems , enum dma_data_direction dir ,
2430
+ int nelems , enum dma_data_direction direction ,
2405
2431
struct dma_attrs * attrs )
2406
2432
{
2433
+ int mapped_pages = 0 , npages = 0 , prot = 0 , i ;
2407
2434
struct protection_domain * domain ;
2408
- int i ;
2435
+ struct dma_ops_domain * dma_dom ;
2409
2436
struct scatterlist * s ;
2410
- phys_addr_t paddr ;
2411
- int mapped_elems = 0 ;
2437
+ unsigned long address ;
2412
2438
u64 dma_mask ;
2413
2439
2414
2440
domain = get_domain (dev );
2415
2441
if (IS_ERR (domain ))
2416
2442
return 0 ;
2417
2443
2444
+ dma_dom = domain -> priv ;
2418
2445
dma_mask = * dev -> dma_mask ;
2419
2446
2447
+ npages = sg_num_pages (dev , sglist , nelems );
2448
+
2449
+ address = dma_ops_alloc_iova (dev , dma_dom , npages , dma_mask );
2450
+ if (address == DMA_ERROR_CODE )
2451
+ goto out_err ;
2452
+
2453
+ prot = dir2prot (direction );
2454
+
2455
+ /* Map all sg entries */
2420
2456
for_each_sg (sglist , s , nelems , i ) {
2421
- paddr = sg_phys (s );
2457
+ int j , pages = iommu_num_pages (sg_phys (s ), s -> length , PAGE_SIZE );
2458
+
2459
+ for (j = 0 ; j < pages ; ++ j ) {
2460
+ unsigned long bus_addr , phys_addr ;
2461
+ int ret ;
2422
2462
2423
- s -> dma_address = __map_single (dev , domain -> priv ,
2424
- paddr , s -> length , dir , dma_mask );
2463
+ bus_addr = address + s -> dma_address + (j << PAGE_SHIFT );
2464
+ phys_addr = (sg_phys (s ) & PAGE_MASK ) + (j << PAGE_SHIFT );
2465
+ ret = iommu_map_page (domain , bus_addr , phys_addr , PAGE_SIZE , prot , GFP_ATOMIC );
2466
+ if (ret )
2467
+ goto out_unmap ;
2425
2468
2426
- if (s -> dma_address ) {
2427
- s -> dma_length = s -> length ;
2428
- mapped_elems ++ ;
2429
- } else
2430
- goto unmap ;
2469
+ mapped_pages += 1 ;
2470
+ }
2431
2471
}
2432
2472
2433
- return mapped_elems ;
2473
+ /* Everything is mapped - write the right values into s->dma_address */
2474
+ for_each_sg (sglist , s , nelems , i ) {
2475
+ s -> dma_address += address + s -> offset ;
2476
+ s -> dma_length = s -> length ;
2477
+ }
2478
+
2479
+ return nelems ;
2480
+
2481
+ out_unmap :
2482
+ pr_err ("%s: IOMMU mapping error in map_sg (io-pages: %d)\n" ,
2483
+ dev_name (dev ), npages );
2484
+
2485
+ for_each_sg (sglist , s , nelems , i ) {
2486
+ int j , pages = iommu_num_pages (sg_phys (s ), s -> length , PAGE_SIZE );
2487
+
2488
+ for (j = 0 ; j < pages ; ++ j ) {
2489
+ unsigned long bus_addr ;
2434
2490
2435
- unmap :
2436
- for_each_sg ( sglist , s , mapped_elems , i ) {
2437
- if ( s -> dma_address )
2438
- __unmap_single ( domain -> priv , s -> dma_address ,
2439
- s -> dma_length , dir ) ;
2440
- s -> dma_address = s -> dma_length = 0 ;
2491
+ bus_addr = address + s -> dma_address + ( j << PAGE_SHIFT );
2492
+ iommu_unmap_page ( domain , bus_addr , PAGE_SIZE );
2493
+
2494
+ if ( -- mapped_pages )
2495
+ goto out_free_iova ;
2496
+ }
2441
2497
}
2442
2498
2499
+ out_free_iova :
2500
+ free_iova_fast (& dma_dom -> iovad , address , npages );
2501
+
2502
+ out_err :
2443
2503
return 0 ;
2444
2504
}
2445
2505
@@ -2452,18 +2512,17 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
2452
2512
struct dma_attrs * attrs )
2453
2513
{
2454
2514
struct protection_domain * domain ;
2455
- struct scatterlist * s ;
2456
- int i ;
2515
+ unsigned long startaddr ;
2516
+ int npages = 2 ;
2457
2517
2458
2518
domain = get_domain (dev );
2459
2519
if (IS_ERR (domain ))
2460
2520
return ;
2461
2521
2462
- for_each_sg (sglist , s , nelems , i ) {
2463
- __unmap_single (domain -> priv , s -> dma_address ,
2464
- s -> dma_length , dir );
2465
- s -> dma_address = s -> dma_length = 0 ;
2466
- }
2522
+ startaddr = sg_dma_address (sglist ) & PAGE_MASK ;
2523
+ npages = sg_num_pages (dev , sglist , nelems );
2524
+
2525
+ __unmap_single (domain -> priv , startaddr , npages << PAGE_SHIFT , dir );
2467
2526
}
2468
2527
2469
2528
/*
0 commit comments