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 <aniemi@nvidia.com>
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 <ganeshrams@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Vincent Chung <vincentc@nvidia.com>
Reviewed-by: Mohit Ingale <mohiti@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
Tested-by: Mohit Ingale <mohiti@nvidia.com>
This commit is contained in:
Aki Niemi
2024-08-11 08:56:16 +00:00
committed by Jon Hunter
parent bcb56180c8
commit 462a2ca50f

View File

@@ -16,6 +16,7 @@
#include <linux/printk.h>
#include <linux/vmalloc.h>
#include <linux/tegra-capture-ivc.h>
#include <linux/tegra-camera-rtcpu.h>
#include <asm/arch_timer.h>
#include <soc/tegra/fuse.h>
@@ -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;
}