summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_display_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_display_engine.c')
-rw-r--r--kernel/gsp_display_engine.c75
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;