drm/vmwgfx: Map the fifo as cached
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / vmwgfx / vmwgfx_drv.c
index ab67d2a7351623ad53b0b4aad0ecb33b6b8232ed..2c7a25c71af2979c784b6cb4a87ee2088d4f8fbb 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -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[] = {
@@ -278,8 +285,8 @@ static void vmw_print_capabilities(uint32_t capabilities)
                DRM_INFO("  Command Buffers 2.\n");
        if (capabilities & SVGA_CAP_GBOBJECTS)
                DRM_INFO("  Guest Backed Resources.\n");
-       if (capabilities & SVGA_CAP_CMD_BUFFERS_3)
-               DRM_INFO("  Command Buffers 3.\n");
+       if (capabilities & SVGA_CAP_DX)
+               DRM_INFO("  DX Features.\n");
 }
 
 /**
@@ -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)
@@ -707,9 +716,12 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                          SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT);
                dev_priv->texture_max_height = vmw_read(dev_priv,
                                                        SVGA_REG_DEV_CAP);
-       } else
+       } else {
+               dev_priv->texture_max_width = 8192;
+               dev_priv->texture_max_height = 8192;
                dev_priv->prim_bb_mem = dev_priv->vram_size;
+       }
+
        vmw_print_capabilities(dev_priv->capabilities);
 
        ret = vmw_dma_masks(dev_priv);
@@ -740,12 +752,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
        dev_priv->active_master = &dev_priv->fbdev_master;
 
-
-       dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
-                                              dev_priv->mmio_size);
-
-       dev_priv->mmio_virt = ioremap_wc(dev_priv->mmio_start,
-                                        dev_priv->mmio_size);
+       dev_priv->mmio_virt = ioremap_cache(dev_priv->mmio_start,
+                                           dev_priv->mmio_size);
 
        if (unlikely(dev_priv->mmio_virt == NULL)) {
                ret = -ENOMEM;
@@ -845,6 +853,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;
@@ -854,6 +870,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);
@@ -891,12 +909,13 @@ out_no_device:
 out_err4:
        iounmap(dev_priv->mmio_virt);
 out_err3:
-       arch_phys_wc_del(dev_priv->mmio_mtrr);
        vmw_ttm_global_release(dev_priv);
 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;
 }
@@ -912,6 +931,7 @@ static int vmw_driver_unload(struct drm_device *dev)
                drm_ht_remove(&dev_priv->ctx.res_ht);
        vfree(dev_priv->ctx.cmd_bounce);
        if (dev_priv->enable_fb) {
+               vmw_fb_off(dev_priv);
                vmw_fb_close(dev_priv);
                vmw_fifo_resource_dec(dev_priv);
                vmw_svga_disable(dev_priv);
@@ -939,8 +959,8 @@ static int vmw_driver_unload(struct drm_device *dev)
 
        ttm_object_device_release(&dev_priv->tdev);
        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)
@@ -1026,10 +1046,15 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
        }
 
        /*
-        * Check if we were previously master, but now dropped.
+        * Check if we were previously master, but now dropped. In that
+        * case, allow at least render node functionality.
         */
        if (vmw_fp->locked_master) {
                mutex_unlock(&dev->master_mutex);
+
+               if (flags & DRM_RENDER_ALLOW)
+                       return NULL;
+
                DRM_ERROR("Dropped master trying to access ioctl that "
                          "requires authentication.\n");
                return ERR_PTR(-EACCES);
@@ -1078,17 +1103,27 @@ 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;
 
        vmaster = vmw_master_check(dev, file_priv, flags);
-       if (unlikely(IS_ERR(vmaster))) {
+       if (IS_ERR(vmaster)) {
                ret = PTR_ERR(vmaster);
 
                if (ret != -ERESTARTSYS)
@@ -1102,6 +1137,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,
@@ -1152,7 +1193,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)
@@ -1260,7 +1300,8 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv)
        if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
                dev_priv->bdev.man[TTM_PL_VRAM].use_type = false;
                vmw_write(dev_priv, SVGA_REG_ENABLE,
-                         SVGA_REG_ENABLE_ENABLE_HIDE);
+                         SVGA_REG_ENABLE_HIDE |
+                         SVGA_REG_ENABLE_ENABLE);
        }
        spin_unlock(&dev_priv->svga_lock);
 }
@@ -1278,11 +1319,12 @@ void vmw_svga_disable(struct vmw_private *dev_priv)
        spin_lock(&dev_priv->svga_lock);
        if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
                dev_priv->bdev.man[TTM_PL_VRAM].use_type = false;
-               vmw_write(dev_priv, SVGA_REG_ENABLE,
-                         SVGA_REG_ENABLE_ENABLE_HIDE);
                spin_unlock(&dev_priv->svga_lock);
                if (ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM))
                        DRM_ERROR("Failed evicting VRAM buffers.\n");
+               vmw_write(dev_priv, SVGA_REG_ENABLE,
+                         SVGA_REG_ENABLE_HIDE |
+                         SVGA_REG_ENABLE_ENABLE);
        } else
                spin_unlock(&dev_priv->svga_lock);
        ttm_write_unlock(&dev_priv->reservation_sem);