diff options
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index c1b98f3..37b2200 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -512,11 +512,14 @@ static int gsp_rm_send_flags(struct gsp_emu_context *ctx, u32 function, : GSPRM_EVENT_BURST_MAX; /* m171: expire the budget by wall time so a long-ago - * flood can never starve a fresh completion post. */ + * flood can never starve a fresh completion post. Only an + * admitted record moves the window: a refused attempt that + * retried (the display completion retry runs every 250 ms) + * must not keep the window perpetually fresh, or the budget + * would never expire and the retry would livelock. */ if (time_after(jiffies, rm->event_burst_at + GSPRM_EVENT_BURST_WINDOW)) rm->event_burst = 0; - rm->event_burst_at = jiffies; if (rm->event_burst >= cap) { rm->events_dropped++; if (rm->events_dropped <= 8 || @@ -529,6 +532,7 @@ static int gsp_rm_send_flags(struct gsp_emu_context *ctx, u32 function, kfree(buf); return -EAGAIN; } + rm->event_burst_at = jiffies; rm->event_burst++; } else { rm->event_burst = 0; @@ -850,7 +854,8 @@ static u32 gsp_rm_ev_function(void) * Safe to call from the progress service's thread: the status queue write is * serialized by rm->stat_lock and the guest is woken with MSI-X vector 0. */ -int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) +static int gsp_rm_post_channel_event_common(struct nv_vgpu_device *vgpu, + u32 h_src, bool force) { struct gsp_emu_context *ctx = vgpu ? vgpu->gsp_comm_ctx : NULL; struct gsp_rm_emu *rm; @@ -908,7 +913,8 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) * client's dispatcher re-reads channel state on any * event - and the 0.5 s hint re-posts late waiters. */ - if (time_before(jiffies, rm->events[i].last_post + + if (!force && + time_before(jiffies, rm->events[i].last_post + GSPRM_EVENT_HINT_DEDUP)) continue; gsp_rm_fill_ev_payload(rm, i, payload); @@ -940,6 +946,28 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) return posted ? 0 : -ENOENT; } +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); +} + +/* + * Force a completion wake-up past the hint dedup. The 250 ms dedup assumes a + * recent post already woke the client, but a waiter that arrived after that + * post misses it, and a busy event stream keeps refreshing every event's + * stamp so the coalesced completion is never delivered (r1649: the X server's + * display UPDATE completion was refused - the coincident hint returned + * -EAGAIN because every event was inside the window - and the flip wait spun + * in the nvidia ioctl forever). Callers use this only for a refused + * completion edge, rate-limited by their own retry window; the event burst + * cap and the status-ring free-space discipline still apply inside + * gsp_rm_send_flags(). + */ +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); +} + /* * r623 experiment: deliver a synthetic OS_ERROR_LOG (0x1006) record to the * guest's RM queue - the error report a real GSP sends into the client's |
