Skip to content

Commit bb8f0f5

Browse files
committed
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 <[email protected]> Cc: Joonas Lahtinen <[email protected]> Reviewed-by: Joonas Lahtinen <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent b403c8f commit bb8f0f5

File tree

4 files changed

+81
-23
lines changed

4 files changed

+81
-23
lines changed

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,15 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
755755
return -ENOMEM;
756756
}
757757

758+
static void i915_engines_cleanup(struct drm_i915_private *i915)
759+
{
760+
struct intel_engine_cs *engine;
761+
enum intel_engine_id id;
762+
763+
for_each_engine(engine, i915, id)
764+
kfree(engine);
765+
}
766+
758767
static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
759768
{
760769
destroy_workqueue(dev_priv->hotplug.dp_wq);
@@ -817,12 +826,15 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
817826
mutex_init(&dev_priv->pps_mutex);
818827

819828
intel_uc_init_early(dev_priv);
820-
821829
i915_memcpy_init_early(dev_priv);
822830

831+
ret = intel_engines_init_early(dev_priv);
832+
if (ret)
833+
return ret;
834+
823835
ret = i915_workqueues_init(dev_priv);
824836
if (ret < 0)
825-
return ret;
837+
goto err_engines;
826838

827839
ret = intel_gvt_init(dev_priv);
828840
if (ret < 0)
@@ -857,6 +869,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
857869
intel_gvt_cleanup(dev_priv);
858870
err_workqueues:
859871
i915_workqueues_cleanup(dev_priv);
872+
err_engines:
873+
i915_engines_cleanup(dev_priv);
860874
return ret;
861875
}
862876

@@ -869,6 +883,7 @@ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
869883
i915_perf_fini(dev_priv);
870884
i915_gem_load_cleanup(dev_priv);
871885
i915_workqueues_cleanup(dev_priv);
886+
i915_engines_cleanup(dev_priv);
872887
}
873888

874889
static int i915_mmio_setup(struct drm_i915_private *dev_priv)

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,6 +2940,9 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
29402940
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
29412941
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
29422942

2943+
int intel_engines_init_early(struct drm_i915_private *dev_priv);
2944+
int intel_engines_init(struct drm_i915_private *dev_priv);
2945+
29432946
/* intel_hotplug.c */
29442947
void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
29452948
u32 pin_mask, u32 long_mask);

drivers/gpu/drm/i915/intel_engine_cs.c

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,21 +110,20 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
110110
}
111111

112112
/**
113-
* intel_engines_init() - allocate, populate and init the Engine Command Streamers
113+
* intel_engines_init_early() - allocate the Engine Command Streamers
114114
* @dev_priv: i915 device private
115115
*
116116
* Return: non-zero if the initialization failed.
117117
*/
118-
int intel_engines_init(struct drm_i915_private *dev_priv)
118+
int intel_engines_init_early(struct drm_i915_private *dev_priv)
119119
{
120120
struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
121121
unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
122122
unsigned int mask = 0;
123-
int (*init)(struct intel_engine_cs *engine);
124123
struct intel_engine_cs *engine;
125124
enum intel_engine_id id;
126125
unsigned int i;
127-
int ret;
126+
int err;
128127

129128
WARN_ON(ring_mask == 0);
130129
WARN_ON(ring_mask &
@@ -134,31 +133,73 @@ int intel_engines_init(struct drm_i915_private *dev_priv)
134133
if (!HAS_ENGINE(dev_priv, i))
135134
continue;
136135

136+
err = intel_engine_setup(dev_priv, i);
137+
if (err)
138+
goto cleanup;
139+
140+
mask |= ENGINE_MASK(i);
141+
}
142+
143+
/*
144+
* Catch failures to update intel_engines table when the new engines
145+
* are added to the driver by a warning and disabling the forgotten
146+
* engines.
147+
*/
148+
if (WARN_ON(mask != ring_mask))
149+
device_info->ring_mask = mask;
150+
151+
device_info->num_rings = hweight32(mask);
152+
153+
return 0;
154+
155+
cleanup:
156+
for_each_engine(engine, dev_priv, id)
157+
kfree(engine);
158+
return err;
159+
}
160+
161+
/**
162+
* intel_engines_init() - allocate, populate and init the Engine Command Streamers
163+
* @dev_priv: i915 device private
164+
*
165+
* Return: non-zero if the initialization failed.
166+
*/
167+
int intel_engines_init(struct drm_i915_private *dev_priv)
168+
{
169+
struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
170+
struct intel_engine_cs *engine;
171+
enum intel_engine_id id, err_id;
172+
unsigned int mask = 0;
173+
int err = 0;
174+
175+
for_each_engine(engine, dev_priv, id) {
176+
int (*init)(struct intel_engine_cs *engine);
177+
137178
if (i915.enable_execlists)
138-
init = intel_engines[i].init_execlists;
179+
init = intel_engines[id].init_execlists;
139180
else
140-
init = intel_engines[i].init_legacy;
141-
142-
if (!init)
181+
init = intel_engines[id].init_legacy;
182+
if (!init) {
183+
kfree(engine);
184+
dev_priv->engine[id] = NULL;
143185
continue;
186+
}
144187

145-
ret = intel_engine_setup(dev_priv, i);
146-
if (ret)
147-
goto cleanup;
148-
149-
ret = init(dev_priv->engine[i]);
150-
if (ret)
188+
err = init(engine);
189+
if (err) {
190+
err_id = id;
151191
goto cleanup;
192+
}
152193

153-
mask |= ENGINE_MASK(i);
194+
mask |= ENGINE_MASK(id);
154195
}
155196

156197
/*
157198
* Catch failures to update intel_engines table when the new engines
158199
* are added to the driver by a warning and disabling the forgotten
159200
* engines.
160201
*/
161-
if (WARN_ON(mask != ring_mask))
202+
if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask))
162203
device_info->ring_mask = mask;
163204

164205
device_info->num_rings = hweight32(mask);
@@ -167,13 +208,14 @@ int intel_engines_init(struct drm_i915_private *dev_priv)
167208

168209
cleanup:
169210
for_each_engine(engine, dev_priv, id) {
170-
if (i915.enable_execlists)
211+
if (id >= err_id)
212+
kfree(engine);
213+
else if (i915.enable_execlists)
171214
intel_logical_ring_cleanup(engine);
172215
else
173216
intel_engine_cleanup(engine);
174217
}
175-
176-
return ret;
218+
return err;
177219
}
178220

179221
void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)

drivers/gpu/drm/i915/intel_lrc.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine);
6868
int logical_render_ring_init(struct intel_engine_cs *engine);
6969
int logical_xcs_ring_init(struct intel_engine_cs *engine);
7070

71-
int intel_engines_init(struct drm_i915_private *dev_priv);
72-
7371
/* Logical Ring Contexts */
7472

7573
/* One extra page is added before LRC for GuC as shared data */

0 commit comments

Comments
 (0)