diff options
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 86 |
1 files changed, 83 insertions, 3 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 4ea6839..9d9f351 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -817,6 +817,17 @@ unsigned gsp_rm_ev_cl; * dispatch. */ unsigned gsp_rm_ev_func; +/* + * r1767: gate the r1765 flip-event association (hSrcResource == 0 -> + * alloc-header hParent). Default 0 keeps the pre-r1766 event semantics; + * the RCA exonerated the association from the r1766 soft-locks but not + * from the r1766 ISR crash class, so it stays off until validated + * end-to-end. + */ +static bool gsp_rm_ev_assoc; /* default 0: pre-r1766 event semantics */ +module_param_named(ev_assoc, gsp_rm_ev_assoc, bool, 0644); +MODULE_PARM_DESC(ev_assoc, + "associate hSrcResource==0 events with their alloc parent (r1765 flip-event fix; default 0)"); static void gsp_rm_fill_ev_payload(const struct gsp_rm_emu *rm, u32 i, u8 *payload) @@ -870,7 +881,7 @@ static u32 gsp_rm_ev_function(void) * serialized by rm->stat_lock and the guest is woken with MSI-X vector 0. */ static int gsp_rm_post_channel_event_common(struct nv_vgpu_device *vgpu, - u32 h_src, bool force) + u32 h_src, bool force, bool strict) { struct gsp_emu_context *ctx = vgpu ? vgpu->gsp_comm_ctx : NULL; struct gsp_rm_emu *rm; @@ -908,6 +919,18 @@ static int gsp_rm_post_channel_event_common(struct nv_vgpu_device *vgpu, } /* + * r1765: strict mode is the display engine's 1:1 contract - a + * channel-scoped completion posts ONLY the events registered on the + * channel (a real RM fires the channel's own event list on AWAKEN). + * Never fall through to the all-events shotgun for such a post: the + * shotgun coalesces flip completions and lets unrelated completions + * nudge the flip event (stray FLIP_OCCURRED -> the nvidia-drm + * dequeue WARN). The caller's retry pump re-posts a refused edge. + */ + if (!posted && strict) + return -ENOENT; + + /* * Fallback when the event's source object could not be associated with * the channel: nudge every registered event. The client's dispatcher * re-reads each channel's state on any event, so a spurious wake-up is @@ -918,6 +941,17 @@ static int gsp_rm_post_channel_event_common(struct nv_vgpu_device *vgpu, if (!rm->events[i].valid) continue; /* + * r1765: display-channel events are driven 1:1 by + * the display engine and must not be nudged by + * unrelated completions. The predicate answers + * false in the legacy default mode (gated on + * disp_events_strict), so this is inert unless the + * strict path is enabled. + */ + if (gsp_disp_engine_owns_object(vgpu, + rm->events[i].h_src)) + continue; + /* * r580: apply the hint dedup to the per-completion * shotgun. Every completion posts ALL registered * events (the ABI gives no source association), so a @@ -963,7 +997,17 @@ static int gsp_rm_post_channel_event_common(struct nv_vgpu_device *vgpu, int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) { - return gsp_rm_post_channel_event_common(vgpu, h_src, false); + return gsp_rm_post_channel_event_common(vgpu, h_src, false, false); +} + +/* + * r1765 strict variants (display engine, disp_events_strict=1): exact-match + * only - no all-events fallback; -ENOENT rather than a shotgun when the + * channel has no registered event (yet). + */ +int gsp_rm_post_channel_event_strict(struct nv_vgpu_device *vgpu, u32 h_src) +{ + return gsp_rm_post_channel_event_common(vgpu, h_src, false, true); } /* @@ -980,7 +1024,13 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) */ int gsp_rm_post_channel_event_force(struct nv_vgpu_device *vgpu, u32 h_src) { - return gsp_rm_post_channel_event_common(vgpu, h_src, true); + return gsp_rm_post_channel_event_common(vgpu, h_src, true, false); +} + +int gsp_rm_post_channel_event_force_strict(struct nv_vgpu_device *vgpu, + u32 h_src) +{ + return gsp_rm_post_channel_event_common(vgpu, h_src, true, true); } /* @@ -1114,6 +1164,15 @@ int gsp_rm_post_all_events(struct nv_vgpu_device *vgpu) for (i = 0; i < rm->events_n; i++) { if (!rm->events[i].valid) continue; + /* + * r1765: the hint must not nudge display-channel events - + * they are driven 1:1 by the display engine's UPDATE + * completions. False in the legacy default mode (the + * predicate is gated on disp_events_strict), so the hint is + * unchanged unless the strict path is enabled. + */ + if (gsp_disp_engine_owns_object(vgpu, rm->events[i].h_src)) + continue; if (time_before(jiffies, rm->events[i].last_post + GSPRM_EVENT_HINT_DEDUP)) { skipped++; @@ -3762,6 +3821,27 @@ static void gsp_rm_handle_rm_alloc(struct gsp_emu_context *ctx, memcpy(¬ify_index, params + 12, 4); memcpy(&data64, params + 16, 8); } + /* + * r1765: the modern NVKMS/kernel events are registered + * with hSrcResource = 0 in NV0005_ALLOC_PARAMETERS; + * their real source is the ALLOC parent object (the + * event is allocated ON the channel handle: + * hParent=0x1001b for hEvent=0x1007a, verified live). + * With h_src = 0 the exact-match post path never fired + * for display completions and every flip rode the + * all-events fallback, which coalesced/delayed flips + * and let ANY other completion nudge the flip event + * (stray FLIP_OCCURRED -> the nvidia-drm dequeue + * WARN). Fall back to the alloc header's hParent when + * the params name no source resource. + * + * r1767: gated behind ev_assoc (default off) until the + * flip fix is validated end-to-end - the r1767 RCA + * exonerated the association from the r1766 soft-lock + * class, but not from the r1766 ISR crash class. + */ + if (gsp_rm_ev_assoc && h_src == 0 && hp != 0 && hp != hc) + h_src = hp; rm->events[slot].h_src = h_src; rm->events[slot].h_event = ho; rm->events[slot].h_client = hc; |
