diff options
-rw-r--r-- | drivers/gpu/drm/msm/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 120 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem_prime.c | 56 |
5 files changed, 179 insertions, 26 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index e17914889e54..e5fa12b0d21e 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile | |||
@@ -21,6 +21,7 @@ msm-y := \ | |||
21 | msm_drv.o \ | 21 | msm_drv.o \ |
22 | msm_fb.o \ | 22 | msm_fb.o \ |
23 | msm_gem.o \ | 23 | msm_gem.o \ |
24 | msm_gem_prime.o \ | ||
24 | msm_gem_submit.o \ | 25 | msm_gem_submit.o \ |
25 | msm_gpu.o \ | 26 | msm_gpu.o \ |
26 | msm_ringbuffer.o | 27 | msm_ringbuffer.o |
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index b3a2f1629041..cfeebdd911dd 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
@@ -680,7 +680,10 @@ static const struct file_operations fops = { | |||
680 | }; | 680 | }; |
681 | 681 | ||
682 | static struct drm_driver msm_driver = { | 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 | .load = msm_load, | 687 | .load = msm_load, |
685 | .unload = msm_unload, | 688 | .unload = msm_unload, |
686 | .open = msm_open, | 689 | .open = msm_open, |
@@ -698,6 +701,16 @@ static struct drm_driver msm_driver = { | |||
698 | .dumb_create = msm_gem_dumb_create, | 701 | .dumb_create = msm_gem_dumb_create, |
699 | .dumb_map_offset = msm_gem_dumb_map_offset, | 702 | .dumb_map_offset = msm_gem_dumb_map_offset, |
700 | .dumb_destroy = drm_gem_dumb_destroy, | 703 | .dumb_destroy = drm_gem_dumb_destroy, |
704 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, | ||
705 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | ||
706 | .gem_prime_export = drm_gem_prime_export, | ||
707 | .gem_prime_import = drm_gem_prime_import, | ||
708 | .gem_prime_pin = msm_gem_prime_pin, | ||
709 | .gem_prime_unpin = msm_gem_prime_unpin, | ||
710 | .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, | ||
711 | .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, | ||
712 | .gem_prime_vmap = msm_gem_prime_vmap, | ||
713 | .gem_prime_vunmap = msm_gem_prime_vunmap, | ||
701 | #ifdef CONFIG_DEBUG_FS | 714 | #ifdef CONFIG_DEBUG_FS |
702 | .debugfs_init = msm_debugfs_init, | 715 | .debugfs_init = msm_debugfs_init, |
703 | .debugfs_cleanup = msm_debugfs_cleanup, | 716 | .debugfs_cleanup = msm_debugfs_cleanup, |
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index df8f1d084bc1..9ce90c267ef8 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
@@ -141,13 +141,20 @@ uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj); | |||
141 | int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, | 141 | int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, |
142 | uint32_t *iova); | 142 | uint32_t *iova); |
143 | int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova); | 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 | void msm_gem_put_iova(struct drm_gem_object *obj, int id); | 146 | void msm_gem_put_iova(struct drm_gem_object *obj, int id); |
145 | int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, | 147 | int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, |
146 | struct drm_mode_create_dumb *args); | 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 | int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, | 149 | int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, |
150 | uint32_t handle, uint64_t *offset); | 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 | void *msm_gem_vaddr_locked(struct drm_gem_object *obj); | 158 | void *msm_gem_vaddr_locked(struct drm_gem_object *obj); |
152 | void *msm_gem_vaddr(struct drm_gem_object *obj); | 159 | void *msm_gem_vaddr(struct drm_gem_object *obj); |
153 | int msm_gem_queue_inactive_work(struct drm_gem_object *obj, | 160 | int msm_gem_queue_inactive_work(struct drm_gem_object *obj, |
@@ -163,6 +170,8 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, | |||
163 | uint32_t size, uint32_t flags, uint32_t *handle); | 170 | uint32_t size, uint32_t flags, uint32_t *handle); |
164 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, | 171 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, |
165 | uint32_t size, uint32_t flags); | 172 | uint32_t size, uint32_t flags); |
173 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, | ||
174 | uint32_t size, struct sg_table *sgt); | ||
166 | 175 | ||
167 | struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); | 176 | struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); |
168 | const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb); | 177 | const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb); |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 2bae46c66a30..ea2c96f9459b 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/shmem_fs.h> | 19 | #include <linux/shmem_fs.h> |
20 | #include <linux/dma-buf.h> | ||
20 | 21 | ||
21 | #include "msm_drv.h" | 22 | #include "msm_drv.h" |
22 | #include "msm_gem.h" | 23 | #include "msm_gem.h" |
@@ -77,6 +78,21 @@ static void put_pages(struct drm_gem_object *obj) | |||
77 | } | 78 | } |
78 | } | 79 | } |
79 | 80 | ||
81 | struct page **msm_gem_get_pages(struct drm_gem_object *obj) | ||
82 | { | ||
83 | struct drm_device *dev = obj->dev; | ||
84 | struct page **p; | ||
85 | mutex_lock(&dev->struct_mutex); | ||
86 | p = get_pages(obj); | ||
87 | mutex_unlock(&dev->struct_mutex); | ||
88 | return p; | ||
89 | } | ||
90 | |||
91 | void msm_gem_put_pages(struct drm_gem_object *obj) | ||
92 | { | ||
93 | /* when we start tracking the pin count, then do something here */ | ||
94 | } | ||
95 | |||
80 | int msm_gem_mmap_obj(struct drm_gem_object *obj, | 96 | int msm_gem_mmap_obj(struct drm_gem_object *obj, |
81 | struct vm_area_struct *vma) | 97 | struct vm_area_struct *vma) |
82 | { | 98 | { |
@@ -510,10 +526,21 @@ void msm_gem_free_object(struct drm_gem_object *obj) | |||
510 | 526 | ||
511 | drm_gem_free_mmap_offset(obj); | 527 | drm_gem_free_mmap_offset(obj); |
512 | 528 | ||
513 | if (msm_obj->vaddr) | 529 | if (obj->import_attach) { |
514 | vunmap(msm_obj->vaddr); | 530 | if (msm_obj->vaddr) |
531 | dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr); | ||
532 | |||
533 | /* Don't drop the pages for imported dmabuf, as they are not | ||
534 | * ours, just free the array we allocated: | ||
535 | */ | ||
536 | if (msm_obj->pages) | ||
537 | drm_free_large(msm_obj->pages); | ||
515 | 538 | ||
516 | put_pages(obj); | 539 | } else { |
540 | if (msm_obj->vaddr) | ||
541 | vunmap(msm_obj->vaddr); | ||
542 | put_pages(obj); | ||
543 | } | ||
517 | 544 | ||
518 | if (msm_obj->resv == &msm_obj->_resv) | 545 | if (msm_obj->resv == &msm_obj->_resv) |
519 | reservation_object_fini(msm_obj->resv); | 546 | reservation_object_fini(msm_obj->resv); |
@@ -549,17 +576,12 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, | |||
549 | return ret; | 576 | return ret; |
550 | } | 577 | } |
551 | 578 | ||
552 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, | 579 | static int msm_gem_new_impl(struct drm_device *dev, |
553 | uint32_t size, uint32_t flags) | 580 | uint32_t size, uint32_t flags, |
581 | struct drm_gem_object **obj) | ||
554 | { | 582 | { |
555 | struct msm_drm_private *priv = dev->dev_private; | 583 | struct msm_drm_private *priv = dev->dev_private; |
556 | struct msm_gem_object *msm_obj; | 584 | struct msm_gem_object *msm_obj; |
557 | struct drm_gem_object *obj = NULL; | ||
558 | int ret; | ||
559 | |||
560 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
561 | |||
562 | size = PAGE_ALIGN(size); | ||
563 | 585 | ||
564 | switch (flags & MSM_BO_CACHE_MASK) { | 586 | switch (flags & MSM_BO_CACHE_MASK) { |
565 | case MSM_BO_UNCACHED: | 587 | case MSM_BO_UNCACHED: |
@@ -569,21 +591,12 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, | |||
569 | default: | 591 | default: |
570 | dev_err(dev->dev, "invalid cache flag: %x\n", | 592 | dev_err(dev->dev, "invalid cache flag: %x\n", |
571 | (flags & MSM_BO_CACHE_MASK)); | 593 | (flags & MSM_BO_CACHE_MASK)); |
572 | ret = -EINVAL; | 594 | return -EINVAL; |
573 | goto fail; | ||
574 | } | 595 | } |
575 | 596 | ||
576 | msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL); | 597 | msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL); |
577 | if (!msm_obj) { | 598 | if (!msm_obj) |
578 | ret = -ENOMEM; | 599 | return -ENOMEM; |
579 | goto fail; | ||
580 | } | ||
581 | |||
582 | obj = &msm_obj->base; | ||
583 | |||
584 | ret = drm_gem_object_init(dev, obj, size); | ||
585 | if (ret) | ||
586 | goto fail; | ||
587 | 600 | ||
588 | msm_obj->flags = flags; | 601 | msm_obj->flags = flags; |
589 | 602 | ||
@@ -594,6 +607,67 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, | |||
594 | INIT_LIST_HEAD(&msm_obj->inactive_work); | 607 | INIT_LIST_HEAD(&msm_obj->inactive_work); |
595 | list_add_tail(&msm_obj->mm_list, &priv->inactive_list); | 608 | list_add_tail(&msm_obj->mm_list, &priv->inactive_list); |
596 | 609 | ||
610 | *obj = &msm_obj->base; | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, | ||
616 | uint32_t size, uint32_t flags) | ||
617 | { | ||
618 | struct drm_gem_object *obj; | ||
619 | int ret; | ||
620 | |||
621 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
622 | |||
623 | size = PAGE_ALIGN(size); | ||
624 | |||
625 | ret = msm_gem_new_impl(dev, size, flags, &obj); | ||
626 | if (ret) | ||
627 | goto fail; | ||
628 | |||
629 | ret = drm_gem_object_init(dev, obj, size); | ||
630 | if (ret) | ||
631 | goto fail; | ||
632 | |||
633 | return obj; | ||
634 | |||
635 | fail: | ||
636 | if (obj) | ||
637 | drm_gem_object_unreference_unlocked(obj); | ||
638 | |||
639 | return ERR_PTR(ret); | ||
640 | } | ||
641 | |||
642 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, | ||
643 | uint32_t size, struct sg_table *sgt) | ||
644 | { | ||
645 | struct msm_gem_object *msm_obj; | ||
646 | struct drm_gem_object *obj; | ||
647 | int ret, npages; | ||
648 | |||
649 | size = PAGE_ALIGN(size); | ||
650 | |||
651 | ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); | ||
652 | if (ret) | ||
653 | goto fail; | ||
654 | |||
655 | drm_gem_private_object_init(dev, obj, size); | ||
656 | |||
657 | npages = size / PAGE_SIZE; | ||
658 | |||
659 | msm_obj = to_msm_bo(obj); | ||
660 | msm_obj->sgt = sgt; | ||
661 | msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); | ||
662 | if (!msm_obj->pages) { | ||
663 | ret = -ENOMEM; | ||
664 | goto fail; | ||
665 | } | ||
666 | |||
667 | ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages); | ||
668 | if (ret) | ||
669 | goto fail; | ||
670 | |||
597 | return obj; | 671 | return obj; |
598 | 672 | ||
599 | fail: | 673 | fail: |
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c new file mode 100644 index 000000000000..d48f9fc5129b --- /dev/null +++ b/drivers/gpu/drm/msm/msm_gem_prime.c | |||
@@ -0,0 +1,56 @@ | |||
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 | } | ||