|
46 | 46 | #include "amd_iommu_proto.h" |
47 | 47 | #include "amd_iommu_types.h" |
48 | 48 | #include "irq_remapping.h" |
49 | | -#include "pci.h" |
50 | 49 |
|
51 | 50 | #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28)) |
52 | 51 |
|
@@ -133,9 +132,6 @@ static void free_dev_data(struct iommu_dev_data *dev_data) |
133 | 132 | list_del(&dev_data->dev_data_list); |
134 | 133 | spin_unlock_irqrestore(&dev_data_list_lock, flags); |
135 | 134 |
|
136 | | - if (dev_data->group) |
137 | | - iommu_group_put(dev_data->group); |
138 | | - |
139 | 135 | kfree(dev_data); |
140 | 136 | } |
141 | 137 |
|
@@ -264,167 +260,17 @@ static bool check_device(struct device *dev) |
264 | 260 | return true; |
265 | 261 | } |
266 | 262 |
|
267 | | -static struct pci_bus *find_hosted_bus(struct pci_bus *bus) |
268 | | -{ |
269 | | - while (!bus->self) { |
270 | | - if (!pci_is_root_bus(bus)) |
271 | | - bus = bus->parent; |
272 | | - else |
273 | | - return ERR_PTR(-ENODEV); |
274 | | - } |
275 | | - |
276 | | - return bus; |
277 | | -} |
278 | | - |
279 | | -#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) |
280 | | - |
281 | | -static struct pci_dev *get_isolation_root(struct pci_dev *pdev) |
282 | | -{ |
283 | | - struct pci_dev *dma_pdev = pdev; |
284 | | - |
285 | | - /* Account for quirked devices */ |
286 | | - swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); |
287 | | - |
288 | | - /* |
289 | | - * If it's a multifunction device that does not support our |
290 | | - * required ACS flags, add to the same group as lowest numbered |
291 | | - * function that also does not suport the required ACS flags. |
292 | | - */ |
293 | | - if (dma_pdev->multifunction && |
294 | | - !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { |
295 | | - u8 i, slot = PCI_SLOT(dma_pdev->devfn); |
296 | | - |
297 | | - for (i = 0; i < 8; i++) { |
298 | | - struct pci_dev *tmp; |
299 | | - |
300 | | - tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); |
301 | | - if (!tmp) |
302 | | - continue; |
303 | | - |
304 | | - if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { |
305 | | - swap_pci_ref(&dma_pdev, tmp); |
306 | | - break; |
307 | | - } |
308 | | - pci_dev_put(tmp); |
309 | | - } |
310 | | - } |
311 | | - |
312 | | - /* |
313 | | - * Devices on the root bus go through the iommu. If that's not us, |
314 | | - * find the next upstream device and test ACS up to the root bus. |
315 | | - * Finding the next device may require skipping virtual buses. |
316 | | - */ |
317 | | - while (!pci_is_root_bus(dma_pdev->bus)) { |
318 | | - struct pci_bus *bus = find_hosted_bus(dma_pdev->bus); |
319 | | - if (IS_ERR(bus)) |
320 | | - break; |
321 | | - |
322 | | - if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) |
323 | | - break; |
324 | | - |
325 | | - swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); |
326 | | - } |
327 | | - |
328 | | - return dma_pdev; |
329 | | -} |
330 | | - |
331 | | -static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev) |
332 | | -{ |
333 | | - struct iommu_group *group = iommu_group_get(&pdev->dev); |
334 | | - int ret; |
335 | | - |
336 | | - if (!group) { |
337 | | - group = iommu_group_alloc(); |
338 | | - if (IS_ERR(group)) |
339 | | - return PTR_ERR(group); |
340 | | - |
341 | | - WARN_ON(&pdev->dev != dev); |
342 | | - } |
343 | | - |
344 | | - ret = iommu_group_add_device(group, dev); |
345 | | - iommu_group_put(group); |
346 | | - return ret; |
347 | | -} |
348 | | - |
349 | | -static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data, |
350 | | - struct device *dev) |
351 | | -{ |
352 | | - if (!dev_data->group) { |
353 | | - struct iommu_group *group = iommu_group_alloc(); |
354 | | - if (IS_ERR(group)) |
355 | | - return PTR_ERR(group); |
356 | | - |
357 | | - dev_data->group = group; |
358 | | - } |
359 | | - |
360 | | - return iommu_group_add_device(dev_data->group, dev); |
361 | | -} |
362 | | - |
363 | 263 | static int init_iommu_group(struct device *dev) |
364 | 264 | { |
365 | | - struct iommu_dev_data *dev_data; |
366 | 265 | struct iommu_group *group; |
367 | | - struct pci_dev *dma_pdev; |
368 | | - int ret; |
369 | 266 |
|
370 | | - group = iommu_group_get(dev); |
371 | | - if (group) { |
372 | | - iommu_group_put(group); |
373 | | - return 0; |
374 | | - } |
| 267 | + group = iommu_group_get_for_dev(dev); |
375 | 268 |
|
376 | | - dev_data = find_dev_data(get_device_id(dev)); |
377 | | - if (!dev_data) |
378 | | - return -ENOMEM; |
379 | | - |
380 | | - if (dev_data->alias_data) { |
381 | | - u16 alias; |
382 | | - struct pci_bus *bus; |
383 | | - |
384 | | - if (dev_data->alias_data->group) |
385 | | - goto use_group; |
| 269 | + if (IS_ERR(group)) |
| 270 | + return PTR_ERR(group); |
386 | 271 |
|
387 | | - /* |
388 | | - * If the alias device exists, it's effectively just a first |
389 | | - * level quirk for finding the DMA source. |
390 | | - */ |
391 | | - alias = amd_iommu_alias_table[dev_data->devid]; |
392 | | - dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff); |
393 | | - if (dma_pdev) { |
394 | | - dma_pdev = get_isolation_root(dma_pdev); |
395 | | - goto use_pdev; |
396 | | - } |
397 | | - |
398 | | - /* |
399 | | - * If the alias is virtual, try to find a parent device |
400 | | - * and test whether the IOMMU group is actualy rooted above |
401 | | - * the alias. Be careful to also test the parent device if |
402 | | - * we think the alias is the root of the group. |
403 | | - */ |
404 | | - bus = pci_find_bus(0, alias >> 8); |
405 | | - if (!bus) |
406 | | - goto use_group; |
407 | | - |
408 | | - bus = find_hosted_bus(bus); |
409 | | - if (IS_ERR(bus) || !bus->self) |
410 | | - goto use_group; |
411 | | - |
412 | | - dma_pdev = get_isolation_root(pci_dev_get(bus->self)); |
413 | | - if (dma_pdev != bus->self || (dma_pdev->multifunction && |
414 | | - !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))) |
415 | | - goto use_pdev; |
416 | | - |
417 | | - pci_dev_put(dma_pdev); |
418 | | - goto use_group; |
419 | | - } |
420 | | - |
421 | | - dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev))); |
422 | | -use_pdev: |
423 | | - ret = use_pdev_iommu_group(dma_pdev, dev); |
424 | | - pci_dev_put(dma_pdev); |
425 | | - return ret; |
426 | | -use_group: |
427 | | - return use_dev_data_iommu_group(dev_data->alias_data, dev); |
| 272 | + iommu_group_put(group); |
| 273 | + return 0; |
428 | 274 | } |
429 | 275 |
|
430 | 276 | static int __last_alias(struct pci_dev *pdev, u16 alias, void *data) |
|
0 commit comments