diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 105 |
1 files changed, 57 insertions, 48 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 4c96a7214482..ff70fc45ba7c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -237,17 +237,18 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) !IS_KABYLAKE(dev_priv)); } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_KBP; - DRM_DEBUG_KMS("Found KabyPoint PCH\n"); + DRM_DEBUG_KMS("Found Kaby Lake PCH (KBP)\n"); WARN_ON(!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv)); + !IS_KABYLAKE(dev_priv) && + !IS_COFFEELAKE(dev_priv)); } else if (id == INTEL_PCH_CNP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CNP; - DRM_DEBUG_KMS("Found CannonPoint PCH\n"); + DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); } else if (id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CNP; - DRM_DEBUG_KMS("Found CannonPoint LP PCH\n"); + DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n"); WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || @@ -388,6 +389,7 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_EXEC_FENCE: case I915_PARAM_HAS_EXEC_CAPTURE: case I915_PARAM_HAS_EXEC_BATCH_FIRST: + case I915_PARAM_HAS_EXEC_FENCE_ARRAY: /* 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 @@ -596,7 +598,8 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { static void i915_gem_fini(struct drm_i915_private *dev_priv) { - flush_workqueue(dev_priv->wq); + /* Flush any outstanding unpin_work. */ + i915_gem_drain_workqueue(dev_priv); mutex_lock(&dev_priv->drm.struct_mutex); intel_uc_fini_hw(dev_priv); @@ -875,7 +878,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, 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); @@ -1240,6 +1242,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) */ static void i915_driver_unregister(struct drm_i915_private *dev_priv) { + intel_fbdev_unregister(dev_priv); intel_audio_deinit(dev_priv); intel_gpu_ips_teardown(); @@ -1371,7 +1374,7 @@ 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; - intel_fbdev_fini(dev); + i915_driver_unregister(dev_priv); if (i915_gem_suspend(dev_priv)) DRM_ERROR("failed to idle hardware; continuing to unload!\n"); @@ -1382,8 +1385,6 @@ void i915_driver_unload(struct drm_device *dev) intel_gvt_cleanup(dev_priv); - i915_driver_unregister(dev_priv); - intel_modeset_cleanup(dev); /* @@ -1409,9 +1410,6 @@ void i915_driver_unload(struct drm_device *dev) cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); i915_reset_error_state(dev_priv); - /* Flush any outstanding unpin_work. */ - drain_workqueue(dev_priv->wq); - i915_gem_fini(dev_priv); intel_uc_fini_fw(dev_priv); intel_fbc_cleanup_cfb(dev_priv); @@ -1835,7 +1833,8 @@ static int i915_resume_switcheroo(struct drm_device *dev) /** * i915_reset - reset chip after a hang - * @dev_priv: device private to reset + * @i915: #drm_i915_private to reset + * @flags: Instructions * * Reset the chip. Useful if a hang is detected. Marks the device as wedged * on failure. @@ -1850,33 +1849,34 @@ static int i915_resume_switcheroo(struct drm_device *dev) * - re-init interrupt state * - re-init display */ -void i915_reset(struct drm_i915_private *dev_priv) +void i915_reset(struct drm_i915_private *i915, unsigned int flags) { - struct i915_gpu_error *error = &dev_priv->gpu_error; + struct i915_gpu_error *error = &i915->gpu_error; int ret; - lockdep_assert_held(&dev_priv->drm.struct_mutex); + lockdep_assert_held(&i915->drm.struct_mutex); GEM_BUG_ON(!test_bit(I915_RESET_BACKOFF, &error->flags)); if (!test_bit(I915_RESET_HANDOFF, &error->flags)) return; /* Clear any previous failed attempts at recovery. Time to try again. */ - if (!i915_gem_unset_wedged(dev_priv)) + if (!i915_gem_unset_wedged(i915)) goto wakeup; + if (!(flags & I915_RESET_QUIET)) + dev_notice(i915->drm.dev, "Resetting chip after gpu hang\n"); error->reset_count++; - pr_notice("drm/i915: Resetting chip after gpu hang\n"); - disable_irq(dev_priv->drm.irq); - ret = i915_gem_reset_prepare(dev_priv); + disable_irq(i915->drm.irq); + ret = i915_gem_reset_prepare(i915); if (ret) { DRM_ERROR("GPU recovery failed\n"); - intel_gpu_reset(dev_priv, ALL_ENGINES); + intel_gpu_reset(i915, ALL_ENGINES); goto error; } - ret = intel_gpu_reset(dev_priv, ALL_ENGINES); + ret = intel_gpu_reset(i915, ALL_ENGINES); if (ret) { if (ret != -ENODEV) DRM_ERROR("Failed to reset chip: %i\n", ret); @@ -1885,16 +1885,22 @@ void i915_reset(struct drm_i915_private *dev_priv) goto error; } - i915_gem_reset(dev_priv); - intel_overlay_reset(dev_priv); + i915_gem_reset(i915); + intel_overlay_reset(i915); /* Ok, now get things going again... */ /* * Everything depends on having the GTT running, so we need to start - * there. Fortunately we don't need to do this unless we reset the - * chip at a PCI level. - * + * there. + */ + ret = i915_ggtt_enable_hw(i915); + if (ret) { + DRM_ERROR("Failed to re-enable GGTT following reset %d\n", ret); + goto error; + } + + /* * Next we need to restore the context, but we don't use those * yet either... * @@ -1902,17 +1908,17 @@ void i915_reset(struct drm_i915_private *dev_priv) * was running at the time of the reset (i.e. we weren't VT * switched away). */ - ret = i915_gem_init_hw(dev_priv); + ret = i915_gem_init_hw(i915); if (ret) { DRM_ERROR("Failed hw init on reset %d\n", ret); goto error; } - i915_queue_hangcheck(dev_priv); + i915_queue_hangcheck(i915); finish: - i915_gem_reset_finish(dev_priv); - enable_irq(dev_priv->drm.irq); + i915_gem_reset_finish(i915); + enable_irq(i915->drm.irq); wakeup: clear_bit(I915_RESET_HANDOFF, &error->flags); @@ -1920,14 +1926,15 @@ wakeup: return; error: - i915_gem_set_wedged(dev_priv); - i915_gem_retire_requests(dev_priv); + i915_gem_set_wedged(i915); + i915_gem_retire_requests(i915); goto finish; } /** * i915_reset_engine - reset GPU engine to recover from a hang * @engine: engine to reset + * @flags: options * * Reset a specific GPU engine. Useful if a hang is detected. * Returns zero on successful reset or otherwise an error code. @@ -1937,7 +1944,7 @@ error: * - reset engine (which will force the engine to idle) * - re-init/configure engine */ -int i915_reset_engine(struct intel_engine_cs *engine) +int i915_reset_engine(struct intel_engine_cs *engine, unsigned int flags) { struct i915_gpu_error *error = &engine->i915->gpu_error; struct drm_i915_gem_request *active_request; @@ -1945,7 +1952,11 @@ int i915_reset_engine(struct intel_engine_cs *engine) GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); - DRM_DEBUG_DRIVER("resetting %s\n", engine->name); + if (!(flags & I915_RESET_QUIET)) { + dev_notice(engine->i915->drm.dev, + "Resetting %s after gpu hang\n", engine->name); + } + error->reset_engine_count[engine->id]++; active_request = i915_gem_reset_prepare_engine(engine); if (IS_ERR(active_request)) { @@ -1954,18 +1965,7 @@ int i915_reset_engine(struct intel_engine_cs *engine) goto out; } - /* - * The request that caused the hang is stuck on elsp, we know the - * active request and can drop it, adjust head to skip the offending - * request to resume executing remaining requests in the queue. - */ - i915_gem_reset_engine(engine, active_request); - - /* Finally, reset just this engine. */ ret = intel_gpu_reset(engine->i915, intel_engine_flag(engine)); - - i915_gem_reset_finish_engine(engine); - if (ret) { /* If we fail here, we expect to fallback to a global reset */ DRM_DEBUG_DRIVER("Failed to reset %s, ret=%d\n", @@ -1974,6 +1974,13 @@ int i915_reset_engine(struct intel_engine_cs *engine) } /* + * The request that caused the hang is stuck on elsp, we know the + * active request and can drop it, adjust head to skip the offending + * request to resume executing remaining requests in the queue. + */ + i915_gem_reset_engine(engine, active_request); + + /* * The engine and its registers (and workarounds in case of render) * have been reset to their default values. Follow the init_ring * process to program RING_MODE, HWSP and re-enable submission. @@ -1982,8 +1989,8 @@ int i915_reset_engine(struct intel_engine_cs *engine) if (ret) goto out; - error->reset_engine_count[engine->id]++; out: + i915_gem_reset_finish_engine(engine); return ret; } @@ -2730,6 +2737,8 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), }; static struct drm_driver driver = { @@ -2738,7 +2747,7 @@ static struct drm_driver driver = { */ .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME | - DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC, + DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ, .release = i915_driver_release, .open = i915_driver_open, .lastclose = i915_driver_lastclose, |