• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019 Google LLC
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
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/ioctl.h>
28 #include "drm-uapi/msm_drm.h"
29 #include "drm-shim/drm_shim.h"
30 
31 bool drm_shim_driver_prefers_first_render_node = true;
32 
33 struct msm_bo {
34 	struct shim_bo base;
35 	uint32_t offset;
36 };
37 
38 static struct msm_bo *
msm_bo(struct shim_bo * bo)39 msm_bo(struct shim_bo *bo)
40 {
41 	return (struct msm_bo *)bo;
42 }
43 
44 struct msm_device {
45 	uint32_t next_offset;
46 };
47 
48 static struct msm_device msm = {
49 	.next_offset = 0x1000,
50 };
51 
52 struct msm_device_info {
53 	uint32_t gpu_id;
54 	uint32_t chip_id;
55 	uint32_t gmem_size;
56 };
57 
58 static const struct msm_device_info *device_info;
59 
60 static int
msm_ioctl_noop(int fd,unsigned long request,void * arg)61 msm_ioctl_noop(int fd, unsigned long request, void *arg)
62 {
63 	return 0;
64 }
65 
66 static int
msm_ioctl_gem_new(int fd,unsigned long request,void * arg)67 msm_ioctl_gem_new(int fd, unsigned long request, void *arg)
68 {
69 	struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
70 	struct drm_msm_gem_new *create = arg;
71 	struct msm_bo *bo = calloc(1, sizeof(*bo));
72 
73 	drm_shim_bo_init(&bo->base, create->size);
74 
75 	assert(UINT_MAX - msm.next_offset > create->size);
76 
77 	bo->offset = msm.next_offset;
78 	msm.next_offset += create->size;
79 
80 	create->handle = drm_shim_bo_get_handle(shim_fd, &bo->base);
81 
82 	drm_shim_bo_put(&bo->base);
83 
84 	return 0;
85 }
86 
87 static int
msm_ioctl_gem_info(int fd,unsigned long request,void * arg)88 msm_ioctl_gem_info(int fd, unsigned long request, void *arg)
89 {
90 	struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
91 	struct drm_msm_gem_info *args = arg;
92 	struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, args->handle);
93 
94 	switch (args->info) {
95 	case MSM_INFO_GET_OFFSET:
96 		args->value = drm_shim_bo_get_mmap_offset(shim_fd, bo);
97 		break;
98 	case MSM_INFO_GET_IOVA:
99 		args->value = msm_bo(bo)->offset;
100 		break;
101 	case MSM_INFO_SET_NAME:
102 		break;
103 	default:
104 		fprintf(stderr, "Unknown DRM_IOCTL_MSM_GEM_INFO %d\n", args->info);
105 		drm_shim_bo_put(bo);
106 		return -1;
107 	}
108 
109 	drm_shim_bo_put(bo);
110 
111 	return 0;
112 }
113 
114 static int
msm_ioctl_get_param(int fd,unsigned long request,void * arg)115 msm_ioctl_get_param(int fd, unsigned long request, void *arg)
116 {
117 	struct drm_msm_param *gp = arg;
118 
119 	switch (gp->param) {
120 	case MSM_PARAM_GPU_ID:
121 		gp->value = device_info->gpu_id;
122 		return 0;
123 	case MSM_PARAM_GMEM_SIZE:
124 		gp->value = device_info->gmem_size;
125 		return 0;
126 	case MSM_PARAM_GMEM_BASE:
127 		gp->value = 0x100000;
128 		return 0;
129 	case MSM_PARAM_CHIP_ID:
130 		gp->value = device_info->chip_id;
131 		return 0;
132 	case MSM_PARAM_NR_RINGS:
133 		gp->value = 1;
134 		return 0;
135 	case MSM_PARAM_MAX_FREQ:
136 		gp->value = 1000000;
137 		return 0;
138 	case MSM_PARAM_TIMESTAMP:
139 		gp->value = 0;
140 		return 0;
141 	case MSM_PARAM_PP_PGTABLE:
142 		gp->value = 1;
143 		return 0;
144 	case MSM_PARAM_FAULTS:
145 		gp->value = 0;
146 		return 0;
147 	default:
148 		fprintf(stderr, "Unknown DRM_IOCTL_MSM_GET_PARAM %d\n",
149 				gp->param);
150 		return -1;
151 	}
152 }
153 
154 static int
msm_ioctl_gem_madvise(int fd,unsigned long request,void * arg)155 msm_ioctl_gem_madvise(int fd, unsigned long request, void *arg)
156 {
157 	struct drm_msm_gem_madvise *args = arg;
158 
159 	args->retained = true;
160 
161 	return 0;
162 }
163 
164 static ioctl_fn_t driver_ioctls[] = {
165 	[DRM_MSM_GET_PARAM] = msm_ioctl_get_param,
166 	[DRM_MSM_GEM_NEW] = msm_ioctl_gem_new,
167 	[DRM_MSM_GEM_INFO] = msm_ioctl_gem_info,
168 	[DRM_MSM_GEM_CPU_PREP] = msm_ioctl_noop,
169 	[DRM_MSM_GEM_CPU_FINI] = msm_ioctl_noop,
170 	[DRM_MSM_GEM_SUBMIT] = msm_ioctl_noop,
171 	[DRM_MSM_WAIT_FENCE] = msm_ioctl_noop,
172 	[DRM_MSM_GEM_MADVISE] = msm_ioctl_gem_madvise,
173 	[DRM_MSM_SUBMITQUEUE_NEW] = msm_ioctl_noop,
174 	[DRM_MSM_SUBMITQUEUE_CLOSE] = msm_ioctl_noop,
175 	[DRM_MSM_SUBMITQUEUE_QUERY] = msm_ioctl_noop,
176 };
177 
178 #define CHIPID(maj, min, rev, pat) \
179 	((maj << 24) | (min << 16) | (rev << 8) | (pat))
180 
181 static const struct msm_device_info device_infos[] = {
182 	{ /* First entry is default */
183 		.gpu_id = 630,
184 		.chip_id = CHIPID(6, 3, 0, 0xff),
185 		.gmem_size = 1024 * 1024,
186 	},
187 	{
188 		.gpu_id = 200,
189 		.chip_id = CHIPID(2, 0, 0, 0),
190 		.gmem_size = 256 * 1024,
191 	},
192 	{
193 		.gpu_id = 201,
194 		.chip_id = CHIPID(2, 0, 0, 1),
195 		.gmem_size = 128 * 1024,
196 	},
197 	{
198 		.gpu_id = 220,
199 		.chip_id = CHIPID(2, 2, 0, 0xff),
200 		.gmem_size = 512 * 1024,
201 	},
202 	{
203 		.gpu_id = 305,
204 		.chip_id = CHIPID(3, 0, 5, 0xff),
205 		.gmem_size = 256 * 1024,
206 	},
207 	{
208 		.gpu_id = 307,
209 		.chip_id = CHIPID(3, 0, 6, 0),
210 		.gmem_size = 128 * 1024,
211 	},
212 	{
213 		.gpu_id = 320,
214 		.chip_id = CHIPID(3, 2, 0xff, 0xff),
215 		.gmem_size = 512 * 1024,
216 	},
217 	{
218 		.gpu_id = 330,
219 		.chip_id = CHIPID(3, 3, 0, 0xff),
220 		.gmem_size = 1024 * 1024,
221 	},
222 	{
223 		.gpu_id = 420,
224 		.chip_id = CHIPID(4, 2, 0, 0xff),
225 		.gmem_size = 1536 * 1024,
226 	},
227 	{
228 		.gpu_id = 430,
229 		.chip_id = CHIPID(4, 3, 0, 0xff),
230 		.gmem_size = 1536 * 1024,
231 	},
232 	{
233 		.gpu_id = 510,
234 		.chip_id = CHIPID(5, 1, 0, 0xff),
235 		.gmem_size = 256 * 1024,
236 	},
237 	{
238 		.gpu_id = 530,
239 		.chip_id = CHIPID(5, 3, 0, 2),
240 		.gmem_size = 1024 * 1024,
241 	},
242 	{
243 		.gpu_id = 540,
244 		.chip_id = CHIPID(5, 4, 0, 2),
245 		.gmem_size = 1024 * 1024,
246 	},
247 	{
248 		.gpu_id = 618,
249 		.chip_id = CHIPID(6, 1, 8, 0xff),
250 		.gmem_size = 512 * 1024,
251 	},
252 	{
253 		.gpu_id = 630,
254 		.chip_id = CHIPID(6, 3, 0, 0xff),
255 		.gmem_size = 1024 * 1024,
256 	},
257 };
258 
259 
260 static void
msm_driver_get_device_info(void)261 msm_driver_get_device_info(void)
262 {
263 	const char *env = getenv("FD_GPU_ID");
264 
265 	if (!env) {
266 		device_info = &device_infos[0];
267 		return;
268 	}
269 
270 	int gpu_id = atoi(env);
271 	for (int i = 0; i < ARRAY_SIZE(device_infos); i++) {
272 		if (device_infos[i].gpu_id == gpu_id) {
273 			device_info = &device_infos[i];
274 			return;
275 		}
276 	}
277 
278 	fprintf(stderr, "FD_GPU_ID unrecognized, shim supports %d",
279 			device_infos[0].gpu_id);
280 	for (int i = 1; i < ARRAY_SIZE(device_infos); i++)
281 		fprintf(stderr, ", %d", device_infos[i].gpu_id);
282 	fprintf(stderr, "\n");
283 	abort();
284 }
285 
286 void
drm_shim_driver_init(void)287 drm_shim_driver_init(void)
288 {
289 	shim_device.bus_type = DRM_BUS_PLATFORM;
290 	shim_device.driver_name = "msm";
291 	shim_device.driver_ioctls = driver_ioctls;
292 	shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls);
293 
294 	/* msm uses the DRM version to expose features, instead of getparam. */
295 	shim_device.version_major = 1;
296 	shim_device.version_minor = 5;
297 	shim_device.version_patchlevel = 0;
298 
299 	msm_driver_get_device_info();
300 
301 	drm_shim_override_file("OF_FULLNAME=/rdb/msm\n"
302 			"OF_COMPATIBLE_N=1\n"
303 			"OF_COMPATIBLE_0=qcom,adreno\n",
304 			"/sys/dev/char/%d:%d/device/uevent",
305 			DRM_MAJOR, render_node_minor);
306 }
307