From 1656f9c566f4128ebbea7a7c57a876bc6391af98 Mon Sep 17 00:00:00 2001 From: Akihiro Mizusawa Date: Fri, 27 Sep 2024 15:50:20 -0700 Subject: [PATCH] nv-oot: rtcpu: Check early boot logs - Define boot log related HSP message ID's. - Call camrtc_hsp_vm_read_boot_log as the first step during the HSP handshake. - The read_boot_log function will wait for 2000 ms for a boot log message. If the RCE has hung during boot, this will timeout, and return with error. - Move dev_set_drvdata to before camrtc_hsp_probe in camrtc_hsp_create. Explanation: The RCE, during a normal boot sequence, will boot before the RTCPU KMD starts probing, so the mailbox will already be full when the HSP driver is initializing. The RTCPU HSP full interrupt handler will be called immediately after the handlers are registered by the mailbox driver. The interrupt handler will reference the HSP device's drvdata, and it was a race condition as to whether the interrupt handler would be called before the drvdata was set. Thus, this change sets drvdata before the interrupt handlers are installed to prevent this race condition. - Update the full interrupt handler to return if camhsp is null. Jira CAMERASW-27443 Change-Id: Ibb7ed41771d2178e0d06adb94ae1955db61b9d92 Signed-off-by: Akihiro Mizusawa Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3239620 Reviewed-by: Chinniah Poosapadi GVS: buildbot_gerritrpt Reviewed-by: Semi Malinen Reviewed-by: Frank Chen --- .../platform/tegra/rtcpu/hsp-mailbox-client.c | 58 ++++++++++++++++++- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c b/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c index 7a1fa70c..251b03a3 100644 --- a/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c +++ b/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c @@ -120,6 +120,9 @@ static void camrtc_hsp_rx_full_notify(mbox_client *cl, void *data) status >>= CAMRTC_HSP_SS_FW_SHIFT; group = status & CAMRTC_HSP_SS_IVC_MASK; + if (WARN_ON(camhsp == NULL)) + return; + if (CAMRTC_HSP_MSG_ID(msg) == CAMRTC_HSP_UNKNOWN) dev_dbg(&camhsp->dev, "request message unknown 0x%08x\n", msg); @@ -230,9 +233,59 @@ static int camrtc_hsp_vm_sendrecv(struct camrtc_hsp *camhsp, return CAMRTC_HSP_MSG_PARAM(response); } +static int camrtc_hsp_vm_read_boot_log(struct camrtc_hsp *camhsp) +{ + uint32_t boot_log; + long msg_timeout; + + if (WARN_ON(camhsp == NULL)) + return -EINVAL; + + msg_timeout = camhsp->timeout; + + for (;;) { + boot_log = camrtc_hsp_recv(camhsp, CAMRTC_HSP_BOOT_COMPLETE, &msg_timeout); + + if (boot_log == -ETIMEDOUT) { + dev_warn(&camhsp->dev, + "%s: Error reading mailbox. Failed to obtain RTCPU boot logs\n", __func__); + return boot_log; + } + + if (CAMRTC_HSP_MSG_ID(boot_log) == CAMRTC_HSP_BOOT_COMPLETE) { + dev_info(&camhsp->dev, "%s: RTCPU boot complete\n", __func__); + break; + } else if (CAMRTC_HSP_MSG_ID(boot_log) == CAMRTC_HSP_BOOT_STAGE) { + dev_dbg(&camhsp->dev, "%s: RTCPU boot stage: %x\n", __func__, boot_log); + } else if (CAMRTC_HSP_MSG_ID(boot_log) == CAMRTC_HSP_BOOT_ERROR) { + uint32_t err_code = CAMRTC_HSP_MSG_PARAM(boot_log); + dev_err(&camhsp->dev, "%s: RTCPU boot failure message received: 0x%x", + __func__, err_code); + return -EINVAL; + } else { + dev_warn(&camhsp->dev, + "%s: Unexpected message received during RTCPU boot: 0x%08x\n", + __func__, boot_log); + } + + } + + return 0U; +} + static int camrtc_hsp_vm_sync(struct camrtc_hsp *camhsp, long *timeout) { - int response = camrtc_hsp_vm_hello(camhsp, timeout); + int response; + + response = camrtc_hsp_vm_read_boot_log(camhsp); + + if (response < 0) { + /* Failing to read boot logs is not a fatal error. + * Log error and continue with HSP handshake. */ + dev_warn(&camhsp->dev, "%s: Failed to read boot logs", __func__); + } + + response = camrtc_hsp_vm_hello(camhsp, timeout); if (response >= 0) { camhsp->cookie = response; @@ -657,6 +710,7 @@ struct camrtc_hsp *camrtc_hsp_create( camhsp->rx.client.rx_callback = camrtc_hsp_rx_full_notify; camhsp->tx.client.tx_done = camrtc_hsp_tx_empty_notify; camhsp->rx.client.dev = camhsp->tx.client.dev = &(camhsp->dev); + dev_set_drvdata(&camhsp->dev, camhsp); ret = camrtc_hsp_probe(camhsp); if (ret < 0) @@ -666,8 +720,6 @@ struct camrtc_hsp *camrtc_hsp_create( if (ret < 0) goto fail; - dev_set_drvdata(&camhsp->dev, camhsp); - return camhsp; fail: