.. | .. |
---|
24 | 24 | /* |
---|
25 | 25 | * Intel IOMMU system wide PASID name space: |
---|
26 | 26 | */ |
---|
27 | | -static DEFINE_SPINLOCK(pasid_lock); |
---|
28 | 27 | u32 intel_pasid_max_id = PASID_MAX; |
---|
29 | 28 | |
---|
30 | 29 | int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid) |
---|
.. | .. |
---|
187 | 186 | attach_out: |
---|
188 | 187 | device_attach_pasid_table(info, pasid_table); |
---|
189 | 188 | |
---|
| 189 | + if (!ecap_coherent(info->iommu->ecap)) |
---|
| 190 | + clflush_cache_range(pasid_table->table, (1 << order) * PAGE_SIZE); |
---|
| 191 | + |
---|
190 | 192 | return 0; |
---|
191 | 193 | } |
---|
192 | 194 | |
---|
.. | .. |
---|
259 | 261 | dir_index = pasid >> PASID_PDE_SHIFT; |
---|
260 | 262 | index = pasid & PASID_PTE_MASK; |
---|
261 | 263 | |
---|
262 | | - spin_lock(&pasid_lock); |
---|
| 264 | +retry: |
---|
263 | 265 | entries = get_pasid_table_from_pde(&dir[dir_index]); |
---|
264 | 266 | if (!entries) { |
---|
265 | 267 | entries = alloc_pgtable_page(info->iommu->node); |
---|
266 | | - if (!entries) { |
---|
267 | | - spin_unlock(&pasid_lock); |
---|
| 268 | + if (!entries) |
---|
268 | 269 | return NULL; |
---|
269 | | - } |
---|
270 | 270 | |
---|
271 | | - WRITE_ONCE(dir[dir_index].val, |
---|
272 | | - (u64)virt_to_phys(entries) | PASID_PTE_PRESENT); |
---|
| 271 | + /* |
---|
| 272 | + * The pasid directory table entry won't be freed after |
---|
| 273 | + * allocation. No worry about the race with free and |
---|
| 274 | + * clear. However, this entry might be populated by others |
---|
| 275 | + * while we are preparing it. Use theirs with a retry. |
---|
| 276 | + */ |
---|
| 277 | + if (cmpxchg64(&dir[dir_index].val, 0ULL, |
---|
| 278 | + (u64)virt_to_phys(entries) | PASID_PTE_PRESENT)) { |
---|
| 279 | + free_pgtable_page(entries); |
---|
| 280 | + goto retry; |
---|
| 281 | + } |
---|
| 282 | + if (!ecap_coherent(info->iommu->ecap)) { |
---|
| 283 | + clflush_cache_range(entries, VTD_PAGE_SIZE); |
---|
| 284 | + clflush_cache_range(&dir[dir_index].val, sizeof(*dir)); |
---|
| 285 | + } |
---|
273 | 286 | } |
---|
274 | | - spin_unlock(&pasid_lock); |
---|
275 | 287 | |
---|
276 | 288 | return &entries[index]; |
---|
277 | 289 | } |
---|