diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2016-07-15 08:52:52 -0400 |
---|---|---|
committer | Vijayakumar Subbu <vsubbu@nvidia.com> | 2016-07-21 08:55:26 -0400 |
commit | 13231006671a1da11cfaf7a67e69430199820788 (patch) | |
tree | 6b4053838d672b158fe636b60768240585a21eb0 /drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |
parent | 83071083d779b67ad73172675a6dfa34ed19b414 (diff) |
gpu: nvgpu: add vidmem allocation ioctl
Add NVGPU_GPU_IOCTL_ALLOC_VIDMEM to the ctrl fd for letting userspace
allocate on-board GPU memory (aka vidmem). The allocations are returned
as dmabuf fds.
Also, report the amount of local video memory in the gpu
characteristics.
Jira DNVGPU-19
Jira DNVGPU-38
Change-Id: I28e361d31bb630b96d06bb1c86d022d91c7592bc
Signed-off-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-on: http://git-master/r/1181152
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index bf3d990c..2dcc4363 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -411,6 +411,14 @@ struct gk20a_dmabuf_priv { | |||
411 | u64 buffer_id; | 411 | u64 buffer_id; |
412 | }; | 412 | }; |
413 | 413 | ||
414 | struct gk20a_vidmem_buf { | ||
415 | struct gk20a *g; | ||
416 | struct mem_desc mem; | ||
417 | struct dma_buf *dmabuf; | ||
418 | void *dmabuf_priv; | ||
419 | void (*dmabuf_priv_delete)(void *); | ||
420 | }; | ||
421 | |||
414 | static void gk20a_vm_remove_support_nofree(struct vm_gk20a *vm); | 422 | static void gk20a_vm_remove_support_nofree(struct vm_gk20a *vm); |
415 | 423 | ||
416 | static int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator, | 424 | static int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator, |
@@ -1833,6 +1841,146 @@ static u64 gk20a_vm_map_duplicate_locked(struct vm_gk20a *vm, | |||
1833 | return mapped_buffer->addr; | 1841 | return mapped_buffer->addr; |
1834 | } | 1842 | } |
1835 | 1843 | ||
1844 | #if defined(CONFIG_GK20A_VIDMEM) | ||
1845 | static struct sg_table *gk20a_vidbuf_map_dma_buf( | ||
1846 | struct dma_buf_attachment *attach, enum dma_data_direction dir) | ||
1847 | { | ||
1848 | struct gk20a_vidmem_buf *buf = attach->dmabuf->priv; | ||
1849 | |||
1850 | return buf->mem.sgt; | ||
1851 | } | ||
1852 | |||
1853 | static void gk20a_vidbuf_unmap_dma_buf(struct dma_buf_attachment *attach, | ||
1854 | struct sg_table *sgt, | ||
1855 | enum dma_data_direction dir) | ||
1856 | { | ||
1857 | } | ||
1858 | |||
1859 | static void gk20a_vidbuf_release(struct dma_buf *dmabuf) | ||
1860 | { | ||
1861 | struct gk20a_vidmem_buf *buf = dmabuf->priv; | ||
1862 | |||
1863 | gk20a_dbg_fn(""); | ||
1864 | |||
1865 | if (buf->dmabuf_priv) | ||
1866 | buf->dmabuf_priv_delete(buf->dmabuf_priv); | ||
1867 | |||
1868 | gk20a_gmmu_free(buf->g, &buf->mem); | ||
1869 | kfree(buf); | ||
1870 | } | ||
1871 | |||
1872 | static void *gk20a_vidbuf_kmap(struct dma_buf *dmabuf, unsigned long page_num) | ||
1873 | { | ||
1874 | WARN_ON("Not supported"); | ||
1875 | return NULL; | ||
1876 | } | ||
1877 | |||
1878 | static void *gk20a_vidbuf_kmap_atomic(struct dma_buf *dmabuf, | ||
1879 | unsigned long page_num) | ||
1880 | { | ||
1881 | WARN_ON("Not supported"); | ||
1882 | return NULL; | ||
1883 | } | ||
1884 | |||
1885 | static int gk20a_vidbuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) | ||
1886 | { | ||
1887 | return -EINVAL; | ||
1888 | } | ||
1889 | |||
1890 | static int gk20a_vidbuf_set_private(struct dma_buf *dmabuf, | ||
1891 | struct device *dev, void *priv, void (*delete)(void *priv)) | ||
1892 | { | ||
1893 | struct gk20a_vidmem_buf *buf = dmabuf->priv; | ||
1894 | |||
1895 | buf->dmabuf_priv = priv; | ||
1896 | buf->dmabuf_priv_delete = delete; | ||
1897 | |||
1898 | return 0; | ||
1899 | } | ||
1900 | |||
1901 | static void *gk20a_vidbuf_get_private(struct dma_buf *dmabuf, | ||
1902 | struct device *dev) | ||
1903 | { | ||
1904 | struct gk20a_vidmem_buf *buf = dmabuf->priv; | ||
1905 | |||
1906 | return buf->dmabuf_priv; | ||
1907 | } | ||
1908 | |||
1909 | static const struct dma_buf_ops gk20a_vidbuf_ops = { | ||
1910 | .map_dma_buf = gk20a_vidbuf_map_dma_buf, | ||
1911 | .unmap_dma_buf = gk20a_vidbuf_unmap_dma_buf, | ||
1912 | .release = gk20a_vidbuf_release, | ||
1913 | .kmap_atomic = gk20a_vidbuf_kmap_atomic, | ||
1914 | .kmap = gk20a_vidbuf_kmap, | ||
1915 | .mmap = gk20a_vidbuf_mmap, | ||
1916 | .set_drvdata = gk20a_vidbuf_set_private, | ||
1917 | .get_drvdata = gk20a_vidbuf_get_private, | ||
1918 | }; | ||
1919 | |||
1920 | static struct dma_buf *gk20a_vidbuf_export(struct gk20a_vidmem_buf *buf) | ||
1921 | { | ||
1922 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) | ||
1923 | DEFINE_DMA_BUF_EXPORT_INFO(exp_info); | ||
1924 | |||
1925 | exp_info.priv = buf; | ||
1926 | exp_info.ops = &gk20a_vidbuf_ops; | ||
1927 | exp_info.size = buf->mem.size; | ||
1928 | exp_info.flags = O_RDWR; | ||
1929 | |||
1930 | return dma_buf_export(&exp_info); | ||
1931 | #else | ||
1932 | return dma_buf_export(buf, &gk20a_vidbuf_ops, buf->mem.size, | ||
1933 | O_RDWR, NULL); | ||
1934 | #endif | ||
1935 | } | ||
1936 | #endif | ||
1937 | |||
1938 | int gk20a_vidmem_buf_alloc(struct gk20a *g, size_t bytes) | ||
1939 | { | ||
1940 | #if defined(CONFIG_GK20A_VIDMEM) | ||
1941 | struct gk20a_vidmem_buf *buf; | ||
1942 | int err, fd; | ||
1943 | |||
1944 | gk20a_dbg_fn(""); | ||
1945 | |||
1946 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); | ||
1947 | if (!buf) | ||
1948 | return -ENOMEM; | ||
1949 | |||
1950 | buf->g = g; | ||
1951 | |||
1952 | err = gk20a_gmmu_alloc_vid(g, bytes, &buf->mem); | ||
1953 | if (err) | ||
1954 | goto err_kfree; | ||
1955 | |||
1956 | buf->dmabuf = gk20a_vidbuf_export(buf); | ||
1957 | if (IS_ERR(buf->dmabuf)) { | ||
1958 | err = PTR_ERR(buf->dmabuf); | ||
1959 | goto err_bfree; | ||
1960 | } | ||
1961 | |||
1962 | fd = get_unused_fd_flags(O_RDWR); | ||
1963 | if (fd < 0) { | ||
1964 | /* ->release frees what we have done */ | ||
1965 | dma_buf_put(buf->dmabuf); | ||
1966 | return fd; | ||
1967 | } | ||
1968 | |||
1969 | /* fclose() on this drops one ref, freeing the dma buf */ | ||
1970 | fd_install(fd, buf->dmabuf->file); | ||
1971 | |||
1972 | return fd; | ||
1973 | |||
1974 | err_bfree: | ||
1975 | gk20a_gmmu_free(g, &buf->mem); | ||
1976 | err_kfree: | ||
1977 | kfree(buf); | ||
1978 | return err; | ||
1979 | #else | ||
1980 | return -ENOSYS; | ||
1981 | #endif | ||
1982 | } | ||
1983 | |||
1836 | u64 gk20a_vm_map(struct vm_gk20a *vm, | 1984 | u64 gk20a_vm_map(struct vm_gk20a *vm, |
1837 | struct dma_buf *dmabuf, | 1985 | struct dma_buf *dmabuf, |
1838 | u64 offset_align, | 1986 | u64 offset_align, |