summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_engine_cs.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-01-24 11:01:34 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2017-01-24 12:29:47 +0000
commitbb8f0f5abdd7845175962a3fb99a5681290f9566 (patch)
treea2cec372f90d43893225d1104e3623b142c3a667 /drivers/gpu/drm/i915/intel_engine_cs.c
parentb403c8feaf4838ad54cb9c15d0ad8453aa90af50 (diff)
downloadop-kernel-dev-bb8f0f5abdd7845175962a3fb99a5681290f9566.zip
op-kernel-dev-bb8f0f5abdd7845175962a3fb99a5681290f9566.tar.gz
drm/i915: Split intel_engine allocation and initialisation
In order to reset the GPU early on in the module load sequence, we need to allocate the basic engine structs (to populate the mmio offsets etc). Currently, the engine initialisation allocates both the base struct and also allocate auxiliary objects, which depend upon state setup quite late in the load sequence. We split off the allocation callback for later and allow ourselves to allocate the engine structs themselves early. v2: Different paint for the unwind following error. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170124110135.6418-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/intel_engine_cs.c')
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 371acf1..69a6416d 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -110,21 +110,20 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
}
/**
- * intel_engines_init() - allocate, populate and init the Engine Command Streamers
+ * intel_engines_init_early() - allocate the Engine Command Streamers
* @dev_priv: i915 device private
*
* Return: non-zero if the initialization failed.
*/
-int intel_engines_init(struct drm_i915_private *dev_priv)
+int intel_engines_init_early(struct drm_i915_private *dev_priv)
{
struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
unsigned int mask = 0;
- int (*init)(struct intel_engine_cs *engine);
struct intel_engine_cs *engine;
enum intel_engine_id id;
unsigned int i;
- int ret;
+ int err;
WARN_ON(ring_mask == 0);
WARN_ON(ring_mask &
@@ -134,23 +133,65 @@ int intel_engines_init(struct drm_i915_private *dev_priv)
if (!HAS_ENGINE(dev_priv, i))
continue;
+ err = intel_engine_setup(dev_priv, i);
+ if (err)
+ goto cleanup;
+
+ mask |= ENGINE_MASK(i);
+ }
+
+ /*
+ * Catch failures to update intel_engines table when the new engines
+ * are added to the driver by a warning and disabling the forgotten
+ * engines.
+ */
+ if (WARN_ON(mask != ring_mask))
+ device_info->ring_mask = mask;
+
+ device_info->num_rings = hweight32(mask);
+
+ return 0;
+
+cleanup:
+ for_each_engine(engine, dev_priv, id)
+ kfree(engine);
+ return err;
+}
+
+/**
+ * intel_engines_init() - allocate, populate and init the Engine Command Streamers
+ * @dev_priv: i915 device private
+ *
+ * Return: non-zero if the initialization failed.
+ */
+int intel_engines_init(struct drm_i915_private *dev_priv)
+{
+ struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id, err_id;
+ unsigned int mask = 0;
+ int err = 0;
+
+ for_each_engine(engine, dev_priv, id) {
+ int (*init)(struct intel_engine_cs *engine);
+
if (i915.enable_execlists)
- init = intel_engines[i].init_execlists;
+ init = intel_engines[id].init_execlists;
else
- init = intel_engines[i].init_legacy;
-
- if (!init)
+ init = intel_engines[id].init_legacy;
+ if (!init) {
+ kfree(engine);
+ dev_priv->engine[id] = NULL;
continue;
+ }
- ret = intel_engine_setup(dev_priv, i);
- if (ret)
- goto cleanup;
-
- ret = init(dev_priv->engine[i]);
- if (ret)
+ err = init(engine);
+ if (err) {
+ err_id = id;
goto cleanup;
+ }
- mask |= ENGINE_MASK(i);
+ mask |= ENGINE_MASK(id);
}
/*
@@ -158,7 +199,7 @@ int intel_engines_init(struct drm_i915_private *dev_priv)
* are added to the driver by a warning and disabling the forgotten
* engines.
*/
- if (WARN_ON(mask != ring_mask))
+ if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask))
device_info->ring_mask = mask;
device_info->num_rings = hweight32(mask);
@@ -167,13 +208,14 @@ int intel_engines_init(struct drm_i915_private *dev_priv)
cleanup:
for_each_engine(engine, dev_priv, id) {
- if (i915.enable_execlists)
+ if (id >= err_id)
+ kfree(engine);
+ else if (i915.enable_execlists)
intel_logical_ring_cleanup(engine);
else
intel_engine_cleanup(engine);
}
-
- return ret;
+ return err;
}
void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
OpenPOWER on IntegriCloud