Pull dma-mapping updates from Christoph Hellwig: - reduce area lock contention for non-primary IO TLB pools (Petr Tesarik) - don't store redundant offsets in the dma_ranges stuctures (Robin Murphy) - clear dev->dma_mem when freeing per-device pools (Joakim Zhang) * tag 'dma-mapping-6.8-2024-01-08' of git://git.infradead.org/users/hch/dma-mapping: dma-mapping: clear dev->dma_mem to NULL after freeing it swiotlb: reduce area lock contention for non-primary IO TLB pools dma-mapping: don't store redundant offsets
Showing the changes to kernel (3 of 6 files). Show all
Unified · Split
| @@ -132,8 +132,10 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, · 131 unmodified lines | ||
| 132 | 132 | |
| 133 | 133 | void dma_release_coherent_memory(struct device *dev) |
| 134 | 134 | { |
| 135 | − if (dev) | |
| 135 | + if (dev) { | |
| 136 | 136 | _dma_release_coherent_memory(dev->dma_mem); |
| 137 | + dev->dma_mem = NULL; | |
| 138 | + } | |
| 137 | 139 | } |
| 138 | 140 | |
| 139 | 141 | static void *__dma_alloc_from_coherent(struct device *dev, |
| @@ -677,7 +677,6 @@ int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start, · 676 unmodified lines | ||
| 677 | 677 | return -ENOMEM; |
| 678 | 678 | map[0].cpu_start = cpu_start; |
| 679 | 679 | map[0].dma_start = dma_start; |
| 680 | − map[0].offset = offset; | |
| 681 | 680 | map[0].size = size; |
| 682 | 681 | dev->dma_range_map = map; |
| 683 | 682 | return 0; |
| @@ -957,7 +957,7 @@ static void dec_used(struct io_tlb_mem *mem, unsigned int nslots) · 956 unmodified lines | ||
| 957 | 957 | #endif /* CONFIG_DEBUG_FS */ |
| 958 | 958 | |
| 959 | 959 | /** |
| 960 | − * swiotlb_area_find_slots() - search for slots in one IO TLB memory area | |
| 960 | + * swiotlb_search_pool_area() - search one memory area in one pool | |
| 961 | 961 | * @dev: Device which maps the buffer. |
| 962 | 962 | * @pool: Memory pool to be searched. |
| 963 | 963 | * @area_index: Index of the IO TLB memory area to be searched. |
| @@ -972,7 +972,7 @@ static void dec_used(struct io_tlb_mem *mem, unsigned int nslots) · 8 unmodified lines | ||
| 972 | 972 | * |
| 973 | 973 | * Return: Index of the first allocated slot, or -1 on error. |
| 974 | 974 | */ |
| 975 | −static int swiotlb_area_find_slots(struct device *dev, struct io_tlb_pool *pool, | |
| 975 | +static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool, | |
| 976 | 976 | int area_index, phys_addr_t orig_addr, size_t alloc_size, |
| 977 | 977 | unsigned int alloc_align_mask) |
| 978 | 978 | { |
| @@ -1066,41 +1066,50 @@ found: · 87 unmodified lines | ||
| 1066 | 1066 | return slot_index; |
| 1067 | 1067 | } |
| 1068 | 1068 | |
| 1069 | +#ifdef CONFIG_SWIOTLB_DYNAMIC | |
| 1070 | + | |
| 1069 | 1071 | /** |
| 1070 | − * swiotlb_pool_find_slots() - search for slots in one memory pool | |
| 1072 | + * swiotlb_search_area() - search one memory area in all pools | |
| 1071 | 1073 | * @dev: Device which maps the buffer. |
| 1072 | − * @pool: Memory pool to be searched. | |
| 1074 | + * @start_cpu: Start CPU number. | |
| 1075 | + * @cpu_offset: Offset from @start_cpu. | |
| 1073 | 1076 | * @orig_addr: Original (non-bounced) IO buffer address. |
| 1074 | 1077 | * @alloc_size: Total requested size of the bounce buffer, |
| 1075 | 1078 | * including initial alignment padding. |
| 1076 | 1079 | * @alloc_align_mask: Required alignment of the allocated buffer. |
| 1080 | + * @retpool: Used memory pool, updated on return. | |
| 1077 | 1081 | * |
| 1078 | − * Search through one memory pool to find a sequence of slots that match the | |
| 1082 | + * Search one memory area in all pools for a sequence of slots that match the | |
| 1079 | 1083 | * allocation constraints. |
| 1080 | 1084 | * |
| 1081 | 1085 | * Return: Index of the first allocated slot, or -1 on error. |
| 1082 | 1086 | */ |
| 1083 | −static int swiotlb_pool_find_slots(struct device *dev, struct io_tlb_pool *pool, | |
| 1084 | − phys_addr_t orig_addr, size_t alloc_size, | |
| 1085 | − unsigned int alloc_align_mask) | |
| 1087 | +static int swiotlb_search_area(struct device *dev, int start_cpu, | |
| 1088 | + int cpu_offset, phys_addr_t orig_addr, size_t alloc_size, | |
| 1089 | + unsigned int alloc_align_mask, struct io_tlb_pool **retpool) | |
| 1086 | 1090 | { |
| 1087 | − int start = raw_smp_processor_id() & (pool->nareas - 1); | |
| 1088 | − int i = start, index; | |
| 1089 | − | |
| 1090 | − do { | |
| 1091 | − index = swiotlb_area_find_slots(dev, pool, i, orig_addr, | |
| 1092 | − alloc_size, alloc_align_mask); | |
| 1093 | − if (index >= 0) | |
| 1094 | − return index; | |
| 1095 | − if (++i >= pool->nareas) | |
| 1096 | − i = 0; | |
| 1097 | − } while (i != start); | |
| 1091 | + struct io_tlb_mem *mem = dev->dma_io_tlb_mem; | |
| 1092 | + struct io_tlb_pool *pool; | |
| 1093 | + int area_index; | |
| 1094 | + int index = -1; | |
| 1098 | 1095 | |
| 1099 | − return -1; | |
| 1096 | + rcu_read_lock(); | |
| 1097 | + list_for_each_entry_rcu(pool, &mem->pools, node) { | |
| 1098 | + if (cpu_offset >= pool->nareas) | |
| 1099 | + continue; | |
| 1100 | + area_index = (start_cpu + cpu_offset) & (pool->nareas - 1); | |
| 1101 | + index = swiotlb_search_pool_area(dev, pool, area_index, | |
| 1102 | + orig_addr, alloc_size, | |
| 1103 | + alloc_align_mask); | |
| 1104 | + if (index >= 0) { | |
| 1105 | + *retpool = pool; | |
| 1106 | + break; | |
| 1107 | + } | |
| 1108 | + } | |
| 1109 | + rcu_read_unlock(); | |
| 1110 | + return index; | |
| 1100 | 1111 | } |
| 1101 | 1112 | |
| 1102 | −#ifdef CONFIG_SWIOTLB_DYNAMIC | |
| 1103 | − | |
| 1104 | 1113 | /** |
| 1105 | 1114 | * swiotlb_find_slots() - search for slots in the whole swiotlb |
| 1106 | 1115 | * @dev: Device which maps the buffer. |
| @@ -1124,18 +1133,17 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr, · 17 unmodified lines | ||
| 1124 | 1133 | unsigned long nslabs; |
| 1125 | 1134 | unsigned long flags; |
| 1126 | 1135 | u64 phys_limit; |
| 1136 | + int cpu, i; | |
| 1127 | 1137 | int index; |
| 1128 | 1138 | |
| 1129 | − rcu_read_lock(); | |
| 1130 | − list_for_each_entry_rcu(pool, &mem->pools, node) { | |
| 1131 | − index = swiotlb_pool_find_slots(dev, pool, orig_addr, | |
| 1132 | − alloc_size, alloc_align_mask); | |
| 1133 | − if (index >= 0) { | |
| 1134 | − rcu_read_unlock(); | |
| 1139 | + cpu = raw_smp_processor_id(); | |
| 1140 | + for (i = 0; i < default_nareas; ++i) { | |
| 1141 | + index = swiotlb_search_area(dev, cpu, i, orig_addr, alloc_size, | |
| 1142 | + alloc_align_mask, &pool); | |
| 1143 | + if (index >= 0) | |
| 1135 | 1144 | goto found; |
| 1136 | − } | |
| 1137 | 1145 | } |
| 1138 | − rcu_read_unlock(); | |
| 1146 | + | |
| 1139 | 1147 | if (!mem->can_grow) |
| 1140 | 1148 | return -1; |
| 1141 | 1149 | |
| @@ -1148,8 +1156,8 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr, · 6 unmodified lines | ||
| 1148 | 1156 | if (!pool) |
| 1149 | 1157 | return -1; |
| 1150 | 1158 | |
| 1151 | − index = swiotlb_pool_find_slots(dev, pool, orig_addr, | |
| 1152 | − alloc_size, alloc_align_mask); | |
| 1159 | + index = swiotlb_search_pool_area(dev, pool, 0, orig_addr, | |
| 1160 | + alloc_size, alloc_align_mask); | |
| 1153 | 1161 | if (index < 0) { |
| 1154 | 1162 | swiotlb_dyn_free(&pool->rcu); |
| 1155 | 1163 | return -1; |
| @@ -1192,9 +1200,21 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr, · 36 unmodified lines | ||
| 1192 | 1200 | size_t alloc_size, unsigned int alloc_align_mask, |
| 1193 | 1201 | struct io_tlb_pool **retpool) |
| 1194 | 1202 | { |
| 1195 | − *retpool = &dev->dma_io_tlb_mem->defpool; | |
| 1196 | − return swiotlb_pool_find_slots(dev, *retpool, | |
| 1197 | − orig_addr, alloc_size, alloc_align_mask); | |
| 1203 | + struct io_tlb_pool *pool; | |
| 1204 | + int start, i; | |
| 1205 | + int index; | |
| 1206 | + | |
| 1207 | + *retpool = pool = &dev->dma_io_tlb_mem->defpool; | |
| 1208 | + i = start = raw_smp_processor_id() & (pool->nareas - 1); | |
| 1209 | + do { | |
| 1210 | + index = swiotlb_search_pool_area(dev, pool, i, orig_addr, | |
| 1211 | + alloc_size, alloc_align_mask); | |
| 1212 | + if (index >= 0) | |
| 1213 | + return index; | |
| 1214 | + if (++i >= pool->nareas) | |
| 1215 | + i = 0; | |
| 1216 | + } while (i != start); | |
| 1217 | + return -1; | |
| 1198 | 1218 | } |
| 1199 | 1219 | |
| 1200 | 1220 | #endif /* CONFIG_SWIOTLB_DYNAMIC */ |