Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+38 -16
+16 -7
include/linux/swiotlb.h
··· 172 172 if (!mem) 173 173 return false; 174 174 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 182 190 return paddr >= mem->defpool.start && paddr < mem->defpool.end; 191 + #endif 183 192 } 184 193 185 194 static inline bool is_swiotlb_force_bounce(struct device *dev)
+22 -9
kernel/dma/swiotlb.c
··· 399 399 } 400 400 401 401 mem->areas = memblock_alloc(array_size(sizeof(struct io_tlb_area), 402 - default_nareas), SMP_CACHE_BYTES); 402 + nareas), SMP_CACHE_BYTES); 403 403 if (!mem->areas) { 404 404 pr_warn("%s: Failed to allocate mem->areas.\n", __func__); 405 405 return; 406 406 } 407 407 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); 410 409 add_mem_pool(&io_tlb_default_mem, mem); 411 410 412 411 if (flags & SWIOTLB_VERBOSE) ··· 728 729 } 729 730 730 731 add_mem_pool(mem, pool); 731 - 732 - /* Pairs with smp_rmb() in is_swiotlb_buffer(). */ 733 - smp_wmb(); 734 732 } 735 733 736 734 /** ··· 1148 1152 spin_unlock_irqrestore(&dev->dma_io_tlb_lock, flags); 1149 1153 1150 1154 found: 1151 - dev->dma_uses_io_tlb = true; 1152 - /* Pairs with smp_rmb() in is_swiotlb_buffer() */ 1153 - smp_wmb(); 1155 + WRITE_ONCE(dev->dma_uses_io_tlb, true); 1156 + 1157 + /* 1158 + * The general barrier orders reads and writes against a presumed store 1159 + * of the SWIOTLB buffer address by a device driver (to a driver private 1160 + * data structure). It serves two purposes. 1161 + * 1162 + * First, the store to dev->dma_uses_io_tlb must be ordered before the 1163 + * presumed store. This guarantees that the returned buffer address 1164 + * cannot be passed to another CPU before updating dev->dma_uses_io_tlb. 1165 + * 1166 + * Second, the load from mem->pools must be ordered before the same 1167 + * presumed store. This guarantees that the returned buffer address 1168 + * cannot be observed by another CPU before an update of the RCU list 1169 + * that was made by swiotlb_dyn_alloc() on a third CPU (cf. multicopy 1170 + * atomicity). 1171 + * 1172 + * See also the comment in is_swiotlb_buffer(). 1173 + */ 1174 + smp_mb(); 1154 1175 1155 1176 *retpool = pool; 1156 1177 return index;