summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_phys_booter.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index fa68945..d20ee7e 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -267,10 +267,17 @@ bool gsp_phys_boot_requested(void)
* NVOS04_FLAGS_CHANNEL_SKIP_SCRUBBER bit 23 (alloc/alloc_channel.h:223-225);
* the RM's own internal CE channel sets it
* (mem_mgr/arch/maxwell/mem_utils_gm107.c:1186-1283). Kernel privilege is
- * internalFlags 1:0 = 2 and GSP-ownership is internalFlags bit 6 = 0x40
- * (generated/g_kernel_channel_nvoc.h:185-203).
+ * internalFlags 1:0 = 2 (generated/g_kernel_channel_nvoc.h:185-203).
*/
#define GSP_PHYS_RMCALL_CHANNEL_FLAG_SKIP_SCRUBBER (1u << 23)
+
+/*
+ * BANNED - do not use: internalFlags bit 6 = 0x40 marks the channel as
+ * GSP-owned. A live run with this bit set wedged the GSP-RM task: the alloc
+ * RPC never replied, every later RPC timed out, and the fail-safe held the
+ * device until reboot. No channel variant may set this bit. The define is
+ * kept only to document the prohibition where the bit was learned.
+ */
#define GSP_PHYS_RMCALL_CHANNEL_INTERNALFLAGS_GSP_OWNED 0x40u
/* Buffers the ladder allocates and registers in stage 2. */
@@ -817,7 +824,8 @@ static struct gsp_phys_boot_stage {
u32 rmcall_subdevice;
u32 rmcall_tsg;
u32 rmcall_channel;
- u32 rmcall_channel_variant; /* winning stage-3 variant (1..4, 0=none) */
+ u32 rmcall_channel_variant; /* winning stage-3 variant (1..N, 0=none) */
+ bool rmcall_channel_server_mem; /* winning variant had server-allocated mem */
u32 rmcall_token; /* GET_WORK_SUBMIT_TOKEN result */
struct pci_dev *pdev; /* borrowed claim pdev (valid while primed) */
struct gsp_phys_boot_chunk rmcall_chunks[GSP_PHYS_RMCALL_BUF_COUNT];
@@ -1328,6 +1336,7 @@ static void gsp_phys_rmcall_reset(void)
boot_stage.rmcall_tsg = 0;
boot_stage.rmcall_channel = 0;
boot_stage.rmcall_channel_variant = 0;
+ boot_stage.rmcall_channel_server_mem = false;
boot_stage.rmcall_token = 0;
for (i = 0; i < GSP_PHYS_RMCALL_BUF_COUNT; i++) {
boot_stage.rmcall_mem_handles[i] = 0;
@@ -4682,13 +4691,14 @@ gsp_phys_rmcall_mem_desc(u32 index)
}
/*
- * Channel-alloc variants tried in order after the TSG exists. V1/V2 mirror the
+ * Channel-alloc variants tried in order after the TSG exists. V1 mirrors the
* RM's internal CE channel template (mem_utils_gm107.c:1186-1283: device
- * parent, hDeviceId, SKIP_SCRUBBER flag, PRIVILEGE_KERNEL internalFlags;
- * V2 adds GSP_OWNED). V3 keeps the reference shape but zeroes the memdescs and
- * GPFIFO so the server allocates channel memory itself (no client ring to
- * fill, so stage 4 refuses). V4 is the previously tried control shape
- * (TSG parent, flags 0).
+ * parent, hDeviceId, SKIP_SCRUBBER flag, PRIVILEGE_KERNEL internalFlags).
+ * V2 keeps the reference shape but zeroes the memdescs and GPFIFO so the
+ * server allocates channel memory itself (no client ring to fill, so stage 4
+ * refuses). V3 is the previously tried control shape (TSG parent, flags 0).
+ * A GSP-owned internalFlags variant used to sit between V1 and V2; it wedged
+ * the RM task and is removed so it can never be selected again.
*/
struct gsp_phys_rmcall_channel_variant {
const char *name;
@@ -4705,11 +4715,6 @@ gsp_phys_rmcall_channel_variants[] = {
GSP_PHYS_RMCALL_CHANNEL_FLAG_SKIP_SCRUBBER,
GSP_PHYS_RMCALL_CHANNEL_INTERNALFLAGS_PRIV_KERNEL, false,
GSP_PHYS_RMCALL_HANDLE_CHANNEL_V1 },
- { "ref-plus-gsp-owned", false,
- GSP_PHYS_RMCALL_CHANNEL_FLAG_SKIP_SCRUBBER,
- GSP_PHYS_RMCALL_CHANNEL_INTERNALFLAGS_PRIV_KERNEL |
- GSP_PHYS_RMCALL_CHANNEL_INTERNALFLAGS_GSP_OWNED, false,
- GSP_PHYS_RMCALL_HANDLE_CHANNEL_V2 },
{ "server-allocated-mem", false,
GSP_PHYS_RMCALL_CHANNEL_FLAG_SKIP_SCRUBBER,
GSP_PHYS_RMCALL_CHANNEL_INTERNALFLAGS_PRIV_KERNEL, true,
@@ -4808,6 +4813,7 @@ static int gsp_phys_rmcall_stage3(void __iomem *bar0)
if (!ret) {
boot_stage.rmcall_channel = v->handle;
boot_stage.rmcall_channel_variant = i + 1;
+ boot_stage.rmcall_channel_server_mem = v->server_mem;
pr_info("gsp-phys-boot: rm-call: stage 3 channel variant %u (%s) WON: hChannel=0x%x\n",
i + 1, v->name, v->handle);
break;
@@ -4930,12 +4936,13 @@ static int gsp_phys_rmcall_stage4(void __iomem *bar0)
int ret;
/*
- * V3 won with server-allocated memdescs: there is no client GPFIFO,
- * USERD or pushbuffer to fill, so no work item can be submitted.
- * Distinct error, nothing is scheduled or rung.
+ * The winning variant requested server-allocated memdescs: there is no
+ * client GPFIFO, USERD or pushbuffer to fill, so no work item can be
+ * submitted. Distinct error, nothing is scheduled or rung.
*/
- if (boot_stage.rmcall_channel_variant == 3) {
- pr_err("gsp-phys-boot: rm-call: stage 4 unavailable: winning channel variant V3 (server-allocated mem) has no client GPFIFO/USERD; submission requires V1, V2 or V4\n");
+ if (boot_stage.rmcall_channel_server_mem) {
+ pr_err("gsp-phys-boot: rm-call: stage 4 unavailable: winning channel variant V%u (server-allocated mem) has no client GPFIFO/USERD; submission requires a client-memory variant (ref-device-skip-scrubber or current-control)\n",
+ boot_stage.rmcall_channel_variant);
return -EOPNOTSUPP;
}