drm/i915: Rename dev_priv->gtt to dev_priv->ggtt
[cascardo/linux.git] / drivers / gpu / drm / i915 / i915_dma.c
index 2df2fac..3565163 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/oom.h>
 
+static unsigned int i915_load_fail_count;
+
+bool __i915_inject_load_failure(const char *func, int line)
+{
+       if (i915_load_fail_count >= i915.inject_load_failure)
+               return false;
+
+       if (++i915_load_fail_count == i915.inject_load_failure) {
+               DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
+                        i915.inject_load_failure, func, line);
+               return true;
+       }
+
+       return false;
+}
 
 static int i915_getparam(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
@@ -87,16 +102,16 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = 1;
                break;
        case I915_PARAM_HAS_BSD:
-               value = intel_ring_initialized(&dev_priv->ring[VCS]);
+               value = intel_engine_initialized(&dev_priv->engine[VCS]);
                break;
        case I915_PARAM_HAS_BLT:
-               value = intel_ring_initialized(&dev_priv->ring[BCS]);
+               value = intel_engine_initialized(&dev_priv->engine[BCS]);
                break;
        case I915_PARAM_HAS_VEBOX:
-               value = intel_ring_initialized(&dev_priv->ring[VECS]);
+               value = intel_engine_initialized(&dev_priv->engine[VECS]);
                break;
        case I915_PARAM_HAS_BSD2:
-               value = intel_ring_initialized(&dev_priv->ring[VCS2]);
+               value = intel_engine_initialized(&dev_priv->engine[VCS2]);
                break;
        case I915_PARAM_HAS_RELAXED_FENCING:
                value = 1;
@@ -370,6 +385,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       if (i915_inject_load_failure())
+               return -ENODEV;
+
        ret = intel_bios_init(dev_priv);
        if (ret)
                DRM_INFO("failed to find VBIOS tables\n");
@@ -444,8 +462,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
 cleanup_gem:
        mutex_lock(&dev->struct_mutex);
-       i915_gem_context_fini(dev);
        i915_gem_cleanup_engines(dev);
+       i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
 cleanup_irq:
        intel_guc_ucode_fini(dev);
@@ -453,6 +471,7 @@ cleanup_irq:
        intel_teardown_gmbus(dev);
 cleanup_csr:
        intel_csr_ucode_fini(dev_priv);
+       intel_power_domains_fini(dev_priv);
        vga_switcheroo_unregister_client(dev->pdev);
 cleanup_vga_client:
        vga_client_register(dev->pdev, NULL, NULL, NULL);
@@ -472,8 +491,8 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
        if (!ap)
                return -ENOMEM;
 
-       ap->ranges[0].base = dev_priv->gtt.mappable_base;
-       ap->ranges[0].size = dev_priv->gtt.mappable_end;
+       ap->ranges[0].base = dev_priv->ggtt.mappable_base;
+       ap->ranges[0].size = dev_priv->ggtt.mappable_end;
 
        primary =
                pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
@@ -853,6 +872,10 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
        else if (INTEL_INFO(dev)->gen >= 9)
                gen9_sseu_info_init(dev);
 
+       /* Snooping is broken on BXT A stepping. */
+       info->has_snoop = !info->has_llc;
+       info->has_snoop &= !IS_BXT_REVID(dev, 0, BXT_REVID_A1);
+
        DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
        DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
        DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
@@ -929,6 +952,86 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
        destroy_workqueue(dev_priv->wq);
 }
 
+/**
+ * i915_driver_init_early - setup state not requiring device access
+ * @dev_priv: device private
+ *
+ * Initialize everything that is a "SW-only" state, that is state not
+ * requiring accessing the device or exposing the driver via kernel internal
+ * or userspace interfaces. Example steps belonging here: lock initialization,
+ * system memory allocation, setting up device specific attributes and
+ * function hooks not requiring accessing the device.
+ */
+static int i915_driver_init_early(struct drm_i915_private *dev_priv,
+                                 struct drm_device *dev,
+                                 struct intel_device_info *info)
+{
+       struct intel_device_info *device_info;
+       int ret = 0;
+
+       if (i915_inject_load_failure())
+               return -ENODEV;
+
+       dev_priv->dev = dev;
+
+       /* Setup the write-once "constant" device info */
+       device_info = (struct intel_device_info *)&dev_priv->info;
+       memcpy(device_info, info, sizeof(dev_priv->info));
+       device_info->device_id = dev->pdev->device;
+
+       spin_lock_init(&dev_priv->irq_lock);
+       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);
+       mutex_init(&dev_priv->sb_lock);
+       mutex_init(&dev_priv->modeset_restore_lock);
+       mutex_init(&dev_priv->av_mutex);
+       mutex_init(&dev_priv->wm.wm_mutex);
+       mutex_init(&dev_priv->pps_mutex);
+
+       ret = i915_workqueues_init(dev_priv);
+       if (ret < 0)
+               return ret;
+
+       /* This must be called before any calls to HAS_PCH_* */
+       intel_detect_pch(dev);
+
+       intel_pm_setup(dev);
+       intel_init_dpio(dev_priv);
+       intel_power_domains_init(dev_priv);
+       intel_irq_init(dev_priv);
+       intel_init_display_hooks(dev_priv);
+       intel_init_clock_gating_hooks(dev_priv);
+       intel_init_audio_hooks(dev_priv);
+       i915_gem_load_init(dev);
+
+       intel_display_crc_init(dev);
+
+       i915_dump_device_info(dev_priv);
+
+       /* Not all pre-production machines fall into this category, only the
+        * very first ones. Almost everything should work, except for maybe
+        * suspend/resume. And we don't implement workarounds that affect only
+        * pre-production machines. */
+       if (IS_HSW_EARLY_SDV(dev))
+               DRM_INFO("This is an early pre-production Haswell machine. "
+                        "It may not be fully functional.\n");
+
+       return 0;
+}
+
+/**
+ * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
+{
+       i915_gem_load_cleanup(dev_priv->dev);
+       i915_workqueues_cleanup(dev_priv);
+}
+
 static int i915_mmio_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -970,84 +1073,73 @@ static void i915_mmio_cleanup(struct drm_device *dev)
 }
 
 /**
- * i915_driver_load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
+ * i915_driver_init_mmio - setup device MMIO
+ * @dev_priv: device private
  *
- * The driver load routine has to do several things:
- *   - drive output discovery via intel_modeset_init()
- *   - initialize the memory manager
- *   - allocate initial config memory
- *   - setup the DRM framebuffer with the allocated memory
+ * Setup minimal device state necessary for MMIO accesses later in the
+ * initialization sequence. The setup here should avoid any other device-wide
+ * side effects or exposing the driver via kernel internal or user space
+ * interfaces.
  */
-int i915_driver_load(struct drm_device *dev, unsigned long flags)
+static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv;
-       struct intel_device_info *info, *device_info;
-       int ret = 0;
-       uint32_t aperture_size;
-
-       info = (struct intel_device_info *) flags;
-
-       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       dev->dev_private = dev_priv;
-       dev_priv->dev = dev;
+       struct drm_device *dev = dev_priv->dev;
+       int ret;
 
-       /* Setup the write-once "constant" device info */
-       device_info = (struct intel_device_info *)&dev_priv->info;
-       memcpy(device_info, info, sizeof(dev_priv->info));
-       device_info->device_id = dev->pdev->device;
+       if (i915_inject_load_failure())
+               return -ENODEV;
 
-       spin_lock_init(&dev_priv->irq_lock);
-       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);
-       mutex_init(&dev_priv->sb_lock);
-       mutex_init(&dev_priv->modeset_restore_lock);
-       mutex_init(&dev_priv->av_mutex);
+       if (i915_get_bridge_dev(dev))
+               return -EIO;
 
-       ret = i915_workqueues_init(dev_priv);
+       ret = i915_mmio_setup(dev);
        if (ret < 0)
-               goto out_free_priv;
+               goto put_bridge;
 
-       intel_pm_setup(dev);
+       intel_uncore_init(dev);
 
-       intel_runtime_pm_get(dev_priv);
+       return 0;
 
-       intel_display_crc_init(dev);
+put_bridge:
+       pci_dev_put(dev_priv->bridge_dev);
 
-       i915_dump_device_info(dev_priv);
+       return ret;
+}
 
-       /* Not all pre-production machines fall into this category, only the
-        * very first ones. Almost everything should work, except for maybe
-        * suspend/resume. And we don't implement workarounds that affect only
       * pre-production machines. */
-       if (IS_HSW_EARLY_SDV(dev))
-               DRM_INFO("This is an early pre-production Haswell machine. "
-                        "It may not be fully functional.\n");
+/**
+ * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
 
-       if (i915_get_bridge_dev(dev)) {
-               ret = -EIO;
-               goto out_runtime_pm_put;
-       }
+       intel_uncore_fini(dev);
+       i915_mmio_cleanup(dev);
+       pci_dev_put(dev_priv->bridge_dev);
+}
 
-       ret = i915_mmio_setup(dev);
-       if (ret < 0)
-               goto put_bridge;
+/**
+ * i915_driver_init_hw - setup state requiring device access
+ * @dev_priv: device private
+ *
+ * Setup state that requires accessing the device, but doesn't require
+ * exposing the driver via kernel internal or userspace interfaces.
+ */
+static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       uint32_t aperture_size;
+       int ret;
 
-       /* This must be called before any calls to HAS_PCH_* */
-       intel_detect_pch(dev);
+       if (i915_inject_load_failure())
+               return -ENODEV;
 
-       intel_uncore_init(dev);
+       intel_device_info_runtime_init(dev);
 
        ret = i915_gem_gtt_init(dev);
        if (ret)
-               goto out_uncore_fini;
+               return ret;
 
        /* WARNING: Apparently we must kick fbdev drivers before vgacon,
         * otherwise the vga fbdev driver falls over. */
@@ -1080,26 +1172,27 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
                dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
 
-       aperture_size = dev_priv->gtt.mappable_end;
+       aperture_size = dev_priv->ggtt.mappable_end;
 
-       dev_priv->gtt.mappable =
-               io_mapping_create_wc(dev_priv->gtt.mappable_base,
+       dev_priv->ggtt.mappable =
+               io_mapping_create_wc(dev_priv->ggtt.mappable_base,
                                     aperture_size);
-       if (dev_priv->gtt.mappable == NULL) {
+       if (dev_priv->ggtt.mappable == NULL) {
                ret = -EIO;
                goto out_gtt;
        }
 
-       dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
+       dev_priv->ggtt.mtrr = arch_phys_wc_add(dev_priv->ggtt.mappable_base,
                                              aperture_size);
 
-       intel_irq_init(dev_priv);
+       pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
+                          PM_QOS_DEFAULT_VALUE);
+
        intel_uncore_sanitize(dev);
 
        intel_opregion_setup(dev);
 
-       i915_gem_load_init(dev);
-       i915_gem_shrinker_init(dev_priv);
+       i915_gem_load_init_fences(dev_priv);
 
        /* On the 945G/GM, the chipset reports the MSI capability on the
         * integrated graphics even though the support isn't actually there
@@ -1117,24 +1210,43 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        DRM_DEBUG_DRIVER("can't enable MSI");
        }
 
-       intel_device_info_runtime_init(dev);
+       return 0;
 
-       intel_init_dpio(dev_priv);
+out_gtt:
+       i915_global_gtt_cleanup(dev);
 
-       if (INTEL_INFO(dev)->num_pipes) {
-               ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
-               if (ret)
-                       goto out_gem_unload;
-       }
+       return ret;
+}
 
-       intel_power_domains_init(dev_priv);
+/**
+ * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
 
-       ret = i915_load_modeset_init(dev);
-       if (ret < 0) {
-               DRM_ERROR("failed to init modeset\n");
-               goto out_power_well;
-       }
+       if (dev->pdev->msi_enabled)
+               pci_disable_msi(dev->pdev);
+
+       pm_qos_remove_request(&dev_priv->pm_qos);
+       arch_phys_wc_del(dev_priv->ggtt.mtrr);
+       io_mapping_free(dev_priv->ggtt.mappable);
+       i915_global_gtt_cleanup(dev);
+}
 
+/**
+ * i915_driver_register - register the driver with the rest of the system
+ * @dev_priv: device private
+ *
+ * Perform any steps necessary to make the driver available via kernel
+ * internal or userspace interfaces.
+ */
+static void i915_driver_register(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+
+       i915_gem_shrinker_init(dev_priv);
        /*
         * Notify a valid surface after modesetting,
         * when running inside a VM.
@@ -1144,47 +1256,104 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        i915_setup_sysfs(dev);
 
-       if (INTEL_INFO(dev)->num_pipes) {
+       if (INTEL_INFO(dev_priv)->num_pipes) {
                /* Must be done after probing outputs */
                intel_opregion_init(dev);
                acpi_video_register();
        }
 
-       if (IS_GEN5(dev))
+       if (IS_GEN5(dev_priv))
                intel_gpu_ips_init(dev_priv);
 
-       intel_runtime_pm_enable(dev_priv);
-
        i915_audio_component_init(dev_priv);
+}
+
+/**
+ * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
+ * @dev_priv: device private
+ */
+static void i915_driver_unregister(struct drm_i915_private *dev_priv)
+{
+       i915_audio_component_cleanup(dev_priv);
+       intel_gpu_ips_teardown();
+       acpi_video_unregister();
+       intel_opregion_fini(dev_priv->dev);
+       i915_teardown_sysfs(dev_priv->dev);
+       i915_gem_shrinker_cleanup(dev_priv);
+}
+
+/**
+ * i915_driver_load - setup chip and create an initial config
+ * @dev: DRM device
+ * @flags: startup flags
+ *
+ * The driver load routine has to do several things:
+ *   - drive output discovery via intel_modeset_init()
+ *   - initialize the memory manager
+ *   - allocate initial config memory
+ *   - setup the DRM framebuffer with the allocated memory
+ */
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       struct drm_i915_private *dev_priv;
+       int ret = 0;
+
+       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       dev->dev_private = dev_priv;
+
+       ret = i915_driver_init_early(dev_priv, dev,
+                                    (struct intel_device_info *)flags);
+
+       if (ret < 0)
+               goto out_free_priv;
+
+       intel_runtime_pm_get(dev_priv);
+
+       ret = i915_driver_init_mmio(dev_priv);
+       if (ret < 0)
+               goto out_runtime_pm_put;
+
+       ret = i915_driver_init_hw(dev_priv);
+       if (ret < 0)
+               goto out_cleanup_mmio;
+
+       /*
+        * TODO: move the vblank init and parts of modeset init steps into one
+        * of the i915_driver_init_/i915_driver_register functions according
+        * to the role/effect of the given init step.
+        */
+       if (INTEL_INFO(dev)->num_pipes) {
+               ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
+               if (ret)
+                       goto out_cleanup_hw;
+       }
+
+       ret = i915_load_modeset_init(dev);
+       if (ret < 0) {
+               DRM_ERROR("failed to init modeset\n");
+               goto out_cleanup_vblank;
+       }
+
+       i915_driver_register(dev_priv);
+
+       intel_runtime_pm_enable(dev_priv);
 
        intel_runtime_pm_put(dev_priv);
 
        return 0;
 
-out_power_well:
-       intel_power_domains_fini(dev_priv);
+out_cleanup_vblank:
        drm_vblank_cleanup(dev);
-out_gem_unload:
-       i915_gem_shrinker_cleanup(dev_priv);
-
-       if (dev->pdev->msi_enabled)
-               pci_disable_msi(dev->pdev);
-
-       intel_teardown_mchbar(dev);
-       pm_qos_remove_request(&dev_priv->pm_qos);
-       arch_phys_wc_del(dev_priv->gtt.mtrr);
-       io_mapping_free(dev_priv->gtt.mappable);
-out_gtt:
-       i915_global_gtt_cleanup(dev);
-out_uncore_fini:
-       intel_uncore_fini(dev);
-       i915_mmio_cleanup(dev);
-put_bridge:
-       pci_dev_put(dev_priv->bridge_dev);
-       i915_gem_load_cleanup(dev);
+out_cleanup_hw:
+       i915_driver_cleanup_hw(dev_priv);
+out_cleanup_mmio:
+       i915_driver_cleanup_mmio(dev_priv);
 out_runtime_pm_put:
        intel_runtime_pm_put(dev_priv);
-       i915_workqueues_cleanup(dev_priv);
+       i915_driver_cleanup_early(dev_priv);
 out_free_priv:
        kfree(dev_priv);
 
@@ -1198,26 +1367,15 @@ int i915_driver_unload(struct drm_device *dev)
 
        intel_fbdev_fini(dev);
 
-       i915_audio_component_cleanup(dev_priv);
-
        ret = i915_gem_suspend(dev);
        if (ret) {
                DRM_ERROR("failed to idle hardware: %d\n", ret);
                return ret;
        }
 
-       intel_power_domains_fini(dev_priv);
-
-       intel_gpu_ips_teardown();
+       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
-       i915_teardown_sysfs(dev);
-
-       i915_gem_shrinker_cleanup(dev_priv);
-
-       io_mapping_free(dev_priv->gtt.mappable);
-       arch_phys_wc_del(dev_priv->gtt.mtrr);
-
-       acpi_video_unregister();
+       i915_driver_unregister(dev_priv);
 
        drm_vblank_cleanup(dev);
 
@@ -1246,31 +1404,24 @@ int i915_driver_unload(struct drm_device *dev)
        cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
        i915_destroy_error_state(dev);
 
-       if (dev->pdev->msi_enabled)
-               pci_disable_msi(dev->pdev);
-
-       intel_opregion_fini(dev);
-
        /* Flush any outstanding unpin_work. */
        flush_workqueue(dev_priv->wq);
 
        intel_guc_ucode_fini(dev);
        mutex_lock(&dev->struct_mutex);
-       i915_gem_context_fini(dev);
        i915_gem_cleanup_engines(dev);
+       i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
        intel_fbc_cleanup_cfb(dev_priv);
 
-       pm_qos_remove_request(&dev_priv->pm_qos);
+       intel_power_domains_fini(dev_priv);
 
-       i915_global_gtt_cleanup(dev);
+       i915_driver_cleanup_hw(dev_priv);
+       i915_driver_cleanup_mmio(dev_priv);
 
-       intel_uncore_fini(dev);
-       i915_mmio_cleanup(dev);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
-       i915_gem_load_cleanup(dev);
-       pci_dev_put(dev_priv->bridge_dev);
-       i915_workqueues_cleanup(dev_priv);
+       i915_driver_cleanup_early(dev_priv);
        kfree(dev_priv);
 
        return 0;