diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2009-06-26 14:10:36 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-06-29 07:37:44 -0400 |
commit | c7ab48d2acaf959e4d59c3f55d12fdb7ca9afd7c (patch) | |
tree | 5474dadf86c95ddf3b347000f5c114f154e7a0ab /drivers/pci/intel-iommu.c | |
parent | b213203e475212a69ad6fedfb73464087e317148 (diff) |
intel-iommu: Clean up identity mapping code, remove CONFIG_DMAR_GFX_WA
There's no need for the GFX workaround now we have 'iommu=pt' for the
cases where people really care about performance. There's no need to
have a special case for just one type of device.
This also speeds up the iommu=pt path and reduces memory usage by
setting up the si_domain _once_ and then using it for all devices,
rather than giving each device its own private page tables.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r-- | drivers/pci/intel-iommu.c | 107 |
1 files changed, 32 insertions, 75 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3a4f347e2f88..fc121967cb5b 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1889,11 +1889,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, | |||
1889 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 1889 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
1890 | pci_name(pdev), start, end); | 1890 | pci_name(pdev), start, end); |
1891 | 1891 | ||
1892 | if (iommu_identity_mapping) | 1892 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
1893 | domain = si_domain; | ||
1894 | else | ||
1895 | /* page table init */ | ||
1896 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | ||
1897 | if (!domain) | 1893 | if (!domain) |
1898 | return -ENOMEM; | 1894 | return -ENOMEM; |
1899 | 1895 | ||
@@ -1922,64 +1918,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | |||
1922 | rmrr->end_address + 1); | 1918 | rmrr->end_address + 1); |
1923 | } | 1919 | } |
1924 | 1920 | ||
1925 | struct iommu_prepare_data { | ||
1926 | struct pci_dev *pdev; | ||
1927 | int ret; | ||
1928 | }; | ||
1929 | |||
1930 | static int __init iommu_prepare_work_fn(unsigned long start_pfn, | ||
1931 | unsigned long end_pfn, void *datax) | ||
1932 | { | ||
1933 | struct iommu_prepare_data *data; | ||
1934 | |||
1935 | data = (struct iommu_prepare_data *)datax; | ||
1936 | |||
1937 | data->ret = iommu_prepare_identity_map(data->pdev, | ||
1938 | start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
1939 | return data->ret; | ||
1940 | |||
1941 | } | ||
1942 | |||
1943 | static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) | ||
1944 | { | ||
1945 | int nid; | ||
1946 | struct iommu_prepare_data data; | ||
1947 | |||
1948 | data.pdev = pdev; | ||
1949 | data.ret = 0; | ||
1950 | |||
1951 | for_each_online_node(nid) { | ||
1952 | work_with_active_regions(nid, iommu_prepare_work_fn, &data); | ||
1953 | if (data.ret) | ||
1954 | return data.ret; | ||
1955 | } | ||
1956 | return data.ret; | ||
1957 | } | ||
1958 | |||
1959 | #ifdef CONFIG_DMAR_GFX_WA | ||
1960 | static void __init iommu_prepare_gfx_mapping(void) | ||
1961 | { | ||
1962 | struct pci_dev *pdev = NULL; | ||
1963 | int ret; | ||
1964 | |||
1965 | for_each_pci_dev(pdev) { | ||
1966 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || | ||
1967 | !IS_GFX_DEVICE(pdev)) | ||
1968 | continue; | ||
1969 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | ||
1970 | pci_name(pdev)); | ||
1971 | ret = iommu_prepare_with_active_regions(pdev); | ||
1972 | if (ret) | ||
1973 | printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | ||
1974 | } | ||
1975 | } | ||
1976 | #else /* !CONFIG_DMAR_GFX_WA */ | ||
1977 | static inline void iommu_prepare_gfx_mapping(void) | ||
1978 | { | ||
1979 | return; | ||
1980 | } | ||
1981 | #endif | ||
1982 | |||
1983 | #ifdef CONFIG_DMAR_FLOPPY_WA | 1921 | #ifdef CONFIG_DMAR_FLOPPY_WA |
1984 | static inline void iommu_prepare_isa(void) | 1922 | static inline void iommu_prepare_isa(void) |
1985 | { | 1923 | { |
@@ -1990,12 +1928,12 @@ static inline void iommu_prepare_isa(void) | |||
1990 | if (!pdev) | 1928 | if (!pdev) |
1991 | return; | 1929 | return; |
1992 | 1930 | ||
1993 | printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); | 1931 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); |
1994 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); | 1932 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
1995 | 1933 | ||
1996 | if (ret) | 1934 | if (ret) |
1997 | printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " | 1935 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " |
1998 | "floppy might not work\n"); | 1936 | "floppy might not work\n"); |
1999 | 1937 | ||
2000 | } | 1938 | } |
2001 | #else | 1939 | #else |
@@ -2023,16 +1961,30 @@ static int __init init_context_pass_through(void) | |||
2023 | } | 1961 | } |
2024 | 1962 | ||
2025 | static int md_domain_init(struct dmar_domain *domain, int guest_width); | 1963 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
1964 | |||
1965 | static int __init si_domain_work_fn(unsigned long start_pfn, | ||
1966 | unsigned long end_pfn, void *datax) | ||
1967 | { | ||
1968 | int *ret = datax; | ||
1969 | |||
1970 | *ret = iommu_domain_identity_map(si_domain, | ||
1971 | (uint64_t)start_pfn << PAGE_SHIFT, | ||
1972 | (uint64_t)end_pfn << PAGE_SHIFT); | ||
1973 | return *ret; | ||
1974 | |||
1975 | } | ||
1976 | |||
2026 | static int si_domain_init(void) | 1977 | static int si_domain_init(void) |
2027 | { | 1978 | { |
2028 | struct dmar_drhd_unit *drhd; | 1979 | struct dmar_drhd_unit *drhd; |
2029 | struct intel_iommu *iommu; | 1980 | struct intel_iommu *iommu; |
2030 | int ret = 0; | 1981 | int nid, ret = 0; |
2031 | 1982 | ||
2032 | si_domain = alloc_domain(); | 1983 | si_domain = alloc_domain(); |
2033 | if (!si_domain) | 1984 | if (!si_domain) |
2034 | return -EFAULT; | 1985 | return -EFAULT; |
2035 | 1986 | ||
1987 | pr_debug("Identity mapping domain is domain %d\n", si_domain->id); | ||
2036 | 1988 | ||
2037 | for_each_active_iommu(iommu, drhd) { | 1989 | for_each_active_iommu(iommu, drhd) { |
2038 | ret = iommu_attach_domain(si_domain, iommu); | 1990 | ret = iommu_attach_domain(si_domain, iommu); |
@@ -2049,6 +2001,12 @@ static int si_domain_init(void) | |||
2049 | 2001 | ||
2050 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | 2002 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; |
2051 | 2003 | ||
2004 | for_each_online_node(nid) { | ||
2005 | work_with_active_regions(nid, si_domain_work_fn, &ret); | ||
2006 | if (ret) | ||
2007 | return ret; | ||
2008 | } | ||
2009 | |||
2052 | return 0; | 2010 | return 0; |
2053 | } | 2011 | } |
2054 | 2012 | ||
@@ -2102,13 +2060,14 @@ static int iommu_prepare_static_identity_mapping(void) | |||
2102 | if (ret) | 2060 | if (ret) |
2103 | return -EFAULT; | 2061 | return -EFAULT; |
2104 | 2062 | ||
2105 | printk(KERN_INFO "IOMMU: Setting identity map:\n"); | ||
2106 | for_each_pci_dev(pdev) { | 2063 | for_each_pci_dev(pdev) { |
2107 | ret = iommu_prepare_with_active_regions(pdev); | 2064 | printk(KERN_INFO "IOMMU: identity mapping for device %s\n", |
2108 | if (ret) { | 2065 | pci_name(pdev)); |
2109 | printk(KERN_INFO "1:1 mapping to one domain failed.\n"); | 2066 | |
2110 | return -EFAULT; | 2067 | ret = domain_context_mapping(si_domain, pdev, |
2111 | } | 2068 | CONTEXT_TT_MULTI_LEVEL); |
2069 | if (ret) | ||
2070 | return ret; | ||
2112 | ret = domain_add_dev_info(si_domain, pdev); | 2071 | ret = domain_add_dev_info(si_domain, pdev); |
2113 | if (ret) | 2072 | if (ret) |
2114 | return ret; | 2073 | return ret; |
@@ -2299,8 +2258,6 @@ int __init init_dmars(void) | |||
2299 | } | 2258 | } |
2300 | } | 2259 | } |
2301 | 2260 | ||
2302 | iommu_prepare_gfx_mapping(); | ||
2303 | |||
2304 | iommu_prepare_isa(); | 2261 | iommu_prepare_isa(); |
2305 | } | 2262 | } |
2306 | 2263 | ||