drm/i915: move dev_priv->suspend around
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_dma.c
index 5c648425c1e053616801b3e1e545791a5fe111c0..e4d2b9f15ae29b3e69673ed2c726a4db948475d9 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -624,9 +626,8 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                            struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-           master_priv->sarea_priv;
+       struct drm_i915_master_private *master_priv;
+       drm_i915_sarea_t *sarea_priv;
        drm_i915_batchbuffer_t *batch = data;
        int ret;
        struct drm_clip_rect *cliprects = NULL;
@@ -634,6 +635,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return -ENODEV;
 
+       master_priv = dev->primary->master->driver_priv;
+       sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv;
+
        if (!dev_priv->dri1.allow_batchbuffer) {
                DRM_ERROR("Batchbuffer ioctl disabled\n");
                return -EINVAL;
@@ -680,9 +684,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-           master_priv->sarea_priv;
+       struct drm_i915_master_private *master_priv;
+       drm_i915_sarea_t *sarea_priv;
        drm_i915_cmdbuffer_t *cmdbuf = data;
        struct drm_clip_rect *cliprects = NULL;
        void *batch_data;
@@ -694,6 +697,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return -ENODEV;
 
+       master_priv = dev->primary->master->driver_priv;
+       sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv;
+
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (cmdbuf->num_cliprects < 0)
@@ -791,7 +797,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
        if (ring->irq_get(ring)) {
-               DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, ring->irq_queue, 3 * HZ,
                            READ_BREADCRUMB(dev_priv) >= irq_nr);
                ring->irq_put(ring);
        } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000))
@@ -828,7 +834,7 @@ static int i915_irq_emit(struct drm_device *dev, void *data,
        result = i915_emit_irq(dev);
        mutex_unlock(&dev->struct_mutex);
 
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
@@ -988,7 +994,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = HAS_WT(dev);
                break;
        case I915_PARAM_HAS_ALIASING_PPGTT:
-               value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
+               value = dev_priv->mm.aliasing_ppgtt || USES_FULL_PPGTT(dev);
                break;
        case I915_PARAM_HAS_WAIT_TIMEOUT:
                value = 1;
@@ -1016,8 +1022,8 @@ static int i915_getparam(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("DRM_COPY_TO_USER failed\n");
+       if (copy_to_user(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user failed\n");
                return -EFAULT;
        }
 
@@ -1315,12 +1321,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
        if (ret)
                goto cleanup_vga_switcheroo;
 
+       intel_power_domains_init_hw(dev_priv);
+
        ret = drm_irq_install(dev);
        if (ret)
                goto cleanup_gem_stolen;
 
-       intel_power_domains_init_hw(dev);
-
        /* Important: The output setup functions called by modeset_init need
         * working irqs for e.g. gmbus and dp aux transfers. */
        intel_modeset_init(dev);
@@ -1337,7 +1343,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
        /* FIXME: do pre/post-mode set stuff in core KMS code */
        dev->vblank_disable_allowed = true;
        if (INTEL_INFO(dev)->num_pipes == 0) {
-               intel_display_power_put(dev, POWER_DOMAIN_VGA);
+               intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
                return 0;
        }
 
@@ -1372,10 +1378,10 @@ cleanup_gem:
        i915_gem_cleanup_ringbuffer(dev);
        i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
-       i915_gem_cleanup_aliasing_ppgtt(dev);
+       WARN_ON(dev_priv->mm.aliasing_ppgtt);
        drm_mm_takedown(&dev_priv->gtt.base.mm);
 cleanup_power:
-       intel_display_power_put(dev, POWER_DOMAIN_VGA);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
        drm_irq_uninstall(dev);
 cleanup_gem_stolen:
        i915_gem_cleanup_stolen(dev);
@@ -1411,7 +1417,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
        master->driver_priv = NULL;
 }
 
-#ifdef CONFIG_DRM_I915_FBDEV
+#if IS_ENABLED(CONFIG_FB)
 static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
        struct apertures_struct *ap;
@@ -1440,7 +1446,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 
 static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 {
-       const struct intel_device_info *info = dev_priv->info;
+       const struct intel_device_info *info = &dev_priv->info;
 
 #define PRINT_S(name) "%s"
 #define SEP_EMPTY
@@ -1457,6 +1463,62 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 #undef SEP_COMMA
 }
 
+/*
+ * Determine various intel_device_info fields at runtime.
+ *
+ * Use it when either:
+ *   - it's judged too laborious to fill n static structures with the limit
+ *     when a simple if statement does the job,
+ *   - run-time checks (eg read fuse/strap registers) are needed.
+ *
+ * This function needs to be called:
+ *   - after the MMIO has been setup as we are reading registers,
+ *   - after the PCH has been detected,
+ *   - before the first usage of the fields it can tweak.
+ */
+static void intel_device_info_runtime_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_device_info *info;
+       enum pipe pipe;
+
+       info = (struct intel_device_info *)&dev_priv->info;
+
+       if (IS_VALLEYVIEW(dev))
+               for_each_pipe(pipe)
+                       info->num_sprites[pipe] = 2;
+       else
+               for_each_pipe(pipe)
+                       info->num_sprites[pipe] = 1;
+
+       if (i915.disable_display) {
+               DRM_INFO("Display disabled (module parameter)\n");
+               info->num_pipes = 0;
+       } else if (info->num_pipes > 0 &&
+                  (INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
+                  !IS_VALLEYVIEW(dev)) {
+               u32 fuse_strap = I915_READ(FUSE_STRAP);
+               u32 sfuse_strap = I915_READ(SFUSE_STRAP);
+
+               /*
+                * SFUSE_STRAP is supposed to have a bit signalling the display
+                * is fused off. Unfortunately it seems that, at least in
+                * certain cases, fused off display means that PCH display
+                * reads don't land anywhere. In that case, we read 0s.
+                *
+                * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
+                * should be set when taking over after the firmware.
+                */
+               if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
+                   sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
+                   (dev_priv->pch_type == PCH_CPT &&
+                    !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
+                       DRM_INFO("Display fused off, disabling\n");
+                       info->num_pipes = 0;
+               }
+       }
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1471,7 +1533,7 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_i915_private *dev_priv;
-       struct intel_device_info *info;
+       struct intel_device_info *info, *device_info;
        int ret = 0, mmio_bar, mmio_size;
        uint32_t aperture_size;
 
@@ -1484,17 +1546,24 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                return -ENODEV;
        }
 
+       /* UMS needs agp support. */
+       if (!drm_core_check_feature(dev, DRIVER_MODESET) && !dev->agp)
+               return -EINVAL;
+
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (dev_priv == NULL)
                return -ENOMEM;
 
        dev->dev_private = (void *)dev_priv;
        dev_priv->dev = dev;
-       dev_priv->info = info;
+
+       /* copy initial configuration to dev_priv->info */
+       device_info = (struct intel_device_info *)&dev_priv->info;
+       *device_info = *info;
 
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->gpu_error.lock);
-       spin_lock_init(&dev_priv->backlight.lock);
+       spin_lock_init(&dev_priv->backlight_lock);
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        mutex_init(&dev_priv->dpio_lock);
@@ -1629,9 +1698,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!IS_I945G(dev) && !IS_I945GM(dev))
                pci_enable_msi(dev->pdev);
 
-       dev_priv->num_plane = 1;
-       if (IS_VALLEYVIEW(dev))
-               dev_priv->num_plane = 2;
+       intel_device_info_runtime_init(dev);
 
        if (INTEL_INFO(dev)->num_pipes) {
                ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
@@ -1639,8 +1706,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        goto out_gem_unload;
        }
 
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_init(dev);
+       intel_power_domains_init(dev_priv);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = i915_load_modeset_init(dev);
@@ -1664,11 +1730,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_GEN5(dev))
                intel_gpu_ips_init(dev_priv);
 
+       intel_init_runtime_pm(dev_priv);
+
        return 0;
 
 out_power_well:
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_remove(dev);
+       intel_power_domains_remove(dev_priv);
        drm_vblank_cleanup(dev);
 out_gem_unload:
        if (dev_priv->mm.inactive_shrinker.scan_objects)
@@ -1679,6 +1746,7 @@ out_gem_unload:
 
        intel_teardown_gmbus(dev);
        intel_teardown_mchbar(dev);
+       pm_qos_remove_request(&dev_priv->pm_qos);
        destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
        arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1704,25 +1772,27 @@ int i915_driver_unload(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       ret = i915_gem_suspend(dev);
+       if (ret) {
+               DRM_ERROR("failed to idle hardware: %d\n", ret);
+               return ret;
+       }
+
+       intel_fini_runtime_pm(dev_priv);
+
        intel_gpu_ips_teardown();
 
-       if (HAS_POWER_WELL(dev)) {
-               /* The i915.ko module is still not prepared to be loaded when
-                * the power well is not enabled, so just enable it in case
-                * we're going to unload/reload. */
-               intel_display_set_init_power(dev, true);
-               intel_power_domains_remove(dev);
-       }
+       /* The i915.ko module is still not prepared to be loaded when
+        * the power well is not enabled, so just enable it in case
+        * we're going to unload/reload. */
+       intel_display_set_init_power(dev_priv, true);
+       intel_power_domains_remove(dev_priv);
 
        i915_teardown_sysfs(dev);
 
        if (dev_priv->mm.inactive_shrinker.scan_objects)
                unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
-       ret = i915_gem_suspend(dev);
-       if (ret)
-               DRM_ERROR("failed to idle hardware: %d\n", ret);
-
        io_mapping_free(dev_priv->gtt.mappable);
        arch_phys_wc_del(dev_priv->gtt.mtrr);
 
@@ -1767,8 +1837,8 @@ int i915_driver_unload(struct drm_device *dev)
                i915_gem_free_all_phys_object(dev);
                i915_gem_cleanup_ringbuffer(dev);
                i915_gem_context_fini(dev);
+               WARN_ON(dev_priv->mm.aliasing_ppgtt);
                mutex_unlock(&dev->struct_mutex);
-               i915_gem_cleanup_aliasing_ppgtt(dev);
                i915_gem_cleanup_stolen(dev);
 
                if (!I915_NEED_GFX_HWS(dev))
@@ -1777,7 +1847,6 @@ int i915_driver_unload(struct drm_device *dev)
 
        list_del(&dev_priv->gtt.base.global_link);
        WARN_ON(!list_empty(&dev_priv->vm_list));
-       drm_mm_takedown(&dev_priv->gtt.base.mm);
 
        drm_vblank_cleanup(dev);
 
@@ -1910,6 +1979,7 @@ const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
This page took 0.03008 seconds and 5 git commands to generate.