]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drm/vmwgfx: Initial DX support
[linux-beck.git] / drivers / gpu / drm / vmwgfx / vmwgfx_drv.c
index b83adea43f3a7243c8fa72046dc5e00b761c3a05..fd0cb8c67d05eb9c23f1be9ba1ad53a6fc547c40 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <drm/drmP.h>
 #include "vmwgfx_drv.h"
+#include "vmwgfx_binding.h"
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_object.h>
 #define DRM_IOCTL_VMW_SYNCCPU                                  \
        DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_SYNCCPU,             \
                 struct drm_vmw_synccpu_arg)
+#define DRM_IOCTL_VMW_CREATE_EXTENDED_CONTEXT                  \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_EXTENDED_CONTEXT,    \
+               struct drm_vmw_context_arg)
 
 /**
  * The core DRM version of this macro doesn't account for
@@ -168,8 +172,8 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
                      DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
                      DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
-       VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+       VMW_IOCTL_DEF(VMW_EXECBUF, NULL, DRM_AUTH | DRM_UNLOCKED |
+                     DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
                      DRM_UNLOCKED | DRM_RENDER_ALLOW),
        VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
@@ -206,6 +210,9 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(VMW_SYNCCPU,
                      vmw_user_dmabuf_synccpu_ioctl,
                      DRM_UNLOCKED | DRM_RENDER_ALLOW),
+       VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
+                     vmw_extended_context_define_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -390,8 +397,10 @@ static int vmw_request_device(struct vmw_private *dev_priv)
        }
        vmw_fence_fifo_up(dev_priv->fman);
        dev_priv->cman = vmw_cmdbuf_man_create(dev_priv);
-       if (IS_ERR(dev_priv->cman))
+       if (IS_ERR(dev_priv->cman)) {
                dev_priv->cman = NULL;
+               dev_priv->has_dx = false;
+       }
 
        ret = vmw_request_device_late(dev_priv);
        if (ret)
@@ -848,6 +857,14 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                }
        }
 
+       if (dev_priv->has_mob) {
+               spin_lock(&dev_priv->cap_lock);
+               vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_DX);
+               dev_priv->has_dx = !!vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+               spin_unlock(&dev_priv->cap_lock);
+       }
+
+
        ret = vmw_kms_init(dev_priv);
        if (unlikely(ret != 0))
                goto out_no_kms;
@@ -857,6 +874,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        if (ret)
                goto out_no_fifo;
 
+       DRM_INFO("DX: %s\n", dev_priv->has_dx ? "yes." : "no.");
+
        if (dev_priv->enable_fb) {
                vmw_fifo_resource_inc(dev_priv);
                vmw_svga_enable(dev_priv);
@@ -900,6 +919,8 @@ out_err0:
        for (i = vmw_res_context; i < vmw_res_max; ++i)
                idr_destroy(&dev_priv->res_idr[i]);
 
+       if (dev_priv->ctx.staged_bindings)
+               vmw_binding_state_free(dev_priv->ctx.staged_bindings);
        kfree(dev_priv);
        return ret;
 }
@@ -945,6 +966,8 @@ static int vmw_driver_unload(struct drm_device *dev)
        iounmap(dev_priv->mmio_virt);
        arch_phys_wc_del(dev_priv->mmio_mtrr);
        (void)ttm_bo_device_release(&dev_priv->bdev);
+       if (dev_priv->ctx.staged_bindings)
+               vmw_binding_state_free(dev_priv->ctx.staged_bindings);
        vmw_ttm_global_release(dev_priv);
 
        for (i = vmw_res_context; i < vmw_res_max; ++i)
@@ -1082,11 +1105,21 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
                const struct drm_ioctl_desc *ioctl =
                        &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
-               if (unlikely(ioctl->cmd != cmd)) {
-                       DRM_ERROR("Invalid command format, ioctl %d\n",
-                                 nr - DRM_COMMAND_BASE);
-                       return -EINVAL;
+               if (nr == DRM_COMMAND_BASE + DRM_VMW_EXECBUF) {
+                       ret = (long) drm_ioctl_permit(ioctl->flags, file_priv);
+                       if (unlikely(ret != 0))
+                               return ret;
+
+                       if (unlikely((cmd & (IOC_IN | IOC_OUT)) != IOC_IN))
+                               goto out_io_encoding;
+
+                       return (long) vmw_execbuf_ioctl(dev, arg, file_priv,
+                                                       _IOC_SIZE(cmd));
                }
+
+               if (unlikely(ioctl->cmd != cmd))
+                       goto out_io_encoding;
+
                flags = ioctl->flags;
        } else if (!drm_ioctl_flags(nr, &flags))
                return -EINVAL;
@@ -1106,6 +1139,12 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
                ttm_read_unlock(&vmaster->lock);
 
        return ret;
+
+out_io_encoding:
+       DRM_ERROR("Invalid command format, ioctl %d\n",
+                 nr - DRM_COMMAND_BASE);
+
+       return -EINVAL;
 }
 
 static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
@@ -1156,7 +1195,6 @@ static void vmw_master_destroy(struct drm_device *dev,
        kfree(vmaster);
 }
 
-
 static int vmw_master_set(struct drm_device *dev,
                          struct drm_file *file_priv,
                          bool from_open)