diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2017-09-18 07:28:14 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-09-26 15:14:04 -0400 |
commit | 38290b2c456ade70db7cedf489332af5e4263fb0 (patch) | |
tree | 6fa6bf91c990c0ed845646a401948db9f781ca07 /drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |
parent | a40cfa0bef9366ad156717078dae681305099a15 (diff) |
drm/amd/amdgpu: add support for iova_to_phys to replace TTM trace (v5)
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(v2): Add domain to iova debugfs
(v3): Add true read/write methods to access system memory of pages
mapped to the device
(v4): Move get_domain call out of loop and return on error
(v5): Just use kmap/kunmap
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 50d20903de4f..c7f8e081a772 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/swap.h> | 43 | #include <linux/swap.h> |
44 | #include <linux/pagemap.h> | 44 | #include <linux/pagemap.h> |
45 | #include <linux/debugfs.h> | 45 | #include <linux/debugfs.h> |
46 | #include <linux/iommu.h> | ||
46 | #include "amdgpu.h" | 47 | #include "amdgpu.h" |
47 | #include "amdgpu_trace.h" | 48 | #include "amdgpu_trace.h" |
48 | #include "bif/bif_4_1_d.h" | 49 | #include "bif/bif_4_1_d.h" |
@@ -1809,7 +1810,104 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { | |||
1809 | 1810 | ||
1810 | #endif | 1811 | #endif |
1811 | 1812 | ||
1813 | static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, | ||
1814 | size_t size, loff_t *pos) | ||
1815 | { | ||
1816 | struct amdgpu_device *adev = file_inode(f)->i_private; | ||
1817 | ssize_t result, n; | ||
1818 | int r; | ||
1819 | uint64_t phys; | ||
1820 | void *ptr; | ||
1821 | struct iommu_domain *dom; | ||
1822 | |||
1823 | dom = iommu_get_domain_for_dev(adev->dev); | ||
1824 | if (!dom) | ||
1825 | return -EFAULT; | ||
1826 | |||
1827 | result = 0; | ||
1828 | while (size) { | ||
1829 | // get physical address and map | ||
1830 | phys = iommu_iova_to_phys(dom, *pos); | ||
1831 | |||
1832 | // copy upto one page | ||
1833 | if (size > PAGE_SIZE) | ||
1834 | n = PAGE_SIZE; | ||
1835 | else | ||
1836 | n = size; | ||
1837 | |||
1838 | // to end of the page | ||
1839 | if (((*pos & (PAGE_SIZE - 1)) + n) >= PAGE_SIZE) | ||
1840 | n = PAGE_SIZE - (*pos & (PAGE_SIZE - 1)); | ||
1841 | |||
1842 | ptr = kmap(pfn_to_page(PFN_DOWN(phys))); | ||
1843 | if (!ptr) | ||
1844 | return -EFAULT; | ||
1845 | |||
1846 | r = copy_to_user(buf, ptr, n); | ||
1847 | kunmap(pfn_to_page(PFN_DOWN(phys))); | ||
1848 | if (r) | ||
1849 | return -EFAULT; | ||
1850 | |||
1851 | *pos += n; | ||
1852 | size -= n; | ||
1853 | result += n; | ||
1854 | } | ||
1855 | |||
1856 | return result; | ||
1857 | } | ||
1858 | |||
1859 | static ssize_t amdgpu_iova_to_phys_write(struct file *f, const char __user *buf, | ||
1860 | size_t size, loff_t *pos) | ||
1861 | { | ||
1862 | struct amdgpu_device *adev = file_inode(f)->i_private; | ||
1863 | ssize_t result, n; | ||
1864 | int r; | ||
1865 | uint64_t phys; | ||
1866 | void *ptr; | ||
1867 | struct iommu_domain *dom; | ||
1868 | |||
1869 | dom = iommu_get_domain_for_dev(adev->dev); | ||
1870 | if (!dom) | ||
1871 | return -EFAULT; | ||
1872 | |||
1873 | result = 0; | ||
1874 | while (size) { | ||
1875 | // get physical address and map | ||
1876 | phys = iommu_iova_to_phys(dom, *pos); | ||
1812 | 1877 | ||
1878 | // copy upto one page | ||
1879 | if (size > PAGE_SIZE) | ||
1880 | n = PAGE_SIZE; | ||
1881 | else | ||
1882 | n = size; | ||
1883 | |||
1884 | // to end of the page | ||
1885 | if (((*pos & (PAGE_SIZE - 1)) + n) >= PAGE_SIZE) | ||
1886 | n = PAGE_SIZE - (*pos & (PAGE_SIZE - 1)); | ||
1887 | |||
1888 | ptr = kmap(pfn_to_page(PFN_DOWN(phys))); | ||
1889 | if (!ptr) | ||
1890 | return -EFAULT; | ||
1891 | |||
1892 | r = copy_from_user(ptr, buf, n); | ||
1893 | kunmap(pfn_to_page(PFN_DOWN(phys))); | ||
1894 | if (r) | ||
1895 | return -EFAULT; | ||
1896 | |||
1897 | *pos += n; | ||
1898 | size -= n; | ||
1899 | result += n; | ||
1900 | } | ||
1901 | |||
1902 | return result; | ||
1903 | } | ||
1904 | |||
1905 | static const struct file_operations amdgpu_ttm_iova_fops = { | ||
1906 | .owner = THIS_MODULE, | ||
1907 | .read = amdgpu_iova_to_phys_read, | ||
1908 | .write = amdgpu_iova_to_phys_write, | ||
1909 | .llseek = default_llseek | ||
1910 | }; | ||
1813 | 1911 | ||
1814 | static const struct { | 1912 | static const struct { |
1815 | char *name; | 1913 | char *name; |
@@ -1820,6 +1918,7 @@ static const struct { | |||
1820 | #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS | 1918 | #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS |
1821 | { "amdgpu_gtt", &amdgpu_ttm_gtt_fops, TTM_PL_TT }, | 1919 | { "amdgpu_gtt", &amdgpu_ttm_gtt_fops, TTM_PL_TT }, |
1822 | #endif | 1920 | #endif |
1921 | { "amdgpu_iova", &amdgpu_ttm_iova_fops, TTM_PL_SYSTEM }, | ||
1823 | }; | 1922 | }; |
1824 | 1923 | ||
1825 | #endif | 1924 | #endif |