aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-10-04 14:13:17 -0400
committerDave Airlie <airlied@redhat.com>2011-10-05 05:17:11 -0400
commit922ade0d16d24be2040be7d55dbb734af779a1dd (patch)
tree95da5e88d006212ece9b079cd7238441b9c32a22 /drivers/gpu/drm
parent6070e9fa6d12d465c65a172a2b1c752ebedc5937 (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.h9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c136
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
450extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data, 451extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
451 struct drm_file *file_priv); 452 struct drm_file *file_priv);
453extern 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
532static int vmw_cmd_check_all(struct vmw_private *dev_priv, 532static 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
727int vmw_execbuf_ioctl(struct drm_device *dev, void *data, 727int 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
879out_err: 863out_err:
880 vmw_free_relocations(sw_context); 864 vmw_free_relocations(sw_context);
881out_throttle: 865out_throttle:
@@ -883,7 +867,47 @@ out_throttle:
883 vmw_clear_validations(sw_context); 867 vmw_clear_validations(sw_context);
884out_unlock: 868out_unlock:
885 mutex_unlock(&dev_priv->cmdbuf_mutex); 869 mutex_unlock(&dev_priv->cmdbuf_mutex);
886out_no_cmd_mutex: 870 return ret;
871}
872
873
874int 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
910out_unlock:
887 ttm_read_unlock(&vmaster->lock); 911 ttm_read_unlock(&vmaster->lock);
888 return ret; 912 return ret;
889} 913}