From 462a2ca50fadb1907ee0d7c32caafe525e49a41f Mon Sep 17 00:00:00 2001 From: Aki Niemi Date: Sun, 11 Aug 2024 08:56:16 +0000 Subject: [PATCH] camera: Fix ISP channel release and reset ISP channels are not released cleanly if the IVC send for CAPTURE_CHANNEL_ISP_RELEASE_REQ were to fail, leaving the rest of the release steps undone, including unregistering the capture and control callbacks. This will prevent any new channel setups, e.g., after an app restart, because the channel is deemed busy. Another problem with ISP channel release is that were the aforementioned IVC sends to fail, the driver will not attempt an RCE reboot to recover the IVC communications. Similarly, if the channel reset IVC request fails or returns an error, the pending capture and program buffers won't be unpinned and their related waits won't be completed. This fix always performs the cleanups regardless of the fate of the control channel requests. Bug 4623451 Bug 4765177 Change-Id: I41ada4bc7dcc72676170d3d30515b5e741120252 Signed-off-by: Aki Niemi Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3192586 (cherry picked from commit feb2be84d1077bec942825bf3cbffc58729f0560) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3219711 Reviewed-by: Ganesh Ram Savithri Sreenivas Murthy GVS: buildbot_gerritrpt Reviewed-by: Vincent Chung Reviewed-by: Mohit Ingale Reviewed-by: svcacv Reviewed-by: Frank Chen Tested-by: Mohit Ingale --- .../tegra/camera/fusa-capture/capture-isp.c | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c index d593ab4f..8276c7f8 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -1285,8 +1286,9 @@ int isp_capture_release( struct isp_capture *capture = chan->capture_data; struct CAPTURE_CONTROL_MSG control_msg; struct CAPTURE_CONTROL_MSG *resp_msg = &capture->control_resp_msg; - int i; int err = 0; + int ret = 0; + int i; nv_camera_log(chan->ndev, __arch_counter_get_cntvct(), @@ -1312,28 +1314,32 @@ int isp_capture_release( err = isp_capture_ivc_send_control(chan, &control_msg, sizeof(control_msg), CAPTURE_CHANNEL_ISP_RELEASE_RESP); - if (err < 0) - goto error; + if (err < 0) { + dev_err(chan->isp_dev, + "%s: release channel IVC failed\n", __func__); + WARN_ON("RTCPU is in a bad state. Reboot to recover"); - if (resp_msg->channel_isp_release_resp.result != CAPTURE_OK) { + tegra_camrtc_reboot(capture->rtcpu_dev); + + err = -EIO; + } else if (resp_msg->channel_isp_release_resp.result != CAPTURE_OK) { dev_err(chan->isp_dev, "%s: control failed, errno %d", __func__, - resp_msg->channel_release_resp.result); - err = -EINVAL; - goto error; + resp_msg->channel_isp_release_resp.result); + err = -EIO; } - err = tegra_capture_ivc_unregister_capture_cb(capture->channel_id); - if (err < 0) { + ret = tegra_capture_ivc_unregister_capture_cb(capture->channel_id); + if (ret < 0 && err == 0) { dev_err(chan->isp_dev, "failed to unregister capture callback\n"); - goto error; + err = ret; } - err = tegra_capture_ivc_unregister_control_cb(capture->channel_id); - if (err < 0) { + ret = tegra_capture_ivc_unregister_control_cb(capture->channel_id); + if (ret < 0 && err == 0) { dev_err(chan->isp_dev, "failed to unregister control callback\n"); - goto error; + err = ret; } for (i = 0; i < capture->program_desc_ctx.queue_depth; i++) { @@ -1380,9 +1386,6 @@ int isp_capture_release( capture->channel_id = CAPTURE_CHANNEL_ISP_INVALID_ID; - return 0; - -error: return err; } @@ -1457,6 +1460,9 @@ int isp_capture_reset( goto error; } + err = 0; + +error: for (i = 0; i < capture->program_desc_ctx.queue_depth; i++) { isp_capture_program_request_unpin(chan, i); complete(&capture->capture_program_resp); @@ -1470,9 +1476,6 @@ int isp_capture_reset( spec_bar(); - err = 0; - -error: mutex_unlock(&capture->reset_lock); return err; }