diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 40 |
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; } |
