aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-02-19 01:07:26 -0500
committerJoerg Roedel <joro@8bytes.org>2014-03-04 11:51:01 -0500
commit745f2586e78efc5c226a60cfc8e7fbd735b1c856 (patch)
treebc4cb38cbf06f6df84d9e353bbed4a4f12c5b46d
parentb94e4117f8c4ffb591b1e462364d725e3a1c63c4 (diff)
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 <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
-rw-r--r--drivers/iommu/intel-iommu.c142
1 files changed, 66 insertions, 76 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index fffe3d166662..67b114e784bc 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1957,18 +1957,71 @@ find_domain(struct pci_dev *pdev)
1957 return NULL; 1957 return NULL;
1958} 1958}
1959 1959
1960static inline struct dmar_domain *
1961dmar_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
1973static 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
1960/* domain is initialized */ 2015/* domain is initialized */
1961static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) 2016static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
1962{ 2017{
1963 struct dmar_domain *domain, *found = NULL; 2018 struct dmar_domain *domain;
1964 struct intel_iommu *iommu; 2019 struct intel_iommu *iommu;
1965 struct dmar_drhd_unit *drhd; 2020 struct dmar_drhd_unit *drhd;
1966 struct device_domain_info *info, *tmp;
1967 struct pci_dev *dev_tmp; 2021 struct pci_dev *dev_tmp;
1968 unsigned long flags; 2022 unsigned long flags;
1969 int bus = 0, devfn = 0; 2023 int bus = 0, devfn = 0;
1970 int segment; 2024 int segment;
1971 int ret;
1972 2025
1973 domain = find_domain(pdev); 2026 domain = find_domain(pdev);
1974 if (domain) 2027 if (domain)
@@ -1986,41 +2039,29 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
1986 devfn = dev_tmp->devfn; 2039 devfn = dev_tmp->devfn;
1987 } 2040 }
1988 spin_lock_irqsave(&device_domain_lock, flags); 2041 spin_lock_irqsave(&device_domain_lock, flags);
1989 list_for_each_entry(info, &device_domain_list, global) { 2042 domain = dmar_search_domain_by_dev_info(segment, bus, devfn);
1990 if (info->segment == segment &&
1991 info->bus == bus && info->devfn == devfn) {
1992 found = info->domain;
1993 break;
1994 }
1995 }
1996 spin_unlock_irqrestore(&device_domain_lock, flags); 2043 spin_unlock_irqrestore(&device_domain_lock, flags);
1997 /* pcie-pci bridge already has a domain, uses it */ 2044 /* pcie-pci bridge already has a domain, uses it */
1998 if (found) { 2045 if (domain)
1999 domain = found;
2000 goto found_domain; 2046 goto found_domain;
2001 }
2002 } 2047 }
2003 2048
2004 domain = alloc_domain();
2005 if (!domain)
2006 goto error;
2007
2008 /* Allocate new domain for the device */
2009 drhd = dmar_find_matched_drhd_unit(pdev); 2049 drhd = dmar_find_matched_drhd_unit(pdev);
2010 if (!drhd) { 2050 if (!drhd) {
2011 printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n", 2051 printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
2012 pci_name(pdev)); 2052 pci_name(pdev));
2013 free_domain_mem(domain);
2014 return NULL; 2053 return NULL;
2015 } 2054 }
2016 iommu = drhd->iommu; 2055 iommu = drhd->iommu;
2017 2056
2018 ret = iommu_attach_domain(domain, iommu); 2057 /* Allocate and intialize new domain for the device */
2019 if (ret) { 2058 domain = alloc_domain();
2059 if (!domain)
2060 goto error;
2061 if (iommu_attach_domain(domain, iommu)) {
2020 free_domain_mem(domain); 2062 free_domain_mem(domain);
2021 goto error; 2063 goto error;
2022 } 2064 }
2023
2024 if (domain_init(domain, gaw)) { 2065 if (domain_init(domain, gaw)) {
2025 domain_exit(domain); 2066 domain_exit(domain);
2026 goto error; 2067 goto error;
@@ -2028,67 +2069,16 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
2028 2069
2029 /* register pcie-to-pci device */ 2070 /* register pcie-to-pci device */
2030 if (dev_tmp) { 2071 if (dev_tmp) {
2031 info = alloc_devinfo_mem(); 2072 if (dmar_insert_dev_info(segment, bus, devfn, NULL, &domain)) {
2032 if (!info) {
2033 domain_exit(domain); 2073 domain_exit(domain);
2034 goto error; 2074 goto error;
2035 } 2075 }
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 }
2064 } 2076 }
2065 2077
2066found_domain: 2078found_domain:
2067 info = alloc_devinfo_mem(); 2079 if (dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
2068 if (!info) 2080 pdev, &domain) == 0)
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);
2085 return domain; 2081 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;
2092error: 2082error:
2093 /* recheck it here, maybe others set it */ 2083 /* recheck it here, maybe others set it */
2094 return find_domain(pdev); 2084 return find_domain(pdev);