aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-06-09 11:48:39 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2011-06-14 06:49:58 -0400
commit2b02b091ab3d1685926bfc76486bf7a22d92979a (patch)
tree0f4279ee639695f4e4934f32b46fccf495819acf
parentec9e79ef062272a119994c4fdd5e434f3e1bf352 (diff)
x86/amd-iommu: Allow dev_data->alias to be NULL
Let dev_data->alias be just NULL if the device has no alias. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r--arch/x86/kernel/amd_iommu.c77
1 files changed, 41 insertions, 36 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index a15a1723190..2d914a49b19 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -183,12 +183,14 @@ static int iommu_init_device(struct device *dev)
183 return -ENOMEM; 183 return -ENOMEM;
184 184
185 alias = amd_iommu_alias_table[dev_data->devid]; 185 alias = amd_iommu_alias_table[dev_data->devid];
186 pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff); 186 if (alias != dev_data->devid) {
187 if (pdev) 187 pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
188 dev_data->alias = &pdev->dev; 188 if (pdev)
189 else { 189 dev_data->alias = &pdev->dev;
190 free_dev_data(dev_data); 190 else {
191 return -ENOTSUPP; 191 free_dev_data(dev_data);
192 return -ENOTSUPP;
193 }
192 } 194 }
193 195
194 dev->archdata.iommu = dev_data; 196 dev->archdata.iommu = dev_data;
@@ -1604,29 +1606,31 @@ static void do_detach(struct iommu_dev_data *dev_data)
1604static int __attach_device(struct iommu_dev_data *dev_data, 1606static int __attach_device(struct iommu_dev_data *dev_data,
1605 struct protection_domain *domain) 1607 struct protection_domain *domain)
1606{ 1608{
1607 struct iommu_dev_data *alias_data;
1608 int ret; 1609 int ret;
1609 1610
1610 alias_data = get_dev_data(dev_data->alias);
1611
1612 if (!alias_data)
1613 return -EINVAL;
1614
1615 /* lock domain */ 1611 /* lock domain */
1616 spin_lock(&domain->lock); 1612 spin_lock(&domain->lock);
1617 1613
1618 /* Some sanity checks */ 1614 if (dev_data->alias != NULL) {
1619 ret = -EBUSY; 1615 struct iommu_dev_data *alias_data;
1620 if (alias_data->domain != NULL && 1616
1621 alias_data->domain != domain) 1617 alias_data = get_dev_data(dev_data->alias);
1622 goto out_unlock; 1618
1619 ret = -EINVAL;
1620 if (!alias_data)
1621 goto out_unlock;
1623 1622
1624 if (dev_data->domain != NULL && 1623 /* Some sanity checks */
1625 dev_data->domain != domain) 1624 ret = -EBUSY;
1626 goto out_unlock; 1625 if (alias_data->domain != NULL &&
1626 alias_data->domain != domain)
1627 goto out_unlock;
1627 1628
1628 /* Do real assignment */ 1629 if (dev_data->domain != NULL &&
1629 if (dev_data->devid != alias_data->devid) { 1630 dev_data->domain != domain)
1631 goto out_unlock;
1632
1633 /* Do real assignment */
1630 if (alias_data->domain == NULL) 1634 if (alias_data->domain == NULL)
1631 do_attach(alias_data, domain); 1635 do_attach(alias_data, domain);
1632 1636
@@ -1696,8 +1700,8 @@ static void __detach_device(struct iommu_dev_data *dev_data)
1696 1700
1697 spin_lock_irqsave(&domain->lock, flags); 1701 spin_lock_irqsave(&domain->lock, flags);
1698 1702
1699 alias_data = get_dev_data(dev_data->alias); 1703 if (dev_data->alias) {
1700 if (dev_data->devid != alias_data->devid) { 1704 alias_data = get_dev_data(dev_data->alias);
1701 if (atomic_dec_and_test(&alias_data->bind)) 1705 if (atomic_dec_and_test(&alias_data->bind))
1702 do_detach(alias_data); 1706 do_detach(alias_data);
1703 } 1707 }
@@ -1744,24 +1748,25 @@ static void detach_device(struct device *dev)
1744 */ 1748 */
1745static struct protection_domain *domain_for_device(struct device *dev) 1749static struct protection_domain *domain_for_device(struct device *dev)
1746{ 1750{
1747 struct protection_domain *dom;
1748 struct iommu_dev_data *dev_data, *alias_data; 1751 struct iommu_dev_data *dev_data, *alias_data;
1752 struct protection_domain *dom = NULL;
1749 unsigned long flags; 1753 unsigned long flags;
1750 1754
1751 dev_data = get_dev_data(dev); 1755 dev_data = get_dev_data(dev);
1752 alias_data = get_dev_data(dev_data->alias);
1753 if (!alias_data)
1754 return NULL;
1755 1756
1756 read_lock_irqsave(&amd_iommu_devtable_lock, flags); 1757 if (dev_data->domain)
1757 dom = dev_data->domain; 1758 return dev_data->domain;
1758 if (dom == NULL &&
1759 alias_data->domain != NULL) {
1760 __attach_device(dev_data, alias_data->domain);
1761 dom = alias_data->domain;
1762 }
1763 1759
1764 read_unlock_irqrestore(&amd_iommu_devtable_lock, flags); 1760 if (dev_data->alias != NULL) {
1761 alias_data = get_dev_data(dev_data->alias);
1762
1763 read_lock_irqsave(&amd_iommu_devtable_lock, flags);
1764 if (alias_data->domain != NULL) {
1765 __attach_device(dev_data, alias_data->domain);
1766 dom = alias_data->domain;
1767 }
1768 read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
1769 }
1765 1770
1766 return dom; 1771 return dom;
1767} 1772}