Merge tag 'topic/designware-baytrail-2017-03-02' of git://anongit.freedesktop.org...
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / i915 / i915_drv.c
index 58eb308..b1e9027 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
@@ -248,6 +249,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_IRQ_ACTIVE:
        case I915_PARAM_ALLOW_BATCHBUFFER:
        case I915_PARAM_LAST_DISPATCH:
+       case I915_PARAM_HAS_EXEC_CONSTANTS:
                /* Reject all old ums/dri params. */
                return -ENODEV;
        case I915_PARAM_CHIPSET_ID:
@@ -274,9 +276,6 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_BSD2:
                value = !!dev_priv->engine[VCS2];
                break;
-       case I915_PARAM_HAS_EXEC_CONSTANTS:
-               value = INTEL_GEN(dev_priv) >= 4;
-               break;
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev_priv);
                break;
@@ -318,10 +317,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool;
                break;
        case I915_PARAM_HUC_STATUS:
-               /* The register is already force-woken. We dont need
-                * any rpm here
-                */
+               intel_runtime_pm_get(dev_priv);
                value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
+               intel_runtime_pm_put(dev_priv);
                break;
        case I915_PARAM_MMAP_GTT_VERSION:
                /* Though we've started our numbering from 1, and so class all
@@ -350,6 +348,8 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_EXEC_HANDLE_LUT:
        case I915_PARAM_HAS_COHERENT_PHYS_GTT:
        case I915_PARAM_HAS_EXEC_SOFTPIN:
+       case I915_PARAM_HAS_EXEC_ASYNC:
+       case I915_PARAM_HAS_EXEC_FENCE:
                /* For the time being all of these are always true;
                 * if some supported hardware does not have one of these
                 * features this value needs to be provided from
@@ -756,6 +756,15 @@ out_err:
        return -ENOMEM;
 }
 
+static void i915_engines_cleanup(struct drm_i915_private *i915)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       for_each_engine(engine, i915, id)
+               kfree(engine);
+}
+
 static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
 {
        destroy_workqueue(dev_priv->hotplug.dp_wq);
@@ -769,10 +778,17 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
  */
 static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
 {
-       if (IS_HSW_EARLY_SDV(dev_priv) ||
-           IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
+       bool pre = false;
+
+       pre |= IS_HSW_EARLY_SDV(dev_priv);
+       pre |= IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0);
+       pre |= IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST);
+
+       if (pre) {
                DRM_ERROR("This is a pre-production stepping. "
                          "It may not be fully functional.\n");
+               add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
+       }
 }
 
 /**
@@ -808,6 +824,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
        spin_lock_init(&dev_priv->gpu_error.lock);
        mutex_init(&dev_priv->backlight_lock);
        spin_lock_init(&dev_priv->uncore.lock);
+
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        spin_lock_init(&dev_priv->mmio_flip_lock);
        spin_lock_init(&dev_priv->wm.dsparb_lock);
@@ -818,12 +835,15 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
        mutex_init(&dev_priv->pps_mutex);
 
        intel_uc_init_early(dev_priv);
-
        i915_memcpy_init_early(dev_priv);
 
+       ret = intel_engines_init_early(dev_priv);
+       if (ret)
+               return ret;
+
        ret = i915_workqueues_init(dev_priv);
        if (ret < 0)
-               return ret;
+               goto err_engines;
 
        /* This must be called before any calls to HAS_PCH_* */
        intel_detect_pch(dev_priv);
@@ -852,6 +872,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
 
 err_workqueues:
        i915_workqueues_cleanup(dev_priv);
+err_engines:
+       i915_engines_cleanup(dev_priv);
        return ret;
 }
 
@@ -864,6 +886,7 @@ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
        i915_perf_fini(dev_priv);
        i915_gem_load_cleanup(dev_priv);
        i915_workqueues_cleanup(dev_priv);
+       i915_engines_cleanup(dev_priv);
 }
 
 static int i915_mmio_setup(struct drm_i915_private *dev_priv)
@@ -930,6 +953,7 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
                goto put_bridge;
 
        intel_uncore_init(dev_priv);
+       i915_gem_init_mmio(dev_priv);
 
        return 0;
 
@@ -967,7 +991,7 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv)
        DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt);
 
        i915.semaphores = intel_sanitize_semaphores(dev_priv, i915.semaphores);
-       DRM_DEBUG_DRIVER("use GPU sempahores? %s\n", yesno(i915.semaphores));
+       DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", yesno(i915.semaphores));
 }
 
 /**
@@ -1139,7 +1163,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
        if (IS_GEN5(dev_priv))
                intel_gpu_ips_init(dev_priv);
 
-       i915_audio_component_init(dev_priv);
+       intel_audio_init(dev_priv);
 
        /*
         * Some ports require correctly set-up hpd registers for detection to
@@ -1157,7 +1181,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
  */
 static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 {
-       i915_audio_component_cleanup(dev_priv);
+       intel_audio_deinit(dev_priv);
 
        intel_gpu_ips_teardown();
        acpi_video_unregister();
@@ -1167,7 +1191,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 
        i915_teardown_sysfs(dev_priv);
        i915_guc_log_unregister(dev_priv);
-       i915_debugfs_unregister(dev_priv);
        drm_dev_unregister(&dev_priv->drm);
 
        i915_gem_shrinker_cleanup(dev_priv);
@@ -1186,11 +1209,15 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
  */
 int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+       const struct intel_device_info *match_info =
+               (struct intel_device_info *)ent->driver_data;
        struct drm_i915_private *dev_priv;
        int ret;
 
-       if (i915.nuclear_pageflip)
-               driver.driver_features |= DRIVER_ATOMIC;
+       /* Enable nuclear pageflip on ILK+, except vlv/chv */
+       if (!i915.nuclear_pageflip &&
+           (match_info->gen < 5 || match_info->has_gmch_display))
+               driver.driver_features &= ~DRIVER_ATOMIC;
 
        ret = -ENOMEM;
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
@@ -1198,8 +1225,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
                ret = drm_dev_init(&dev_priv->drm, &driver, &pdev->dev);
        if (ret) {
                DRM_DEV_ERROR(&pdev->dev, "allocation failed\n");
-               kfree(dev_priv);
-               return ret;
+               goto out_free;
        }
 
        dev_priv->drm.pdev = pdev;
@@ -1207,7 +1233,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        ret = pci_enable_device(pdev);
        if (ret)
-               goto out_free_priv;
+               goto out_fini;
 
        pci_set_drvdata(pdev, &dev_priv->drm);
 
@@ -1271,9 +1297,11 @@ out_runtime_pm_put:
        i915_driver_cleanup_early(dev_priv);
 out_pci_disable:
        pci_disable_device(pdev);
-out_free_priv:
+out_fini:
        i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
-       drm_dev_unref(&dev_priv->drm);
+       drm_dev_fini(&dev_priv->drm);
+out_free:
+       kfree(dev_priv);
        return ret;
 }
 
@@ -1281,6 +1309,8 @@ void i915_driver_unload(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct drm_modeset_acquire_ctx ctx;
+       int ret;
 
        intel_fbdev_fini(dev);
 
@@ -1289,6 +1319,24 @@ void i915_driver_unload(struct drm_device *dev)
 
        intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
+       drm_modeset_acquire_init(&ctx, 0);
+       while (1) {
+               ret = drm_modeset_lock_all_ctx(dev, &ctx);
+               if (!ret)
+                       ret = drm_atomic_helper_disable_all(dev, &ctx);
+
+               if (ret != -EDEADLK)
+                       break;
+
+               drm_modeset_backoff(&ctx);
+       }
+
+       if (ret)
+               DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
+
+       drm_modeset_drop_locks(&ctx);
+       drm_modeset_acquire_fini(&ctx);
+
        intel_gvt_cleanup(dev_priv);
 
        i915_driver_unregister(dev_priv);
@@ -1318,7 +1366,7 @@ void i915_driver_unload(struct drm_device *dev)
 
        /* Free error state after interrupts are fully disabled. */
        cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
-       i915_destroy_error_state(dev_priv);
+       i915_reset_error_state(dev_priv);
 
        /* Flush any outstanding unpin_work. */
        drain_workqueue(dev_priv->wq);
@@ -1334,8 +1382,16 @@ void i915_driver_unload(struct drm_device *dev)
        i915_driver_cleanup_mmio(dev_priv);
 
        intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+}
+
+static void i915_driver_release(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
 
        i915_driver_cleanup_early(dev_priv);
+       drm_dev_fini(&dev_priv->drm);
+
+       kfree(dev_priv);
 }
 
 static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
@@ -1717,6 +1773,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
            !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
                intel_power_domains_init_hw(dev_priv, true);
 
+       i915_gem_sanitize(dev_priv);
+
        enable_rpm_wakeref_asserts(dev_priv);
 
 out:
@@ -1788,7 +1846,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
                goto error;
        }
 
-       i915_gem_reset_finish(dev_priv);
+       i915_gem_reset(dev_priv);
        intel_overlay_reset(dev_priv);
 
        /* Ok, now get things going again... */
@@ -1814,6 +1872,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
        i915_queue_hangcheck(dev_priv);
 
 wakeup:
+       i915_gem_reset_finish(dev_priv);
        enable_irq(dev_priv->drm.irq);
        wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS);
        return;
@@ -2533,7 +2592,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
@@ -2575,7 +2634,8 @@ static struct drm_driver driver = {
         */
        .driver_features =
            DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
-           DRIVER_RENDER | DRIVER_MODESET,
+           DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
+       .release = i915_driver_release,
        .open = i915_driver_open,
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
@@ -2604,3 +2664,7 @@ static struct drm_driver driver = {
        .minor = DRIVER_MINOR,
        .patchlevel = DRIVER_PATCHLEVEL,
 };
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_drm.c"
+#endif