@@ -1957,18 +1957,71 @@ find_domain(struct pci_dev *pdev)
1957
1957
return NULL ;
1958
1958
}
1959
1959
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
+
1960
2015
/* domain is initialized */
1961
2016
static 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
2019
struct intel_iommu * iommu ;
1965
2020
struct dmar_drhd_unit * drhd ;
1966
- struct device_domain_info * info , * tmp ;
1967
2021
struct pci_dev * dev_tmp ;
1968
2022
unsigned long flags ;
1969
2023
int bus = 0 , devfn = 0 ;
1970
2024
int segment ;
1971
- int ret ;
1972
2025
1973
2026
domain = find_domain (pdev );
1974
2027
if (domain )
@@ -1986,109 +2039,46 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
1986
2039
devfn = dev_tmp -> devfn ;
1987
2040
}
1988
2041
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 );
1996
2043
spin_unlock_irqrestore (& device_domain_lock , flags );
1997
2044
/* pcie-pci bridge already has a domain, uses it */
1998
- if (found ) {
1999
- domain = found ;
2045
+ if (domain )
2000
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
2049
drhd = dmar_find_matched_drhd_unit (pdev );
2010
2050
if (!drhd ) {
2011
2051
printk (KERN_ERR "IOMMU: can't find DMAR for device %s\n" ,
2012
2052
pci_name (pdev ));
2013
- free_domain_mem (domain );
2014
2053
return NULL ;
2015
2054
}
2016
2055
iommu = drhd -> iommu ;
2017
2056
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 )) {
2020
2062
free_domain_mem (domain );
2021
2063
goto error ;
2022
2064
}
2023
-
2024
2065
if (domain_init (domain , gaw )) {
2025
2066
domain_exit (domain );
2026
2067
goto error ;
2027
2068
}
2028
2069
2029
2070
/* register pcie-to-pci device */
2030
2071
if (dev_tmp ) {
2031
- info = alloc_devinfo_mem ();
2032
- if (!info ) {
2072
+ if (dmar_insert_dev_info (segment , bus , devfn , NULL , & domain )) {
2033
2073
domain_exit (domain );
2034
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
2066
2078
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 )
2085
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 ;
2092
2082
error :
2093
2083
/* recheck it here, maybe others set it */
2094
2084
return find_domain (pdev );
0 commit comments