diff mbox series

drm/i915: Engine relative MMIO

Message ID 20190222234918.35463-1-John.C.Harrison@Intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Engine relative MMIO | expand

Commit Message

John Harrison Feb. 22, 2019, 11:49 p.m. UTC
From: John Harrison <John.C.Harrison@Intel.com>

With virtual engines, it is no longer possible to know which specific
physical engine a given request will be executed on at the time that
request is generated. This means that the request itself must be engine
agnostic - any direct register writes must be relative to the engine
and not absolute addresses.

The LRI command has support for engine relative addressing. However,
the mechanism is not transparent to the driver. The scheme for Gen11
(MI_LRI_ADD_CS_MMIO_START) requires the LRI address to have no
absolute engine base component. The hardware then adds on the correct
engine offset at execution time.

Due to the non-trivial and differing schemes on different hardware, it
is not possible to simply update the code that creates the LRI
commands to set a remap flag and let the hardware get on with it.
Instead, this patch adds function wrappers for generating the LRI
command itself and then for constructing the correct address to use
with the LRI.

Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c     |  4 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  4 +-
 drivers/gpu/drm/i915/i915_perf.c           | 19 ++++---
 drivers/gpu/drm/i915/intel_engine_cs.c     | 11 ++++
 drivers/gpu/drm/i915/intel_gpu_commands.h  |  6 ++-
 drivers/gpu/drm/i915/intel_lrc.c           | 80 ++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_lrc_reg.h       |  4 +-
 drivers/gpu/drm/i915/intel_mocs.c          | 17 ++++---
 drivers/gpu/drm/i915/intel_ringbuffer.c    | 46 ++++++++++++++---
 drivers/gpu/drm/i915/intel_ringbuffer.h    |  5 ++
 drivers/gpu/drm/i915/intel_workarounds.c   |  4 +-
 11 files changed, 133 insertions(+), 67 deletions(-)

Comments

Chris Wilson Feb. 22, 2019, 11:57 p.m. UTC | #1
Quoting John.C.Harrison@Intel.com (2019-02-22 23:49:18)
> From: John Harrison <John.C.Harrison@Intel.com>
> 
> With virtual engines, it is no longer possible to know which specific
> physical engine a given request will be executed on at the time that
> request is generated. This means that the request itself must be engine
> agnostic - any direct register writes must be relative to the engine
> and not absolute addresses.
> 
> The LRI command has support for engine relative addressing. However,
> the mechanism is not transparent to the driver. The scheme for Gen11
> (MI_LRI_ADD_CS_MMIO_START) requires the LRI address to have no
> absolute engine base component. The hardware then adds on the correct
> engine offset at execution time.
> 
> Due to the non-trivial and differing schemes on different hardware, it
> is not possible to simply update the code that creates the LRI
> commands to set a remap flag and let the hardware get on with it.
> Instead, this patch adds function wrappers for generating the LRI
> command itself and then for constructing the correct address to use
> with the LRI.

But the flags isn't compulsory? So why so many changes to unaffected
code?
-Chris
kernel test robot Feb. 23, 2019, 7:37 a.m. UTC | #2
Hi John,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20190222]
[cannot apply to v5.0-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/John-C-Harrison-Intel-com/drm-i915-Engine-relative-MMIO/20190223-131519
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-allyesconfig (attached as .config)
compiler: gcc-8 (Debian 8.2.0-20) 8.2.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/i915/gvt/mmio_context.c: In function 'restore_context_mmio_for_inhibit':
>> drivers/gpu/drm/i915/gvt/mmio_context.c:202:10: error: implicit declaration of function 'MI_LOAD_REGISTER_IMM'; did you mean 'MI_LOAD_REGISTER_MEM'? [-Werror=implicit-function-declaration]
     *cs++ = MI_LOAD_REGISTER_IMM(count);
             ^~~~~~~~~~~~~~~~~~~~
             MI_LOAD_REGISTER_MEM
   cc1: some warnings being treated as errors

vim +202 drivers/gpu/drm/i915/gvt/mmio_context.c

17865713 drivers/gpu/drm/i915/gvt/render.c       Zhi Wang  2016-05-01  179  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  180  static int
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  181  restore_context_mmio_for_inhibit(struct intel_vgpu *vgpu,
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  182  				 struct i915_request *req)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  183  {
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  184  	u32 *cs;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  185  	int ret;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  186  	struct engine_mmio *mmio;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  187  	struct intel_gvt *gvt = vgpu->gvt;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  188  	int ring_id = req->engine->id;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  189  	int count = gvt->engine_mmio_list.ctx_mmio_count[ring_id];
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  190  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  191  	if (count == 0)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  192  		return 0;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  193  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  194  	ret = req->engine->emit_flush(req, EMIT_BARRIER);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  195  	if (ret)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  196  		return ret;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  197  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  198  	cs = intel_ring_begin(req, count * 2 + 2);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  199  	if (IS_ERR(cs))
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  200  		return PTR_ERR(cs);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  201  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23 @202  	*cs++ = MI_LOAD_REGISTER_IMM(count);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  203  	for (mmio = gvt->engine_mmio_list.mmio;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  204  	     i915_mmio_reg_valid(mmio->reg); mmio++) {
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  205  		if (mmio->ring_id != ring_id ||
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  206  		    !mmio->in_context)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  207  			continue;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  208  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  209  		*cs++ = i915_mmio_reg_offset(mmio->reg);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  210  		*cs++ = vgpu_vreg_t(vgpu, mmio->reg) |
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  211  				(mmio->mask << 16);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  212  		gvt_dbg_core("add lri reg pair 0x%x:0x%x in inhibit ctx, vgpu:%d, rind_id:%d\n",
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  213  			      *(cs-2), *(cs-1), vgpu->id, ring_id);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  214  	}
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  215  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  216  	*cs++ = MI_NOOP;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  217  	intel_ring_advance(req, cs);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  218  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  219  	ret = req->engine->emit_flush(req, EMIT_BARRIER);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  220  	if (ret)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  221  		return ret;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  222  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  223  	return 0;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  224  }
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  225  

:::::: The code at line 202 was first introduced by commit
:::::: cd7e61b93d068a80bfe6cb55bf00f17332d831a1 drm/i915/gvt: init mmio by lri command in vgpu inhibit context

:::::: TO: Weinan Li <weinan.z.li@intel.com>
:::::: CC: Zhenyu Wang <zhenyuw@linux.intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Feb. 23, 2019, 9:27 a.m. UTC | #3
Hi John,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20190222]
[cannot apply to v5.0-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/John-C-Harrison-Intel-com/drm-i915-Engine-relative-MMIO/20190223-131519
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-fedora-25 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/i915/gvt/mmio_context.c: In function 'restore_context_mmio_for_inhibit':
>> drivers/gpu/drm/i915/gvt/mmio_context.c:202:10: error: implicit declaration of function 'MI_LOAD_REGISTER_IMM'; did you mean '__MI_LOAD_REGISTER_IMM'? [-Werror=implicit-function-declaration]
     *cs++ = MI_LOAD_REGISTER_IMM(count);
             ^~~~~~~~~~~~~~~~~~~~
             __MI_LOAD_REGISTER_IMM
   cc1: some warnings being treated as errors

vim +202 drivers/gpu/drm/i915/gvt/mmio_context.c

17865713 drivers/gpu/drm/i915/gvt/render.c       Zhi Wang  2016-05-01  179  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  180  static int
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  181  restore_context_mmio_for_inhibit(struct intel_vgpu *vgpu,
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  182  				 struct i915_request *req)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  183  {
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  184  	u32 *cs;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  185  	int ret;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  186  	struct engine_mmio *mmio;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  187  	struct intel_gvt *gvt = vgpu->gvt;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  188  	int ring_id = req->engine->id;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  189  	int count = gvt->engine_mmio_list.ctx_mmio_count[ring_id];
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  190  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  191  	if (count == 0)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  192  		return 0;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  193  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  194  	ret = req->engine->emit_flush(req, EMIT_BARRIER);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  195  	if (ret)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  196  		return ret;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  197  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  198  	cs = intel_ring_begin(req, count * 2 + 2);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  199  	if (IS_ERR(cs))
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  200  		return PTR_ERR(cs);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  201  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23 @202  	*cs++ = MI_LOAD_REGISTER_IMM(count);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  203  	for (mmio = gvt->engine_mmio_list.mmio;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  204  	     i915_mmio_reg_valid(mmio->reg); mmio++) {
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  205  		if (mmio->ring_id != ring_id ||
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  206  		    !mmio->in_context)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  207  			continue;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  208  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  209  		*cs++ = i915_mmio_reg_offset(mmio->reg);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  210  		*cs++ = vgpu_vreg_t(vgpu, mmio->reg) |
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  211  				(mmio->mask << 16);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  212  		gvt_dbg_core("add lri reg pair 0x%x:0x%x in inhibit ctx, vgpu:%d, rind_id:%d\n",
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  213  			      *(cs-2), *(cs-1), vgpu->id, ring_id);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  214  	}
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  215  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  216  	*cs++ = MI_NOOP;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  217  	intel_ring_advance(req, cs);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  218  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  219  	ret = req->engine->emit_flush(req, EMIT_BARRIER);
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  220  	if (ret)
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  221  		return ret;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  222  
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  223  	return 0;
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  224  }
cd7e61b9 drivers/gpu/drm/i915/gvt/mmio_context.c Weinan Li 2018-02-23  225  

:::::: The code at line 202 was first introduced by commit
:::::: cd7e61b93d068a80bfe6cb55bf00f17332d831a1 drm/i915/gvt: init mmio by lri command in vgpu inhibit context

:::::: TO: Weinan Li <weinan.z.li@intel.com>
:::::: CC: Zhenyu Wang <zhenyuw@linux.intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 33e8eed64423..9794a99d56a7 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -220,7 +220,7 @@  static const struct drm_i915_cmd_descriptor common_cmds[] = {
 	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
 	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   R  ),
-	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   W,
+	CMD(  __MI_LOAD_REGISTER_IMM(1),        SMI,   !F,  0xFF,   W,
 	      .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 }    ),
 	CMD(  MI_STORE_REGISTER_MEM,            SMI,    F,  3,     W | B,
 	      .reg = { .offset = 1, .mask = 0x007FFFFC },
@@ -1182,7 +1182,7 @@  static bool check_cmd(const struct intel_engine_cs *engine,
 					return false;
 				}
 
-				if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) &&
+				if (desc->cmd.value == __MI_LOAD_REGISTER_IMM(1) &&
 				    (offset + 2 > length ||
 				     (cmd[offset + 1] & reg->mask) != reg->value)) {
 					DRM_DEBUG_DRIVER("CMD: Rejected LRI to masked register 0x%08X\n",
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 02adcaf6ebea..052ea1663c15 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1966,9 +1966,9 @@  static int i915_reset_gen7_sol_offsets(struct i915_request *rq)
 	if (IS_ERR(cs))
 		return PTR_ERR(cs);
 
-	*cs++ = MI_LOAD_REGISTER_IMM(4);
+	*cs++ = i915_get_lri_cmd(rq->engine, 4, 0);
 	for (i = 0; i < 4; i++) {
-		*cs++ = i915_mmio_reg_offset(GEN7_SO_WRITE_OFFSET(i));
+		*cs++ = i915_get_lri_reg(rq->engine, GEN7_SO_WRITE_OFFSET(i));
 		*cs++ = 0;
 	}
 	*cs++ = MI_NOOP;
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 9ebf99f3d8d3..6b5a574a4c99 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -1629,7 +1629,8 @@  static void hsw_disable_metric_set(struct drm_i915_private *dev_priv)
  * It's fine to put out-of-date values into these per-context registers
  * in the case that the OA unit has been disabled.
  */
-static void gen8_update_reg_state_unlocked(struct i915_gem_context *ctx,
+static void gen8_update_reg_state_unlocked(struct intel_engine_cs *engine,
+					   struct i915_gem_context *ctx,
 					   u32 *reg_state,
 					   const struct i915_oa_config *oa_config)
 {
@@ -1648,7 +1649,12 @@  static void gen8_update_reg_state_unlocked(struct i915_gem_context *ctx,
 	};
 	int i;
 
-	CTX_REG(reg_state, ctx_oactxctrl, GEN8_OACTXCONTROL,
+	/*
+	 * NB: The LRI instruction is generated by the hardware.
+	 * Should we read it in and check that it has the OFFSET flag set?
+	 */
+
+	CTX_REG(engine, reg_state, ctx_oactxctrl, GEN8_OACTXCONTROL,
 		(dev_priv->perf.oa.period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
 		(dev_priv->perf.oa.periodic ? GEN8_OA_TIMER_ENABLE : 0) |
 		GEN8_OA_COUNTER_RESUME);
@@ -1675,10 +1681,10 @@  static void gen8_update_reg_state_unlocked(struct i915_gem_context *ctx,
 			}
 		}
 
-		CTX_REG(reg_state, state_offset, flex_regs[i], value);
+		CTX_REG(engine, reg_state, state_offset, flex_regs[i], value);
 	}
 
-	CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE,
+	CTX_REG(engine, reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE,
 		gen8_make_rpcs(dev_priv,
 			       &to_intel_context(ctx,
 						 dev_priv->engine[RCS])->sseu));
@@ -1754,7 +1760,7 @@  static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
 		ce->state->obj->mm.dirty = true;
 		regs += LRC_STATE_PN * PAGE_SIZE / sizeof(*regs);
 
-		gen8_update_reg_state_unlocked(ctx, regs, oa_config);
+		gen8_update_reg_state_unlocked(engine, ctx, regs, oa_config);
 
 		i915_gem_object_unpin_map(ce->state->obj);
 	}
@@ -2148,7 +2154,8 @@  void i915_oa_init_reg_state(struct intel_engine_cs *engine,
 
 	stream = engine->i915->perf.oa.exclusive_stream;
 	if (stream)
-		gen8_update_reg_state_unlocked(ctx, reg_state, stream->oa_config);
+		gen8_update_reg_state_unlocked(engine, ctx,
+					       reg_state, stream->oa_config);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 81b80f8fd9ea..e3da616c7a9a 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -255,6 +255,17 @@  static u32 __engine_mmio_base(struct drm_i915_private *i915,
 	return bases[i].base;
 }
 
+bool i915_engine_has_relative_lri(const struct intel_engine_cs *engine)
+{
+	if (INTEL_GEN(engine->i915) < 11)
+		return false;
+
+	if (engine->id == BCS)
+		return false;
+
+	return true;
+}
+
 static void __sprint_engine_name(char *name, const struct engine_info *info)
 {
 	WARN_ON(snprintf(name, INTEL_ENGINE_CS_MAX_NAME, "%s%u",
diff --git a/drivers/gpu/drm/i915/intel_gpu_commands.h b/drivers/gpu/drm/i915/intel_gpu_commands.h
index b96a31bc1080..69dfc593a586 100644
--- a/drivers/gpu/drm/i915/intel_gpu_commands.h
+++ b/drivers/gpu/drm/i915/intel_gpu_commands.h
@@ -118,9 +118,13 @@ 
  *   simply ignores the register load under certain conditions.
  * - One can actually load arbitrary many arbitrary registers: Simply issue x
  *   address/value pairs. Don't overdue it, though, x <= 2^4 must hold!
+ * - Newer hardware supports engine relative addresses but older hardware does
+ *   not. So never call MI_LRI directly, always use the i915_get_lri_cmd()
+ *   and i915_get_lri_reg() helper functions.
  */
-#define MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*(x)-1)
+#define __MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*(x)-1)
 #define   MI_LRI_FORCE_POSTED		(1<<12)
+#define   MI_LRI_ADD_CS_MMIO_START	(1<<19)
 #define MI_STORE_REGISTER_MEM        MI_INSTR(0x24, 1)
 #define MI_STORE_REGISTER_MEM_GEN8   MI_INSTR(0x24, 2)
 #define   MI_SRM_LRM_GLOBAL_GTT		(1<<22)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 34a0866959c5..030c0f9a2ab1 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1438,13 +1438,14 @@  static int emit_pdps(struct i915_request *rq)
 		return PTR_ERR(cs);
 
 	/* Ensure the LRI have landed before we invalidate & continue */
-	*cs++ = MI_LOAD_REGISTER_IMM(2 * GEN8_3LVL_PDPES) | MI_LRI_FORCE_POSTED;
+	*cs++ = i915_get_lri_cmd(engine, 2 * GEN8_3LVL_PDPES,
+				 MI_LRI_FORCE_POSTED);
 	for (i = GEN8_3LVL_PDPES; i--; ) {
 		const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
 
-		*cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i));
+		*cs++ = i915_get_lri_reg(engine, GEN8_RING_PDP_UDW(engine, i));
 		*cs++ = upper_32_bits(pd_daddr);
-		*cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i));
+		*cs++ = i915_get_lri_reg(engine, GEN8_RING_PDP_LDW(engine, i));
 		*cs++ = lower_32_bits(pd_daddr);
 	}
 	*cs++ = MI_NOOP;
@@ -1518,8 +1519,8 @@  gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, u32 *batch)
 	*batch++ = i915_scratch_offset(engine->i915) + 256;
 	*batch++ = 0;
 
-	*batch++ = MI_LOAD_REGISTER_IMM(1);
-	*batch++ = i915_mmio_reg_offset(GEN8_L3SQCREG4);
+	*batch++ = i915_get_lri_cmd(engine, 1, 0);
+	*batch++ = i915_get_lri_reg(engine, GEN8_L3SQCREG4);
 	*batch++ = 0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES;
 
 	batch = gen8_emit_pipe_control(batch,
@@ -1589,13 +1590,14 @@  struct lri {
 	u32 value;
 };
 
-static u32 *emit_lri(u32 *batch, const struct lri *lri, unsigned int count)
+static u32 *emit_lri(struct intel_engine_cs *engine, u32 *batch,
+		     const struct lri *lri, unsigned int count)
 {
 	GEM_BUG_ON(!count || count > 63);
 
-	*batch++ = MI_LOAD_REGISTER_IMM(count);
+	*batch++ = i915_get_lri_cmd(engine, count, 0);
 	do {
-		*batch++ = i915_mmio_reg_offset(lri->reg);
+		*batch++ = i915_get_lri_reg(engine, lri->reg);
 		*batch++ = lri->value;
 	} while (lri++, --count);
 	*batch++ = MI_NOOP;
@@ -1633,7 +1635,7 @@  static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
 	/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */
 	batch = gen8_emit_flush_coherentl3_wa(engine, batch);
 
-	batch = emit_lri(batch, lri, ARRAY_SIZE(lri));
+	batch = emit_lri(engine, batch, lri, ARRAY_SIZE(lri));
 
 	/* WaMediaPoolStateCmdInWABB:bxt,glk */
 	if (HAS_POOLED_EU(engine->i915)) {
@@ -2658,10 +2660,10 @@  static void execlists_init_reg_state(u32 *regs,
 	 * values (including all the missing MI_LOAD_REGISTER_IMM commands that
 	 * we are not initializing here).
 	 */
-	regs[CTX_LRI_HEADER_0] = MI_LOAD_REGISTER_IMM(rcs ? 14 : 11) |
-				 MI_LRI_FORCE_POSTED;
+	regs[CTX_LRI_HEADER_0] = i915_get_lri_cmd(engine, rcs ? 14 : 11,
+						  MI_LRI_FORCE_POSTED);
 
-	CTX_REG(regs, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(engine),
+	CTX_REG(engine, regs, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(engine),
 		_MASKED_BIT_DISABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT) |
 		_MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH));
 	if (INTEL_GEN(dev_priv) < 11) {
@@ -2669,22 +2671,23 @@  static void execlists_init_reg_state(u32 *regs,
 			_MASKED_BIT_DISABLE(CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT |
 					    CTX_CTRL_RS_CTX_ENABLE);
 	}
-	CTX_REG(regs, CTX_RING_HEAD, RING_HEAD(base), 0);
-	CTX_REG(regs, CTX_RING_TAIL, RING_TAIL(base), 0);
-	CTX_REG(regs, CTX_RING_BUFFER_START, RING_START(base), 0);
-	CTX_REG(regs, CTX_RING_BUFFER_CONTROL, RING_CTL(base),
+	CTX_REG(engine, regs, CTX_RING_HEAD, RING_HEAD(base), 0);
+	CTX_REG(engine, regs, CTX_RING_TAIL, RING_TAIL(base), 0);
+	CTX_REG(engine, regs, CTX_RING_BUFFER_START, RING_START(base), 0);
+	CTX_REG(engine, regs, CTX_RING_BUFFER_CONTROL, RING_CTL(base),
 		RING_CTL_SIZE(ring->size) | RING_VALID);
-	CTX_REG(regs, CTX_BB_HEAD_U, RING_BBADDR_UDW(base), 0);
-	CTX_REG(regs, CTX_BB_HEAD_L, RING_BBADDR(base), 0);
-	CTX_REG(regs, CTX_BB_STATE, RING_BBSTATE(base), RING_BB_PPGTT);
-	CTX_REG(regs, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(base), 0);
-	CTX_REG(regs, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(base), 0);
-	CTX_REG(regs, CTX_SECOND_BB_STATE, RING_SBBSTATE(base), 0);
+	CTX_REG(engine, regs, CTX_BB_HEAD_U, RING_BBADDR_UDW(base), 0);
+	CTX_REG(engine, regs, CTX_BB_HEAD_L, RING_BBADDR(base), 0);
+	CTX_REG(engine, regs, CTX_BB_STATE, RING_BBSTATE(base), RING_BB_PPGTT);
+	CTX_REG(engine, regs, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(base), 0);
+	CTX_REG(engine, regs, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(base), 0);
+	CTX_REG(engine, regs, CTX_SECOND_BB_STATE, RING_SBBSTATE(base), 0);
 	if (rcs) {
 		struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
 
-		CTX_REG(regs, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(base), 0);
-		CTX_REG(regs, CTX_RCS_INDIRECT_CTX_OFFSET,
+		CTX_REG(engine, regs, CTX_RCS_INDIRECT_CTX,
+			RING_INDIRECT_CTX(base), 0);
+		CTX_REG(engine, regs, CTX_RCS_INDIRECT_CTX_OFFSET,
 			RING_INDIRECT_CTX_OFFSET(base), 0);
 		if (wa_ctx->indirect_ctx.size) {
 			u32 ggtt_offset = i915_ggtt_offset(wa_ctx->vma);
@@ -2697,7 +2700,8 @@  static void execlists_init_reg_state(u32 *regs,
 				intel_lr_indirect_ctx_offset(engine) << 6;
 		}
 
-		CTX_REG(regs, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(base), 0);
+		CTX_REG(engine, regs, CTX_BB_PER_CTX_PTR,
+			RING_BB_PER_CTX_PTR(base), 0);
 		if (wa_ctx->per_ctx.size) {
 			u32 ggtt_offset = i915_ggtt_offset(wa_ctx->vma);
 
@@ -2706,18 +2710,19 @@  static void execlists_init_reg_state(u32 *regs,
 		}
 	}
 
-	regs[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9) | MI_LRI_FORCE_POSTED;
+	regs[CTX_LRI_HEADER_1] = i915_get_lri_cmd(engine, 9,
+						  MI_LRI_FORCE_POSTED);
 
-	CTX_REG(regs, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(base), 0);
+	CTX_REG(engine, regs, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(base), 0);
 	/* PDP values well be assigned later if needed */
-	CTX_REG(regs, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(engine, 3), 0);
-	CTX_REG(regs, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(engine, 3), 0);
-	CTX_REG(regs, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(engine, 2), 0);
-	CTX_REG(regs, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(engine, 2), 0);
-	CTX_REG(regs, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(engine, 1), 0);
-	CTX_REG(regs, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(engine, 1), 0);
-	CTX_REG(regs, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0), 0);
-	CTX_REG(regs, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0), 0);
+	CTX_REG(engine, regs, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(engine, 3), 0);
+	CTX_REG(engine, regs, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(engine, 3), 0);
+	CTX_REG(engine, regs, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(engine, 2), 0);
+	CTX_REG(engine, regs, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(engine, 2), 0);
+	CTX_REG(engine, regs, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(engine, 1), 0);
+	CTX_REG(engine, regs, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(engine, 1), 0);
+	CTX_REG(engine, regs, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0), 0);
+	CTX_REG(engine, regs, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0), 0);
 
 	if (i915_vm_is_48bit(&ctx->ppgtt->vm)) {
 		/* 64b PPGTT (48bit canonical)
@@ -2733,8 +2738,9 @@  static void execlists_init_reg_state(u32 *regs,
 	}
 
 	if (rcs) {
-		regs[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1);
-		CTX_REG(regs, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE, 0);
+		regs[CTX_LRI_HEADER_2] = i915_get_lri_cmd(engine, 1, 0);
+		CTX_REG(engine, regs, CTX_R_PWR_CLK_STATE,
+			GEN8_R_PWR_CLK_STATE, 0);
 
 		i915_oa_init_reg_state(engine, ctx, regs);
 	}
diff --git a/drivers/gpu/drm/i915/intel_lrc_reg.h b/drivers/gpu/drm/i915/intel_lrc_reg.h
index 5ef932d810a7..40b1142d0d74 100644
--- a/drivers/gpu/drm/i915/intel_lrc_reg.h
+++ b/drivers/gpu/drm/i915/intel_lrc_reg.h
@@ -39,10 +39,10 @@ 
 #define CTX_R_PWR_CLK_STATE		0x42
 #define CTX_END				0x44
 
-#define CTX_REG(reg_state, pos, reg, val) do { \
+#define CTX_REG(engine, reg_state, pos, reg, val) do { \
 	u32 *reg_state__ = (reg_state); \
 	const u32 pos__ = (pos); \
-	(reg_state__)[(pos__) + 0] = i915_mmio_reg_offset(reg); \
+	(reg_state__)[(pos__) + 0] = i915_get_lri_reg((engine), (reg)); \
 	(reg_state__)[(pos__) + 1] = (val); \
 } while (0)
 
diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c
index 331e7a678fb7..0e27d318f0a3 100644
--- a/drivers/gpu/drm/i915/intel_mocs.c
+++ b/drivers/gpu/drm/i915/intel_mocs.c
@@ -322,9 +322,6 @@  static u32 get_entry_control(const struct drm_i915_mocs_table *table,
 /**
  * intel_mocs_init_engine() - emit the mocs control table
  * @engine:	The engine for whom to emit the registers.
- *
- * This function simply emits a MI_LOAD_REGISTER_IMM command for the
- * given table starting at the given address.
  */
 void intel_mocs_init_engine(struct intel_engine_cs *engine)
 {
@@ -378,18 +375,20 @@  static int emit_mocs_control_table(struct i915_request *rq,
 	if (IS_ERR(cs))
 		return PTR_ERR(cs);
 
-	*cs++ = MI_LOAD_REGISTER_IMM(table->n_entries);
+	*cs++ = i915_get_lri_cmd(rq->engine, table->n_entries, 0);
 
 	for (index = 0; index < table->size; index++) {
 		u32 value = get_entry_control(table, index);
 
-		*cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
+		*cs++ = i915_get_lri_reg(rq->engine,
+					 mocs_register(engine, index));
 		*cs++ = value;
 	}
 
 	/* All remaining entries are also unused */
 	for (; index < table->n_entries; index++) {
-		*cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
+		*cs++ = i915_get_lri_reg(rq->engine,
+					 mocs_register(engine, index));
 		*cs++ = unused_value;
 	}
 
@@ -447,7 +446,11 @@  static int emit_mocs_l3cc_table(struct i915_request *rq,
 	if (IS_ERR(cs))
 		return PTR_ERR(cs);
 
-	*cs++ = MI_LOAD_REGISTER_IMM(table->n_entries / 2);
+	/*
+	 * GEN9_LNCFCMOCS is not engine relative, therefore there is no
+	 * need for relative addressing?
+	 */
+	*cs++ = __MI_LOAD_REGISTER_IMM(table->n_entries / 2);
 
 	for (i = 0; i < table->size / 2; i++) {
 		u16 low = get_entry_l3cc(table, 2 * i);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 7f841dba87b3..71cc0c4e2624 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1666,12 +1666,13 @@  static int load_pd_dir(struct i915_request *rq,
 	if (IS_ERR(cs))
 		return PTR_ERR(cs);
 
-	*cs++ = MI_LOAD_REGISTER_IMM(1);
-	*cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine));
+	/* Can these not be merged into a single LRI??? */
+	*cs++ = i915_get_lri_cmd(engine, 1, 0);
+	*cs++ = i915_get_lri_reg(engine, RING_PP_DIR_DCLV(engine));
 	*cs++ = PP_DIR_DCLV_2G;
 
-	*cs++ = MI_LOAD_REGISTER_IMM(1);
-	*cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine));
+	*cs++ = i915_get_lri_cmd(engine, 1, 0);
+	*cs++ = i915_get_lri_reg(engine, RING_PP_DIR_BASE(engine));
 	*cs++ = ppgtt->pd.base.ggtt_offset << 10;
 
 	intel_ring_advance(rq, cs);
@@ -1736,7 +1737,11 @@  static inline int mi_set_context(struct i915_request *rq, u32 flags)
 		if (num_rings) {
 			struct intel_engine_cs *signaller;
 
-			*cs++ = MI_LOAD_REGISTER_IMM(num_rings);
+			/*
+			 * Must use absolute engine address as the register
+			 * write is targeting a different engine.
+			 */
+			*cs++ = __MI_LOAD_REGISTER_IMM(num_rings);
 			for_each_engine(signaller, i915, id) {
 				if (signaller == engine)
 					continue;
@@ -1783,7 +1788,11 @@  static inline int mi_set_context(struct i915_request *rq, u32 flags)
 			struct intel_engine_cs *signaller;
 			i915_reg_t last_reg = {}; /* keep gcc quiet */
 
-			*cs++ = MI_LOAD_REGISTER_IMM(num_rings);
+			/*
+			 * Must use absolute engine address as the register
+			 * write is targeting a different engine.
+			 */
+			*cs++ = __MI_LOAD_REGISTER_IMM(num_rings);
 			for_each_engine(signaller, i915, id) {
 				if (signaller == engine)
 					continue;
@@ -1825,9 +1834,9 @@  static int remap_l3(struct i915_request *rq, int slice)
 	 * here because no other code should access these registers other than
 	 * at initialization time.
 	 */
-	*cs++ = MI_LOAD_REGISTER_IMM(GEN7_L3LOG_SIZE/4);
+	*cs++ = i915_get_lri_cmd(rq->engine, GEN7_L3LOG_SIZE/4, 0);
 	for (i = 0; i < GEN7_L3LOG_SIZE/4; i++) {
-		*cs++ = i915_mmio_reg_offset(GEN7_L3LOG(slice, i));
+		*cs++ = i915_get_lri_reg(rq->engine, GEN7_L3LOG(slice, i));
 		*cs++ = remap_info[i];
 	}
 	*cs++ = MI_NOOP;
@@ -2412,3 +2421,24 @@  int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine)
 
 	return intel_init_ring_buffer(engine);
 }
+
+u32 i915_get_lri_cmd(const struct intel_engine_cs *engine,
+		     u32 word_count, u32 flags)
+{
+	u32 word;
+
+	word = __MI_LOAD_REGISTER_IMM(word_count) | flags;
+
+	if (i915_engine_has_relative_lri(engine))
+		word |= MI_LRI_ADD_CS_MMIO_START;
+
+	return word;
+}
+
+u32 i915_get_lri_reg(const struct intel_engine_cs *engine, i915_reg_t reg)
+{
+	if (!i915_engine_has_relative_lri(engine))
+		return i915_mmio_reg_offset(reg);
+
+	return i915_mmio_reg_offset(reg) - engine->mmio_base;
+}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 710ffb221775..10613d904486 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -1086,4 +1086,9 @@  static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
 
 #endif
 
+bool i915_engine_has_relative_lri(const struct intel_engine_cs *engine);
+u32 i915_get_lri_cmd(const struct intel_engine_cs *engine, u32 word_count,
+		     u32 flags);
+u32 i915_get_lri_reg(const struct intel_engine_cs *engine, i915_reg_t reg);
+
 #endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c
index 15f4a6dee5aa..3347254a8605 100644
--- a/drivers/gpu/drm/i915/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/intel_workarounds.c
@@ -609,9 +609,9 @@  int intel_engine_emit_ctx_wa(struct i915_request *rq)
 	if (IS_ERR(cs))
 		return PTR_ERR(cs);
 
-	*cs++ = MI_LOAD_REGISTER_IMM(wal->count);
+	*cs++ = i915_get_lri_cmd(rq->engine, wal->count, 0);
 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
-		*cs++ = i915_mmio_reg_offset(wa->reg);
+		*cs++ = i915_get_lri_reg(rq->engine, wa->reg);
 		*cs++ = wa->val;
 	}
 	*cs++ = MI_NOOP;