From 9f18463541eee28977c4e8639fa13ae78ed37f38 Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Sun, 9 May 2021 02:16:46 +0530 Subject: [PATCH] Revert "Revert "msm: camera: req_mgr: Enhance camera v4l2 subdev shutdown sequence"" This reverts commit 4a487d963840940caf55c9de4026573bf0768eed. Change-Id: I9d052d9260581ed8155d3fbd3e5eff3a81247306 Signed-off-by: Sridhar Gujje --- drivers/cam_core/cam_context.c | 27 +++++++- drivers/cam_core/cam_context.h | 19 ++++- drivers/cam_core/cam_node.c | 23 ++++++- drivers/cam_core/cam_node.h | 26 +++++++ drivers/cam_core/cam_subdev.c | 15 ++++ drivers/cam_cpas/cam_cpas_intf.c | 24 ++++++- drivers/cam_cust/cam_custom_context.c | 18 +++++ drivers/cam_cust/cam_custom_context.h | 12 ++++ drivers/cam_cust/cam_custom_dev.c | 16 ++++- drivers/cam_fd/cam_fd_context.c | 26 ++++++- drivers/cam_fd/cam_fd_context.h | 11 +++ drivers/cam_fd/cam_fd_dev.c | 21 +++++- drivers/cam_icp/cam_icp_context.c | 19 ++++- drivers/cam_icp/cam_icp_context.h | 8 +++ drivers/cam_icp/cam_icp_subdev.c | 23 +++++-- drivers/cam_isp/cam_isp_context.c | 11 +++ drivers/cam_isp/cam_isp_context.h | 11 +++ drivers/cam_isp/cam_isp_dev.c | 15 +++- drivers/cam_jpeg/cam_jpeg_context.c | 26 +++++++ drivers/cam_jpeg/cam_jpeg_context.h | 12 ++++ drivers/cam_jpeg/cam_jpeg_dev.c | 16 ++++- drivers/cam_lrme/cam_lrme_context.c | 19 ++++- drivers/cam_lrme/cam_lrme_context.h | 12 ++++ drivers/cam_lrme/cam_lrme_dev.c | 15 +++- drivers/cam_ope/cam_ope_context.c | 19 ++++- drivers/cam_ope/cam_ope_context.h | 8 +++ drivers/cam_ope/cam_ope_subdev.c | 16 ++++- drivers/cam_req_mgr/cam_req_mgr_dev.c | 66 +++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_dev.h | 6 ++ drivers/cam_req_mgr/cam_req_mgr_util.c | 31 +++++++++ drivers/cam_req_mgr/cam_req_mgr_util.h | 7 ++ drivers/cam_req_mgr/cam_subdev.h | 27 ++++++++ .../cam_actuator/cam_actuator_dev.c | 63 ++++++++++++----- .../cam_csiphy/cam_csiphy_dev.c | 69 ++++++++++++------- .../cam_eeprom/cam_eeprom_dev.c | 66 ++++++++++++------ .../cam_flash/cam_flash_dev.c | 58 +++++++++++----- .../cam_sensor_module/cam_ois/cam_ois_dev.c | 67 +++++++++++------- .../cam_sensor/cam_sensor_dev.c | 69 ++++++++++++------- 38 files changed, 843 insertions(+), 154 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 9637a8715af6..a9a635d606f9 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -583,6 +583,31 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid stop device command payload"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev( + (struct v4l2_subdev *)cmd->handle, fh); + else + CAM_WARN(CAM_CORE, "No shutdown device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + + return rc; +} + int cam_context_handle_info_dump(void *context, enum cam_context_dump_id id) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 5be078536ff5..e55da3c3c4e7 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -9,6 +9,7 @@ #include #include #include +#include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" #include "cam_smmu_api.h" @@ -95,6 +96,7 @@ struct cam_ctx_request { * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * @dump_dev: Function pointer for dump dev + * @shutdown_dev: Function pointer for shutdown dev * */ struct cam_ctx_ioctl_ops { @@ -114,6 +116,8 @@ struct cam_ctx_ioctl_ops { int (*release_hw)(struct cam_context *ctx, void *args); int (*dump_dev)(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); + int (*shutdown_dev)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); }; /** @@ -479,6 +483,19 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +/** + * cam_context_handle_shutdown_dev() + * + * @brief: Handle shutdown device command + * + * @ctx: Object pointer for cam_context + * @cmd: Shutdown device command payload + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + /** * cam_context_handle_dump_dev() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index c3770f2df745..d27bcdd6bf0d 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -297,6 +297,27 @@ static int __cam_node_handle_stop_dev(struct cam_node *node, return rc; } +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + struct cam_context *ctx = NULL; + int32_t dev_index = -1; + int rc = 0, ret = 0; + + while ((dev_index = cam_get_dev_handle_info(cmd->handle, + &ctx, dev_index)) < CAM_REQ_MGR_MAX_HANDLES_V2) { + ret = cam_context_handle_shutdown_dev(ctx, cmd, fh); + if (ret) { + rc = ret; + CAM_ERR(CAM_CORE, "Shutdown failure for node %s", + node->name); + continue; + } + } + + return rc; +} + static int __cam_node_handle_config_dev(struct cam_node *node, struct cam_config_dev_cmd *config) { diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h index 640798b387d6..81503f28974f 100644 --- a/drivers/cam_core/cam_node.h +++ b/drivers/cam_core/cam_node.h @@ -100,4 +100,30 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, */ void cam_node_put_ctxt_to_free_list(struct kref *ref); +/** + * cam_get_dev_handle_info() + * + * @brief: provides the active dev index. + * + * @handle: pointer to struct v4l2_dev + * @ctx: pointer to struct cam_context + * @dev_index: dev index + * + */ +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index); + +/** + * cam_node_handle_shutdown_dev() + * + * @brief: Shutdowns all the active devices. + * + * @node: pointer to struct node + * @cmd: pointer to struct cmd + * @fh: pointer to struct v4l2_subdev_fh + * + */ +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + #endif /* _CAM_NODE_H_ */ diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c index 52612951dca7..cbe1b4ca3336 100644 --- a/drivers/cam_core/cam_subdev.c +++ b/drivers/cam_core/cam_subdev.c @@ -45,6 +45,8 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, long rc; struct cam_node *node = (struct cam_node *) v4l2_get_subdevdata(sd); + struct v4l2_subdev_fh *fh = (struct v4l2_subdev_fh *)arg; + struct cam_control cntrl_cmd; if (!node || node->state == CAM_NODE_STATE_UNINIT) { rc = -EINVAL; @@ -56,6 +58,19 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, rc = cam_node_handle_ioctl(node, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_WARN(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + cntrl_cmd.op_code = CAM_SD_SHUTDOWN; + cntrl_cmd.handle = (uint64_t)sd; + rc = cam_node_handle_shutdown_dev(node, &cntrl_cmd, fh); + if (rc) + CAM_ERR(CAM_CORE, "shutdown device failed(rc = %d)", + rc); + break; default: CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, node->name); diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f5bb5db85c29..3c8f5dc166e2 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -691,7 +691,7 @@ static int cam_cpas_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_cpas_subdev_close(struct v4l2_subdev *sd, +static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); @@ -702,6 +702,11 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, } mutex_lock(&cpas_intf->intf_lock); + if (cpas_intf->open_cnt <= 0) { + CAM_WARN(CAM_CPAS, "device already closed, open_cnt: %d", cpas_intf->open_cnt); + mutex_unlock(&cpas_intf->intf_lock); + return 0; + } cpas_intf->open_cnt--; CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt); mutex_unlock(&cpas_intf->intf_lock); @@ -709,6 +714,19 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_cpas_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CPAS); + + if (crm_active) { + CAM_DBG(CAM_CPAS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return __cam_cpas_subdev_close(sd, fh); +} + static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -724,6 +742,9 @@ static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, case VIDIOC_CAM_CONTROL: rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + rc = __cam_cpas_subdev_close(sd, NULL); + break; default: CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); rc = -EINVAL; @@ -811,6 +832,7 @@ static int cam_cpas_subdev_register(struct platform_device *pdev) subdev->sd_flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->ent_function = CAM_CPAS_DEVICE_TYPE; + subdev->close_seq_prior = CAM_SD_CLOSE_LOW_PRIORITY; rc = cam_register_subdev(subdev); if (rc) { diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index ca4d1d1e35d5..2b617b15f5a0 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1604,6 +1604,19 @@ static int __cam_custom_ctx_apply_default_req( return rc; } +static int __cam_custom_ctx_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_CUSTOM, "Invalid input pointer"); + return rc; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1618,6 +1631,7 @@ static struct cam_ctx_ops .ioctl_ops = { .acquire_dev = __cam_custom_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -1629,6 +1643,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev_in_acquired, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .link = __cam_custom_ctx_link_in_acquired, @@ -1647,6 +1662,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1664,6 +1680,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1680,6 +1697,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index ef7fe1f87434..74c45d541610 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -150,4 +150,16 @@ int cam_custom_dev_context_init(struct cam_custom_context *ctx, */ int cam_custom_dev_context_deinit(struct cam_custom_context *ctx); +/** + * cam_custom_subdev_close_internal() + * + * @brief: Close function for the Custom context + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_CUSTOM_CONTEXT_H_ */ diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index 3c3bea4c22c0..36dde62fc51d 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -58,7 +58,7 @@ static int cam_custom_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_custom_subdev_close(struct v4l2_subdev *sd, +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -86,6 +86,19 @@ end: return rc; } +static int cam_custom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CUSTOM); + + if (crm_active) { + CAM_DBG(CAM_CUSTOM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { .close = cam_custom_subdev_close, .open = cam_custom_subdev_open, @@ -102,6 +115,7 @@ static int cam_custom_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; + g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME, CAM_CUSTOM_DEVICE_TYPE); diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index c79f2f90e007..0f3fa85f079e 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -169,6 +169,19 @@ static int __cam_fd_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_fd_shutdown_dev(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_FD, "Invalid input pointer"); + return rc; + } + + return cam_fd_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -182,6 +195,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_fd_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -192,18 +206,25 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_acquired, .config_dev = __cam_fd_ctx_config_dev_in_acquired, .start_dev = __cam_fd_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = { }, + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, + }, /* Activated */ { .ioctl_ops = { @@ -212,6 +233,7 @@ static struct cam_ctx_ops .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, diff --git a/drivers/cam_fd/cam_fd_context.h b/drivers/cam_fd/cam_fd_context.h index a751a04d2d67..615e8d94cf6e 100644 --- a/drivers/cam_fd/cam_fd_context.h +++ b/drivers/cam_fd/cam_fd_context.h @@ -27,4 +27,15 @@ int cam_fd_context_init(struct cam_fd_context *fd_ctx, uint32_t ctx_id); int cam_fd_context_deinit(struct cam_fd_context *ctx); +/** + * cam_fd_dev_close_internal() + * + * @brief: Close function for the fd dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_fd_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_FD_CONTEXT_H_ */ diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index bc1864edb24e..a58db056f6fb 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -57,7 +57,7 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_fd_dev_close(struct v4l2_subdev *sd, +static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_fd_dev *fd_dev = &g_fd_dev; @@ -69,6 +69,11 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, } mutex_lock(&fd_dev->lock); + if (fd_dev->open_cnt == 0) { + CAM_WARN(CAM_FD, "device already closed"); + mutex_unlock(&fd_dev->lock); + return 0; + } fd_dev->open_cnt--; CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); mutex_unlock(&fd_dev->lock); @@ -83,6 +88,19 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, return 0; } +static int cam_fd_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FD); + + if (crm_active) { + CAM_DBG(CAM_FD, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_fd_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { .open = cam_fd_dev_open, .close = cam_fd_dev_close, @@ -98,6 +116,7 @@ static int cam_fd_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; + g_fd_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ rc = cam_subdev_probe(&g_fd_dev.sd, pdev, CAM_FD_DEV_NAME, diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 57a80bcd7341..03ead2c3b693 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -221,6 +221,12 @@ static int __cam_icp_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_icp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_icp_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -233,6 +239,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_icp_acquire_dev_in_available, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -245,6 +252,7 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, @@ -258,16 +266,23 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, .pagefault_ops = cam_icp_context_dump_active_request, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_icp_context_dump_active_request, diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h index dc9018d1c229..9150bcf43f62 100644 --- a/drivers/cam_icp/cam_icp_context.h +++ b/drivers/cam_icp/cam_icp_context.h @@ -39,4 +39,12 @@ int cam_icp_context_init(struct cam_icp_context *ctx, */ int cam_icp_context_deinit(struct cam_icp_context *ctx); +/** + * cam_icp_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_ICP_CONTEXT_H_ */ diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 6a12cdd3e2fc..3288964444ef 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -98,7 +98,7 @@ end: return rc; } -static int cam_icp_subdev_close(struct v4l2_subdev *sd, +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -107,9 +107,8 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_DBG(CAM_ICP, "ICP subdev is already closed"); - rc = -EINVAL; - goto end; + CAM_WARN(CAM_ICP, "ICP subdev is already closed"); + return 0; } g_icp_dev.open_cnt--; if (!node) { @@ -133,7 +132,20 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, end: mutex_unlock(&g_icp_dev.icp_lock); - return 0; + return rc; +} + +static int cam_icp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ICP); + + if (crm_active) { + CAM_DBG(CAM_ICP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_icp_subdev_close_internal(sd, fh); } const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { @@ -157,6 +169,7 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.sd.pdev = pdev; g_icp_dev.sd.internal_ops = &cam_icp_subdev_internal_ops; + g_icp_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME, CAM_ICP_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f7a95795744b..d7cdaa4aa67e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5837,6 +5837,12 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_isp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_isp_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -5850,6 +5856,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_isp_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -5861,6 +5868,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, @@ -5880,6 +5888,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5897,6 +5906,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_flushed, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5914,6 +5924,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index c0861f07964e..108dc096d897 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -364,5 +364,16 @@ int cam_isp_context_init(struct cam_isp_context *ctx, */ int cam_isp_context_deinit(struct cam_isp_context *ctx); +/** + * cam_isp_subdev_close_internal() + * + * @brief: Close function for the isp dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); #endif /* __CAM_ISP_CONTEXT_H__ */ diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 98de92cb3d58..9409c1015c6c 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -71,7 +71,7 @@ static int cam_isp_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_isp_subdev_close(struct v4l2_subdev *sd, +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -99,6 +99,18 @@ end: return rc; } +static int cam_isp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ISP); + + if (crm_active) { + CAM_DBG(CAM_ISP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_isp_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .close = cam_isp_subdev_close, .open = cam_isp_subdev_open, @@ -120,6 +132,7 @@ static int cam_isp_dev_component_bind(struct device *dev, (const char **)&compat_str); g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; + g_isp_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ if (strnstr(compat_str, "ife", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index 93d4ade12c42..20dd4a02127b 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -135,6 +135,12 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_jpeg_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_jpeg_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -148,6 +154,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = NULL, @@ -160,11 +167,30 @@ static struct cam_ctx_ops .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, .pagefault_ops = cam_jpeg_context_dump_active_request, }, + /* Ready */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Activated */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, }; int cam_jpeg_context_init(struct cam_jpeg_context *ctx, diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h index 85394047d97f..f8a8b06d09f0 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.h +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -64,4 +64,16 @@ int cam_jpeg_context_init(struct cam_jpeg_context *ctx, */ int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx); +/** + * cam_jpeg_subdev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* __CAM_JPEG_CONTEXT_H__ */ diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 966bbb1fab06..a47476a06144 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -56,13 +56,12 @@ static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); - mutex_lock(&g_jpeg_dev.jpeg_mutex); if (g_jpeg_dev.open_cnt <= 0) { CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); @@ -86,6 +85,18 @@ end: return rc; } +static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_JPEG); + + if (crm_active) { + CAM_DBG(CAM_JPEG, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_jpeg_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .close = cam_jpeg_subdev_close, .open = cam_jpeg_subdev_open, @@ -102,6 +113,7 @@ static int cam_jpeg_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; + g_jpeg_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, CAM_JPEG_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index 537432f982bf..7025b384b1d2 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -172,6 +172,12 @@ static int __cam_lrme_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_lrme_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_lrme_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -185,6 +191,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_lrme_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -195,18 +202,25 @@ static struct cam_ctx_ops .config_dev = __cam_lrme_ctx_config_dev_in_activated, .release_dev = __cam_lrme_ctx_release_dev_in_acquired, .start_dev = __cam_lrme_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, + }, /* Activate */ { .ioctl_ops = { @@ -215,6 +229,7 @@ static struct cam_ctx_ops .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, .dump_dev = __cam_lrme_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h index bc459cce2f95..34ed1693f944 100644 --- a/drivers/cam_lrme/cam_lrme_context.h +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -30,4 +30,16 @@ int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, uint32_t index); int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx); +/** + * cam_lrme_dev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_LRME_CONTEXT_H_ */ diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 3735ff9370a2..5055444c3d8a 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -72,7 +72,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_lrme_dev_close(struct v4l2_subdev *sd, +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -106,6 +106,18 @@ end: return rc; } +static int cam_lrme_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_LRME); + + if (crm_active) { + CAM_DBG(CAM_LRME, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_lrme_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { .open = cam_lrme_dev_open, .close = cam_lrme_dev_close, @@ -126,6 +138,7 @@ static int cam_lrme_component_bind(struct device *dev, return -ENOMEM; } g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops; + g_lrme_dev->sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; mutex_init(&g_lrme_dev->lock); diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index d1f39e8fce17..c8be0da353d4 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -195,6 +195,12 @@ static int __cam_ope_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_ope_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_ope_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -207,6 +213,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_ope_acquire_dev_in_available, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -219,6 +226,7 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -232,14 +240,23 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, .pagefault_ops = cam_ope_context_dump_active_request, }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_ope_context_dump_active_request, diff --git a/drivers/cam_ope/cam_ope_context.h b/drivers/cam_ope/cam_ope_context.h index e79e0f33225d..5e6d28c3ff59 100644 --- a/drivers/cam_ope/cam_ope_context.h +++ b/drivers/cam_ope/cam_ope_context.h @@ -41,4 +41,12 @@ int cam_ope_context_init(struct cam_ope_context *ctx, */ int cam_ope_context_deinit(struct cam_ope_context *ctx); +/** + * cam_ope_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_OPE_CONTEXT_H_ */ diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index edfdd1e75e77..a04abe3bcf8c 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -95,7 +95,7 @@ end: return rc; } -static int cam_ope_subdev_close(struct v4l2_subdev *sd, +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -134,6 +134,19 @@ end: return rc; } +static int cam_ope_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OPE); + + if (crm_active) { + CAM_DBG(CAM_OPE, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ope_subdev_close_internal(sd, fh); +} + const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { .open = cam_ope_subdev_open, .close = cam_ope_subdev_close, @@ -156,6 +169,7 @@ static int cam_ope_subdev_component_bind(struct device *dev, g_ope_dev.sd.pdev = pdev; g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops; + g_ope_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME, CAM_OPE_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 6ae85e826c5e..350c9ea171bf 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" @@ -32,6 +33,7 @@ static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; +static struct list_head cam_req_mgr_ordered_sd_list; static struct device_attribute camera_debug_sysfs_attr = __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); @@ -122,6 +124,7 @@ static int cam_req_mgr_open(struct file *filep) spin_unlock_bh(&g_dev.cam_eventq_lock); g_dev.open_cnt++; + g_dev.read_active_dev_id_hdls = 0; rc = cam_mem_mgr_init(); if (rc) { g_dev.open_cnt--; @@ -158,6 +161,7 @@ static unsigned int cam_req_mgr_poll(struct file *f, static int cam_req_mgr_close(struct file *filep) { struct v4l2_subdev *sd; + struct cam_subdev *csd; struct v4l2_fh *vfh = filep->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); @@ -172,18 +176,23 @@ static int cam_req_mgr_close(struct file *filep) } cam_req_mgr_handle_core_shutdown(); + g_dev.shutdown_state = true; - list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + list_for_each_entry(csd, &cam_req_mgr_ordered_sd_list, list) { + sd = &csd->sd; if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) continue; - if (sd->internal_ops && sd->internal_ops->close) { + if (sd->internal_ops) { CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", sd->name); - sd->internal_ops->close(sd, subdev_fh); + v4l2_subdev_call(sd, core, ioctl, + CAM_SD_SHUTDOWN, subdev_fh); } } g_dev.open_cnt--; + g_dev.shutdown_state = false; + g_dev.read_active_dev_id_hdls = 0; v4l2_fh_release(filep); spin_lock_bh(&g_dev.cam_eventq_lock); @@ -659,6 +668,51 @@ void cam_subdev_notify_message(u32 subdev_type, } EXPORT_SYMBOL(cam_subdev_notify_message); + +static int cam_req_mgr_ordered_list_cmp(void *priv, + struct list_head *head_1, struct list_head *head_2) +{ + struct cam_subdev *entry_1 = + list_entry(head_1, struct cam_subdev, list); + struct cam_subdev *entry_2 = + list_entry(head_2, struct cam_subdev, list); + int ret = -1; + + if (entry_1->close_seq_prior > entry_2->close_seq_prior) + return 1; + else if (entry_1->close_seq_prior < entry_2->close_seq_prior) + return ret; + else + return 0; +} + +bool cam_req_mgr_is_open(uint64_t dev_id) +{ + bool crm_status; + bool dev_id_status; + + mutex_lock(&g_dev.cam_lock); + crm_status = g_dev.open_cnt ? true : false; + + if (!g_dev.read_active_dev_id_hdls) { + g_dev.active_dev_id_hdls = cam_get_dev_handle_status(); + g_dev.read_active_dev_id_hdls++; + } + + dev_id_status = (g_dev.active_dev_id_hdls & dev_id) ? true : false; + crm_status &= dev_id_status; + mutex_unlock(&g_dev.cam_lock); + + return crm_status; +} +EXPORT_SYMBOL(cam_req_mgr_is_open); + +bool cam_req_mgr_is_shutdown(void) +{ + return g_dev.shutdown_state; +} +EXPORT_SYMBOL(cam_req_mgr_is_shutdown); + int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -687,6 +741,10 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; + list_add(&csd->list, &cam_req_mgr_ordered_sd_list); + list_sort(NULL, &cam_req_mgr_ordered_sd_list, + cam_req_mgr_ordered_list_cmp); + rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); @@ -747,6 +805,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto video_setup_fail; g_dev.open_cnt = 0; + g_dev.shutdown_state = false; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); mutex_init(&g_dev.dev_lock); @@ -764,6 +823,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) } g_dev.state = true; + INIT_LIST_HEAD(&cam_req_mgr_ordered_sd_list); if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index d374f6cce319..0a55789b7c7d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -19,6 +19,9 @@ * @cam_lock: per file handle lock * @cam_eventq: event queue * @cam_eventq_lock: lock for event queue + * @shutdown_state: shutdown state + * @active_dev_id_hdls: active dev id handles + * @read_active_dev_id_hdls: read active_dev_id_hdls status */ struct cam_req_mgr_device { struct video_device *video; @@ -30,6 +33,9 @@ struct cam_req_mgr_device { struct mutex cam_lock; struct v4l2_fh *cam_eventq; spinlock_t cam_eventq_lock; + bool shutdown_state; + uint64_t active_dev_id_hdls; + int read_active_dev_id_hdls; }; #define CAM_REQ_MGR_GET_PAYLOAD_PTR(ev, type) \ diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 02e4e53ef5d7..00b919fcec30 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -14,6 +14,7 @@ #include #include "cam_req_mgr_util.h" #include "cam_debug_util.h" +#include "cam_context.h" static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static DEFINE_SPINLOCK(hdl_tbl_lock); @@ -209,6 +210,36 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) return handle; } +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index) +{ + int32_t idx; + struct v4l2_subdev *sd = (struct v4l2_subdev *)handle; + + for (idx = dev_index + 1; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) { + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) { + *ctx = (struct cam_context *)cam_get_device_priv( + hdl_tbl->hdl[idx].hdl_value); + if ((*ctx) && !strcmp(sd->name, (*ctx)->dev_name)) + return idx; + } + } + *ctx = NULL; + return CAM_REQ_MGR_MAX_HANDLES_V2; +} + +uint64_t cam_get_dev_handle_status(void) +{ + int32_t idx; + uint64_t active_dev_hdls = 0; + + for (idx = 0; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) + active_dev_hdls |= hdl_tbl->hdl[idx].dev_id; + + return active_dev_hdls; +} + void *cam_get_device_priv(int32_t dev_hdl) { int idx; diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index 0d0fec1f8e01..fb70401306d9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -166,4 +166,11 @@ int32_t cam_req_mgr_util_deinit(void); */ int32_t cam_req_mgr_util_free_hdls(void); +/** + * cam_get_dev_handle_status() - get dev handles status + * + * Returns dev handle status + */ +uint64_t cam_get_dev_handle_status(void); + #endif /* _CAM_REQ_MGR_UTIL_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index a6f6d7062c0f..e37d7177c8a3 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -21,6 +21,13 @@ enum cam_subdev_message_type_t { CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; +/* Enum for close sequence priority */ +enum cam_subdev_close_seq_priority { + CAM_SD_CLOSE_HIGH_PRIORITY, + CAM_SD_CLOSE_MEDIUM_PRIORITY, + CAM_SD_CLOSE_LOW_PRIORITY +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -39,6 +46,8 @@ enum cam_subdev_message_type_t { * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. + * @list: list pointer + * @close_seq_prior: cam_subdev_close_seq_priority type * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be @@ -58,6 +67,8 @@ struct cam_subdev { struct v4l2_subdev *sd, enum cam_subdev_message_type_t msg_type, uint32_t data); + struct list_head list; + enum cam_subdev_close_seq_priority close_seq_prior; }; /** @@ -119,4 +130,20 @@ int cam_register_subdev(struct cam_subdev *sd); */ int cam_unregister_subdev(struct cam_subdev *sd); +/** + * cam_req_mgr_is_open() + * + * @brief: This common utility function returns the crm active status + * + * @dev_id: device id type + */ +bool cam_req_mgr_is_open(uint64_t dev_id); + +/** + * cam_req_mgr_is_shutdown() + * + * @brief: This common utility function returns the shutdown state + */ +bool cam_req_mgr_is_shutdown(void); + #endif /* _CAM_SUBDEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 96435bcd5fe6..d51dae6d37d7 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -10,6 +10,38 @@ #include "cam_trace.h" #include "camera_main.h" +static int cam_actuator_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + cam_actuator_shutdown(a_ctrl); + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + +static int cam_actuator_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); + + if (crm_active) { + CAM_INFO(CAM_ACTUATOR, + "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_actuator_subdev_close_internal(sd, fh); +} + static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -24,6 +56,14 @@ static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, CAM_ERR(CAM_ACTUATOR, "Failed for driver_cmd: %d", rc); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_actuator_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd: %u", cmd); rc = -ENOIOCTLCMD; @@ -77,24 +117,6 @@ static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, } #endif -static int cam_actuator_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_actuator_ctrl_t *a_ctrl = - v4l2_get_subdevdata(sd); - - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&(a_ctrl->actuator_mutex)); - cam_actuator_shutdown(a_ctrl); - mutex_unlock(&(a_ctrl->actuator_mutex)); - - return 0; -} - static struct v4l2_subdev_core_ops cam_actuator_subdev_core_ops = { .ioctl = cam_actuator_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -127,10 +149,13 @@ static int cam_actuator_init_subdev(struct cam_actuator_ctrl_t *a_ctrl) a_ctrl->v4l2_dev_str.ent_function = CAM_ACTUATOR_DEVICE_TYPE; a_ctrl->v4l2_dev_str.token = a_ctrl; + a_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str)); if (rc) - CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); + CAM_ERR(CAM_ACTUATOR, + "Fail with cam_register_subdev rc: %d", rc); return rc; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index fbe53591fc6e..17216d86d038 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -77,29 +77,7 @@ static void cam_csiphy_debug_unregister(void) root_dentry = NULL; } -static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); - int rc = 0; - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_csiphy_core_cfg(csiphy_dev, arg); - if (rc) - CAM_ERR(CAM_CSIPHY, - "Failed in configuring the device: %d", rc); - break; - default: - CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, +static int cam_csiphy_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct csiphy_device *csiphy_dev = @@ -117,6 +95,49 @@ static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); + + if (crm_active) { + CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_csiphy_subdev_close_internal(sd, fh); +} + +static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + int rc = 0; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_core_cfg(csiphy_dev, arg); + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in configuring the device: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_csiphy_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + #ifdef CONFIG_COMPAT static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -236,6 +257,8 @@ static int cam_csiphy_component_bind(struct device *dev, cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; + new_csiphy_dev->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str)); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 2c0f791b6f7e..cfcc166892d7 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -10,28 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_eeprom_driver_cmd(e_ctrl, arg); - if (rc) - CAM_ERR(CAM_EEPROM, - "Failed in Driver cmd: %d", rc); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, +static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_eeprom_ctrl_t *e_ctrl = @@ -49,6 +28,48 @@ static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); + + if (crm_active) { + CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_eeprom_subdev_close_internal(sd, fh); +} + +static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_driver_cmd(e_ctrl, arg); + if (rc) + CAM_ERR(CAM_EEPROM, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_eeprom_subdev_close_internal(sd, NULL); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_i2c_info_t *i2c_info) { @@ -147,6 +168,7 @@ static int cam_eeprom_init_subdev(struct cam_eeprom_ctrl_t *e_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE; e_ctrl->v4l2_dev_str.token = e_ctrl; + e_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 5a4655834eaa..8386d8d6b817 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -236,6 +236,37 @@ static const struct of_device_id cam_flash_dt_match[] = { {} }; +static int cam_flash_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_flash_ctrl *fctrl = + v4l2_get_subdevdata(sd); + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + +static int cam_flash_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FLASH); + + if (crm_active) { + CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_flash_subdev_close_internal(sd, fh); +} + static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -257,6 +288,14 @@ static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, "Failed in driver cmd: %d", rc); break; } + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_flash_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); rc = -ENOIOCTLCMD; @@ -328,24 +367,6 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) return rc; } -static int cam_flash_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_flash_ctrl *fctrl = - v4l2_get_subdevdata(sd); - - if (!fctrl) { - CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&fctrl->flash_mutex); - cam_flash_shutdown(fctrl); - mutex_unlock(&fctrl->flash_mutex); - - return 0; -} - static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = { .ioctl = cam_flash_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -375,6 +396,7 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; fctrl->v4l2_dev_str.token = fctrl; + fctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index b47d90225ca0..94b6a9cd8271 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -10,29 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_ois_driver_cmd(o_ctrl, arg); - if (rc) - CAM_ERR(CAM_OIS, - "Failed with driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_ois_subdev_close(struct v4l2_subdev *sd, +static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_ois_ctrl_t *o_ctrl = @@ -50,6 +28,48 @@ static int cam_ois_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_ois_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OIS); + + if (crm_active) { + CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ois_subdev_close_internal(sd, fh); +} + +static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_driver_cmd(o_ctrl, arg); + if (rc) + CAM_ERR(CAM_OIS, + "Failed with driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + rc = cam_ois_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl, struct cam_ois_i2c_info_t *i2c_info) { @@ -144,6 +164,7 @@ static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE; o_ctrl->v4l2_dev_str.token = o_ctrl; + o_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 92a5d940f339..9c6e2f2a2060 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -9,29 +9,7 @@ #include "cam_sensor_core.h" #include "camera_main.h" -static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_sensor_ctrl_t *s_ctrl = - v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_sensor_driver_cmd(s_ctrl, arg); - if (rc) - CAM_ERR(CAM_SENSOR, - "Failed in Driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -static int cam_sensor_subdev_close(struct v4l2_subdev *sd, +static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_sensor_ctrl_t *s_ctrl = @@ -49,6 +27,49 @@ static int cam_sensor_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_sensor_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); + + if (crm_active) { + CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_sensor_subdev_close_internal(sd, fh); +} + +static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_sensor_driver_cmd(s_ctrl, arg); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_sensor_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + #ifdef CONFIG_COMPAT static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -122,6 +143,8 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE; s_ctrl->v4l2_dev_str.token = s_ctrl; + s_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); if (rc)