diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-10-04 14:13:17 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-10-05 05:17:11 -0400 |
commit | 922ade0d16d24be2040be7d55dbb734af779a1dd (patch) | |
tree | 95da5e88d006212ece9b079cd7238441b9c32a22 /drivers/gpu/drm | |
parent | 6070e9fa6d12d465c65a172a2b1c752ebedc5937 (diff) |
vmwgfx: Break out execbuf command processing
This will make it easier to execute commands operating on user-space
resources but generated by the kernel.
JB: Added tracking if the sw_context was called from the kernel or userspace.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Jakob Bornecrantz <jakob@vmware.com>
Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 136 |
2 files changed, 89 insertions, 56 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 564a81582111..edd1e8362f3b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -139,6 +139,7 @@ struct vmw_sw_context{ | |||
139 | struct ida bo_list; | 139 | struct ida bo_list; |
140 | uint32_t last_cid; | 140 | uint32_t last_cid; |
141 | bool cid_valid; | 141 | bool cid_valid; |
142 | bool kernel; /**< is the called made from the kernel */ | ||
142 | uint32_t last_sid; | 143 | uint32_t last_sid; |
143 | uint32_t sid_translation; | 144 | uint32_t sid_translation; |
144 | bool sid_valid; | 145 | bool sid_valid; |
@@ -449,6 +450,14 @@ extern int vmw_dma_quiescent(struct drm_device *dev); | |||
449 | 450 | ||
450 | extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | 451 | extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data, |
451 | struct drm_file *file_priv); | 452 | struct drm_file *file_priv); |
453 | extern int vmw_execbuf_process(struct drm_file *file_priv, | ||
454 | struct vmw_private *dev_priv, | ||
455 | void __user *user_commands, | ||
456 | void *kernel_commands, | ||
457 | uint32_t command_size, | ||
458 | uint64_t throttle_us, | ||
459 | struct drm_vmw_fence_rep __user | ||
460 | *user_fence_rep); | ||
452 | 461 | ||
453 | /** | 462 | /** |
454 | * IRQs and wating - vmwgfx_irq.c | 463 | * IRQs and wating - vmwgfx_irq.c |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index cc8c08b35102..542c852f8eb5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
@@ -531,9 +531,9 @@ out_err: | |||
531 | 531 | ||
532 | static int vmw_cmd_check_all(struct vmw_private *dev_priv, | 532 | static int vmw_cmd_check_all(struct vmw_private *dev_priv, |
533 | struct vmw_sw_context *sw_context, | 533 | struct vmw_sw_context *sw_context, |
534 | void *buf, | ||
534 | uint32_t size) | 535 | uint32_t size) |
535 | { | 536 | { |
536 | void *buf = sw_context->cmd_bounce; | ||
537 | int32_t cur_size = size; | 537 | int32_t cur_size = size; |
538 | int ret; | 538 | int ret; |
539 | 539 | ||
@@ -724,58 +724,44 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, | |||
724 | return 0; | 724 | return 0; |
725 | } | 725 | } |
726 | 726 | ||
727 | int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | 727 | int vmw_execbuf_process(struct drm_file *file_priv, |
728 | struct drm_file *file_priv) | 728 | struct vmw_private *dev_priv, |
729 | void __user *user_commands, | ||
730 | void *kernel_commands, | ||
731 | uint32_t command_size, | ||
732 | uint64_t throttle_us, | ||
733 | struct drm_vmw_fence_rep __user *user_fence_rep) | ||
729 | { | 734 | { |
730 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
731 | struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data; | ||
732 | struct drm_vmw_fence_rep fence_rep; | ||
733 | struct drm_vmw_fence_rep __user *user_fence_rep; | ||
734 | int ret; | ||
735 | void *user_cmd; | ||
736 | void *cmd; | ||
737 | struct vmw_sw_context *sw_context = &dev_priv->ctx; | 735 | struct vmw_sw_context *sw_context = &dev_priv->ctx; |
738 | struct vmw_master *vmaster = vmw_master(file_priv->master); | 736 | struct drm_vmw_fence_rep fence_rep; |
739 | struct vmw_fence_obj *fence; | 737 | struct vmw_fence_obj *fence; |
740 | uint32_t handle; | 738 | uint32_t handle; |
739 | void *cmd; | ||
740 | int ret; | ||
741 | 741 | ||
742 | /* | 742 | ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); |
743 | * This will allow us to extend the ioctl argument while | ||
744 | * maintaining backwards compatibility: | ||
745 | * We take different code paths depending on the value of | ||
746 | * arg->version. | ||
747 | */ | ||
748 | |||
749 | if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) { | ||
750 | DRM_ERROR("Incorrect execbuf version.\n"); | ||
751 | DRM_ERROR("You're running outdated experimental " | ||
752 | "vmwgfx user-space drivers."); | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | |||
756 | ret = ttm_read_lock(&vmaster->lock, true); | ||
757 | if (unlikely(ret != 0)) | 743 | if (unlikely(ret != 0)) |
758 | return ret; | 744 | return -ERESTARTSYS; |
759 | 745 | ||
760 | ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); | 746 | if (kernel_commands == NULL) { |
761 | if (unlikely(ret != 0)) { | 747 | sw_context->kernel = false; |
762 | ret = -ERESTARTSYS; | ||
763 | goto out_no_cmd_mutex; | ||
764 | } | ||
765 | 748 | ||
766 | ret = vmw_resize_cmd_bounce(sw_context, arg->command_size); | 749 | ret = vmw_resize_cmd_bounce(sw_context, command_size); |
767 | if (unlikely(ret != 0)) | 750 | if (unlikely(ret != 0)) |
768 | goto out_unlock; | 751 | goto out_unlock; |
769 | 752 | ||
770 | user_cmd = (void __user *)(unsigned long)arg->commands; | ||
771 | ret = copy_from_user(sw_context->cmd_bounce, | ||
772 | user_cmd, arg->command_size); | ||
773 | 753 | ||
774 | if (unlikely(ret != 0)) { | 754 | ret = copy_from_user(sw_context->cmd_bounce, |
775 | ret = -EFAULT; | 755 | user_commands, command_size); |
776 | DRM_ERROR("Failed copying commands.\n"); | 756 | |
777 | goto out_unlock; | 757 | if (unlikely(ret != 0)) { |
778 | } | 758 | ret = -EFAULT; |
759 | DRM_ERROR("Failed copying commands.\n"); | ||
760 | goto out_unlock; | ||
761 | } | ||
762 | kernel_commands = sw_context->cmd_bounce; | ||
763 | } else | ||
764 | sw_context->kernel = true; | ||
779 | 765 | ||
780 | sw_context->tfile = vmw_fpriv(file_priv)->tfile; | 766 | sw_context->tfile = vmw_fpriv(file_priv)->tfile; |
781 | sw_context->cid_valid = false; | 767 | sw_context->cid_valid = false; |
@@ -786,7 +772,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | |||
786 | 772 | ||
787 | INIT_LIST_HEAD(&sw_context->validate_nodes); | 773 | INIT_LIST_HEAD(&sw_context->validate_nodes); |
788 | 774 | ||
789 | ret = vmw_cmd_check_all(dev_priv, sw_context, arg->command_size); | 775 | ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, |
776 | command_size); | ||
790 | if (unlikely(ret != 0)) | 777 | if (unlikely(ret != 0)) |
791 | goto out_err; | 778 | goto out_err; |
792 | 779 | ||
@@ -800,26 +787,24 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | |||
800 | 787 | ||
801 | vmw_apply_relocations(sw_context); | 788 | vmw_apply_relocations(sw_context); |
802 | 789 | ||
803 | if (arg->throttle_us) { | 790 | if (throttle_us) { |
804 | ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, | 791 | ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, |
805 | arg->throttle_us); | 792 | throttle_us); |
806 | 793 | ||
807 | if (unlikely(ret != 0)) | 794 | if (unlikely(ret != 0)) |
808 | goto out_throttle; | 795 | goto out_throttle; |
809 | } | 796 | } |
810 | 797 | ||
811 | cmd = vmw_fifo_reserve(dev_priv, arg->command_size); | 798 | cmd = vmw_fifo_reserve(dev_priv, command_size); |
812 | if (unlikely(cmd == NULL)) { | 799 | if (unlikely(cmd == NULL)) { |
813 | DRM_ERROR("Failed reserving fifo space for commands.\n"); | 800 | DRM_ERROR("Failed reserving fifo space for commands.\n"); |
814 | ret = -ENOMEM; | 801 | ret = -ENOMEM; |
815 | goto out_err; | 802 | goto out_throttle; |
816 | } | 803 | } |
817 | 804 | ||
818 | memcpy(cmd, sw_context->cmd_bounce, arg->command_size); | 805 | memcpy(cmd, kernel_commands, command_size); |
819 | vmw_fifo_commit(dev_priv, arg->command_size); | 806 | vmw_fifo_commit(dev_priv, command_size); |
820 | 807 | ||
821 | user_fence_rep = (struct drm_vmw_fence_rep __user *) | ||
822 | (unsigned long)arg->fence_rep; | ||
823 | ret = vmw_execbuf_fence_commands(file_priv, dev_priv, | 808 | ret = vmw_execbuf_fence_commands(file_priv, dev_priv, |
824 | &fence, | 809 | &fence, |
825 | (user_fence_rep) ? &handle : NULL); | 810 | (user_fence_rep) ? &handle : NULL); |
@@ -836,7 +821,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | |||
836 | (void *) fence); | 821 | (void *) fence); |
837 | 822 | ||
838 | vmw_clear_validations(sw_context); | 823 | vmw_clear_validations(sw_context); |
839 | mutex_unlock(&dev_priv->cmdbuf_mutex); | ||
840 | 824 | ||
841 | if (user_fence_rep) { | 825 | if (user_fence_rep) { |
842 | fence_rep.error = ret; | 826 | fence_rep.error = ret; |
@@ -873,9 +857,9 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | |||
873 | if (likely(fence != NULL)) | 857 | if (likely(fence != NULL)) |
874 | vmw_fence_obj_unreference(&fence); | 858 | vmw_fence_obj_unreference(&fence); |
875 | 859 | ||
876 | vmw_kms_cursor_post_execbuf(dev_priv); | 860 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
877 | ttm_read_unlock(&vmaster->lock); | ||
878 | return 0; | 861 | return 0; |
862 | |||
879 | out_err: | 863 | out_err: |
880 | vmw_free_relocations(sw_context); | 864 | vmw_free_relocations(sw_context); |
881 | out_throttle: | 865 | out_throttle: |
@@ -883,7 +867,47 @@ out_throttle: | |||
883 | vmw_clear_validations(sw_context); | 867 | vmw_clear_validations(sw_context); |
884 | out_unlock: | 868 | out_unlock: |
885 | mutex_unlock(&dev_priv->cmdbuf_mutex); | 869 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
886 | out_no_cmd_mutex: | 870 | return ret; |
871 | } | ||
872 | |||
873 | |||
874 | int vmw_execbuf_ioctl(struct drm_device *dev, void *data, | ||
875 | struct drm_file *file_priv) | ||
876 | { | ||
877 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
878 | struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data; | ||
879 | struct vmw_master *vmaster = vmw_master(file_priv->master); | ||
880 | int ret; | ||
881 | |||
882 | /* | ||
883 | * This will allow us to extend the ioctl argument while | ||
884 | * maintaining backwards compatibility: | ||
885 | * We take different code paths depending on the value of | ||
886 | * arg->version. | ||
887 | */ | ||
888 | |||
889 | if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) { | ||
890 | DRM_ERROR("Incorrect execbuf version.\n"); | ||
891 | DRM_ERROR("You're running outdated experimental " | ||
892 | "vmwgfx user-space drivers."); | ||
893 | return -EINVAL; | ||
894 | } | ||
895 | |||
896 | ret = ttm_read_lock(&vmaster->lock, true); | ||
897 | if (unlikely(ret != 0)) | ||
898 | return ret; | ||
899 | |||
900 | ret = vmw_execbuf_process(file_priv, dev_priv, | ||
901 | (void __user *)(unsigned long)arg->commands, | ||
902 | NULL, arg->command_size, arg->throttle_us, | ||
903 | (void __user *)(unsigned long)arg->fence_rep); | ||
904 | |||
905 | if (unlikely(ret != 0)) | ||
906 | goto out_unlock; | ||
907 | |||
908 | vmw_kms_cursor_post_execbuf(dev_priv); | ||
909 | |||
910 | out_unlock: | ||
887 | ttm_read_unlock(&vmaster->lock); | 911 | ttm_read_unlock(&vmaster->lock); |
888 | return ret; | 912 | return ret; |
889 | } | 913 | } |