• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include "msm_priv.h"
28 
bo_allocate(struct msm_bo * msm_bo)29 static int bo_allocate(struct msm_bo *msm_bo)
30 {
31 	struct fd_bo *bo = &msm_bo->base;
32 	if (!msm_bo->offset) {
33 		struct drm_msm_gem_info req = {
34 				.handle = bo->handle,
35 				.info = MSM_INFO_GET_OFFSET,
36 		};
37 		int ret;
38 
39 		/* if the buffer is already backed by pages then this
40 		 * doesn't actually do anything (other than giving us
41 		 * the offset)
42 		 */
43 		ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO,
44 				&req, sizeof(req));
45 		if (ret) {
46 			ERROR_MSG("alloc failed: %s", strerror(errno));
47 			return ret;
48 		}
49 
50 		msm_bo->offset = req.value;
51 	}
52 
53 	return 0;
54 }
55 
msm_bo_offset(struct fd_bo * bo,uint64_t * offset)56 static int msm_bo_offset(struct fd_bo *bo, uint64_t *offset)
57 {
58 	struct msm_bo *msm_bo = to_msm_bo(bo);
59 	int ret = bo_allocate(msm_bo);
60 	if (ret)
61 		return ret;
62 	*offset = msm_bo->offset;
63 	return 0;
64 }
65 
msm_bo_cpu_prep(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t op)66 static int msm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
67 {
68 	struct drm_msm_gem_cpu_prep req = {
69 			.handle = bo->handle,
70 			.op = op,
71 	};
72 
73 	get_abs_timeout(&req.timeout, 5000000000);
74 
75 	return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req));
76 }
77 
msm_bo_cpu_fini(struct fd_bo * bo)78 static void msm_bo_cpu_fini(struct fd_bo *bo)
79 {
80 	struct drm_msm_gem_cpu_fini req = {
81 			.handle = bo->handle,
82 	};
83 
84 	drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));
85 }
86 
msm_bo_madvise(struct fd_bo * bo,int willneed)87 static int msm_bo_madvise(struct fd_bo *bo, int willneed)
88 {
89 	struct drm_msm_gem_madvise req = {
90 			.handle = bo->handle,
91 			.madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,
92 	};
93 	int ret;
94 
95 	/* older kernels do not support this: */
96 	if (bo->dev->version < FD_VERSION_MADVISE)
97 		return willneed;
98 
99 	ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));
100 	if (ret)
101 		return ret;
102 
103 	return req.retained;
104 }
105 
msm_bo_iova(struct fd_bo * bo)106 static uint64_t msm_bo_iova(struct fd_bo *bo)
107 {
108 	struct drm_msm_gem_info req = {
109 			.handle = bo->handle,
110 			.info = MSM_INFO_GET_IOVA,
111 	};
112 	int ret;
113 
114 	ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
115 	if (ret)
116 		return 0;
117 
118 	return req.value;
119 }
120 
msm_bo_set_name(struct fd_bo * bo,const char * fmt,va_list ap)121 static void msm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)
122 {
123 	struct drm_msm_gem_info req = {
124 			.handle = bo->handle,
125 			.info = MSM_INFO_SET_NAME,
126 	};
127 	char buf[32];
128 	int sz;
129 
130 	if (bo->dev->version < FD_VERSION_SOFTPIN)
131 		return;
132 
133 	sz = vsnprintf(buf, sizeof(buf), fmt, ap);
134 
135 	req.value = VOID2U64(buf);
136 	req.len = MIN2(sz, sizeof(buf));
137 
138 	drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
139 }
140 
msm_bo_destroy(struct fd_bo * bo)141 static void msm_bo_destroy(struct fd_bo *bo)
142 {
143 	struct msm_bo *msm_bo = to_msm_bo(bo);
144 	free(msm_bo);
145 }
146 
147 static const struct fd_bo_funcs funcs = {
148 		.offset = msm_bo_offset,
149 		.cpu_prep = msm_bo_cpu_prep,
150 		.cpu_fini = msm_bo_cpu_fini,
151 		.madvise = msm_bo_madvise,
152 		.iova = msm_bo_iova,
153 		.set_name = msm_bo_set_name,
154 		.destroy = msm_bo_destroy,
155 };
156 
157 /* allocate a buffer handle: */
msm_bo_new_handle(struct fd_device * dev,uint32_t size,uint32_t flags,uint32_t * handle)158 int msm_bo_new_handle(struct fd_device *dev,
159 		uint32_t size, uint32_t flags, uint32_t *handle)
160 {
161 	struct drm_msm_gem_new req = {
162 			.size = size,
163 			.flags = MSM_BO_WC,  // TODO figure out proper flags..
164 	};
165 	int ret;
166 
167 	if (flags & DRM_FREEDRENO_GEM_SCANOUT)
168 		req.flags |= MSM_BO_SCANOUT;
169 
170 	if (flags & DRM_FREEDRENO_GEM_GPUREADONLY)
171 		req.flags |= MSM_BO_GPU_READONLY;
172 
173 	ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW,
174 			&req, sizeof(req));
175 	if (ret)
176 		return ret;
177 
178 	*handle = req.handle;
179 
180 	return 0;
181 }
182 
183 /* allocate a new buffer object */
msm_bo_from_handle(struct fd_device * dev,uint32_t size,uint32_t handle)184 struct fd_bo * msm_bo_from_handle(struct fd_device *dev,
185 		uint32_t size, uint32_t handle)
186 {
187 	struct msm_bo *msm_bo;
188 	struct fd_bo *bo;
189 
190 	msm_bo = calloc(1, sizeof(*msm_bo));
191 	if (!msm_bo)
192 		return NULL;
193 
194 	bo = &msm_bo->base;
195 	bo->funcs = &funcs;
196 
197 	return bo;
198 }
199