diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 96e135b..40b8063 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -20886,15 +20886,29 @@ static bool svc_ddx_notif_idle(const struct svc_channel *ch) * captured a class-2D NOTIFY VA therefore owns a kick-idle page for slots * 0..3; the RC-watchdog/beef kernel channels (which never arm notify2d) * keep the r864 behaviour. + * + * CONT.457: the "slot 0 status must be 0xFFFF" reading of the r1706/r1716 + * probes is RETRACTED - ground truth says slot 0 is the ERROR notifier + * and 0xFFFF there aborts the client as a channel error (see the + * correction note below svc_kick_idle_page). Do not re-add the write. */ static bool svc_kick_idle_page(const struct svc_channel *ch) { return svc_ddx_notif_idle(ch) || ch->notify2d_va != 0; } -static u32 svc_ddx_idle_log; -static u64 svc_ddx_idle_n; - +/* + * CONT.457 correction (570.144 ground truth; nvidia_drv.so disassembly): + * slot 0 of an nvPush channel's notifier block is the ERROR notifier + * (raw index 0). nvPushCheckChannelError reads its status u16 at +0x0e + * (DDX nvidia_drv.so+0xb66c0) and 0xFFFF means "channel error" - every + * nvPushWaitForNotifier/idle wait then aborts as errored. There is no + * "pb_kickIfIdle" in 570.144; the DDX DMA-idle test reads the + * progress-tracker semaphore word, not this slot. Never fabricate + * 0xFFFF into slot 0's status (the CONT.408/409 restore did), and never + * ack it from here either - a real 0x8000 arm on slot 0 is handled by + * the class-2D completion sweep (svc_client_slot_sweep). + */ static void svc_notify2d_keepalive(struct nv_vgpu_device *vgpu, struct svc_channel *ch) { @@ -20911,36 +20925,18 @@ static void svc_notify2d_keepalive(struct nv_vgpu_device *vgpu, u16 st; memcpy(&st, slots + slot * 16 + 14, 2); + /* Slot 0 is the nvPush ERROR notifier: leave it untouched. */ + if (slot == 0 && svc_kick_idle_page(ch)) + continue; /* - * CONT.408: on the X DDX family 0xFFFF is the kick-idle - * marker pb_kickIfIdle requires, never an arm. Restore it - * on slot 0 (the kick gate) instead of zeroing it, and only - * ack a real 0x8000 arm on the other slots. + * CONT.408/409: on kick-idle pages slots 1..3 carry class-2D + * user notifiers; ack only a real 0x8000 arm. Non-kick pages + * (RC watchdog / beef) keep the r864 behaviour: 0xFFFF or + * 0x8000 -> zeroed completion. */ if (svc_kick_idle_page(ch)) { - if (slot == 0) { - u16 idle = 0xffff; - - if (st == 0xffff) - continue; - if (svc_write_ap(vgpu, - ch->notifier_pa, - ch->notifier_as, &idle, - sizeof(idle))) - continue; - svc_ddx_idle_n++; - if (svc_ddx_idle_log < 32) { - svc_ddx_idle_log++; - pr_info("sema-chan: kick idle h=0x%x pa=0x%llx restored 0x%04x -> 0xffff (n=%llu)\n", - ch->h_object, ch->notifier_pa, - st, - (unsigned long long) - svc_ddx_idle_n); - } - continue; - } if (!(st & 0x8000)) - continue; /* 0xffff is idle here */ + continue; } else if (st != 0xffff && !(st & 0x8000)) { continue; /* not armed - nothing to ack */ } |
