summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c105
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,