drm/xe: Prepare to emit non-register state while recording default LRC
authorMatt Roper <matthew.d.roper@intel.com>
Wed, 25 Oct 2023 15:17:34 +0000 (08:17 -0700)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:43:22 +0000 (11:43 -0500)
On some platforms we need to emit some non-register state while
recording an engine class' default LRC.  Add the infrastructure to
support this; actual per-platform tables will be added in future
patches.

v2:
 - Checkpatch whitespace fix
 - Add extra assertion to ensure num_dw != 0.  (Bala)

Reviewed-by: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Link: https://lore.kernel.org/r/20231025151732.3461842-6-matthew.d.roper@intel.com
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_gt.c
drivers/gpu/drm/xe/xe_lrc.c
drivers/gpu/drm/xe/xe_lrc.h

index 74e1f47bd40114be58c4b2c37ded755bc0d3548b..8618275b1877f3b1b4d1fc36b2901ef554078efc 100644 (file)
@@ -136,7 +136,13 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
        long timeout;
        int count = 0;
 
-       bb = xe_bb_new(gt, SZ_4K, false);       /* Just pick a large BB size */
+       if (q->hwe->class == XE_ENGINE_CLASS_RENDER)
+               /* Big enough to emit all of the context's 3DSTATE */
+               bb = xe_bb_new(gt, xe_lrc_size(gt_to_xe(gt), q->hwe->class), false);
+       else
+               /* Just pick a large BB size */
+               bb = xe_bb_new(gt, SZ_4K, false);
+
        if (IS_ERR(bb))
                return PTR_ERR(bb);
 
@@ -173,6 +179,8 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
                }
        }
 
+       xe_lrc_emit_hwe_state_instructions(q, bb);
+
        job = xe_bb_create_job(q, bb);
        if (IS_ERR(job)) {
                xe_bb_free(bb, NULL);
index 332fc0602074ec6a46c75a5d7174f04ec29d72bb..184707223098ce9f0073ed7995ac234bfd54ff93 100644 (file)
@@ -12,6 +12,7 @@
 #include "regs/xe_gt_regs.h"
 #include "regs/xe_lrc_layout.h"
 #include "regs/xe_regs.h"
+#include "xe_bb.h"
 #include "xe_bo.h"
 #include "xe_device.h"
 #include "xe_drm_client.h"
@@ -1108,3 +1109,47 @@ void xe_lrc_dump_default(struct drm_printer *p,
                remaining_dw -= num_dw;
        }
 }
+
+struct instr_state {
+       u32 instr;
+       u16 num_dw;
+};
+
+void xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, struct xe_bb *bb)
+{
+       struct xe_gt *gt = q->hwe->gt;
+       struct xe_device *xe = gt_to_xe(gt);
+       const struct instr_state *state_table = NULL;
+       int state_table_size = 0;
+
+       /*
+        * At the moment we only need to emit non-register state for the RCS
+        * engine.
+        */
+       if (q->hwe->class != XE_ENGINE_CLASS_RENDER)
+               return;
+
+       switch (GRAPHICS_VERx100(xe)) {
+       default:
+               xe_gt_dbg(gt, "No non-register state to emit on graphics ver %d.%02d\n",
+                         GRAPHICS_VER(xe), GRAPHICS_VERx100(xe) % 100);
+               return;
+       }
+
+       for (int i = 0; i < state_table_size; i++) {
+               u32 instr = state_table[i].instr;
+               u16 num_dw = state_table[i].num_dw;
+               bool is_single_dw = ((instr & GFXPIPE_PIPELINE) == PIPELINE_SINGLE_DW);
+
+               xe_gt_assert(gt, (instr & XE_INSTR_CMD_TYPE) == XE_INSTR_GFXPIPE);
+               xe_gt_assert(gt, num_dw != 0);
+               xe_gt_assert(gt, is_single_dw ^ (num_dw > 1));
+
+               bb->cs[bb->len] = instr;
+               if (!is_single_dw)
+                       bb->cs[bb->len] |= (num_dw - 2);
+
+               bb->len += num_dw;
+       }
+}
+
index a7056eda5e0c4f674bf42539defd75b414089e30..28b1d3f404d4ff4876c4c58af382d48d453963ca 100644 (file)
@@ -8,6 +8,7 @@
 #include "xe_lrc_types.h"
 
 struct drm_printer;
+struct xe_bb;
 struct xe_device;
 struct xe_exec_queue;
 enum xe_engine_class;
@@ -52,4 +53,6 @@ void xe_lrc_dump_default(struct drm_printer *p,
                         struct xe_gt *gt,
                         enum xe_engine_class);
 
+void xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, struct xe_bb *bb);
+
 #endif