diff options
Diffstat (limited to 'kernel/gsp_display_engine.c')
| -rw-r--r-- | kernel/gsp_display_engine.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c index c97458c..98f85fe 100644 --- a/kernel/gsp_display_engine.c +++ b/kernel/gsp_display_engine.c @@ -212,6 +212,19 @@ static unsigned gsp_disp_events = 1; module_param_named(disp_events, gsp_disp_events, uint, 0644); MODULE_PARM_DESC(disp_events, "Post the channel completion event on an armed UPDATE (default 1)"); +/* + * r1765: strict display-event delivery. Default 0 keeps the legacy + * behaviour bit-for-bit (full A/B revert); when set, an armed UPDATE posts + * only to the events registered on that channel (no all-events fallback), + * and unrelated completions/the 0.5 s hint skip display-channel events + * (see gsp_disp_engine_owns_object()). Live A/B: echo 1 > + * /sys/module/vgsp/parameters/disp_events_strict. + */ +static unsigned gsp_disp_events_strict = 0; +module_param_named(disp_events_strict, gsp_disp_events_strict, uint, 0644); +MODULE_PARM_DESC(disp_events_strict, + "Deliver a display UPDATE completion only to events registered on that channel, no all-events fallback (default 0 = legacy; 1 = r1765 strict)"); + static unsigned long long gsp_disp_notifier_pa; module_param_named(disp_notifier_pa, gsp_disp_notifier_pa, ullong, 0644); MODULE_PARM_DESC(disp_notifier_pa, "Explicit notifier surface guest PA override (0 = resolve from the display instance table)"); @@ -1010,6 +1023,36 @@ void gsp_disp_engine_channel_add(struct nv_vgpu_device *vgpu, u32 hclass, } /* + * r1765 flip-event shield predicate: is @h_object a registered display + * channel object of @vgpu whose events must stay off the all-events + * shotgun? Called by gsp_rm_emulation.c before nudging an event in the + * fallback paths. Only meaningful while disp_events_strict is enabled - + * with the legacy default (0) this always returns false, so every shield + * site is inert and the shotgun path is unchanged. + */ +bool gsp_disp_engine_owns_object(struct nv_vgpu_device *vgpu, u32 h_object) +{ + unsigned long flags; + bool owned = false; + int i; + + if (!gsp_disp_engine || !gsp_disp_events_strict || !vgpu || !h_object) + return false; + + spin_lock_irqsave(&disp.lock, flags); + for (i = 0; i < GSP_DISP_MAX_CHANNELS; i++) { + if (disp.ch[i].valid && disp.ch[i].vgpu == vgpu && + disp.ch[i].h_object == h_object) { + owned = true; + break; + } + } + spin_unlock_irqrestore(&disp.lock, flags); + return owned; +} +EXPORT_SYMBOL_GPL(gsp_disp_engine_owns_object); + +/* * Apply one parsed method. Only the completion-notifier programming and the * UPDATE completion point carry engine semantics for the boot; everything * else is state the engine would apply to the display pipeline (head/window/ @@ -1138,7 +1181,16 @@ static void gsp_disp_method(struct nv_vgpu_device *vgpu, * layer retry (Xorg spun there at 100 % in r1665). */ if (gsp_disp_events && ch->h_object && wrote) { - int rc = gsp_rm_post_channel_event(vgpu, ch->h_object); + /* + * r1765: strict mode delivers only to the events + * registered on this channel; a miss returns -ENOENT + * and the pump retries instead of shotgunning every + * registered event. + */ + int rc = (gsp_disp_events_strict ? + gsp_rm_post_channel_event_strict : + gsp_rm_post_channel_event)(vgpu, + ch->h_object); if (!rc) { ch->notifier_posts++; @@ -1430,7 +1482,12 @@ void gsp_disp_engine_pump(struct nv_vgpu_device *vgpu) */ if (s->event_pending && s->h_object && gsp_disp_events && time_after_eq(jiffies, s->event_retry_at)) { - if (!gsp_rm_post_channel_event_force(vgpu, s->h_object)) { + /* r1765: retry with the same strict/legacy entry + * point the UPDATE post used. */ + if (!(gsp_disp_events_strict ? + gsp_rm_post_channel_event_force_strict : + gsp_rm_post_channel_event_force)(vgpu, + s->h_object)) { s->event_pending = false; s->notifier_posts++; pr_info("h=0x%x UPDATE completion event re-posted after deferral (posts=%u)\n", |
