summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 983fecb..2d66912 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -3090,9 +3090,43 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
out_params_size = req.paramsSize;
if (req.paramsSize &&
req.paramsSize + GSP_RM_CTRL_HDR_SIZE <=
- GSPRM_MAX_SINGLE_ELEM_DATA)
- memcpy(reply + GSP_RM_CTRL_HDR_SIZE, pp,
- req.paramsSize);
+ GSPRM_MAX_SINGLE_ELEM_DATA) {
+ u8 *rp = reply + GSP_RM_CTRL_HDR_SIZE;
+ u32 cleared = 0;
+
+ memcpy(rp, pp, req.paramsSize);
+ /*
+ * The caller (kgrobjPromoteContext_IMPL) marks each ctx
+ * buffer initialized ONLY when the REPLY's bInitialize is
+ * clear:
+ * if (!params.promoteEntry[i].bInitialize)
+ * continue;
+ * kgrctxMarkCtxBufferInitialized(...);
+ * Echoing the request back keeps bInitialize set forever,
+ * so the RM re-promotes the same context on every pass and
+ * never submits the channel's first work (the client's
+ * CUDA init then spins with an empty GR ring). Clear the
+ * flag on the reply to acknowledge the (host-side)
+ * initialization.
+ */
+ if (req.paramsSize >= 48) {
+ u32 ec = 0, k;
+
+ memcpy(&ec, pp + 40, 4);
+ for (k = 0; k < ec &&
+ 48u + (k + 1u) * 32u <= req.paramsSize;
+ k++) {
+ if (rp[48 + k * 32 + 30]) {
+ rp[48 + k * 32 + 30] = 0;
+ cleared++;
+ }
+ }
+ }
+ if (cleared)
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: PROMOTE_CTX reply acked init on %u entr%s (bInitialize cleared)",
+ cleared, cleared == 1 ? "y" : "ies");
+ }
break;
}