summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c32
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 =