diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2018-02-23 09:46:23 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-03-07 16:11:54 -0500 |
commit | ebb043f267511a6e6ba2ee92e0146552432e8db2 (patch) | |
tree | ebc6fce5998699ce67ded595ce58c298ef7658aa /drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |
parent | 65e4b49019029e7effcfc7855af822cd75f28c47 (diff) |
drm/amdgpu: replace iova debugfs file with iomem (v3)
This allows access to pages allocated through the driver with optional
IOMMU mapping.
v2: Fix number of bytes copied and add write method
v3: drop check for kmap return
Original-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 102 |
1 files changed, 81 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index b19a4f7a845e..28c33d711bab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -1957,38 +1957,98 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { | |||
1957 | 1957 | ||
1958 | #endif | 1958 | #endif |
1959 | 1959 | ||
1960 | static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, | 1960 | static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, |
1961 | size_t size, loff_t *pos) | 1961 | size_t size, loff_t *pos) |
1962 | { | 1962 | { |
1963 | struct amdgpu_device *adev = file_inode(f)->i_private; | 1963 | struct amdgpu_device *adev = file_inode(f)->i_private; |
1964 | int r; | ||
1965 | uint64_t phys; | ||
1966 | struct iommu_domain *dom; | 1964 | struct iommu_domain *dom; |
1965 | ssize_t result = 0; | ||
1966 | int r; | ||
1967 | 1967 | ||
1968 | // always return 8 bytes | 1968 | dom = iommu_get_domain_for_dev(adev->dev); |
1969 | if (size != 8) | ||
1970 | return -EINVAL; | ||
1971 | 1969 | ||
1972 | // only accept page addresses | 1970 | while (size) { |
1973 | if (*pos & 0xFFF) | 1971 | phys_addr_t addr = *pos & PAGE_MASK; |
1974 | return -EINVAL; | 1972 | loff_t off = *pos & ~PAGE_MASK; |
1973 | size_t bytes = PAGE_SIZE - off; | ||
1974 | unsigned long pfn; | ||
1975 | struct page *p; | ||
1976 | void *ptr; | ||
1977 | |||
1978 | bytes = bytes < size ? bytes : size; | ||
1979 | |||
1980 | addr = dom ? iommu_iova_to_phys(dom, addr) : addr; | ||
1981 | |||
1982 | pfn = addr >> PAGE_SHIFT; | ||
1983 | if (!pfn_valid(pfn)) | ||
1984 | return -EPERM; | ||
1985 | |||
1986 | p = pfn_to_page(pfn); | ||
1987 | if (p->mapping != adev->mman.bdev.dev_mapping) | ||
1988 | return -EPERM; | ||
1989 | |||
1990 | ptr = kmap(p); | ||
1991 | r = copy_to_user(buf, ptr, bytes); | ||
1992 | kunmap(p); | ||
1993 | if (r) | ||
1994 | return -EFAULT; | ||
1995 | |||
1996 | size -= bytes; | ||
1997 | *pos += bytes; | ||
1998 | result += bytes; | ||
1999 | } | ||
2000 | |||
2001 | return result; | ||
2002 | } | ||
2003 | |||
2004 | static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf, | ||
2005 | size_t size, loff_t *pos) | ||
2006 | { | ||
2007 | struct amdgpu_device *adev = file_inode(f)->i_private; | ||
2008 | struct iommu_domain *dom; | ||
2009 | ssize_t result = 0; | ||
2010 | int r; | ||
1975 | 2011 | ||
1976 | dom = iommu_get_domain_for_dev(adev->dev); | 2012 | dom = iommu_get_domain_for_dev(adev->dev); |
1977 | if (dom) | ||
1978 | phys = iommu_iova_to_phys(dom, *pos); | ||
1979 | else | ||
1980 | phys = *pos; | ||
1981 | 2013 | ||
1982 | r = copy_to_user(buf, &phys, 8); | 2014 | while (size) { |
1983 | if (r) | 2015 | phys_addr_t addr = *pos & PAGE_MASK; |
1984 | return -EFAULT; | 2016 | loff_t off = *pos & ~PAGE_MASK; |
2017 | size_t bytes = PAGE_SIZE - off; | ||
2018 | unsigned long pfn; | ||
2019 | struct page *p; | ||
2020 | void *ptr; | ||
2021 | |||
2022 | bytes = bytes < size ? bytes : size; | ||
1985 | 2023 | ||
1986 | return 8; | 2024 | addr = dom ? iommu_iova_to_phys(dom, addr) : addr; |
2025 | |||
2026 | pfn = addr >> PAGE_SHIFT; | ||
2027 | if (!pfn_valid(pfn)) | ||
2028 | return -EPERM; | ||
2029 | |||
2030 | p = pfn_to_page(pfn); | ||
2031 | if (p->mapping != adev->mman.bdev.dev_mapping) | ||
2032 | return -EPERM; | ||
2033 | |||
2034 | ptr = kmap(p); | ||
2035 | r = copy_from_user(ptr, buf, bytes); | ||
2036 | kunmap(p); | ||
2037 | if (r) | ||
2038 | return -EFAULT; | ||
2039 | |||
2040 | size -= bytes; | ||
2041 | *pos += bytes; | ||
2042 | result += bytes; | ||
2043 | } | ||
2044 | |||
2045 | return result; | ||
1987 | } | 2046 | } |
1988 | 2047 | ||
1989 | static const struct file_operations amdgpu_ttm_iova_fops = { | 2048 | static const struct file_operations amdgpu_ttm_iomem_fops = { |
1990 | .owner = THIS_MODULE, | 2049 | .owner = THIS_MODULE, |
1991 | .read = amdgpu_iova_to_phys_read, | 2050 | .read = amdgpu_iomem_read, |
2051 | .write = amdgpu_iomem_write, | ||
1992 | .llseek = default_llseek | 2052 | .llseek = default_llseek |
1993 | }; | 2053 | }; |
1994 | 2054 | ||
@@ -2001,7 +2061,7 @@ static const struct { | |||
2001 | #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS | 2061 | #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS |
2002 | { "amdgpu_gtt", &amdgpu_ttm_gtt_fops, TTM_PL_TT }, | 2062 | { "amdgpu_gtt", &amdgpu_ttm_gtt_fops, TTM_PL_TT }, |
2003 | #endif | 2063 | #endif |
2004 | { "amdgpu_iova", &amdgpu_ttm_iova_fops, TTM_PL_SYSTEM }, | 2064 | { "amdgpu_iomem", &amdgpu_ttm_iomem_fops, TTM_PL_SYSTEM }, |
2005 | }; | 2065 | }; |
2006 | 2066 | ||
2007 | #endif | 2067 | #endif |