Loading drivers/gpu/drm/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ msm-y := \ msm_drv.o \ msm_fb.o \ msm_gem.o \ msm_gem_prime.o \ msm_gem_submit.o \ msm_gpu.o \ msm_ringbuffer.o Loading drivers/gpu/drm/msm/msm_drv.c +14 −1 Original line number Diff line number Diff line Loading @@ -680,7 +680,10 @@ static const struct file_operations fops = { }; static struct drm_driver msm_driver = { .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET, .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_PRIME | DRIVER_MODESET, .load = msm_load, .unload = msm_unload, .open = msm_open, Loading @@ -698,6 +701,16 @@ static struct drm_driver msm_driver = { .dumb_create = msm_gem_dumb_create, .dumb_map_offset = msm_gem_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = msm_gem_prime_pin, .gem_prime_unpin = msm_gem_prime_unpin, .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, .gem_prime_vmap = msm_gem_prime_vmap, .gem_prime_vunmap = msm_gem_prime_vunmap, #ifdef CONFIG_DEBUG_FS .debugfs_init = msm_debugfs_init, .debugfs_cleanup = msm_debugfs_cleanup, Loading drivers/gpu/drm/msm/msm_drv.h +11 −2 Original line number Diff line number Diff line Loading @@ -141,13 +141,20 @@ uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj); int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, uint32_t *iova); int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova); struct page **msm_gem_get_pages(struct drm_gem_object *obj); void msm_gem_put_pages(struct drm_gem_object *obj); void msm_gem_put_iova(struct drm_gem_object *obj, int id); int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); int msm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, uint32_t handle); int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); void *msm_gem_prime_vmap(struct drm_gem_object *obj); void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, size_t size, struct sg_table *sg); int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_vaddr_locked(struct drm_gem_object *obj); void *msm_gem_vaddr(struct drm_gem_object *obj); int msm_gem_queue_inactive_work(struct drm_gem_object *obj, Loading @@ -163,6 +170,8 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, uint32_t size, uint32_t flags, uint32_t *handle); struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags); struct drm_gem_object *msm_gem_import(struct drm_device *dev, uint32_t size, struct sg_table *sgt); struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb); Loading drivers/gpu/drm/msm/msm_gem.c +97 −23 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/spinlock.h> #include <linux/shmem_fs.h> #include <linux/dma-buf.h> #include "msm_drv.h" #include "msm_gem.h" Loading Loading @@ -77,6 +78,21 @@ static void put_pages(struct drm_gem_object *obj) } } struct page **msm_gem_get_pages(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct page **p; mutex_lock(&dev->struct_mutex); p = get_pages(obj); mutex_unlock(&dev->struct_mutex); return p; } void msm_gem_put_pages(struct drm_gem_object *obj) { /* when we start tracking the pin count, then do something here */ } int msm_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma) { Loading Loading @@ -510,10 +526,21 @@ void msm_gem_free_object(struct drm_gem_object *obj) drm_gem_free_mmap_offset(obj); if (obj->import_attach) { if (msm_obj->vaddr) vunmap(msm_obj->vaddr); dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr); /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */ if (msm_obj->pages) drm_free_large(msm_obj->pages); } else { if (msm_obj->vaddr) vunmap(msm_obj->vaddr); put_pages(obj); } if (msm_obj->resv == &msm_obj->_resv) reservation_object_fini(msm_obj->resv); Loading Loading @@ -549,17 +576,12 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, return ret; } struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags) static int msm_gem_new_impl(struct drm_device *dev, uint32_t size, uint32_t flags, struct drm_gem_object **obj) { struct msm_drm_private *priv = dev->dev_private; struct msm_gem_object *msm_obj; struct drm_gem_object *obj = NULL; int ret; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); size = PAGE_ALIGN(size); switch (flags & MSM_BO_CACHE_MASK) { case MSM_BO_UNCACHED: Loading @@ -569,21 +591,12 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, default: dev_err(dev->dev, "invalid cache flag: %x\n", (flags & MSM_BO_CACHE_MASK)); ret = -EINVAL; goto fail; return -EINVAL; } msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL); if (!msm_obj) { ret = -ENOMEM; goto fail; } obj = &msm_obj->base; ret = drm_gem_object_init(dev, obj, size); if (ret) goto fail; if (!msm_obj) return -ENOMEM; msm_obj->flags = flags; Loading @@ -594,6 +607,67 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, INIT_LIST_HEAD(&msm_obj->inactive_work); list_add_tail(&msm_obj->mm_list, &priv->inactive_list); *obj = &msm_obj->base; return 0; } struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags) { struct drm_gem_object *obj; int ret; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); size = PAGE_ALIGN(size); ret = msm_gem_new_impl(dev, size, flags, &obj); if (ret) goto fail; ret = drm_gem_object_init(dev, obj, size); if (ret) goto fail; return obj; fail: if (obj) drm_gem_object_unreference_unlocked(obj); return ERR_PTR(ret); } struct drm_gem_object *msm_gem_import(struct drm_device *dev, uint32_t size, struct sg_table *sgt) { struct msm_gem_object *msm_obj; struct drm_gem_object *obj; int ret, npages; size = PAGE_ALIGN(size); ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); if (ret) goto fail; drm_gem_private_object_init(dev, obj, size); npages = size / PAGE_SIZE; msm_obj = to_msm_bo(obj); msm_obj->sgt = sgt; msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); if (!msm_obj->pages) { ret = -ENOMEM; goto fail; } ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages); if (ret) goto fail; return obj; fail: Loading drivers/gpu/drm/msm/msm_gem_prime.c 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ #include "msm_drv.h" #include "msm_gem.h" struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); BUG_ON(!msm_obj->sgt); /* should have already pinned! */ return msm_obj->sgt; } void *msm_gem_prime_vmap(struct drm_gem_object *obj) { return msm_gem_vaddr(obj); } void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) { /* TODO msm_gem_vunmap() */ } struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, size_t size, struct sg_table *sg) { return msm_gem_import(dev, size, sg); } int msm_gem_prime_pin(struct drm_gem_object *obj) { if (!obj->import_attach) msm_gem_get_pages(obj); return 0; } void msm_gem_prime_unpin(struct drm_gem_object *obj) { if (!obj->import_attach) msm_gem_put_pages(obj); } Loading
drivers/gpu/drm/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ msm-y := \ msm_drv.o \ msm_fb.o \ msm_gem.o \ msm_gem_prime.o \ msm_gem_submit.o \ msm_gpu.o \ msm_ringbuffer.o Loading
drivers/gpu/drm/msm/msm_drv.c +14 −1 Original line number Diff line number Diff line Loading @@ -680,7 +680,10 @@ static const struct file_operations fops = { }; static struct drm_driver msm_driver = { .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET, .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_PRIME | DRIVER_MODESET, .load = msm_load, .unload = msm_unload, .open = msm_open, Loading @@ -698,6 +701,16 @@ static struct drm_driver msm_driver = { .dumb_create = msm_gem_dumb_create, .dumb_map_offset = msm_gem_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = msm_gem_prime_pin, .gem_prime_unpin = msm_gem_prime_unpin, .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, .gem_prime_vmap = msm_gem_prime_vmap, .gem_prime_vunmap = msm_gem_prime_vunmap, #ifdef CONFIG_DEBUG_FS .debugfs_init = msm_debugfs_init, .debugfs_cleanup = msm_debugfs_cleanup, Loading
drivers/gpu/drm/msm/msm_drv.h +11 −2 Original line number Diff line number Diff line Loading @@ -141,13 +141,20 @@ uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj); int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, uint32_t *iova); int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova); struct page **msm_gem_get_pages(struct drm_gem_object *obj); void msm_gem_put_pages(struct drm_gem_object *obj); void msm_gem_put_iova(struct drm_gem_object *obj, int id); int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); int msm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, uint32_t handle); int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); void *msm_gem_prime_vmap(struct drm_gem_object *obj); void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, size_t size, struct sg_table *sg); int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_vaddr_locked(struct drm_gem_object *obj); void *msm_gem_vaddr(struct drm_gem_object *obj); int msm_gem_queue_inactive_work(struct drm_gem_object *obj, Loading @@ -163,6 +170,8 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, uint32_t size, uint32_t flags, uint32_t *handle); struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags); struct drm_gem_object *msm_gem_import(struct drm_device *dev, uint32_t size, struct sg_table *sgt); struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb); Loading
drivers/gpu/drm/msm/msm_gem.c +97 −23 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/spinlock.h> #include <linux/shmem_fs.h> #include <linux/dma-buf.h> #include "msm_drv.h" #include "msm_gem.h" Loading Loading @@ -77,6 +78,21 @@ static void put_pages(struct drm_gem_object *obj) } } struct page **msm_gem_get_pages(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct page **p; mutex_lock(&dev->struct_mutex); p = get_pages(obj); mutex_unlock(&dev->struct_mutex); return p; } void msm_gem_put_pages(struct drm_gem_object *obj) { /* when we start tracking the pin count, then do something here */ } int msm_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma) { Loading Loading @@ -510,10 +526,21 @@ void msm_gem_free_object(struct drm_gem_object *obj) drm_gem_free_mmap_offset(obj); if (obj->import_attach) { if (msm_obj->vaddr) vunmap(msm_obj->vaddr); dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr); /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */ if (msm_obj->pages) drm_free_large(msm_obj->pages); } else { if (msm_obj->vaddr) vunmap(msm_obj->vaddr); put_pages(obj); } if (msm_obj->resv == &msm_obj->_resv) reservation_object_fini(msm_obj->resv); Loading Loading @@ -549,17 +576,12 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, return ret; } struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags) static int msm_gem_new_impl(struct drm_device *dev, uint32_t size, uint32_t flags, struct drm_gem_object **obj) { struct msm_drm_private *priv = dev->dev_private; struct msm_gem_object *msm_obj; struct drm_gem_object *obj = NULL; int ret; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); size = PAGE_ALIGN(size); switch (flags & MSM_BO_CACHE_MASK) { case MSM_BO_UNCACHED: Loading @@ -569,21 +591,12 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, default: dev_err(dev->dev, "invalid cache flag: %x\n", (flags & MSM_BO_CACHE_MASK)); ret = -EINVAL; goto fail; return -EINVAL; } msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL); if (!msm_obj) { ret = -ENOMEM; goto fail; } obj = &msm_obj->base; ret = drm_gem_object_init(dev, obj, size); if (ret) goto fail; if (!msm_obj) return -ENOMEM; msm_obj->flags = flags; Loading @@ -594,6 +607,67 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, INIT_LIST_HEAD(&msm_obj->inactive_work); list_add_tail(&msm_obj->mm_list, &priv->inactive_list); *obj = &msm_obj->base; return 0; } struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags) { struct drm_gem_object *obj; int ret; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); size = PAGE_ALIGN(size); ret = msm_gem_new_impl(dev, size, flags, &obj); if (ret) goto fail; ret = drm_gem_object_init(dev, obj, size); if (ret) goto fail; return obj; fail: if (obj) drm_gem_object_unreference_unlocked(obj); return ERR_PTR(ret); } struct drm_gem_object *msm_gem_import(struct drm_device *dev, uint32_t size, struct sg_table *sgt) { struct msm_gem_object *msm_obj; struct drm_gem_object *obj; int ret, npages; size = PAGE_ALIGN(size); ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); if (ret) goto fail; drm_gem_private_object_init(dev, obj, size); npages = size / PAGE_SIZE; msm_obj = to_msm_bo(obj); msm_obj->sgt = sgt; msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); if (!msm_obj->pages) { ret = -ENOMEM; goto fail; } ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages); if (ret) goto fail; return obj; fail: Loading
drivers/gpu/drm/msm/msm_gem_prime.c 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ #include "msm_drv.h" #include "msm_gem.h" struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); BUG_ON(!msm_obj->sgt); /* should have already pinned! */ return msm_obj->sgt; } void *msm_gem_prime_vmap(struct drm_gem_object *obj) { return msm_gem_vaddr(obj); } void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) { /* TODO msm_gem_vunmap() */ } struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, size_t size, struct sg_table *sg) { return msm_gem_import(dev, size, sg); } int msm_gem_prime_pin(struct drm_gem_object *obj) { if (!obj->import_attach) msm_gem_get_pages(obj); return 0; } void msm_gem_prime_unpin(struct drm_gem_object *obj) { if (!obj->import_attach) msm_gem_put_pages(obj); }