summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c53
1 files changed, 43 insertions, 10 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 8c23abe..033af6e 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -4148,9 +4148,13 @@ struct gsp_phys_rmcall_mem_desc {
__le32 cache_attrib;
};
-/* NV_CHANNEL_GROUP_ALLOCATION_PARAMETERS (nvos.h:2511-2518): hParent is the
- * subdevice, engineType the group engine (COPY0), hVASpace 0 for a physical
- * group. */
+/* NV_CHANNEL_GROUP_ALLOCATION_PARAMETERS (nvos.h:2511-2518): the TSG's
+ * hParent is the device (kernel_channel_group_api.c:150), engineType the
+ * group engine (COPY0). hVASpace 0 selects the parent device's default VAS
+ * when the device vaMode is not MULTIPLE_VASPACES
+ * (kernel_channel_group_api.c:222-233, mem_mgr/vaspace.c:232-242); with a
+ * MULTIPLE_VASPACES device an explicit VAS is required and 0 fails with
+ * NV_ERR_INVALID_STATE. */
struct gsp_phys_rmcall_tsg_params {
__le32 h_object_error;
__le32 h_object_ecc_error;
@@ -4209,6 +4213,26 @@ static u32 gsp_phys_rmcall_reply_u32(const struct gsp_phys_rx_record *rec,
off);
}
+/* Decode the handful of NV_STATUS values seen in this ladder; the raw value is
+ * always logged too. Names from the reference nvstatuscodes.h. */
+static const char *gsp_phys_rmcall_status_str(u32 status)
+{
+ switch (status) {
+ case 0x00:
+ return "NV_OK";
+ case 0x23:
+ return "NV_ERR_INVALID_CLIENT";
+ case 0x36:
+ return "NV_ERR_INVALID_OBJECT_PARENT";
+ case 0x56:
+ return "NV_ERR_NOT_SUPPORTED";
+ case 0x59:
+ return "NV_ERR_OPERATING_SYSTEM";
+ default:
+ return "unknown";
+ }
+}
+
/* First 48 bytes of a reply payload at dynamic-debug level only (cheap). */
static void gsp_phys_rmcall_dump_reply(const struct gsp_phys_rx_record *rec)
{
@@ -4307,8 +4331,9 @@ static int gsp_phys_rmcall_rpc(void __iomem *bar0, u32 function,
gsp_phys_rmcall_dump_reply(rec);
if (rec->rpc_result != 0) {
- pr_err("gsp-phys-boot: rm-call: fn%u server rpc_result=0x%x (not success)\n",
- function, rec->rpc_result);
+ pr_err("gsp-phys-boot: rm-call: fn%u server rpc_result=0x%x (%s, not success)\n",
+ function, rec->rpc_result,
+ gsp_phys_rmcall_status_str(rec->rpc_result));
gsp_phys_rmcall_dump_failed_reply(rec);
return -EIO;
}
@@ -4382,8 +4407,8 @@ static int gsp_phys_rmcall_alloc(void __iomem *bar0, u32 h_client,
gsp_phys_rx_record_free(&rec);
if (status != 0) {
- pr_err("gsp-phys-boot: rm-call: %s alloc server status=0x%x\n",
- what, status);
+ pr_err("gsp-phys-boot: rm-call: %s alloc server status=0x%x (%s)\n",
+ what, status, gsp_phys_rmcall_status_str(status));
return -EIO;
}
return 0;
@@ -4496,8 +4521,8 @@ static int gsp_phys_rmcall_control(void __iomem *bar0, u32 h_object, u32 cmd,
pr_info("gsp-phys-boot: rm-call: %s ctrl 0x%x (hObject=0x%x, params %u B) status=0x%x\n",
what, cmd, h_object, params_len, status);
if (status != 0) {
- pr_err("gsp-phys-boot: rm-call: %s server status=0x%x\n",
- what, status);
+ pr_err("gsp-phys-boot: rm-call: %s server status=0x%x (%s)\n",
+ what, status, gsp_phys_rmcall_status_str(status));
return -EIO;
}
return 0;
@@ -4644,8 +4669,16 @@ static int gsp_phys_rmcall_stage3(void __iomem *bar0)
memset(&tsg, 0, sizeof(tsg));
tsg.engine_type = cpu_to_le32(GSP_PHYS_RMCALL_ENGINE_COPY0);
+ /*
+ * The TSG's hParent must be the DEVICE, not the subdevice: the server
+ * resolves it with deviceGetByHandle (kernel_channel_group_api.c:150)
+ * and a subdevice parent is the observed NV_ERR_INVALID_OBJECT_PARENT
+ * (0x36). The reference CE/UVM path allocates the TSG with
+ * hParent=device->handle (rmapi/nv_gpu_ops.c:6087-6093). The channel
+ * below keeps the TSG handle as its parent.
+ */
ret = gsp_phys_rmcall_alloc(bar0, boot_stage.rmcall_client,
- boot_stage.rmcall_subdevice,
+ boot_stage.rmcall_device,
GSP_PHYS_RMCALL_HANDLE_TSG,
GSP_PHYS_RMCALL_CLASS_TSG,
&tsg, sizeof(tsg), false, NULL,