1 /* 2 * Copyright (C) 2015 Red Hat, Inc. 3 * All Rights Reserved. 4 * 5 * Authors: 6 * Dave Airlie 7 * Alon Levy 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #include <linux/file.h> 29 #include <linux/sync_file.h> 30 #include <linux/uaccess.h> 31 32 #include <drm/drm_file.h> 33 #include <drm/virtgpu_drm.h> 34 35 #include "virtgpu_drv.h" 36 37 #define VIRTGPU_BLOB_FLAG_USE_MASK (VIRTGPU_BLOB_FLAG_USE_MAPPABLE | \ 38 VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \ 39 VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) 40 41 /* Must be called with &virtio_gpu_fpriv.struct_mutex held. */ 42 static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev, 43 struct virtio_gpu_fpriv *vfpriv) 44 { 45 if (vfpriv->explicit_debug_name) { 46 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, 47 vfpriv->context_init, 48 strlen(vfpriv->debug_name), 49 vfpriv->debug_name); 50 } else { 51 char dbgname[TASK_COMM_LEN]; 52 53 get_task_comm(dbgname, current); 54 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, 55 vfpriv->context_init, strlen(dbgname), 56 dbgname); 57 } 58 59 vfpriv->context_created = true; 60 } 61 62 void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file) 63 { 64 struct virtio_gpu_device *vgdev = dev->dev_private; 65 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 66 67 mutex_lock(&vfpriv->context_lock); 68 if (vfpriv->context_created) 69 goto out_unlock; 70 71 virtio_gpu_create_context_locked(vgdev, vfpriv); 72 73 out_unlock: 74 mutex_unlock(&vfpriv->context_lock); 75 } 76 77 static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data, 78 struct drm_file *file) 79 { 80 struct virtio_gpu_device *vgdev = dev->dev_private; 81 struct drm_virtgpu_map *virtio_gpu_map = data; 82 83 return drm_gem_dumb_map_offset(file, vgdev->ddev, 84 virtio_gpu_map->handle, 85 &virtio_gpu_map->offset); 86 } 87 88 static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, 89 struct drm_file *file) 90 { 91 struct virtio_gpu_device *vgdev = dev->dev_private; 92 struct drm_virtgpu_getparam *param = data; 93 int value; 94 95 switch (param->param) { 96 case VIRTGPU_PARAM_3D_FEATURES: 97 value = vgdev->has_virgl_3d ? 1 : 0; 98 break; 99 case VIRTGPU_PARAM_CAPSET_QUERY_FIX: 100 value = 1; 101 break; 102 case VIRTGPU_PARAM_RESOURCE_BLOB: 103 value = vgdev->has_resource_blob ? 1 : 0; 104 break; 105 case VIRTGPU_PARAM_HOST_VISIBLE: 106 value = vgdev->has_host_visible ? 1 : 0; 107 break; 108 case VIRTGPU_PARAM_CROSS_DEVICE: 109 value = vgdev->has_resource_assign_uuid ? 1 : 0; 110 break; 111 case VIRTGPU_PARAM_CONTEXT_INIT: 112 value = vgdev->has_context_init ? 1 : 0; 113 break; 114 case VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs: 115 value = vgdev->capset_id_mask; 116 break; 117 case VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME: 118 value = vgdev->has_context_init ? 1 : 0; 119 break; 120 default: 121 return -EINVAL; 122 } 123 if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int))) 124 return -EFAULT; 125 126 return 0; 127 } 128 129 static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, 130 struct drm_file *file) 131 { 132 struct virtio_gpu_device *vgdev = dev->dev_private; 133 struct drm_virtgpu_resource_create *rc = data; 134 struct virtio_gpu_fence *fence; 135 int ret; 136 struct virtio_gpu_object *qobj; 137 struct drm_gem_object *obj; 138 uint32_t handle = 0; 139 struct virtio_gpu_object_params params = { 0 }; 140 141 if (vgdev->has_virgl_3d) { 142 virtio_gpu_create_context(dev, file); 143 params.virgl = true; 144 params.target = rc->target; 145 params.bind = rc->bind; 146 params.depth = rc->depth; 147 params.array_size = rc->array_size; 148 params.last_level = rc->last_level; 149 params.nr_samples = rc->nr_samples; 150 params.flags = rc->flags; 151 } else { 152 if (rc->depth > 1) 153 return -EINVAL; 154 if (rc->nr_samples > 1) 155 return -EINVAL; 156 if (rc->last_level > 1) 157 return -EINVAL; 158 if (rc->target != 2) 159 return -EINVAL; 160 if (rc->array_size > 1) 161 return -EINVAL; 162 } 163 164 params.format = rc->format; 165 params.width = rc->width; 166 params.height = rc->height; 167 params.size = rc->size; 168 /* allocate a single page size object */ 169 if (params.size == 0) 170 params.size = PAGE_SIZE; 171 172 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0); 173 if (!fence) 174 return -ENOMEM; 175 ret = virtio_gpu_object_create(vgdev, ¶ms, &qobj, fence); 176 dma_fence_put(&fence->f); 177 if (ret < 0) 178 return ret; 179 obj = &qobj->base.base; 180 181 ret = drm_gem_handle_create(file, obj, &handle); 182 if (ret) { 183 drm_gem_object_release(obj); 184 return ret; 185 } 186 187 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */ 188 rc->bo_handle = handle; 189 190 /* 191 * The handle owns the reference now. But we must drop our 192 * remaining reference *after* we no longer need to dereference 193 * the obj. Otherwise userspace could guess the handle and 194 * race closing it from another thread. 195 */ 196 drm_gem_object_put(obj); 197 198 return 0; 199 } 200 201 static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data, 202 struct drm_file *file) 203 { 204 struct drm_virtgpu_resource_info *ri = data; 205 struct drm_gem_object *gobj = NULL; 206 struct virtio_gpu_object *qobj = NULL; 207 208 gobj = drm_gem_object_lookup(file, ri->bo_handle); 209 if (gobj == NULL) 210 return -ENOENT; 211 212 qobj = gem_to_virtio_gpu_obj(gobj); 213 214 ri->size = qobj->base.base.size; 215 ri->res_handle = qobj->hw_res_handle; 216 if (qobj->host3d_blob || qobj->guest_blob) 217 ri->blob_mem = qobj->blob_mem; 218 219 drm_gem_object_put(gobj); 220 return 0; 221 } 222 223 static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, 224 void *data, 225 struct drm_file *file) 226 { 227 struct virtio_gpu_device *vgdev = dev->dev_private; 228 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 229 struct drm_virtgpu_3d_transfer_from_host *args = data; 230 struct virtio_gpu_object *bo; 231 struct virtio_gpu_object_array *objs; 232 struct virtio_gpu_fence *fence; 233 int ret; 234 u32 offset = args->offset; 235 236 if (vgdev->has_virgl_3d == false) 237 return -ENOSYS; 238 239 virtio_gpu_create_context(dev, file); 240 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); 241 if (objs == NULL) 242 return -ENOENT; 243 244 bo = gem_to_virtio_gpu_obj(objs->objs[0]); 245 if (bo->guest_blob && !bo->host3d_blob) { 246 ret = -EINVAL; 247 goto err_put_free; 248 } 249 250 if (!bo->host3d_blob && (args->stride || args->layer_stride)) { 251 ret = -EINVAL; 252 goto err_put_free; 253 } 254 255 ret = virtio_gpu_array_lock_resv(objs); 256 if (ret != 0) 257 goto err_put_free; 258 259 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0); 260 if (!fence) { 261 ret = -ENOMEM; 262 goto err_unlock; 263 } 264 265 virtio_gpu_cmd_transfer_from_host_3d 266 (vgdev, vfpriv->ctx_id, offset, args->level, args->stride, 267 args->layer_stride, &args->box, objs, fence); 268 dma_fence_put(&fence->f); 269 virtio_gpu_notify(vgdev); 270 return 0; 271 272 err_unlock: 273 virtio_gpu_array_unlock_resv(objs); 274 err_put_free: 275 virtio_gpu_array_put_free(objs); 276 return ret; 277 } 278 279 static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, 280 struct drm_file *file) 281 { 282 struct virtio_gpu_device *vgdev = dev->dev_private; 283 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 284 struct drm_virtgpu_3d_transfer_to_host *args = data; 285 struct virtio_gpu_object *bo; 286 struct virtio_gpu_object_array *objs; 287 struct virtio_gpu_fence *fence; 288 int ret; 289 u32 offset = args->offset; 290 291 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); 292 if (objs == NULL) 293 return -ENOENT; 294 295 bo = gem_to_virtio_gpu_obj(objs->objs[0]); 296 if (bo->guest_blob && !bo->host3d_blob) { 297 ret = -EINVAL; 298 goto err_put_free; 299 } 300 301 if (!vgdev->has_virgl_3d) { 302 virtio_gpu_cmd_transfer_to_host_2d 303 (vgdev, offset, 304 args->box.w, args->box.h, args->box.x, args->box.y, 305 objs, NULL); 306 } else { 307 virtio_gpu_create_context(dev, file); 308 309 if (!bo->host3d_blob && (args->stride || args->layer_stride)) { 310 ret = -EINVAL; 311 goto err_put_free; 312 } 313 314 ret = virtio_gpu_array_lock_resv(objs); 315 if (ret != 0) 316 goto err_put_free; 317 318 ret = -ENOMEM; 319 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 320 0); 321 if (!fence) 322 goto err_unlock; 323 324 virtio_gpu_cmd_transfer_to_host_3d 325 (vgdev, 326 vfpriv ? vfpriv->ctx_id : 0, offset, args->level, 327 args->stride, args->layer_stride, &args->box, objs, 328 fence); 329 dma_fence_put(&fence->f); 330 } 331 virtio_gpu_notify(vgdev); 332 return 0; 333 334 err_unlock: 335 virtio_gpu_array_unlock_resv(objs); 336 err_put_free: 337 virtio_gpu_array_put_free(objs); 338 return ret; 339 } 340 341 static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data, 342 struct drm_file *file) 343 { 344 struct drm_virtgpu_3d_wait *args = data; 345 struct drm_gem_object *obj; 346 long timeout = 15 * HZ; 347 int ret; 348 349 obj = drm_gem_object_lookup(file, args->handle); 350 if (obj == NULL) 351 return -ENOENT; 352 353 if (args->flags & VIRTGPU_WAIT_NOWAIT) { 354 ret = dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ); 355 } else { 356 ret = dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ, 357 true, timeout); 358 } 359 if (ret == 0) 360 ret = -EBUSY; 361 else if (ret > 0) 362 ret = 0; 363 364 drm_gem_object_put(obj); 365 return ret; 366 } 367 368 static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, 369 void *data, struct drm_file *file) 370 { 371 struct virtio_gpu_device *vgdev = dev->dev_private; 372 struct drm_virtgpu_get_caps *args = data; 373 unsigned size, host_caps_size; 374 int i; 375 int found_valid = -1; 376 int ret; 377 struct virtio_gpu_drv_cap_cache *cache_ent; 378 void *ptr; 379 380 if (vgdev->num_capsets == 0) 381 return -ENOSYS; 382 383 /* don't allow userspace to pass 0 */ 384 if (args->size == 0) 385 return -EINVAL; 386 387 spin_lock(&vgdev->display_info_lock); 388 for (i = 0; i < vgdev->num_capsets; i++) { 389 if (vgdev->capsets[i].id == args->cap_set_id) { 390 if (vgdev->capsets[i].max_version >= args->cap_set_ver) { 391 found_valid = i; 392 break; 393 } 394 } 395 } 396 397 if (found_valid == -1) { 398 spin_unlock(&vgdev->display_info_lock); 399 return -EINVAL; 400 } 401 402 host_caps_size = vgdev->capsets[found_valid].max_size; 403 /* only copy to user the minimum of the host caps size or the guest caps size */ 404 size = min(args->size, host_caps_size); 405 406 list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { 407 if (cache_ent->id == args->cap_set_id && 408 cache_ent->version == args->cap_set_ver) { 409 spin_unlock(&vgdev->display_info_lock); 410 goto copy_exit; 411 } 412 } 413 spin_unlock(&vgdev->display_info_lock); 414 415 /* not in cache - need to talk to hw */ 416 ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, 417 &cache_ent); 418 if (ret) 419 return ret; 420 virtio_gpu_notify(vgdev); 421 422 copy_exit: 423 ret = wait_event_timeout(vgdev->resp_wq, 424 atomic_read(&cache_ent->is_valid), 5 * HZ); 425 if (!ret) 426 return -EBUSY; 427 428 /* is_valid check must proceed before copy of the cache entry. */ 429 smp_rmb(); 430 431 ptr = cache_ent->caps_cache; 432 433 if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size)) 434 return -EFAULT; 435 436 return 0; 437 } 438 439 static int verify_blob(struct virtio_gpu_device *vgdev, 440 struct virtio_gpu_fpriv *vfpriv, 441 struct virtio_gpu_object_params *params, 442 struct drm_virtgpu_resource_create_blob *rc_blob, 443 bool *guest_blob, bool *host3d_blob) 444 { 445 if (!vgdev->has_resource_blob) 446 return -EINVAL; 447 448 if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK) 449 return -EINVAL; 450 451 if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { 452 if (!vgdev->has_resource_assign_uuid) 453 return -EINVAL; 454 } 455 456 switch (rc_blob->blob_mem) { 457 case VIRTGPU_BLOB_MEM_GUEST: 458 *guest_blob = true; 459 break; 460 case VIRTGPU_BLOB_MEM_HOST3D_GUEST: 461 *guest_blob = true; 462 fallthrough; 463 case VIRTGPU_BLOB_MEM_HOST3D: 464 *host3d_blob = true; 465 break; 466 default: 467 return -EINVAL; 468 } 469 470 if (*host3d_blob) { 471 if (!vgdev->has_virgl_3d) 472 return -EINVAL; 473 474 /* Must be dword aligned. */ 475 if (rc_blob->cmd_size % 4 != 0) 476 return -EINVAL; 477 478 params->ctx_id = vfpriv->ctx_id; 479 params->blob_id = rc_blob->blob_id; 480 } else { 481 if (rc_blob->blob_id != 0) 482 return -EINVAL; 483 484 if (rc_blob->cmd_size != 0) 485 return -EINVAL; 486 } 487 488 params->blob_mem = rc_blob->blob_mem; 489 params->size = rc_blob->size; 490 params->blob = true; 491 params->blob_flags = rc_blob->blob_flags; 492 params->blob_hints = rc_blob->blob_hints; 493 return 0; 494 } 495 496 static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, 497 void *data, 498 struct drm_file *file) 499 { 500 int ret = 0; 501 uint32_t handle = 0; 502 bool guest_blob = false; 503 bool host3d_blob = false; 504 struct drm_gem_object *obj; 505 struct virtio_gpu_object *bo; 506 struct virtio_gpu_object_params params = { 0 }; 507 struct virtio_gpu_device *vgdev = dev->dev_private; 508 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 509 struct drm_virtgpu_resource_create_blob *rc_blob = data; 510 511 if (verify_blob(vgdev, vfpriv, ¶ms, rc_blob, 512 &guest_blob, &host3d_blob)) 513 return -EINVAL; 514 515 if (vgdev->has_virgl_3d) 516 virtio_gpu_create_context(dev, file); 517 518 if (rc_blob->cmd_size) { 519 void *buf; 520 521 buf = memdup_user(u64_to_user_ptr(rc_blob->cmd), 522 rc_blob->cmd_size); 523 524 if (IS_ERR(buf)) 525 return PTR_ERR(buf); 526 527 virtio_gpu_cmd_submit(vgdev, buf, rc_blob->cmd_size, 528 vfpriv->ctx_id, NULL, NULL); 529 } 530 531 if (guest_blob) 532 ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL); 533 else if (!guest_blob && host3d_blob) 534 ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo); 535 else 536 return -EINVAL; 537 538 if (ret < 0) 539 return ret; 540 541 bo->guest_blob = guest_blob; 542 bo->host3d_blob = host3d_blob; 543 bo->blob_mem = rc_blob->blob_mem; 544 bo->blob_flags = rc_blob->blob_flags; 545 546 obj = &bo->base.base; 547 if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { 548 ret = virtio_gpu_resource_assign_uuid(vgdev, bo); 549 if (ret) { 550 drm_gem_object_release(obj); 551 return ret; 552 } 553 } 554 555 ret = drm_gem_handle_create(file, obj, &handle); 556 if (ret) { 557 drm_gem_object_release(obj); 558 return ret; 559 } 560 561 rc_blob->res_handle = bo->hw_res_handle; 562 rc_blob->bo_handle = handle; 563 564 /* 565 * The handle owns the reference now. But we must drop our 566 * remaining reference *after* we no longer need to dereference 567 * the obj. Otherwise userspace could guess the handle and 568 * race closing it from another thread. 569 */ 570 drm_gem_object_put(obj); 571 572 return 0; 573 } 574 575 static int virtio_gpu_context_init_ioctl(struct drm_device *dev, 576 void *data, struct drm_file *file) 577 { 578 int ret = 0; 579 uint32_t num_params, i; 580 uint64_t valid_ring_mask, param, value; 581 size_t len; 582 struct drm_virtgpu_context_set_param *ctx_set_params = NULL; 583 struct virtio_gpu_device *vgdev = dev->dev_private; 584 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 585 struct drm_virtgpu_context_init *args = data; 586 587 num_params = args->num_params; 588 len = num_params * sizeof(struct drm_virtgpu_context_set_param); 589 590 if (!vgdev->has_context_init || !vgdev->has_virgl_3d) 591 return -EINVAL; 592 593 /* Number of unique parameters supported at this time. */ 594 if (num_params > 4) 595 return -EINVAL; 596 597 ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params), 598 len); 599 600 if (IS_ERR(ctx_set_params)) 601 return PTR_ERR(ctx_set_params); 602 603 mutex_lock(&vfpriv->context_lock); 604 if (vfpriv->context_created) { 605 ret = -EEXIST; 606 goto out_unlock; 607 } 608 609 for (i = 0; i < num_params; i++) { 610 param = ctx_set_params[i].param; 611 value = ctx_set_params[i].value; 612 613 switch (param) { 614 case VIRTGPU_CONTEXT_PARAM_CAPSET_ID: 615 if (value > MAX_CAPSET_ID) { 616 ret = -EINVAL; 617 goto out_unlock; 618 } 619 620 if ((vgdev->capset_id_mask & (1ULL << value)) == 0) { 621 ret = -EINVAL; 622 goto out_unlock; 623 } 624 625 /* Context capset ID already set */ 626 if (vfpriv->context_init & 627 VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) { 628 ret = -EINVAL; 629 goto out_unlock; 630 } 631 632 vfpriv->context_init |= value; 633 break; 634 case VIRTGPU_CONTEXT_PARAM_NUM_RINGS: 635 if (vfpriv->base_fence_ctx) { 636 ret = -EINVAL; 637 goto out_unlock; 638 } 639 640 if (value > MAX_RINGS) { 641 ret = -EINVAL; 642 goto out_unlock; 643 } 644 645 vfpriv->base_fence_ctx = dma_fence_context_alloc(value); 646 vfpriv->num_rings = value; 647 break; 648 case VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK: 649 if (vfpriv->ring_idx_mask) { 650 ret = -EINVAL; 651 goto out_unlock; 652 } 653 654 vfpriv->ring_idx_mask = value; 655 break; 656 case VIRTGPU_CONTEXT_PARAM_DEBUG_NAME: 657 if (vfpriv->explicit_debug_name) { 658 ret = -EINVAL; 659 goto out_unlock; 660 } 661 662 ret = strncpy_from_user(vfpriv->debug_name, 663 u64_to_user_ptr(value), 664 DEBUG_NAME_MAX_LEN - 1); 665 if (ret < 0) 666 goto out_unlock; 667 668 vfpriv->explicit_debug_name = true; 669 ret = 0; 670 break; 671 default: 672 ret = -EINVAL; 673 goto out_unlock; 674 } 675 } 676 677 if (vfpriv->ring_idx_mask) { 678 valid_ring_mask = 0; 679 for (i = 0; i < vfpriv->num_rings; i++) 680 valid_ring_mask |= 1ULL << i; 681 682 if (~valid_ring_mask & vfpriv->ring_idx_mask) { 683 ret = -EINVAL; 684 goto out_unlock; 685 } 686 } 687 688 virtio_gpu_create_context_locked(vgdev, vfpriv); 689 virtio_gpu_notify(vgdev); 690 691 out_unlock: 692 mutex_unlock(&vfpriv->context_lock); 693 kfree(ctx_set_params); 694 return ret; 695 } 696 697 struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { 698 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, 699 DRM_RENDER_ALLOW), 700 701 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, 702 DRM_RENDER_ALLOW), 703 704 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, 705 DRM_RENDER_ALLOW), 706 707 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, 708 virtio_gpu_resource_create_ioctl, 709 DRM_RENDER_ALLOW), 710 711 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, 712 DRM_RENDER_ALLOW), 713 714 /* make transfer async to the main ring? - no sure, can we 715 * thread these in the underlying GL 716 */ 717 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, 718 virtio_gpu_transfer_from_host_ioctl, 719 DRM_RENDER_ALLOW), 720 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, 721 virtio_gpu_transfer_to_host_ioctl, 722 DRM_RENDER_ALLOW), 723 724 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, 725 DRM_RENDER_ALLOW), 726 727 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, 728 DRM_RENDER_ALLOW), 729 730 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB, 731 virtio_gpu_resource_create_blob_ioctl, 732 DRM_RENDER_ALLOW), 733 734 DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl, 735 DRM_RENDER_ALLOW), 736 }; 737