diff options
Diffstat (limited to 'kernel/gsp_display_engine.c')
| -rw-r--r-- | kernel/gsp_display_engine.c | 75 |
1 files changed, 48 insertions, 27 deletions
diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c index f96fc6a..c7c9dca 100644 --- a/kernel/gsp_display_engine.c +++ b/kernel/gsp_display_engine.c @@ -101,6 +101,11 @@ #define GSP_DISP_NOTIFIER_CTRL_NOTIFY BIT(12) /* The CONTROL offset field is in 16-byte units; expose it in bytes. */ #define GSP_DISP_NOTIFIER_CTRL_OFFSET(c) ((((c) >> 4) & 0xff) * 16) +/* Coalesce a refused completion wake-up, then re-post it. Must be at least + * the RM event hint dedup window (HZ / 4 = 250 ms) so the retry is not + * coalesced into the same post that starved it; at most four attempts/s per + * waiting channel. */ +#define GSP_DISP_EVENT_RETRY_MS 250 /* Display instance memory (v03_00 layout). */ #define GSP_DISP_INST_HASH_OFF 0x0000 @@ -136,6 +141,7 @@ struct gsp_disp_chan { u32 notifier_writes; u32 notifier_posts; bool event_pending; /* completion event send failed; retry in pump */ + unsigned long event_retry_at; /* next forced re-post attempt */ u32 event_drop_logs; u32 update_logs; @@ -1115,6 +1121,8 @@ static void gsp_disp_method(struct nv_vgpu_device *vgpu, * pump instead of giving up. */ ch->event_pending = true; + ch->event_retry_at = jiffies + + msecs_to_jiffies(GSP_DISP_EVENT_RETRY_MS); if (ch->event_drop_logs < 8) { ch->event_drop_logs++; pr_info("h=0x%x UPDATE completion event deferred rc=%d (hObj=0x%x)\n", @@ -1353,39 +1361,51 @@ void gsp_disp_engine_pump(struct nv_vgpu_device *vgpu) s->hclass, s->instance, put, s->consumed, s->ctl_off); } - if (put == s->consumed) - continue; - - gsp_disp_run(vgpu, s, put); + if (put != s->consumed) { + gsp_disp_run(vgpu, s, put); - /* - * Publish our read pointer; the driver's nvEvoMakeRoom and - * EvoCoreReadGet rely on it to reuse the ring. - */ - gsp_disp_bar0_write(vgpu, s->ctl_off + GSP_DISP_REG_GET, - s->consumed); - get = gsp_disp_bar0_read(vgpu, - s->ctl_off + GSP_DISP_REG_GET); - - if (disp.log_budget < 4096) { - u64 age = (u64)(now - disp.boot_jiffies) * - (NSEC_PER_SEC / HZ); - - disp.log_budget++; - pr_info("pump h=0x%x inst=%u put=0x%x get=0x%x consumed=0x%x at %llu ms\n", - s->hclass, s->instance, put, get, s->consumed, - div_u64(age, 1000000)); + /* + * Publish our read pointer; the driver's nvEvoMakeRoom + * and EvoCoreReadGet rely on it to reuse the ring. + */ + gsp_disp_bar0_write(vgpu, s->ctl_off + GSP_DISP_REG_GET, + s->consumed); + get = gsp_disp_bar0_read(vgpu, + s->ctl_off + GSP_DISP_REG_GET); + + if (disp.log_budget < 4096) { + u64 age = (u64)(now - disp.boot_jiffies) * + (NSEC_PER_SEC / HZ); + + disp.log_budget++; + pr_info("pump h=0x%x inst=%u put=0x%x get=0x%x consumed=0x%x at %llu ms\n", + s->hclass, s->instance, put, get, + s->consumed, div_u64(age, 1000000)); + } } /* - * Retry a completion event whose send was refused (burst - * cap / transient queue state). Runs outside disp.lock: - * the post takes the RM status-queue lock. + * Retry a completion event whose send was refused (burst cap / + * transient queue state, or the hint dedup coalescing it into a + * post the waiter never saw). Runs outside disp.lock (the post + * takes the RM status-queue lock) and on idle passes too: the + * fatal case is an UPDATE that is the channel's last push, so a + * retry gated on new work never runs (r1649). The forced post + * ignores the per-event hint dedup; the retry window bounds it + * to one attempt per 250 ms per waiting channel while the burst + * cap still guards the status ring. */ if (s->event_pending && s->h_object && gsp_disp_events && - !gsp_rm_post_channel_event(vgpu, s->h_object)) { - s->event_pending = false; - s->notifier_posts++; + time_after_eq(jiffies, s->event_retry_at)) { + if (!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", + s->hclass, s->notifier_posts); + } else { + s->event_retry_at = jiffies + + msecs_to_jiffies(GSP_DISP_EVENT_RETRY_MS); + } } /* Write the bookkeeping back if the slot still names this @@ -1412,6 +1432,7 @@ void gsp_disp_engine_pump(struct nv_vgpu_device *vgpu) c->notifier_writes = s->notifier_writes; c->notifier_posts = s->notifier_posts; c->event_pending = s->event_pending; + c->event_retry_at = s->event_retry_at; c->event_drop_logs = s->event_drop_logs; c->update_logs = s->update_logs; c->logged_update = s->logged_update; |
