Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 347499
b: refs/heads/master
c: 78bfa9f
h: refs/heads/master
i:
  347497: 511f890
  347495: 50375b5
v: v3
  • Loading branch information
Alex Williamson authored and Joerg Roedel committed Oct 24, 2012
1 parent c6c21a6 commit 3e744ad
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ce7ac4abf2401dfdcb1ac4c7277dab8ed90c8788
refs/heads/master: 78bfa9f395f6bbab168b83f69b99659818517b02
61 changes: 56 additions & 5 deletions trunk/drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ static void free_dev_data(struct iommu_dev_data *dev_data)
list_del(&dev_data->dev_data_list);
spin_unlock_irqrestore(&dev_data_list_lock, flags);

if (dev_data->group)
iommu_group_put(dev_data->group);

kfree(dev_data);
}

Expand Down Expand Up @@ -343,11 +346,25 @@ static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev)
return ret;
}

static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data,
struct device *dev)
{
if (!dev_data->group) {
struct iommu_group *group = iommu_group_alloc();
if (IS_ERR(group))
return PTR_ERR(group);

dev_data->group = group;
}

return iommu_group_add_device(dev_data->group, dev);
}

static int init_iommu_group(struct device *dev)
{
struct iommu_dev_data *dev_data;
struct iommu_group *group;
struct pci_dev *dma_pdev = NULL;
struct pci_dev *dma_pdev;
int ret;

group = iommu_group_get(dev);
Expand All @@ -362,18 +379,52 @@ static int init_iommu_group(struct device *dev)

if (dev_data->alias_data) {
u16 alias;
struct pci_bus *bus;

if (dev_data->alias_data->group)
goto use_group;

/*
* If the alias device exists, it's effectively just a first
* level quirk for finding the DMA source.
*/
alias = amd_iommu_alias_table[dev_data->devid];
dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
}
if (dma_pdev) {
dma_pdev = get_isolation_root(dma_pdev);
goto use_pdev;
}

/*
* If the alias is virtual, try to find a parent device
* and test whether the IOMMU group is actualy rooted above
* the alias. Be careful to also test the parent device if
* we think the alias is the root of the group.
*/
bus = pci_find_bus(0, alias >> 8);
if (!bus)
goto use_group;

bus = find_hosted_bus(bus);
if (IS_ERR(bus) || !bus->self)
goto use_group;

if (!dma_pdev)
dma_pdev = pci_dev_get(to_pci_dev(dev));
dma_pdev = get_isolation_root(pci_dev_get(bus->self));
if (dma_pdev != bus->self || (dma_pdev->multifunction &&
!pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)))
goto use_pdev;

pci_dev_put(dma_pdev);
goto use_group;
}

dma_pdev = get_isolation_root(dma_pdev);
dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
use_pdev:
ret = use_pdev_iommu_group(dma_pdev, dev);
pci_dev_put(dma_pdev);
return ret;
use_group:
return use_dev_data_iommu_group(dev_data->alias_data, dev);
}

static int iommu_init_device(struct device *dev)
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/iommu/amd_iommu_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ struct iommu_dev_data {
struct iommu_dev_data *alias_data;/* The alias dev_data */
struct protection_domain *domain; /* Domain the device is bound to */
atomic_t bind; /* Domain attach reference count */
struct iommu_group *group; /* IOMMU group for virtual aliases */
u16 devid; /* PCI Device ID */
bool iommu_v2; /* Device can make use of IOMMUv2 */
bool passthrough; /* Default for device is pt_domain */
Expand Down

0 comments on commit 3e744ad

Please sign in to comment.