69
69
* @alloc_size: Size of the allocated buffer.
70
70
* @list: The free list describing the number of free entries available
71
71
* from each index.
72
+ * @pad_slots: Number of preceding padding slots. Valid only in the first
73
+ * allocated non-padding slot.
72
74
*/
73
75
struct io_tlb_slot {
74
76
phys_addr_t orig_addr ;
75
77
size_t alloc_size ;
76
- unsigned int list ;
78
+ unsigned short list ;
79
+ unsigned short pad_slots ;
77
80
};
78
81
79
82
static bool swiotlb_force_bounce ;
@@ -287,6 +290,7 @@ static void swiotlb_init_io_tlb_pool(struct io_tlb_pool *mem, phys_addr_t start,
287
290
mem -> nslabs - i );
288
291
mem -> slots [i ].orig_addr = INVALID_PHYS_ADDR ;
289
292
mem -> slots [i ].alloc_size = 0 ;
293
+ mem -> slots [i ].pad_slots = 0 ;
290
294
}
291
295
292
296
memset (vaddr , 0 , bytes );
@@ -821,12 +825,30 @@ void swiotlb_dev_init(struct device *dev)
821
825
#endif
822
826
}
823
827
824
- /*
825
- * Return the offset into a iotlb slot required to keep the device happy.
828
+ /**
829
+ * swiotlb_align_offset() - Get required offset into an IO TLB allocation.
830
+ * @dev: Owning device.
831
+ * @align_mask: Allocation alignment mask.
832
+ * @addr: DMA address.
833
+ *
834
+ * Return the minimum offset from the start of an IO TLB allocation which is
835
+ * required for a given buffer address and allocation alignment to keep the
836
+ * device happy.
837
+ *
838
+ * First, the address bits covered by min_align_mask must be identical in the
839
+ * original address and the bounce buffer address. High bits are preserved by
840
+ * choosing a suitable IO TLB slot, but bits below IO_TLB_SHIFT require extra
841
+ * padding bytes before the bounce buffer.
842
+ *
843
+ * Second, @align_mask specifies which bits of the first allocated slot must
844
+ * be zero. This may require allocating additional padding slots, and then the
845
+ * offset (in bytes) from the first such padding slot is returned.
826
846
*/
827
- static unsigned int swiotlb_align_offset (struct device * dev , u64 addr )
847
+ static unsigned int swiotlb_align_offset (struct device * dev ,
848
+ unsigned int align_mask , u64 addr )
828
849
{
829
- return addr & dma_get_min_align_mask (dev ) & (IO_TLB_SIZE - 1 );
850
+ return addr & dma_get_min_align_mask (dev ) &
851
+ (align_mask | (IO_TLB_SIZE - 1 ));
830
852
}
831
853
832
854
/*
@@ -841,27 +863,23 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
841
863
size_t alloc_size = mem -> slots [index ].alloc_size ;
842
864
unsigned long pfn = PFN_DOWN (orig_addr );
843
865
unsigned char * vaddr = mem -> vaddr + tlb_addr - mem -> start ;
844
- unsigned int tlb_offset , orig_addr_offset ;
866
+ int tlb_offset ;
845
867
846
868
if (orig_addr == INVALID_PHYS_ADDR )
847
869
return ;
848
870
849
- tlb_offset = tlb_addr & (IO_TLB_SIZE - 1 );
850
- orig_addr_offset = swiotlb_align_offset (dev , orig_addr );
851
- if (tlb_offset < orig_addr_offset ) {
852
- dev_WARN_ONCE (dev , 1 ,
853
- "Access before mapping start detected. orig offset %u, requested offset %u.\n" ,
854
- orig_addr_offset , tlb_offset );
855
- return ;
856
- }
857
-
858
- tlb_offset -= orig_addr_offset ;
859
- if (tlb_offset > alloc_size ) {
860
- dev_WARN_ONCE (dev , 1 ,
861
- "Buffer overflow detected. Allocation size: %zu. Mapping size: %zu+%u.\n" ,
862
- alloc_size , size , tlb_offset );
863
- return ;
864
- }
871
+ /*
872
+ * It's valid for tlb_offset to be negative. This can happen when the
873
+ * "offset" returned by swiotlb_align_offset() is non-zero, and the
874
+ * tlb_addr is pointing within the first "offset" bytes of the second
875
+ * or subsequent slots of the allocated swiotlb area. While it's not
876
+ * valid for tlb_addr to be pointing within the first "offset" bytes
877
+ * of the first slot, there's no way to check for such an error since
878
+ * this function can't distinguish the first slot from the second and
879
+ * subsequent slots.
880
+ */
881
+ tlb_offset = (tlb_addr & (IO_TLB_SIZE - 1 )) -
882
+ swiotlb_align_offset (dev , 0 , orig_addr );
865
883
866
884
orig_addr += tlb_offset ;
867
885
alloc_size -= tlb_offset ;
@@ -1005,7 +1023,7 @@ static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool
1005
1023
unsigned long max_slots = get_max_slots (boundary_mask );
1006
1024
unsigned int iotlb_align_mask = dma_get_min_align_mask (dev );
1007
1025
unsigned int nslots = nr_slots (alloc_size ), stride ;
1008
- unsigned int offset = swiotlb_align_offset (dev , orig_addr );
1026
+ unsigned int offset = swiotlb_align_offset (dev , 0 , orig_addr );
1009
1027
unsigned int index , slots_checked , count = 0 , i ;
1010
1028
unsigned long flags ;
1011
1029
unsigned int slot_base ;
@@ -1328,11 +1346,12 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
1328
1346
unsigned long attrs )
1329
1347
{
1330
1348
struct io_tlb_mem * mem = dev -> dma_io_tlb_mem ;
1331
- unsigned int offset = swiotlb_align_offset ( dev , orig_addr ) ;
1349
+ unsigned int offset ;
1332
1350
struct io_tlb_pool * pool ;
1333
1351
unsigned int i ;
1334
1352
int index ;
1335
1353
phys_addr_t tlb_addr ;
1354
+ unsigned short pad_slots ;
1336
1355
1337
1356
if (!mem || !mem -> nslabs ) {
1338
1357
dev_warn_ratelimited (dev ,
@@ -1349,6 +1368,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
1349
1368
return (phys_addr_t )DMA_MAPPING_ERROR ;
1350
1369
}
1351
1370
1371
+ offset = swiotlb_align_offset (dev , alloc_align_mask , orig_addr );
1352
1372
index = swiotlb_find_slots (dev , orig_addr ,
1353
1373
alloc_size + offset , alloc_align_mask , & pool );
1354
1374
if (index == -1 ) {
@@ -1364,6 +1384,10 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
1364
1384
* This is needed when we sync the memory. Then we sync the buffer if
1365
1385
* needed.
1366
1386
*/
1387
+ pad_slots = offset >> IO_TLB_SHIFT ;
1388
+ offset &= (IO_TLB_SIZE - 1 );
1389
+ index += pad_slots ;
1390
+ pool -> slots [index ].pad_slots = pad_slots ;
1367
1391
for (i = 0 ; i < nr_slots (alloc_size + offset ); i ++ )
1368
1392
pool -> slots [index + i ].orig_addr = slot_addr (orig_addr , i );
1369
1393
tlb_addr = slot_addr (pool -> start , index ) + offset ;
@@ -1384,13 +1408,17 @@ static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr)
1384
1408
{
1385
1409
struct io_tlb_pool * mem = swiotlb_find_pool (dev , tlb_addr );
1386
1410
unsigned long flags ;
1387
- unsigned int offset = swiotlb_align_offset (dev , tlb_addr );
1388
- int index = (tlb_addr - offset - mem -> start ) >> IO_TLB_SHIFT ;
1389
- int nslots = nr_slots (mem -> slots [index ].alloc_size + offset );
1390
- int aindex = index / mem -> area_nslabs ;
1391
- struct io_tlb_area * area = & mem -> areas [aindex ];
1411
+ unsigned int offset = swiotlb_align_offset (dev , 0 , tlb_addr );
1412
+ int index , nslots , aindex ;
1413
+ struct io_tlb_area * area ;
1392
1414
int count , i ;
1393
1415
1416
+ index = (tlb_addr - offset - mem -> start ) >> IO_TLB_SHIFT ;
1417
+ index -= mem -> slots [index ].pad_slots ;
1418
+ nslots = nr_slots (mem -> slots [index ].alloc_size + offset );
1419
+ aindex = index / mem -> area_nslabs ;
1420
+ area = & mem -> areas [aindex ];
1421
+
1394
1422
/*
1395
1423
* Return the buffer to the free list by setting the corresponding
1396
1424
* entries to indicate the number of contiguous entries available.
@@ -1413,6 +1441,7 @@ static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr)
1413
1441
mem -> slots [i ].list = ++ count ;
1414
1442
mem -> slots [i ].orig_addr = INVALID_PHYS_ADDR ;
1415
1443
mem -> slots [i ].alloc_size = 0 ;
1444
+ mem -> slots [i ].pad_slots = 0 ;
1416
1445
}
1417
1446
1418
1447
/*
@@ -1647,9 +1676,6 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_io_tlb_hiwater, io_tlb_hiwater_get,
1647
1676
static void swiotlb_create_debugfs_files (struct io_tlb_mem * mem ,
1648
1677
const char * dirname )
1649
1678
{
1650
- atomic_long_set (& mem -> total_used , 0 );
1651
- atomic_long_set (& mem -> used_hiwater , 0 );
1652
-
1653
1679
mem -> debugfs = debugfs_create_dir (dirname , io_tlb_default_mem .debugfs );
1654
1680
if (!mem -> nslabs )
1655
1681
return ;
@@ -1660,7 +1686,6 @@ static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem,
1660
1686
debugfs_create_file ("io_tlb_used_hiwater" , 0600 , mem -> debugfs , mem ,
1661
1687
& fops_io_tlb_hiwater );
1662
1688
#ifdef CONFIG_SWIOTLB_DYNAMIC
1663
- atomic_long_set (& mem -> transient_nslabs , 0 );
1664
1689
debugfs_create_file ("io_tlb_transient_nslabs" , 0400 , mem -> debugfs ,
1665
1690
mem , & fops_io_tlb_transient_used );
1666
1691
#endif
0 commit comments