diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index b025dde..17b2ae4 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -153,6 +153,8 @@ struct svc_channel { u32 logged_expected; /* last pool value logged (rate limit) */ unsigned long rescue_last; /* rate limit for the full-RAM rescue scan */ u32 rescue_fail; /* consecutive failed rescues for the entry */ + u32 op_retry; /* passes an entry has been held while an operand + * targeted scan was in progress (0 = none) */ unsigned long defer_since; /* first failure of the pending GR entry * (0 = none): the entry is left pending * for the GR grace window so a late @@ -355,6 +357,7 @@ struct sema_svc { u64 lda_log; /* LAUNCH_DMA inventory budget */ u64 sem256_log; /* 256-byte op trace budget */ u64 op_tr_log; /* operand targeted-resolve budget */ + u32 op_tr_pending; /* an operand's targeted scan is in progress */ u64 copy_watch_log; /* sema_copy_watch log budget */ u64 copy_pat_log; /* sema_copy_pat log budget */ u64 copy_dst_log; /* sema_copy_dst log budget */ @@ -2017,6 +2020,14 @@ static int svc_op_translate(struct nv_vgpu_device *vgpu, u64 va, u64 *addr, } return 0; } + /* + * The RAM scan is incremental (-EAGAIN = scan slice done, keep + * calling for this same page). Tell the pump so it can hold the entry + * and retry it while the scan is in progress: a copy whose operand is + * only resolvable by the scan needs several passes. + */ + if (svc_resolve_in_progress(va & ~0xfffULL)) + svc.op_tr_pending = 1; return -ENOENT; } @@ -4823,6 +4834,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) u64 rel_before = svc_rel_va_seen; bool rel_seen; + svc.op_tr_pending = 0; svc_decode_stream(vgpu, pb, len, 0, allow_ops || injected, @@ -4830,6 +4842,26 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) idx, va, injected); + /* + * An operand of this push + * failed to translate but a + * targeted RAM scan for it is + * in progress: hold the entry + * and retry it next pass (the + * scan is incremental), like + * the unreadable-push hold. + * Bounded so a scan that finds + * nothing cannot wedge the + * channel. + */ + if (svc.op_tr_pending && + ch->op_retry < 24) { + ch->op_retry++; + svc.gpfifo_nomap++; + kfree(pb); + break; + } + ch->op_retry = 0; rel_seen = (svc_rel_va_seen != rel_before); if (rel_seen) ch->last_rel_va = |
