mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-04 04:06:26 +00:00
dma-mapping fixes for Linux 6.6
- fix the narea calculation in swiotlb initialization (Ross Lagerwall) - fix the check whether a device has used swiotlb (Petr Tesarik) -----BEGIN PGP SIGNATURE----- iQI/BAABCgApFiEEgdbnc3r/njty3Iq9D55TZVIEUYMFAmUYWTULHGhjaEBsc3Qu ZGUACgkQD55TZVIEUYMilA/8DomLRCrDy792MoRvBCThWaY6auW4bCUoY7S6VZe7 LVECKAJRwFH7b+dk1mNjPhWTyq8/wB7kr/OLuU9HDcVIeiP9zxks4BMQ4RGc/ZuK rSZ5ZHPVVCC4EOI3ncjQXrODwgGkGUvtdriByCtX2r4NLBjO1T0vUQB4bLyBTZf+ GnTCLxCkSrIxaqniRvM0K34yO/0rq0ci5840MNneR7MKQkVqPUDY83sHwL1KcQPf s16lwclQdjZdOVpFMPxFin5NpvPIrjdrvhoaxdnz+8ZuwSACqRUZDQuNlZ3+Zep6 iaynNR04o0c2p0PTT5l3ZRD5vsyCjvc+/3kB3KlM33XbBArWi6XV+694QQn59JnZ 5MmHoIulwZGLsIlTG188QreZBlLrmxylUX311Kot5ood/HW8DsYbTo/krbiiUgEk MXKWq9k6cQOdhgriS4zxvUl+xkjby12jvSFxv9tN3HHvFsFB8+veVrTuLZzEDXpX a5PrmI/dcQmlVpCZllzVzeTgL2KeE1Jo0uRZ1vXhuoX8IBys4/TstIXOB4jnyVb4 kzrHbLIoVqLSN42eVMRKBrqGXGlZSWETBpkdSQ41St6t/3MurhKAWZ/1SFPXlI06 SnatIdOU7nSZRofK8/Xe1CnWia5NUpyUQpb+tLUHTgo4kZzGV330bf34iJ+BvC1h aks= =bhgc -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
3b517966c5
@ -172,14 +172,23 @@ static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr)
|
||||
if (!mem)
|
||||
return false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_SWIOTLB_DYNAMIC)) {
|
||||
/* Pairs with smp_wmb() in swiotlb_find_slots() and
|
||||
* swiotlb_dyn_alloc(), which modify the RCU lists.
|
||||
*/
|
||||
smp_rmb();
|
||||
return swiotlb_find_pool(dev, paddr);
|
||||
}
|
||||
#ifdef CONFIG_SWIOTLB_DYNAMIC
|
||||
/*
|
||||
* All SWIOTLB buffer addresses must have been returned by
|
||||
* swiotlb_tbl_map_single() and passed to a device driver.
|
||||
* If a SWIOTLB address is checked on another CPU, then it was
|
||||
* presumably loaded by the device driver from an unspecified private
|
||||
* data structure. Make sure that this load is ordered before reading
|
||||
* dev->dma_uses_io_tlb here and mem->pools in swiotlb_find_pool().
|
||||
*
|
||||
* This barrier pairs with smp_mb() in swiotlb_find_slots().
|
||||
*/
|
||||
smp_rmb();
|
||||
return READ_ONCE(dev->dma_uses_io_tlb) &&
|
||||
swiotlb_find_pool(dev, paddr);
|
||||
#else
|
||||
return paddr >= mem->defpool.start && paddr < mem->defpool.end;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool is_swiotlb_force_bounce(struct device *dev)
|
||||
|
@ -399,14 +399,13 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
|
||||
}
|
||||
|
||||
mem->areas = memblock_alloc(array_size(sizeof(struct io_tlb_area),
|
||||
default_nareas), SMP_CACHE_BYTES);
|
||||
nareas), SMP_CACHE_BYTES);
|
||||
if (!mem->areas) {
|
||||
pr_warn("%s: Failed to allocate mem->areas.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
swiotlb_init_io_tlb_pool(mem, __pa(tlb), nslabs, false,
|
||||
default_nareas);
|
||||
swiotlb_init_io_tlb_pool(mem, __pa(tlb), nslabs, false, nareas);
|
||||
add_mem_pool(&io_tlb_default_mem, mem);
|
||||
|
||||
if (flags & SWIOTLB_VERBOSE)
|
||||
@ -729,9 +728,6 @@ static void swiotlb_dyn_alloc(struct work_struct *work)
|
||||
}
|
||||
|
||||
add_mem_pool(mem, pool);
|
||||
|
||||
/* Pairs with smp_rmb() in is_swiotlb_buffer(). */
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1152,9 +1148,26 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
|
||||
spin_unlock_irqrestore(&dev->dma_io_tlb_lock, flags);
|
||||
|
||||
found:
|
||||
dev->dma_uses_io_tlb = true;
|
||||
/* Pairs with smp_rmb() in is_swiotlb_buffer() */
|
||||
smp_wmb();
|
||||
WRITE_ONCE(dev->dma_uses_io_tlb, true);
|
||||
|
||||
/*
|
||||
* The general barrier orders reads and writes against a presumed store
|
||||
* of the SWIOTLB buffer address by a device driver (to a driver private
|
||||
* data structure). It serves two purposes.
|
||||
*
|
||||
* First, the store to dev->dma_uses_io_tlb must be ordered before the
|
||||
* presumed store. This guarantees that the returned buffer address
|
||||
* cannot be passed to another CPU before updating dev->dma_uses_io_tlb.
|
||||
*
|
||||
* Second, the load from mem->pools must be ordered before the same
|
||||
* presumed store. This guarantees that the returned buffer address
|
||||
* cannot be observed by another CPU before an update of the RCU list
|
||||
* that was made by swiotlb_dyn_alloc() on a third CPU (cf. multicopy
|
||||
* atomicity).
|
||||
*
|
||||
* See also the comment in is_swiotlb_buffer().
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
*retpool = pool;
|
||||
return index;
|
||||
|
Loading…
Reference in New Issue
Block a user