Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm: prime support

Signed-off-by: Rob Clark <robdclark@gmail.com>
Acked-by: David Brown <davidb@codeaurora.org>

Rob Clark 05b84911 959f5854

+179 -26
+1
drivers/gpu/drm/msm/Makefile
··· 21 21 msm_drv.o \ 22 22 msm_fb.o \ 23 23 msm_gem.o \ 24 + msm_gem_prime.o \ 24 25 msm_gem_submit.o \ 25 26 msm_gpu.o \ 26 27 msm_ringbuffer.o
+14 -1
drivers/gpu/drm/msm/msm_drv.c
··· 680 680 }; 681 681 682 682 static struct drm_driver msm_driver = { 683 - .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET, 683 + .driver_features = DRIVER_HAVE_IRQ | 684 + DRIVER_GEM | 685 + DRIVER_PRIME | 686 + DRIVER_MODESET, 684 687 .load = msm_load, 685 688 .unload = msm_unload, 686 689 .open = msm_open, ··· 701 698 .dumb_create = msm_gem_dumb_create, 702 699 .dumb_map_offset = msm_gem_dumb_map_offset, 703 700 .dumb_destroy = drm_gem_dumb_destroy, 701 + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 702 + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 703 + .gem_prime_export = drm_gem_prime_export, 704 + .gem_prime_import = drm_gem_prime_import, 705 + .gem_prime_pin = msm_gem_prime_pin, 706 + .gem_prime_unpin = msm_gem_prime_unpin, 707 + .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, 708 + .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, 709 + .gem_prime_vmap = msm_gem_prime_vmap, 710 + .gem_prime_vunmap = msm_gem_prime_vunmap, 704 711 #ifdef CONFIG_DEBUG_FS 705 712 .debugfs_init = msm_debugfs_init, 706 713 .debugfs_cleanup = msm_debugfs_cleanup,
+11 -2
drivers/gpu/drm/msm/msm_drv.h
··· 141 141 int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, 142 142 uint32_t *iova); 143 143 int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova); 144 + struct page **msm_gem_get_pages(struct drm_gem_object *obj); 145 + void msm_gem_put_pages(struct drm_gem_object *obj); 144 146 void msm_gem_put_iova(struct drm_gem_object *obj, int id); 145 147 int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, 146 148 struct drm_mode_create_dumb *args); 147 - int msm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, 148 - uint32_t handle); 149 149 int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, 150 150 uint32_t handle, uint64_t *offset); 151 + struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); 152 + void *msm_gem_prime_vmap(struct drm_gem_object *obj); 153 + void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); 154 + struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, 155 + size_t size, struct sg_table *sg); 156 + int msm_gem_prime_pin(struct drm_gem_object *obj); 157 + void msm_gem_prime_unpin(struct drm_gem_object *obj); 151 158 void *msm_gem_vaddr_locked(struct drm_gem_object *obj); 152 159 void *msm_gem_vaddr(struct drm_gem_object *obj); 153 160 int msm_gem_queue_inactive_work(struct drm_gem_object *obj, ··· 170 163 uint32_t size, uint32_t flags, uint32_t *handle); 171 164 struct drm_gem_object *msm_gem_new(struct drm_device *dev, 172 165 uint32_t size, uint32_t flags); 166 + struct drm_gem_object *msm_gem_import(struct drm_device *dev, 167 + uint32_t size, struct sg_table *sgt); 173 168 174 169 struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); 175 170 const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb);
+97 -23
drivers/gpu/drm/msm/msm_gem.c
··· 17 17 18 18 #include <linux/spinlock.h> 19 19 #include <linux/shmem_fs.h> 20 + #include <linux/dma-buf.h> 20 21 21 22 #include "msm_drv.h" 22 23 #include "msm_gem.h" ··· 76 75 drm_gem_put_pages(obj, msm_obj->pages, true, false); 77 76 msm_obj->pages = NULL; 78 77 } 78 + } 79 + 80 + struct page **msm_gem_get_pages(struct drm_gem_object *obj) 81 + { 82 + struct drm_device *dev = obj->dev; 83 + struct page **p; 84 + mutex_lock(&dev->struct_mutex); 85 + p = get_pages(obj); 86 + mutex_unlock(&dev->struct_mutex); 87 + return p; 88 + } 89 + 90 + void msm_gem_put_pages(struct drm_gem_object *obj) 91 + { 92 + /* when we start tracking the pin count, then do something here */ 79 93 } 80 94 81 95 int msm_gem_mmap_obj(struct drm_gem_object *obj, ··· 526 510 527 511 drm_gem_free_mmap_offset(obj); 528 512 529 - if (msm_obj->vaddr) 530 - vunmap(msm_obj->vaddr); 513 + if (obj->import_attach) { 514 + if (msm_obj->vaddr) 515 + dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr); 531 516 532 - put_pages(obj); 517 + /* Don't drop the pages for imported dmabuf, as they are not 518 + * ours, just free the array we allocated: 519 + */ 520 + if (msm_obj->pages) 521 + drm_free_large(msm_obj->pages); 522 + 523 + } else { 524 + if (msm_obj->vaddr) 525 + vunmap(msm_obj->vaddr); 526 + put_pages(obj); 527 + } 533 528 534 529 if (msm_obj->resv == &msm_obj->_resv) 535 530 reservation_object_fini(msm_obj->resv); ··· 576 549 return ret; 577 550 } 578 551 579 - struct drm_gem_object *msm_gem_new(struct drm_device *dev, 580 - uint32_t size, uint32_t flags) 552 + static int msm_gem_new_impl(struct drm_device *dev, 553 + uint32_t size, uint32_t flags, 554 + struct drm_gem_object **obj) 581 555 { 582 556 struct msm_drm_private *priv = dev->dev_private; 583 557 struct msm_gem_object *msm_obj; 584 - struct drm_gem_object *obj = NULL; 585 - int ret; 586 - 587 - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 588 - 589 - size = PAGE_ALIGN(size); 590 558 591 559 switch (flags & MSM_BO_CACHE_MASK) { 592 560 case MSM_BO_UNCACHED: ··· 591 569 default: 592 570 dev_err(dev->dev, "invalid cache flag: %x\n", 593 571 (flags & MSM_BO_CACHE_MASK)); 594 - ret = -EINVAL; 595 - goto fail; 572 + return -EINVAL; 596 573 } 597 574 598 575 msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL); 599 - if (!msm_obj) { 600 - ret = -ENOMEM; 601 - goto fail; 602 - } 603 - 604 - obj = &msm_obj->base; 605 - 606 - ret = drm_gem_object_init(dev, obj, size); 607 - if (ret) 608 - goto fail; 576 + if (!msm_obj) 577 + return -ENOMEM; 609 578 610 579 msm_obj->flags = flags; 611 580 ··· 606 593 INIT_LIST_HEAD(&msm_obj->submit_entry); 607 594 INIT_LIST_HEAD(&msm_obj->inactive_work); 608 595 list_add_tail(&msm_obj->mm_list, &priv->inactive_list); 596 + 597 + *obj = &msm_obj->base; 598 + 599 + return 0; 600 + } 601 + 602 + struct drm_gem_object *msm_gem_new(struct drm_device *dev, 603 + uint32_t size, uint32_t flags) 604 + { 605 + struct drm_gem_object *obj; 606 + int ret; 607 + 608 + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 609 + 610 + size = PAGE_ALIGN(size); 611 + 612 + ret = msm_gem_new_impl(dev, size, flags, &obj); 613 + if (ret) 614 + goto fail; 615 + 616 + ret = drm_gem_object_init(dev, obj, size); 617 + if (ret) 618 + goto fail; 619 + 620 + return obj; 621 + 622 + fail: 623 + if (obj) 624 + drm_gem_object_unreference_unlocked(obj); 625 + 626 + return ERR_PTR(ret); 627 + } 628 + 629 + struct drm_gem_object *msm_gem_import(struct drm_device *dev, 630 + uint32_t size, struct sg_table *sgt) 631 + { 632 + struct msm_gem_object *msm_obj; 633 + struct drm_gem_object *obj; 634 + int ret, npages; 635 + 636 + size = PAGE_ALIGN(size); 637 + 638 + ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); 639 + if (ret) 640 + goto fail; 641 + 642 + drm_gem_private_object_init(dev, obj, size); 643 + 644 + npages = size / PAGE_SIZE; 645 + 646 + msm_obj = to_msm_bo(obj); 647 + msm_obj->sgt = sgt; 648 + msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); 649 + if (!msm_obj->pages) { 650 + ret = -ENOMEM; 651 + goto fail; 652 + } 653 + 654 + ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages); 655 + if (ret) 656 + goto fail; 609 657 610 658 return obj; 611 659
+56
drivers/gpu/drm/msm/msm_gem_prime.c
··· 1 + /* 2 + * Copyright (C) 2013 Red Hat 3 + * Author: Rob Clark <robdclark@gmail.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License version 2 as published by 7 + * the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, but WITHOUT 10 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + * more details. 13 + * 14 + * You should have received a copy of the GNU General Public License along with 15 + * this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + 18 + #include "msm_drv.h" 19 + #include "msm_gem.h" 20 + 21 + 22 + struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) 23 + { 24 + struct msm_gem_object *msm_obj = to_msm_bo(obj); 25 + BUG_ON(!msm_obj->sgt); /* should have already pinned! */ 26 + return msm_obj->sgt; 27 + } 28 + 29 + void *msm_gem_prime_vmap(struct drm_gem_object *obj) 30 + { 31 + return msm_gem_vaddr(obj); 32 + } 33 + 34 + void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) 35 + { 36 + /* TODO msm_gem_vunmap() */ 37 + } 38 + 39 + struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, 40 + size_t size, struct sg_table *sg) 41 + { 42 + return msm_gem_import(dev, size, sg); 43 + } 44 + 45 + int msm_gem_prime_pin(struct drm_gem_object *obj) 46 + { 47 + if (!obj->import_attach) 48 + msm_gem_get_pages(obj); 49 + return 0; 50 + } 51 + 52 + void msm_gem_prime_unpin(struct drm_gem_object *obj) 53 + { 54 + if (!obj->import_attach) 55 + msm_gem_put_pages(obj); 56 + }