Skip to content

Commit 3b51796

Browse files
committed
Merge tag 'dma-mapping-6.6-2023-09-30' of git://git.infradead.org/users/hch/dma-mapping
Pull dma-mapping fixes from Christoph Hellwig: - fix the narea calculation in swiotlb initialization (Ross Lagerwall) - fix the check whether a device has used swiotlb (Petr Tesarik) * tag 'dma-mapping-6.6-2023-09-30' of git://git.infradead.org/users/hch/dma-mapping: swiotlb: fix the check whether a device has used software IO TLB swiotlb: use the calculated number of areas
2 parents 25d48d5 + 2d5780b commit 3b51796

File tree

2 files changed

+38
-16
lines changed

2 files changed

+38
-16
lines changed

include/linux/swiotlb.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,23 @@ static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr)
172172
if (!mem)
173173
return false;
174174

175-
if (IS_ENABLED(CONFIG_SWIOTLB_DYNAMIC)) {
176-
/* Pairs with smp_wmb() in swiotlb_find_slots() and
177-
* swiotlb_dyn_alloc(), which modify the RCU lists.
178-
*/
179-
smp_rmb();
180-
return swiotlb_find_pool(dev, paddr);
181-
}
175+
#ifdef CONFIG_SWIOTLB_DYNAMIC
176+
/*
177+
* All SWIOTLB buffer addresses must have been returned by
178+
* swiotlb_tbl_map_single() and passed to a device driver.
179+
* If a SWIOTLB address is checked on another CPU, then it was
180+
* presumably loaded by the device driver from an unspecified private
181+
* data structure. Make sure that this load is ordered before reading
182+
* dev->dma_uses_io_tlb here and mem->pools in swiotlb_find_pool().
183+
*
184+
* This barrier pairs with smp_mb() in swiotlb_find_slots().
185+
*/
186+
smp_rmb();
187+
return READ_ONCE(dev->dma_uses_io_tlb) &&
188+
swiotlb_find_pool(dev, paddr);
189+
#else
182190
return paddr >= mem->defpool.start && paddr < mem->defpool.end;
191+
#endif
183192
}
184193

185194
static inline bool is_swiotlb_force_bounce(struct device *dev)

kernel/dma/swiotlb.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,13 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
399399
}
400400

401401
mem->areas = memblock_alloc(array_size(sizeof(struct io_tlb_area),
402-
default_nareas), SMP_CACHE_BYTES);
402+
nareas), SMP_CACHE_BYTES);
403403
if (!mem->areas) {
404404
pr_warn("%s: Failed to allocate mem->areas.\n", __func__);
405405
return;
406406
}
407407

408-
swiotlb_init_io_tlb_pool(mem, __pa(tlb), nslabs, false,
409-
default_nareas);
408+
swiotlb_init_io_tlb_pool(mem, __pa(tlb), nslabs, false, nareas);
410409
add_mem_pool(&io_tlb_default_mem, mem);
411410

412411
if (flags & SWIOTLB_VERBOSE)
@@ -729,9 +728,6 @@ static void swiotlb_dyn_alloc(struct work_struct *work)
729728
}
730729

731730
add_mem_pool(mem, pool);
732-
733-
/* Pairs with smp_rmb() in is_swiotlb_buffer(). */
734-
smp_wmb();
735731
}
736732

737733
/**
@@ -1152,9 +1148,26 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
11521148
spin_unlock_irqrestore(&dev->dma_io_tlb_lock, flags);
11531149

11541150
found:
1155-
dev->dma_uses_io_tlb = true;
1156-
/* Pairs with smp_rmb() in is_swiotlb_buffer() */
1157-
smp_wmb();
1151+
WRITE_ONCE(dev->dma_uses_io_tlb, true);
1152+
1153+
/*
1154+
* The general barrier orders reads and writes against a presumed store
1155+
* of the SWIOTLB buffer address by a device driver (to a driver private
1156+
* data structure). It serves two purposes.
1157+
*
1158+
* First, the store to dev->dma_uses_io_tlb must be ordered before the
1159+
* presumed store. This guarantees that the returned buffer address
1160+
* cannot be passed to another CPU before updating dev->dma_uses_io_tlb.
1161+
*
1162+
* Second, the load from mem->pools must be ordered before the same
1163+
* presumed store. This guarantees that the returned buffer address
1164+
* cannot be observed by another CPU before an update of the RCU list
1165+
* that was made by swiotlb_dyn_alloc() on a third CPU (cf. multicopy
1166+
* atomicity).
1167+
*
1168+
* See also the comment in is_swiotlb_buffer().
1169+
*/
1170+
smp_mb();
11581171

11591172
*retpool = pool;
11601173
return index;

0 commit comments

Comments
 (0)