xref: /linux/drivers/gpu/drm/msm/msm_gem_prime.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013 Red Hat
4  * Author: Rob Clark <robdclark@gmail.com>
5  */
6 
7 #include <linux/dma-buf.h>
8 
9 #include <drm/drm_drv.h>
10 #include <drm/drm_prime.h>
11 
12 #include "msm_drv.h"
13 #include "msm_gem.h"
14 
msm_gem_prime_get_sg_table(struct drm_gem_object * obj)15 struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
16 {
17 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
18 	int npages = obj->size >> PAGE_SHIFT;
19 
20 	if (msm_obj->flags & MSM_BO_NO_SHARE)
21 		return ERR_PTR(-EINVAL);
22 
23 	if (WARN_ON(!msm_obj->pages))  /* should have already pinned! */
24 		return ERR_PTR(-ENOMEM);
25 
26 	return drm_prime_pages_to_sg(obj->dev, msm_obj->pages, npages);
27 }
28 
msm_gem_prime_vmap(struct drm_gem_object * obj,struct iosys_map * map)29 int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
30 {
31 	void *vaddr;
32 
33 	vaddr = msm_gem_get_vaddr_locked(obj);
34 	if (IS_ERR(vaddr))
35 		return PTR_ERR(vaddr);
36 	iosys_map_set_vaddr(map, vaddr);
37 
38 	return 0;
39 }
40 
msm_gem_prime_vunmap(struct drm_gem_object * obj,struct iosys_map * map)41 void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
42 {
43 	msm_gem_put_vaddr_locked(obj);
44 }
45 
msm_gem_dmabuf_release(struct dma_buf * dma_buf)46 static void msm_gem_dmabuf_release(struct dma_buf *dma_buf)
47 {
48 	struct drm_gem_object *obj = dma_buf->priv;
49 
50 	msm_gem_vma_put(obj);
51 	drm_gem_dmabuf_release(dma_buf);
52 }
53 
54 static const struct dma_buf_ops msm_gem_prime_dmabuf_ops =  {
55 	.attach = drm_gem_map_attach,
56 	.detach = drm_gem_map_detach,
57 	.map_dma_buf = drm_gem_map_dma_buf,
58 	.unmap_dma_buf = drm_gem_unmap_dma_buf,
59 	.release = msm_gem_dmabuf_release,
60 	.mmap = drm_gem_dmabuf_mmap,
61 	.vmap = drm_gem_dmabuf_vmap,
62 	.vunmap = drm_gem_dmabuf_vunmap,
63 };
64 
msm_gem_prime_import(struct drm_device * dev,struct dma_buf * buf)65 struct drm_gem_object *msm_gem_prime_import(struct drm_device *dev,
66 					    struct dma_buf *buf)
67 {
68 	if (buf->ops == &msm_gem_prime_dmabuf_ops) {
69 		struct drm_gem_object *obj = buf->priv;
70 		if (obj->dev == dev) {
71 			/*
72 			 * Importing dmabuf exported from our own gem increases
73 			 * refcount on gem itself instead of f_count of dmabuf.
74 			 */
75 			drm_gem_object_get(obj);
76 			return obj;
77 		}
78 	}
79 
80 	return drm_gem_prime_import(dev, buf);
81 }
82 
msm_gem_prime_import_sg_table(struct drm_device * dev,struct dma_buf_attachment * attach,struct sg_table * sg)83 struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
84 		struct dma_buf_attachment *attach, struct sg_table *sg)
85 {
86 	return msm_gem_import(dev, attach->dmabuf, sg);
87 }
88 
msm_gem_prime_export(struct drm_gem_object * obj,int flags)89 struct dma_buf *msm_gem_prime_export(struct drm_gem_object *obj, int flags)
90 {
91 	if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE)
92 		return ERR_PTR(-EPERM);
93 
94 	msm_gem_vma_get(obj);
95 
96 	struct drm_device *dev = obj->dev;
97 	struct dma_buf_export_info exp_info = {
98 		.exp_name = KBUILD_MODNAME, /* white lie for debug */
99 		.owner = dev->driver->fops->owner,
100 		.ops = &msm_gem_prime_dmabuf_ops,
101 		.size = obj->size,
102 		.flags = flags,
103 		.priv = obj,
104 		.resv = obj->resv,
105 	};
106 
107 	return drm_gem_dmabuf_export(dev, &exp_info);
108 }
109 
msm_gem_prime_pin(struct drm_gem_object * obj)110 int msm_gem_prime_pin(struct drm_gem_object *obj)
111 {
112 	struct page **pages;
113 	int ret = 0;
114 
115 	if (drm_gem_is_imported(obj))
116 		return 0;
117 
118 	if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE)
119 		return -EINVAL;
120 
121 	pages = msm_gem_pin_pages_locked(obj);
122 	if (IS_ERR(pages))
123 		ret = PTR_ERR(pages);
124 
125 	return ret;
126 }
127 
msm_gem_prime_unpin(struct drm_gem_object * obj)128 void msm_gem_prime_unpin(struct drm_gem_object *obj)
129 {
130 	if (drm_gem_is_imported(obj))
131 		return;
132 
133 	msm_gem_unpin_pages_locked(obj);
134 }
135