6969 * @alloc_size: Size of the allocated buffer.
7070 * @list: The free list describing the number of free entries available
7171 * from each index.
72+ * @pad_slots: Number of preceding padding slots. Valid only in the first
73+ * allocated non-padding slot.
7274 */
7375struct io_tlb_slot {
7476 phys_addr_t orig_addr ;
7577 size_t alloc_size ;
76- unsigned int list ;
78+ unsigned short list ;
79+ unsigned short pad_slots ;
7780};
7881
7982static bool swiotlb_force_bounce ;
@@ -287,6 +290,7 @@ static void swiotlb_init_io_tlb_pool(struct io_tlb_pool *mem, phys_addr_t start,
287290 mem -> nslabs - i );
288291 mem -> slots [i ].orig_addr = INVALID_PHYS_ADDR ;
289292 mem -> slots [i ].alloc_size = 0 ;
293+ mem -> slots [i ].pad_slots = 0 ;
290294 }
291295
292296 memset (vaddr , 0 , bytes );
@@ -821,12 +825,30 @@ void swiotlb_dev_init(struct device *dev)
821825#endif
822826}
823827
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.
826846 */
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 )
828849{
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 ));
830852}
831853
832854/*
@@ -841,27 +863,23 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
841863 size_t alloc_size = mem -> slots [index ].alloc_size ;
842864 unsigned long pfn = PFN_DOWN (orig_addr );
843865 unsigned char * vaddr = mem -> vaddr + tlb_addr - mem -> start ;
844- unsigned int tlb_offset , orig_addr_offset ;
866+ int tlb_offset ;
845867
846868 if (orig_addr == INVALID_PHYS_ADDR )
847869 return ;
848870
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 );
865883
866884 orig_addr += tlb_offset ;
867885 alloc_size -= tlb_offset ;
@@ -1005,7 +1023,7 @@ static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool
10051023 unsigned long max_slots = get_max_slots (boundary_mask );
10061024 unsigned int iotlb_align_mask = dma_get_min_align_mask (dev );
10071025 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 );
10091027 unsigned int index , slots_checked , count = 0 , i ;
10101028 unsigned long flags ;
10111029 unsigned int slot_base ;
@@ -1328,11 +1346,12 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
13281346 unsigned long attrs )
13291347{
13301348 struct io_tlb_mem * mem = dev -> dma_io_tlb_mem ;
1331- unsigned int offset = swiotlb_align_offset ( dev , orig_addr ) ;
1349+ unsigned int offset ;
13321350 struct io_tlb_pool * pool ;
13331351 unsigned int i ;
13341352 int index ;
13351353 phys_addr_t tlb_addr ;
1354+ unsigned short pad_slots ;
13361355
13371356 if (!mem || !mem -> nslabs ) {
13381357 dev_warn_ratelimited (dev ,
@@ -1349,6 +1368,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
13491368 return (phys_addr_t )DMA_MAPPING_ERROR ;
13501369 }
13511370
1371+ offset = swiotlb_align_offset (dev , alloc_align_mask , orig_addr );
13521372 index = swiotlb_find_slots (dev , orig_addr ,
13531373 alloc_size + offset , alloc_align_mask , & pool );
13541374 if (index == -1 ) {
@@ -1364,6 +1384,10 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
13641384 * This is needed when we sync the memory. Then we sync the buffer if
13651385 * needed.
13661386 */
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 ;
13671391 for (i = 0 ; i < nr_slots (alloc_size + offset ); i ++ )
13681392 pool -> slots [index + i ].orig_addr = slot_addr (orig_addr , i );
13691393 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)
13841408{
13851409 struct io_tlb_pool * mem = swiotlb_find_pool (dev , tlb_addr );
13861410 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 ;
13921414 int count , i ;
13931415
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+
13941422 /*
13951423 * Return the buffer to the free list by setting the corresponding
13961424 * 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)
14131441 mem -> slots [i ].list = ++ count ;
14141442 mem -> slots [i ].orig_addr = INVALID_PHYS_ADDR ;
14151443 mem -> slots [i ].alloc_size = 0 ;
1444+ mem -> slots [i ].pad_slots = 0 ;
14161445 }
14171446
14181447 /*
@@ -1647,9 +1676,6 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_io_tlb_hiwater, io_tlb_hiwater_get,
16471676static void swiotlb_create_debugfs_files (struct io_tlb_mem * mem ,
16481677 const char * dirname )
16491678{
1650- atomic_long_set (& mem -> total_used , 0 );
1651- atomic_long_set (& mem -> used_hiwater , 0 );
1652-
16531679 mem -> debugfs = debugfs_create_dir (dirname , io_tlb_default_mem .debugfs );
16541680 if (!mem -> nslabs )
16551681 return ;
@@ -1660,7 +1686,6 @@ static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem,
16601686 debugfs_create_file ("io_tlb_used_hiwater" , 0600 , mem -> debugfs , mem ,
16611687 & fops_io_tlb_hiwater );
16621688#ifdef CONFIG_SWIOTLB_DYNAMIC
1663- atomic_long_set (& mem -> transient_nslabs , 0 );
16641689 debugfs_create_file ("io_tlb_transient_nslabs" , 0400 , mem -> debugfs ,
16651690 mem , & fops_io_tlb_transient_used );
16661691#endif
0 commit comments