aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-12-01 06:04:58 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2011-12-12 09:19:06 -0500
commit6a113ddc03bcc32d3d440dce42b445868d5be093 (patch)
tree2788087070898e12721ea94ddcde336f748ce7ff /drivers/iommu/amd_iommu.c
parentf3572db823decfd747e6afd4c4ddfd67e8af8b6d (diff)
iommu/amd: Add device errata handling
Add infrastructure for errata-handling and handle two known erratas in the IOMMUv2 code. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r--drivers/iommu/amd_iommu.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 71773d0fb76..e453bbd0944 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -172,6 +172,15 @@ static bool pci_iommuv2_capable(struct pci_dev *pdev)
172 return true; 172 return true;
173} 173}
174 174
175static bool pdev_pri_erratum(struct pci_dev *pdev, u32 erratum)
176{
177 struct iommu_dev_data *dev_data;
178
179 dev_data = get_dev_data(&pdev->dev);
180
181 return dev_data->errata & (1 << erratum) ? true : false;
182}
183
175/* 184/*
176 * In this function the list of preallocated protection domains is traversed to 185 * In this function the list of preallocated protection domains is traversed to
177 * find the domain for a specific device 186 * find the domain for a specific device
@@ -1934,9 +1943,33 @@ static void pdev_iommuv2_disable(struct pci_dev *pdev)
1934 pci_disable_pasid(pdev); 1943 pci_disable_pasid(pdev);
1935} 1944}
1936 1945
1946/* FIXME: Change generic reset-function to do the same */
1947static int pri_reset_while_enabled(struct pci_dev *pdev)
1948{
1949 u16 control;
1950 int pos;
1951
1952 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
1953 if (!pos)
1954 return -EINVAL;
1955
1956 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
1957 control |= PCI_PRI_RESET;
1958 pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
1959
1960 return 0;
1961}
1962
1937static int pdev_iommuv2_enable(struct pci_dev *pdev) 1963static int pdev_iommuv2_enable(struct pci_dev *pdev)
1938{ 1964{
1939 int ret; 1965 bool reset_enable;
1966 int reqs, ret;
1967
1968 /* FIXME: Hardcode number of outstanding requests for now */
1969 reqs = 32;
1970 if (pdev_pri_erratum(pdev, AMD_PRI_DEV_ERRATUM_LIMIT_REQ_ONE))
1971 reqs = 1;
1972 reset_enable = pdev_pri_erratum(pdev, AMD_PRI_DEV_ERRATUM_ENABLE_RESET);
1940 1973
1941 /* Only allow access to user-accessible pages */ 1974 /* Only allow access to user-accessible pages */
1942 ret = pci_enable_pasid(pdev, 0); 1975 ret = pci_enable_pasid(pdev, 0);
@@ -1948,11 +1981,17 @@ static int pdev_iommuv2_enable(struct pci_dev *pdev)
1948 if (ret) 1981 if (ret)
1949 goto out_err; 1982 goto out_err;
1950 1983
1951 /* FIXME: Hardcode number of outstanding requests for now */ 1984 /* Enable PRI */
1952 ret = pci_enable_pri(pdev, 32); 1985 ret = pci_enable_pri(pdev, reqs);
1953 if (ret) 1986 if (ret)
1954 goto out_err; 1987 goto out_err;
1955 1988
1989 if (reset_enable) {
1990 ret = pri_reset_while_enabled(pdev);
1991 if (ret)
1992 goto out_err;
1993 }
1994
1956 ret = pci_enable_ats(pdev, PAGE_SHIFT); 1995 ret = pci_enable_ats(pdev, PAGE_SHIFT);
1957 if (ret) 1996 if (ret)
1958 goto out_err; 1997 goto out_err;
@@ -3481,3 +3520,15 @@ struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev)
3481 return domain->iommu_domain; 3520 return domain->iommu_domain;
3482} 3521}
3483EXPORT_SYMBOL(amd_iommu_get_v2_domain); 3522EXPORT_SYMBOL(amd_iommu_get_v2_domain);
3523
3524void amd_iommu_enable_device_erratum(struct pci_dev *pdev, u32 erratum)
3525{
3526 struct iommu_dev_data *dev_data;
3527
3528 if (!amd_iommu_v2_supported())
3529 return;
3530
3531 dev_data = get_dev_data(&pdev->dev);
3532 dev_data->errata |= (1 << erratum);
3533}
3534EXPORT_SYMBOL(amd_iommu_enable_device_erratum);