Skip to content

Commit 745f258

Browse files
Jiang Liujoergroedel
Jiang Liu
authored andcommitted
iommu/vt-d: Simplify function get_domain_for_dev()
Function get_domain_for_dev() is a little complex, simplify it by factoring out dmar_search_domain_by_dev_info() and dmar_insert_dev_info(). Signed-off-by: Jiang Liu <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent b94e411 commit 745f258

File tree

1 file changed

+66
-76
lines changed

1 file changed

+66
-76
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 66 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,18 +1957,71 @@ find_domain(struct pci_dev *pdev)
19571957
return NULL;
19581958
}
19591959

1960+
static inline struct dmar_domain *
1961+
dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
1962+
{
1963+
struct device_domain_info *info;
1964+
1965+
list_for_each_entry(info, &device_domain_list, global)
1966+
if (info->segment == segment && info->bus == bus &&
1967+
info->devfn == devfn)
1968+
return info->domain;
1969+
1970+
return NULL;
1971+
}
1972+
1973+
static int dmar_insert_dev_info(int segment, int bus, int devfn,
1974+
struct pci_dev *dev, struct dmar_domain **domp)
1975+
{
1976+
struct dmar_domain *found, *domain = *domp;
1977+
struct device_domain_info *info;
1978+
unsigned long flags;
1979+
1980+
info = alloc_devinfo_mem();
1981+
if (!info)
1982+
return -ENOMEM;
1983+
1984+
info->segment = segment;
1985+
info->bus = bus;
1986+
info->devfn = devfn;
1987+
info->dev = dev;
1988+
info->domain = domain;
1989+
if (!dev)
1990+
domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
1991+
1992+
spin_lock_irqsave(&device_domain_lock, flags);
1993+
if (dev)
1994+
found = find_domain(dev);
1995+
else
1996+
found = dmar_search_domain_by_dev_info(segment, bus, devfn);
1997+
if (found) {
1998+
spin_unlock_irqrestore(&device_domain_lock, flags);
1999+
free_devinfo_mem(info);
2000+
if (found != domain) {
2001+
domain_exit(domain);
2002+
*domp = found;
2003+
}
2004+
} else {
2005+
list_add(&info->link, &domain->devices);
2006+
list_add(&info->global, &device_domain_list);
2007+
if (dev)
2008+
dev->dev.archdata.iommu = info;
2009+
spin_unlock_irqrestore(&device_domain_lock, flags);
2010+
}
2011+
2012+
return 0;
2013+
}
2014+
19602015
/* domain is initialized */
19612016
static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
19622017
{
1963-
struct dmar_domain *domain, *found = NULL;
2018+
struct dmar_domain *domain;
19642019
struct intel_iommu *iommu;
19652020
struct dmar_drhd_unit *drhd;
1966-
struct device_domain_info *info, *tmp;
19672021
struct pci_dev *dev_tmp;
19682022
unsigned long flags;
19692023
int bus = 0, devfn = 0;
19702024
int segment;
1971-
int ret;
19722025

19732026
domain = find_domain(pdev);
19742027
if (domain)
@@ -1986,109 +2039,46 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
19862039
devfn = dev_tmp->devfn;
19872040
}
19882041
spin_lock_irqsave(&device_domain_lock, flags);
1989-
list_for_each_entry(info, &device_domain_list, global) {
1990-
if (info->segment == segment &&
1991-
info->bus == bus && info->devfn == devfn) {
1992-
found = info->domain;
1993-
break;
1994-
}
1995-
}
2042+
domain = dmar_search_domain_by_dev_info(segment, bus, devfn);
19962043
spin_unlock_irqrestore(&device_domain_lock, flags);
19972044
/* pcie-pci bridge already has a domain, uses it */
1998-
if (found) {
1999-
domain = found;
2045+
if (domain)
20002046
goto found_domain;
2001-
}
20022047
}
20032048

2004-
domain = alloc_domain();
2005-
if (!domain)
2006-
goto error;
2007-
2008-
/* Allocate new domain for the device */
20092049
drhd = dmar_find_matched_drhd_unit(pdev);
20102050
if (!drhd) {
20112051
printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
20122052
pci_name(pdev));
2013-
free_domain_mem(domain);
20142053
return NULL;
20152054
}
20162055
iommu = drhd->iommu;
20172056

2018-
ret = iommu_attach_domain(domain, iommu);
2019-
if (ret) {
2057+
/* Allocate and intialize new domain for the device */
2058+
domain = alloc_domain();
2059+
if (!domain)
2060+
goto error;
2061+
if (iommu_attach_domain(domain, iommu)) {
20202062
free_domain_mem(domain);
20212063
goto error;
20222064
}
2023-
20242065
if (domain_init(domain, gaw)) {
20252066
domain_exit(domain);
20262067
goto error;
20272068
}
20282069

20292070
/* register pcie-to-pci device */
20302071
if (dev_tmp) {
2031-
info = alloc_devinfo_mem();
2032-
if (!info) {
2072+
if (dmar_insert_dev_info(segment, bus, devfn, NULL, &domain)) {
20332073
domain_exit(domain);
20342074
goto error;
20352075
}
2036-
info->segment = segment;
2037-
info->bus = bus;
2038-
info->devfn = devfn;
2039-
info->dev = NULL;
2040-
info->domain = domain;
2041-
/* This domain is shared by devices under p2p bridge */
2042-
domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
2043-
2044-
/* pcie-to-pci bridge already has a domain, uses it */
2045-
found = NULL;
2046-
spin_lock_irqsave(&device_domain_lock, flags);
2047-
list_for_each_entry(tmp, &device_domain_list, global) {
2048-
if (tmp->segment == segment &&
2049-
tmp->bus == bus && tmp->devfn == devfn) {
2050-
found = tmp->domain;
2051-
break;
2052-
}
2053-
}
2054-
if (found) {
2055-
spin_unlock_irqrestore(&device_domain_lock, flags);
2056-
free_devinfo_mem(info);
2057-
domain_exit(domain);
2058-
domain = found;
2059-
} else {
2060-
list_add(&info->link, &domain->devices);
2061-
list_add(&info->global, &device_domain_list);
2062-
spin_unlock_irqrestore(&device_domain_lock, flags);
2063-
}
20642076
}
20652077

20662078
found_domain:
2067-
info = alloc_devinfo_mem();
2068-
if (!info)
2069-
goto error;
2070-
info->segment = segment;
2071-
info->bus = pdev->bus->number;
2072-
info->devfn = pdev->devfn;
2073-
info->dev = pdev;
2074-
info->domain = domain;
2075-
spin_lock_irqsave(&device_domain_lock, flags);
2076-
/* somebody is fast */
2077-
found = find_domain(pdev);
2078-
if (found != NULL) {
2079-
spin_unlock_irqrestore(&device_domain_lock, flags);
2080-
if (found != domain) {
2081-
domain_exit(domain);
2082-
domain = found;
2083-
}
2084-
free_devinfo_mem(info);
2079+
if (dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
2080+
pdev, &domain) == 0)
20852081
return domain;
2086-
}
2087-
list_add(&info->link, &domain->devices);
2088-
list_add(&info->global, &device_domain_list);
2089-
pdev->dev.archdata.iommu = info;
2090-
spin_unlock_irqrestore(&device_domain_lock, flags);
2091-
return domain;
20922082
error:
20932083
/* recheck it here, maybe others set it */
20942084
return find_domain(pdev);

0 commit comments

Comments
 (0)