Skip to content

Commit 65d5352

Browse files
Alex Williamsonjoergroedel
authored andcommitted
iommu/amd: Use iommu_group_get_for_dev()
The common iommu_group_get_for_dev() allows us to greatly simplify our group lookup for a new device. Also, since we insert IVRS aliases into the PCI DMA alias quirks, we should alway come up with the same results as the existing code. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Cc: Joerg Roedel <joro@8bytes.org> Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent c193109 commit 65d5352

File tree

2 files changed

+5
-160
lines changed

2 files changed

+5
-160
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 5 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
#include "amd_iommu_proto.h"
4747
#include "amd_iommu_types.h"
4848
#include "irq_remapping.h"
49-
#include "pci.h"
5049

5150
#define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
5251

@@ -133,9 +132,6 @@ static void free_dev_data(struct iommu_dev_data *dev_data)
133132
list_del(&dev_data->dev_data_list);
134133
spin_unlock_irqrestore(&dev_data_list_lock, flags);
135134

136-
if (dev_data->group)
137-
iommu_group_put(dev_data->group);
138-
139135
kfree(dev_data);
140136
}
141137

@@ -264,167 +260,17 @@ static bool check_device(struct device *dev)
264260
return true;
265261
}
266262

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-
363263
static int init_iommu_group(struct device *dev)
364264
{
365-
struct iommu_dev_data *dev_data;
366265
struct iommu_group *group;
367-
struct pci_dev *dma_pdev;
368-
int ret;
369266

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);
375268

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);
386271

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;
428274
}
429275

430276
static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)

drivers/iommu/amd_iommu_types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,6 @@ struct iommu_dev_data {
432432
struct iommu_dev_data *alias_data;/* The alias dev_data */
433433
struct protection_domain *domain; /* Domain the device is bound to */
434434
atomic_t bind; /* Domain attach reference count */
435-
struct iommu_group *group; /* IOMMU group for virtual aliases */
436435
u16 devid; /* PCI Device ID */
437436
bool iommu_v2; /* Device can make use of IOMMUv2 */
438437
bool passthrough; /* Default for device is pt_domain */

0 commit comments

Comments
 (0)