aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2009-12-22 10:53:41 -0500
committerDave Airlie <airlied@redhat.com>2009-12-22 19:06:24 -0500
commit7a73ba7469cbea631050094fd14f73acebb97cf9 (patch)
tree2c1bc2b28a395578967343e14a3a4b90c66e55f5 /drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
parent3d3a5b3290043618e8409f3fb68a63de6156fdd4 (diff)
drm/vmwgfx: Use TTM handles instead of SIDs as user-space surface handles.
Improve the command verifier to catch all occurences of surface handles, and translate to SIDs. This way DMA buffers and 3D surfaces share a common handle space, which makes it possible for the kms code to differentiate. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_resource.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c149
1 files changed, 70 insertions, 79 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index a1ceed0c8e07..c012d5927f65 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -488,28 +488,44 @@ static void vmw_user_surface_free(struct vmw_resource *res)
488 kfree(user_srf); 488 kfree(user_srf);
489} 489}
490 490
491int vmw_user_surface_lookup(struct vmw_private *dev_priv, 491int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
492 struct ttm_object_file *tfile, 492 struct ttm_object_file *tfile,
493 int sid, struct vmw_surface **out) 493 uint32_t handle, struct vmw_surface **out)
494{ 494{
495 struct vmw_resource *res; 495 struct vmw_resource *res;
496 struct vmw_surface *srf; 496 struct vmw_surface *srf;
497 struct vmw_user_surface *user_srf; 497 struct vmw_user_surface *user_srf;
498 struct ttm_base_object *base;
499 int ret = -EINVAL;
498 500
499 res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, sid); 501 base = ttm_base_object_lookup(tfile, handle);
500 if (unlikely(res == NULL)) 502 if (unlikely(base == NULL))
501 return -EINVAL; 503 return -EINVAL;
502 504
503 if (res->res_free != &vmw_user_surface_free) 505 if (unlikely(base->object_type != VMW_RES_SURFACE))
504 return -EINVAL; 506 goto out_bad_resource;
505 507
506 srf = container_of(res, struct vmw_surface, res); 508 user_srf = container_of(base, struct vmw_user_surface, base);
507 user_srf = container_of(srf, struct vmw_user_surface, srf); 509 srf = &user_srf->srf;
508 if (user_srf->base.tfile != tfile && !user_srf->base.shareable) 510 res = &srf->res;
509 return -EPERM; 511
512 read_lock(&dev_priv->resource_lock);
513
514 if (!res->avail || res->res_free != &vmw_user_surface_free) {
515 read_unlock(&dev_priv->resource_lock);
516 goto out_bad_resource;
517 }
518
519 kref_get(&res->kref);
520 read_unlock(&dev_priv->resource_lock);
510 521
511 *out = srf; 522 *out = srf;
512 return 0; 523 ret = 0;
524
525out_bad_resource:
526 ttm_base_object_unref(&base);
527
528 return ret;
513} 529}
514 530
515static void vmw_user_surface_base_release(struct ttm_base_object **p_base) 531static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
@@ -526,35 +542,10 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
526int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 542int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
527 struct drm_file *file_priv) 543 struct drm_file *file_priv)
528{ 544{
529 struct vmw_private *dev_priv = vmw_priv(dev);
530 struct vmw_resource *res;
531 struct vmw_surface *srf;
532 struct vmw_user_surface *user_srf;
533 struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data; 545 struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
534 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 546 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
535 int ret = 0;
536
537 res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, arg->sid);
538 if (unlikely(res == NULL))
539 return -EINVAL;
540
541 if (res->res_free != &vmw_user_surface_free) {
542 ret = -EINVAL;
543 goto out;
544 }
545 547
546 srf = container_of(res, struct vmw_surface, res); 548 return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
547 user_srf = container_of(srf, struct vmw_user_surface, srf);
548 if (user_srf->base.tfile != tfile && !user_srf->base.shareable) {
549 ret = -EPERM;
550 goto out;
551 }
552
553 ttm_ref_object_base_unref(tfile, user_srf->base.hash.key,
554 TTM_REF_USAGE);
555out:
556 vmw_resource_unreference(&res);
557 return ret;
558} 549}
559 550
560int vmw_surface_define_ioctl(struct drm_device *dev, void *data, 551int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
@@ -649,7 +640,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
649 } 640 }
650 srf->snooper.crtc = NULL; 641 srf->snooper.crtc = NULL;
651 642
652 rep->sid = res->id; 643 rep->sid = user_srf->base.hash.key;
644 if (rep->sid == SVGA3D_INVALID_ID)
645 DRM_ERROR("Created bad Surface ID.\n");
646
653 vmw_resource_unreference(&res); 647 vmw_resource_unreference(&res);
654 return 0; 648 return 0;
655out_err1: 649out_err1:
@@ -662,39 +656,33 @@ out_err0:
662int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, 656int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
663 struct drm_file *file_priv) 657 struct drm_file *file_priv)
664{ 658{
665 struct vmw_private *dev_priv = vmw_priv(dev);
666 union drm_vmw_surface_reference_arg *arg = 659 union drm_vmw_surface_reference_arg *arg =
667 (union drm_vmw_surface_reference_arg *)data; 660 (union drm_vmw_surface_reference_arg *)data;
668 struct drm_vmw_surface_arg *req = &arg->req; 661 struct drm_vmw_surface_arg *req = &arg->req;
669 struct drm_vmw_surface_create_req *rep = &arg->rep; 662 struct drm_vmw_surface_create_req *rep = &arg->rep;
670 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 663 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
671 struct vmw_resource *res;
672 struct vmw_surface *srf; 664 struct vmw_surface *srf;
673 struct vmw_user_surface *user_srf; 665 struct vmw_user_surface *user_srf;
674 struct drm_vmw_size __user *user_sizes; 666 struct drm_vmw_size __user *user_sizes;
675 int ret; 667 struct ttm_base_object *base;
668 int ret = -EINVAL;
676 669
677 res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, req->sid); 670 base = ttm_base_object_lookup(tfile, req->sid);
678 if (unlikely(res == NULL)) 671 if (unlikely(base == NULL)) {
672 DRM_ERROR("Could not find surface to reference.\n");
679 return -EINVAL; 673 return -EINVAL;
680
681 if (res->res_free != &vmw_user_surface_free) {
682 ret = -EINVAL;
683 goto out;
684 } 674 }
685 675
686 srf = container_of(res, struct vmw_surface, res); 676 if (unlikely(base->object_type != VMW_RES_SURFACE))
687 user_srf = container_of(srf, struct vmw_user_surface, srf); 677 goto out_bad_resource;
688 if (user_srf->base.tfile != tfile && !user_srf->base.shareable) { 678
689 DRM_ERROR("Tried to reference none shareable surface\n"); 679 user_srf = container_of(base, struct vmw_user_surface, base);
690 ret = -EPERM; 680 srf = &user_srf->srf;
691 goto out;
692 }
693 681
694 ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL); 682 ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
695 if (unlikely(ret != 0)) { 683 if (unlikely(ret != 0)) {
696 DRM_ERROR("Could not add a reference to a surface.\n"); 684 DRM_ERROR("Could not add a reference to a surface.\n");
697 goto out; 685 goto out_no_reference;
698 } 686 }
699 687
700 rep->flags = srf->flags; 688 rep->flags = srf->flags;
@@ -706,40 +694,43 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
706 if (user_sizes) 694 if (user_sizes)
707 ret = copy_to_user(user_sizes, srf->sizes, 695 ret = copy_to_user(user_sizes, srf->sizes,
708 srf->num_sizes * sizeof(*srf->sizes)); 696 srf->num_sizes * sizeof(*srf->sizes));
709 if (unlikely(ret != 0)) { 697 if (unlikely(ret != 0))
710 DRM_ERROR("copy_to_user failed %p %u\n", 698 DRM_ERROR("copy_to_user failed %p %u\n",
711 user_sizes, srf->num_sizes); 699 user_sizes, srf->num_sizes);
712 /** 700out_bad_resource:
713 * FIXME: Unreference surface here? 701out_no_reference:
714 */ 702 ttm_base_object_unref(&base);
715 goto out; 703
716 }
717out:
718 vmw_resource_unreference(&res);
719 return ret; 704 return ret;
720} 705}
721 706
722int vmw_surface_check(struct vmw_private *dev_priv, 707int vmw_surface_check(struct vmw_private *dev_priv,
723 struct ttm_object_file *tfile, 708 struct ttm_object_file *tfile,
724 int id) 709 uint32_t handle, int *id)
725{ 710{
726 struct vmw_resource *res; 711 struct ttm_base_object *base;
727 int ret = 0; 712 struct vmw_user_surface *user_srf;
728 713
729 read_lock(&dev_priv->resource_lock); 714 int ret = -EPERM;
730 res = idr_find(&dev_priv->surface_idr, id);
731 if (res && res->avail) {
732 struct vmw_surface *srf =
733 container_of(res, struct vmw_surface, res);
734 struct vmw_user_surface *usrf =
735 container_of(srf, struct vmw_user_surface, srf);
736 715
737 if (usrf->base.tfile != tfile && !usrf->base.shareable) 716 base = ttm_base_object_lookup(tfile, handle);
738 ret = -EPERM; 717 if (unlikely(base == NULL))
739 } else 718 return -EINVAL;
740 ret = -EINVAL; 719
741 read_unlock(&dev_priv->resource_lock); 720 if (unlikely(base->object_type != VMW_RES_SURFACE))
721 goto out_bad_surface;
742 722
723 user_srf = container_of(base, struct vmw_user_surface, base);
724 *id = user_srf->srf.res.id;
725 ret = 0;
726
727out_bad_surface:
728 /**
729 * FIXME: May deadlock here when called from the
730 * command parsing code.
731 */
732
733 ttm_base_object_unref(&base);
743 return ret; 734 return ret;
744} 735}
745 736