Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b3f1650 authored by Akash Goel's avatar Akash Goel Committed by Tvrtko Ursulin
Browse files

drm/i915: Allocate intel_engine_cs structure only for the enabled engines



With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
	struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
	struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.

There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).

v2:
- Remove the engine iterator field added in drm_i915_private structure,
  instead pass a local iterator variable to the for_each_engine**
  macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
  NULL pointer check on engine pointer. (Chris)

v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
  can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
  engine specific init is done later in Driver load sequence.

v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().

v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
  allocation of intel_engine_cs structure. (Chris)

v6:
- Rebase.

v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.

v8: Rebase.

v9: Rebase.

v10:
- For index calculation use engine ID instead of pointer based arithmetic in
  intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
  check for NULL engine pointer in cleanup() routines. (Joonas)

v11: Rebase.

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarAkash Goel <akash.goel@intel.com>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
parent 86e83e35
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1308,10 +1308,11 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	bool active = false;

	/* If the command parser is not enabled, report 0 - unsupported */
	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		if (intel_engine_needs_cmd_parser(engine)) {
			active = true;
			break;
+35 −24
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
		   obj->base.size / 1024,
		   obj->base.read_domains,
		   obj->base.write_domain);
	for_each_engine_id(engine, dev_priv, id)
	for_each_engine(engine, dev_priv, id)
		seq_printf(m, "%x ",
			   i915_gem_active_get_seqno(&obj->last_read[id],
						     &obj->base.dev->struct_mutex));
@@ -323,11 +323,12 @@ static void print_batch_pool_stats(struct seq_file *m,
	struct drm_i915_gem_object *obj;
	struct file_stats stats;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int j;

	memset(&stats, 0, sizeof(stats));

	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
			list_for_each_entry(obj,
					    &engine->batch_pool.cache_list[j],
@@ -596,6 +597,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
	struct drm_device *dev = &dev_priv->drm;
	struct drm_i915_gem_object *obj;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int total = 0;
	int ret, j;

@@ -603,7 +605,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
	if (ret)
		return ret;

	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
			int count;

@@ -655,8 +657,9 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct drm_device *dev = &dev_priv->drm;
	struct intel_engine_cs *engine;
	struct drm_i915_gem_request *req;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int ret, any;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -664,7 +667,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
		return ret;

	any = 0;
	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		int count;

		count = 0;
@@ -710,8 +713,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	for_each_engine(engine, dev_priv)
	for_each_engine(engine, dev_priv, id)
		i915_ring_seqno_info(m, engine);

	return 0;
@@ -722,6 +726,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int i, pipe;

	intel_runtime_pm_get(dev_priv);
@@ -890,7 +895,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
		seq_printf(m, "Graphics Interrupt mask:		%08x\n",
			   I915_READ(GTIMR));
	}
	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		if (INTEL_GEN(dev_priv) >= 6) {
			seq_printf(m,
				   "Graphics Interrupt mask (%s):	%08x\n",
@@ -938,7 +943,7 @@ static int i915_hws_info(struct seq_file *m, void *data)
	const u32 *hws;
	int i;

	engine = &dev_priv->engine[(uintptr_t)node->info_ent->data];
	engine = dev_priv->engine[(uintptr_t)node->info_ent->data];
	hws = engine->status_page.page_addr;
	if (hws == NULL)
		return 0;
@@ -1329,12 +1334,12 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)

	intel_runtime_pm_get(dev_priv);

	for_each_engine_id(engine, dev_priv, id) {
	for_each_engine(engine, dev_priv, id) {
		acthd[id] = intel_engine_get_active_head(engine);
		seqno[id] = intel_engine_get_seqno(engine);
	}

	intel_engine_get_instdone(&dev_priv->engine[RCS], &instdone);
	intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);

	intel_runtime_pm_put(dev_priv);

@@ -1345,7 +1350,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
	} else
		seq_printf(m, "Hangcheck inactive\n");

	for_each_engine_id(engine, dev_priv, id) {
	for_each_engine(engine, dev_priv, id) {
		struct intel_breadcrumbs *b = &engine->breadcrumbs;
		struct rb_node *rb;

@@ -1944,6 +1949,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
	struct drm_device *dev = &dev_priv->drm;
	struct intel_engine_cs *engine;
	struct i915_gem_context *ctx;
	enum intel_engine_id id;
	int ret;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1970,7 +1976,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
		seq_putc(m, ctx->remap_slice ? 'R' : 'r');
		seq_putc(m, '\n');

		for_each_engine(engine, dev_priv) {
		for_each_engine(engine, dev_priv, id) {
			struct intel_context *ce = &ctx->engine[engine->id];

			seq_printf(m, "%s: ", engine->name);
@@ -2037,6 +2043,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
	struct drm_device *dev = &dev_priv->drm;
	struct intel_engine_cs *engine;
	struct i915_gem_context *ctx;
	enum intel_engine_id id;
	int ret;

	if (!i915.enable_execlists) {
@@ -2049,7 +2056,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
		return ret;

	list_for_each_entry(ctx, &dev_priv->context_list, link)
		for_each_engine(engine, dev_priv)
		for_each_engine(engine, dev_priv, id)
			i915_dump_lrc_obj(m, ctx, engine);

	mutex_unlock(&dev->struct_mutex);
@@ -2158,14 +2165,15 @@ static int per_file_ctx(int id, void *ptr, void *data)
static void gen8_ppgtt_info(struct seq_file *m,
			    struct drm_i915_private *dev_priv)
{
	struct intel_engine_cs *engine;
	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int i;

	if (!ppgtt)
		return;

	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		seq_printf(m, "%s\n", engine->name);
		for (i = 0; i < 4; i++) {
			u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i));
@@ -2180,11 +2188,12 @@ static void gen6_ppgtt_info(struct seq_file *m,
			    struct drm_i915_private *dev_priv)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	if (IS_GEN6(dev_priv))
		seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));

	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		seq_printf(m, "%s\n", engine->name);
		if (IS_GEN7(dev_priv))
			seq_printf(m, "GFX_MODE: 0x%08x\n",
@@ -2253,9 +2262,10 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
static int count_irq_waiters(struct drm_i915_private *i915)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int count = 0;

	for_each_engine(engine, i915)
	for_each_engine(engine, i915, id)
		count += intel_engine_has_waiter(engine);

	return count;
@@ -2418,7 +2428,7 @@ static void i915_guc_client_info(struct seq_file *m,
	seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
	seq_printf(m, "\tLast submission result: %d\n", client->retcode);

	for_each_engine_id(engine, dev_priv, id) {
	for_each_engine(engine, dev_priv, id) {
		u64 submissions = client->submissions[id];
		tot += submissions;
		seq_printf(m, "\tSubmissions: %llu %s\n",
@@ -2461,7 +2471,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
	seq_printf(m, "GuC last action error code: %d\n", guc.action_err);

	seq_printf(m, "\nGuC submissions:\n");
	for_each_engine_id(engine, dev_priv, id) {
	for_each_engine(engine, dev_priv, id) {
		u64 submissions = guc.submissions[id];
		total += submissions;
		seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
@@ -3082,8 +3092,9 @@ static int i915_engine_info(struct seq_file *m, void *unused)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		struct intel_breadcrumbs *b = &engine->breadcrumbs;
		struct drm_i915_gem_request *rq;
		struct rb_node *rb;
@@ -3231,7 +3242,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
		page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0);

		seqno = (uint64_t *)kmap_atomic(page);
		for_each_engine_id(engine, dev_priv, id) {
		for_each_engine(engine, dev_priv, id) {
			uint64_t offset;

			seq_printf(m, "%s\n", engine->name);
@@ -3256,7 +3267,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
		kunmap_atomic(seqno);
	} else {
		seq_puts(m, "  Last signal:");
		for_each_engine(engine, dev_priv)
		for_each_engine(engine, dev_priv, id)
			for (j = 0; j < num_rings; j++)
				seq_printf(m, "0x%08x\n",
					   I915_READ(engine->semaphore.mbox.signal[j]));
@@ -3264,7 +3275,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
	}

	seq_puts(m, "\nSync seqno:\n");
	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		for (j = 0; j < num_rings; j++)
			seq_printf(m, "  0x%08x ",
				   engine->semaphore.sync_seqno[j]);
@@ -3320,7 +3331,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
	intel_runtime_pm_get(dev_priv);

	seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
	for_each_engine_id(engine, dev_priv, id)
	for_each_engine(engine, dev_priv, id)
		seq_printf(m, "HW whitelist count for %s: %d\n",
			   engine->name, workarounds->hw_whitelist_count[id]);
	for (i = 0; i < workarounds->count; ++i) {
+6 −5
Original line number Diff line number Diff line
@@ -255,16 +255,16 @@ static int i915_getparam(struct drm_device *dev, void *data,
		value = dev_priv->overlay ? 1 : 0;
		break;
	case I915_PARAM_HAS_BSD:
		value = intel_engine_initialized(&dev_priv->engine[VCS]);
		value = !!dev_priv->engine[VCS];
		break;
	case I915_PARAM_HAS_BLT:
		value = intel_engine_initialized(&dev_priv->engine[BCS]);
		value = !!dev_priv->engine[BCS];
		break;
	case I915_PARAM_HAS_VEBOX:
		value = intel_engine_initialized(&dev_priv->engine[VECS]);
		value = !!dev_priv->engine[VECS];
		break;
	case I915_PARAM_HAS_BSD2:
		value = intel_engine_initialized(&dev_priv->engine[VCS2]);
		value = !!dev_priv->engine[VCS2];
		break;
	case I915_PARAM_HAS_EXEC_CONSTANTS:
		value = INTEL_GEN(dev_priv) >= 4;
@@ -1707,10 +1707,11 @@ int i915_resume_switcheroo(struct drm_device *dev)
static void disable_engines_irq(struct drm_i915_private *dev_priv)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	/* Ensure irq handler finishes, and not run again. */
	disable_irq(dev_priv->drm.irq);
	for_each_engine(engine, dev_priv)
	for_each_engine(engine, dev_priv, id)
		tasklet_kill(&engine->irq_tasklet);
}

+7 −15
Original line number Diff line number Diff line
@@ -1808,7 +1808,7 @@ struct drm_i915_private {

	struct pci_dev *bridge_dev;
	struct i915_gem_context *kernel_context;
	struct intel_engine_cs engine[I915_NUM_ENGINES];
	struct intel_engine_cs *engine[I915_NUM_ENGINES];
	struct i915_vma *semaphore;
	u32 next_seqno;

@@ -2125,19 +2125,11 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
}

/* Simple iterator over all initialised engines */
#define for_each_engine(engine__, dev_priv__) \
	for ((engine__) = &(dev_priv__)->engine[0]; \
	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
	     (engine__)++) \
		for_each_if (intel_engine_initialized(engine__))

/* Iterator with engine_id */
#define for_each_engine_id(engine__, dev_priv__, id__) \
	for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \
	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
	     (engine__)++) \
		for_each_if (((id__) = (engine__)->id, \
			      intel_engine_initialized(engine__)))
#define for_each_engine(engine__, dev_priv__, id__) \
	for ((id__) = 0; \
	     (id__) < I915_NUM_ENGINES; \
	     (id__)++) \
		for_each_if ((engine__) = (dev_priv__)->engine[(id__)])

#define __mask_next_bit(mask) ({					\
	int __idx = ffs(mask) - 1;					\
@@ -2148,7 +2140,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
/* Iterator over subset of engines selected by mask */
#define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \
	for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask;	\
	     tmp__ ? (engine__ = &(dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; )
	     tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; )

enum hdmi_force_audio {
	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
+13 −16
Original line number Diff line number Diff line
@@ -2626,10 +2626,11 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
void i915_gem_reset(struct drm_i915_private *dev_priv)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	i915_gem_retire_requests(dev_priv);

	for_each_engine(engine, dev_priv)
	for_each_engine(engine, dev_priv, id)
		i915_gem_reset_engine(engine);

	i915_gem_restore_fences(&dev_priv->drm);
@@ -2677,12 +2678,13 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine)
void i915_gem_set_wedged(struct drm_i915_private *dev_priv)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	lockdep_assert_held(&dev_priv->drm.struct_mutex);
	set_bit(I915_WEDGED, &dev_priv->gpu_error.flags);

	i915_gem_context_lost(dev_priv);
	for_each_engine(engine, dev_priv)
	for_each_engine(engine, dev_priv, id)
		i915_gem_cleanup_engine(engine);
	mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0);

@@ -2721,6 +2723,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
		container_of(work, typeof(*dev_priv), gt.idle_work.work);
	struct drm_device *dev = &dev_priv->drm;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	bool rearm_hangcheck;

	if (!READ_ONCE(dev_priv->gt.awake))
@@ -2743,7 +2746,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
	if (dev_priv->gt.active_engines)
		goto out_unlock;

	for_each_engine(engine, dev_priv)
	for_each_engine(engine, dev_priv, id)
		i915_gem_batch_pool_fini(&engine->batch_pool);

	GEM_BUG_ON(!dev_priv->gt.awake);
@@ -2936,9 +2939,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
			   unsigned int flags)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int ret;

	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		if (engine->last_context == NULL)
			continue;

@@ -3181,7 +3185,7 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
	 */
	wmb();
	if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv))
		POSTING_READ(RING_ACTHD(dev_priv->engine[RCS].mmio_base));
		POSTING_READ(RING_ACTHD(dev_priv->engine[RCS]->mmio_base));

	intel_fb_obj_flush(obj, false, write_origin(obj, I915_GEM_DOMAIN_GTT));

@@ -4416,6 +4420,7 @@ i915_gem_init_hw(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int ret;

	/* Double layer security blanket, see i915_gem_init() */
@@ -4459,7 +4464,7 @@ i915_gem_init_hw(struct drm_device *dev)
	}

	/* Need to do basic initialisation of all rings first: */
	for_each_engine(engine, dev_priv) {
	for_each_engine(engine, dev_priv, id) {
		ret = engine->init_hw(engine);
		if (ret)
			goto out;
@@ -4558,17 +4563,12 @@ i915_gem_cleanup_engines(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	for_each_engine(engine, dev_priv)
	for_each_engine(engine, dev_priv, id)
		dev_priv->gt.cleanup_engine(engine);
}

static void
init_engine_lists(struct intel_engine_cs *engine)
{
	INIT_LIST_HEAD(&engine->request_list);
}

void
i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
{
@@ -4605,7 +4605,6 @@ void
i915_gem_load_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	int i;

	dev_priv->objects =
		kmem_cache_create("i915_gem_object",
@@ -4629,8 +4628,6 @@ i915_gem_load_init(struct drm_device *dev)
	INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
	INIT_LIST_HEAD(&dev_priv->mm.bound_list);
	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
	for (i = 0; i < I915_NUM_ENGINES; i++)
		init_engine_lists(&dev_priv->engine[i]);
	INIT_DELAYED_WORK(&dev_priv->gt.retire_work,
			  i915_gem_retire_work_handler);
	INIT_DELAYED_WORK(&dev_priv->gt.idle_work,
Loading