diff options
Diffstat (limited to 'drivers/char/drm/drm_context.c')
-rw-r--r-- | drivers/char/drm/drm_context.c | 151 |
1 files changed, 53 insertions, 98 deletions
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index 4037a3602f1e..17fe69e7bfc1 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c | |||
@@ -139,21 +139,16 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev) | |||
139 | * Gets the map from drm_device::ctx_idr with the handle specified and | 139 | * Gets the map from drm_device::ctx_idr with the handle specified and |
140 | * returns its handle. | 140 | * returns its handle. |
141 | */ | 141 | */ |
142 | int drm_getsareactx(struct inode *inode, struct drm_file *file_priv, | 142 | int drm_getsareactx(struct drm_device *dev, void *data, |
143 | unsigned int cmd, unsigned long arg) | 143 | struct drm_file *file_priv) |
144 | { | 144 | { |
145 | struct drm_device *dev = file_priv->head->dev; | 145 | struct drm_ctx_priv_map *request = data; |
146 | struct drm_ctx_priv_map __user *argp = (void __user *)arg; | ||
147 | struct drm_ctx_priv_map request; | ||
148 | struct drm_map *map; | 146 | struct drm_map *map; |
149 | struct drm_map_list *_entry; | 147 | struct drm_map_list *_entry; |
150 | 148 | ||
151 | if (copy_from_user(&request, argp, sizeof(request))) | ||
152 | return -EFAULT; | ||
153 | |||
154 | mutex_lock(&dev->struct_mutex); | 149 | mutex_lock(&dev->struct_mutex); |
155 | 150 | ||
156 | map = idr_find(&dev->ctx_idr, request.ctx_id); | 151 | map = idr_find(&dev->ctx_idr, request->ctx_id); |
157 | if (!map) { | 152 | if (!map) { |
158 | mutex_unlock(&dev->struct_mutex); | 153 | mutex_unlock(&dev->struct_mutex); |
159 | return -EINVAL; | 154 | return -EINVAL; |
@@ -161,19 +156,17 @@ int drm_getsareactx(struct inode *inode, struct drm_file *file_priv, | |||
161 | 156 | ||
162 | mutex_unlock(&dev->struct_mutex); | 157 | mutex_unlock(&dev->struct_mutex); |
163 | 158 | ||
164 | request.handle = NULL; | 159 | request->handle = NULL; |
165 | list_for_each_entry(_entry, &dev->maplist, head) { | 160 | list_for_each_entry(_entry, &dev->maplist, head) { |
166 | if (_entry->map == map) { | 161 | if (_entry->map == map) { |
167 | request.handle = | 162 | request->handle = |
168 | (void *)(unsigned long)_entry->user_token; | 163 | (void *)(unsigned long)_entry->user_token; |
169 | break; | 164 | break; |
170 | } | 165 | } |
171 | } | 166 | } |
172 | if (request.handle == NULL) | 167 | if (request->handle == NULL) |
173 | return -EINVAL; | 168 | return -EINVAL; |
174 | 169 | ||
175 | if (copy_to_user(argp, &request, sizeof(request))) | ||
176 | return -EFAULT; | ||
177 | return 0; | 170 | return 0; |
178 | } | 171 | } |
179 | 172 | ||
@@ -189,23 +182,17 @@ int drm_getsareactx(struct inode *inode, struct drm_file *file_priv, | |||
189 | * Searches the mapping specified in \p arg and update the entry in | 182 | * Searches the mapping specified in \p arg and update the entry in |
190 | * drm_device::ctx_idr with it. | 183 | * drm_device::ctx_idr with it. |
191 | */ | 184 | */ |
192 | int drm_setsareactx(struct inode *inode, struct drm_file *file_priv, | 185 | int drm_setsareactx(struct drm_device *dev, void *data, |
193 | unsigned int cmd, unsigned long arg) | 186 | struct drm_file *file_priv) |
194 | { | 187 | { |
195 | struct drm_device *dev = file_priv->head->dev; | 188 | struct drm_ctx_priv_map *request = data; |
196 | struct drm_ctx_priv_map request; | ||
197 | struct drm_map *map = NULL; | 189 | struct drm_map *map = NULL; |
198 | struct drm_map_list *r_list = NULL; | 190 | struct drm_map_list *r_list = NULL; |
199 | 191 | ||
200 | if (copy_from_user(&request, | ||
201 | (struct drm_ctx_priv_map __user *) arg, | ||
202 | sizeof(request))) | ||
203 | return -EFAULT; | ||
204 | |||
205 | mutex_lock(&dev->struct_mutex); | 192 | mutex_lock(&dev->struct_mutex); |
206 | list_for_each_entry(r_list, &dev->maplist, head) { | 193 | list_for_each_entry(r_list, &dev->maplist, head) { |
207 | if (r_list->map | 194 | if (r_list->map |
208 | && r_list->user_token == (unsigned long)request.handle) | 195 | && r_list->user_token == (unsigned long) request->handle) |
209 | goto found; | 196 | goto found; |
210 | } | 197 | } |
211 | bad: | 198 | bad: |
@@ -217,10 +204,11 @@ int drm_setsareactx(struct inode *inode, struct drm_file *file_priv, | |||
217 | if (!map) | 204 | if (!map) |
218 | goto bad; | 205 | goto bad; |
219 | 206 | ||
220 | if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id))) | 207 | if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id))) |
221 | goto bad; | 208 | goto bad; |
222 | 209 | ||
223 | mutex_unlock(&dev->struct_mutex); | 210 | mutex_unlock(&dev->struct_mutex); |
211 | |||
224 | return 0; | 212 | return 0; |
225 | } | 213 | } |
226 | 214 | ||
@@ -295,29 +283,23 @@ static int drm_context_switch_complete(struct drm_device * dev, int new) | |||
295 | * \param arg user argument pointing to a drm_ctx_res structure. | 283 | * \param arg user argument pointing to a drm_ctx_res structure. |
296 | * \return zero on success or a negative number on failure. | 284 | * \return zero on success or a negative number on failure. |
297 | */ | 285 | */ |
298 | int drm_resctx(struct inode *inode, struct drm_file *file_priv, | 286 | int drm_resctx(struct drm_device *dev, void *data, |
299 | unsigned int cmd, unsigned long arg) | 287 | struct drm_file *file_priv) |
300 | { | 288 | { |
301 | struct drm_ctx_res res; | 289 | struct drm_ctx_res *res = data; |
302 | struct drm_ctx_res __user *argp = (void __user *)arg; | ||
303 | struct drm_ctx ctx; | 290 | struct drm_ctx ctx; |
304 | int i; | 291 | int i; |
305 | 292 | ||
306 | if (copy_from_user(&res, argp, sizeof(res))) | 293 | if (res->count >= DRM_RESERVED_CONTEXTS) { |
307 | return -EFAULT; | ||
308 | |||
309 | if (res.count >= DRM_RESERVED_CONTEXTS) { | ||
310 | memset(&ctx, 0, sizeof(ctx)); | 294 | memset(&ctx, 0, sizeof(ctx)); |
311 | for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { | 295 | for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { |
312 | ctx.handle = i; | 296 | ctx.handle = i; |
313 | if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx))) | 297 | if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx))) |
314 | return -EFAULT; | 298 | return -EFAULT; |
315 | } | 299 | } |
316 | } | 300 | } |
317 | res.count = DRM_RESERVED_CONTEXTS; | 301 | res->count = DRM_RESERVED_CONTEXTS; |
318 | 302 | ||
319 | if (copy_to_user(argp, &res, sizeof(res))) | ||
320 | return -EFAULT; | ||
321 | return 0; | 303 | return 0; |
322 | } | 304 | } |
323 | 305 | ||
@@ -332,32 +314,27 @@ int drm_resctx(struct inode *inode, struct drm_file *file_priv, | |||
332 | * | 314 | * |
333 | * Get a new handle for the context and copy to userspace. | 315 | * Get a new handle for the context and copy to userspace. |
334 | */ | 316 | */ |
335 | int drm_addctx(struct inode *inode, struct drm_file *file_priv, | 317 | int drm_addctx(struct drm_device *dev, void *data, |
336 | unsigned int cmd, unsigned long arg) | 318 | struct drm_file *file_priv) |
337 | { | 319 | { |
338 | struct drm_device *dev = file_priv->head->dev; | ||
339 | struct drm_ctx_list *ctx_entry; | 320 | struct drm_ctx_list *ctx_entry; |
340 | struct drm_ctx __user *argp = (void __user *)arg; | 321 | struct drm_ctx *ctx = data; |
341 | struct drm_ctx ctx; | ||
342 | |||
343 | if (copy_from_user(&ctx, argp, sizeof(ctx))) | ||
344 | return -EFAULT; | ||
345 | 322 | ||
346 | ctx.handle = drm_ctxbitmap_next(dev); | 323 | ctx->handle = drm_ctxbitmap_next(dev); |
347 | if (ctx.handle == DRM_KERNEL_CONTEXT) { | 324 | if (ctx->handle == DRM_KERNEL_CONTEXT) { |
348 | /* Skip kernel's context and get a new one. */ | 325 | /* Skip kernel's context and get a new one. */ |
349 | ctx.handle = drm_ctxbitmap_next(dev); | 326 | ctx->handle = drm_ctxbitmap_next(dev); |
350 | } | 327 | } |
351 | DRM_DEBUG("%d\n", ctx.handle); | 328 | DRM_DEBUG("%d\n", ctx->handle); |
352 | if (ctx.handle == -1) { | 329 | if (ctx->handle == -1) { |
353 | DRM_DEBUG("Not enough free contexts.\n"); | 330 | DRM_DEBUG("Not enough free contexts.\n"); |
354 | /* Should this return -EBUSY instead? */ | 331 | /* Should this return -EBUSY instead? */ |
355 | return -ENOMEM; | 332 | return -ENOMEM; |
356 | } | 333 | } |
357 | 334 | ||
358 | if (ctx.handle != DRM_KERNEL_CONTEXT) { | 335 | if (ctx->handle != DRM_KERNEL_CONTEXT) { |
359 | if (dev->driver->context_ctor) | 336 | if (dev->driver->context_ctor) |
360 | if (!dev->driver->context_ctor(dev, ctx.handle)) { | 337 | if (!dev->driver->context_ctor(dev, ctx->handle)) { |
361 | DRM_DEBUG("Running out of ctxs or memory.\n"); | 338 | DRM_DEBUG("Running out of ctxs or memory.\n"); |
362 | return -ENOMEM; | 339 | return -ENOMEM; |
363 | } | 340 | } |
@@ -370,7 +347,7 @@ int drm_addctx(struct inode *inode, struct drm_file *file_priv, | |||
370 | } | 347 | } |
371 | 348 | ||
372 | INIT_LIST_HEAD(&ctx_entry->head); | 349 | INIT_LIST_HEAD(&ctx_entry->head); |
373 | ctx_entry->handle = ctx.handle; | 350 | ctx_entry->handle = ctx->handle; |
374 | ctx_entry->tag = file_priv; | 351 | ctx_entry->tag = file_priv; |
375 | 352 | ||
376 | mutex_lock(&dev->ctxlist_mutex); | 353 | mutex_lock(&dev->ctxlist_mutex); |
@@ -378,13 +355,10 @@ int drm_addctx(struct inode *inode, struct drm_file *file_priv, | |||
378 | ++dev->ctx_count; | 355 | ++dev->ctx_count; |
379 | mutex_unlock(&dev->ctxlist_mutex); | 356 | mutex_unlock(&dev->ctxlist_mutex); |
380 | 357 | ||
381 | if (copy_to_user(argp, &ctx, sizeof(ctx))) | ||
382 | return -EFAULT; | ||
383 | return 0; | 358 | return 0; |
384 | } | 359 | } |
385 | 360 | ||
386 | int drm_modctx(struct inode *inode, struct drm_file *file_priv, | 361 | int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv) |
387 | unsigned int cmd, unsigned long arg) | ||
388 | { | 362 | { |
389 | /* This does nothing */ | 363 | /* This does nothing */ |
390 | return 0; | 364 | return 0; |
@@ -399,20 +373,13 @@ int drm_modctx(struct inode *inode, struct drm_file *file_priv, | |||
399 | * \param arg user argument pointing to a drm_ctx structure. | 373 | * \param arg user argument pointing to a drm_ctx structure. |
400 | * \return zero on success or a negative number on failure. | 374 | * \return zero on success or a negative number on failure. |
401 | */ | 375 | */ |
402 | int drm_getctx(struct inode *inode, struct drm_file *file_priv, | 376 | int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) |
403 | unsigned int cmd, unsigned long arg) | ||
404 | { | 377 | { |
405 | struct drm_ctx __user *argp = (void __user *)arg; | 378 | struct drm_ctx *ctx = data; |
406 | struct drm_ctx ctx; | ||
407 | |||
408 | if (copy_from_user(&ctx, argp, sizeof(ctx))) | ||
409 | return -EFAULT; | ||
410 | 379 | ||
411 | /* This is 0, because we don't handle any context flags */ | 380 | /* This is 0, because we don't handle any context flags */ |
412 | ctx.flags = 0; | 381 | ctx->flags = 0; |
413 | 382 | ||
414 | if (copy_to_user(argp, &ctx, sizeof(ctx))) | ||
415 | return -EFAULT; | ||
416 | return 0; | 383 | return 0; |
417 | } | 384 | } |
418 | 385 | ||
@@ -427,17 +394,13 @@ int drm_getctx(struct inode *inode, struct drm_file *file_priv, | |||
427 | * | 394 | * |
428 | * Calls context_switch(). | 395 | * Calls context_switch(). |
429 | */ | 396 | */ |
430 | int drm_switchctx(struct inode *inode, struct drm_file *file_priv, | 397 | int drm_switchctx(struct drm_device *dev, void *data, |
431 | unsigned int cmd, unsigned long arg) | 398 | struct drm_file *file_priv) |
432 | { | 399 | { |
433 | struct drm_device *dev = file_priv->head->dev; | 400 | struct drm_ctx *ctx = data; |
434 | struct drm_ctx ctx; | ||
435 | 401 | ||
436 | if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx))) | 402 | DRM_DEBUG("%d\n", ctx->handle); |
437 | return -EFAULT; | 403 | return drm_context_switch(dev, dev->last_context, ctx->handle); |
438 | |||
439 | DRM_DEBUG("%d\n", ctx.handle); | ||
440 | return drm_context_switch(dev, dev->last_context, ctx.handle); | ||
441 | } | 404 | } |
442 | 405 | ||
443 | /** | 406 | /** |
@@ -451,17 +414,13 @@ int drm_switchctx(struct inode *inode, struct drm_file *file_priv, | |||
451 | * | 414 | * |
452 | * Calls context_switch_complete(). | 415 | * Calls context_switch_complete(). |
453 | */ | 416 | */ |
454 | int drm_newctx(struct inode *inode, struct drm_file *file_priv, | 417 | int drm_newctx(struct drm_device *dev, void *data, |
455 | unsigned int cmd, unsigned long arg) | 418 | struct drm_file *file_priv) |
456 | { | 419 | { |
457 | struct drm_device *dev = file_priv->head->dev; | 420 | struct drm_ctx *ctx = data; |
458 | struct drm_ctx ctx; | ||
459 | 421 | ||
460 | if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx))) | 422 | DRM_DEBUG("%d\n", ctx->handle); |
461 | return -EFAULT; | 423 | drm_context_switch_complete(dev, ctx->handle); |
462 | |||
463 | DRM_DEBUG("%d\n", ctx.handle); | ||
464 | drm_context_switch_complete(dev, ctx.handle); | ||
465 | 424 | ||
466 | return 0; | 425 | return 0; |
467 | } | 426 | } |
@@ -477,23 +436,19 @@ int drm_newctx(struct inode *inode, struct drm_file *file_priv, | |||
477 | * | 436 | * |
478 | * If not the special kernel context, calls ctxbitmap_free() to free the specified context. | 437 | * If not the special kernel context, calls ctxbitmap_free() to free the specified context. |
479 | */ | 438 | */ |
480 | int drm_rmctx(struct inode *inode, struct drm_file *file_priv, | 439 | int drm_rmctx(struct drm_device *dev, void *data, |
481 | unsigned int cmd, unsigned long arg) | 440 | struct drm_file *file_priv) |
482 | { | 441 | { |
483 | struct drm_device *dev = file_priv->head->dev; | 442 | struct drm_ctx *ctx = data; |
484 | struct drm_ctx ctx; | ||
485 | |||
486 | if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx))) | ||
487 | return -EFAULT; | ||
488 | 443 | ||
489 | DRM_DEBUG("%d\n", ctx.handle); | 444 | DRM_DEBUG("%d\n", ctx->handle); |
490 | if (ctx.handle == DRM_KERNEL_CONTEXT + 1) { | 445 | if (ctx->handle == DRM_KERNEL_CONTEXT + 1) { |
491 | file_priv->remove_auth_on_close = 1; | 446 | file_priv->remove_auth_on_close = 1; |
492 | } | 447 | } |
493 | if (ctx.handle != DRM_KERNEL_CONTEXT) { | 448 | if (ctx->handle != DRM_KERNEL_CONTEXT) { |
494 | if (dev->driver->context_dtor) | 449 | if (dev->driver->context_dtor) |
495 | dev->driver->context_dtor(dev, ctx.handle); | 450 | dev->driver->context_dtor(dev, ctx->handle); |
496 | drm_ctxbitmap_free(dev, ctx.handle); | 451 | drm_ctxbitmap_free(dev, ctx->handle); |
497 | } | 452 | } |
498 | 453 | ||
499 | mutex_lock(&dev->ctxlist_mutex); | 454 | mutex_lock(&dev->ctxlist_mutex); |
@@ -501,7 +456,7 @@ int drm_rmctx(struct inode *inode, struct drm_file *file_priv, | |||
501 | struct drm_ctx_list *pos, *n; | 456 | struct drm_ctx_list *pos, *n; |
502 | 457 | ||
503 | list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { | 458 | list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { |
504 | if (pos->handle == ctx.handle) { | 459 | if (pos->handle == ctx->handle) { |
505 | list_del(&pos->head); | 460 | list_del(&pos->head); |
506 | drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST); | 461 | drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST); |
507 | --dev->ctx_count; | 462 | --dev->ctx_count; |