Browse Source

msm: camera: isp: Updates to CSID IRQ handling

When streaming off, issue a reset and then maskout all CSID
IRQs together as opposed to manipulating the mask bit by bit.
There is no atomic way to maskout all IRQs, in the process of
masking out IRQ bits an IRQ could still fire. This change ensures
we maskout the IRQs in a clean way post that unsubscribe for
those events from the IRQ controller. The change also ensures
the rx input is cut off prior to issuing a SW reset, this is
to rule out any spurious activity in HW caused due to incoming
data. At the time of the SW reset we are certain, we are not
in the middle of processing frames.

CRs-Fixed: 3336496
Change-Id: I1f714d290d31bb744809b2df9e2a4245b59641fe
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 2 years ago
parent
commit
927451569c

+ 63 - 4
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -461,11 +461,14 @@ static inline void __cam_irq_controller_disable_irq(
 {
 	struct cam_irq_register_obj *irq_register;
 	uint32_t *update_mask;
-	int i, priority;
+	int i, priority = 0;
 
 	update_mask = evt_handler->evt_bit_mask_arr;
 	priority    = evt_handler->priority;
 
+	if (unlikely(priority >= CAM_IRQ_PRIORITY_MAX))
+		return;
+
 	for (i = 0; i < controller->num_registers; i++) {
 		irq_register = &controller->irq_register_arr[i];
 		irq_register->top_half_enable_mask[priority] &= ~update_mask[i];
@@ -475,17 +478,41 @@ static inline void __cam_irq_controller_disable_irq(
 	}
 }
 
+static inline void __cam_irq_controller_disable_irq_evt(
+	struct cam_irq_controller  *controller,
+	struct cam_irq_evt_handler *evt_handler)
+{
+	struct cam_irq_register_obj *irq_register;
+	uint32_t *update_mask;
+	int i, priority = 0;
+
+	update_mask = evt_handler->evt_bit_mask_arr;
+	priority    = evt_handler->priority;
+
+	if (unlikely(priority >= CAM_IRQ_PRIORITY_MAX))
+		return;
+
+	for (i = 0; i < controller->num_registers; i++) {
+		irq_register = &controller->irq_register_arr[i];
+		irq_register->top_half_enable_mask[priority] &= ~update_mask[i];
+		irq_register->aggr_mask &= ~update_mask[i];
+	}
+}
+
 static inline void __cam_irq_controller_enable_irq(
 	struct cam_irq_controller  *controller,
 	struct cam_irq_evt_handler *evt_handler)
 {
 	struct cam_irq_register_obj *irq_register;
 	uint32_t *update_mask;
-	int i, priority;
+	int i, priority = 0;
 
 	update_mask = evt_handler->evt_bit_mask_arr;
 	priority    = evt_handler->priority;
 
+	if (unlikely(priority >= CAM_IRQ_PRIORITY_MAX))
+		return;
+
 	for (i = 0; i < controller->num_registers; i++) {
 		irq_register = &controller->irq_register_arr[i];
 		irq_register->top_half_enable_mask[priority] |= update_mask[i];
@@ -709,6 +736,37 @@ end:
 	return rc;
 }
 
+int cam_irq_controller_unsubscribe_irq_evt(void *irq_controller,
+	uint32_t handle)
+{
+	struct cam_irq_controller   *controller  = irq_controller;
+	struct cam_irq_evt_handler  *evt_handler = NULL;
+	unsigned long               flags = 0;
+	int                         rc = 0;
+
+	flags = cam_irq_controller_lock_irqsave(controller);
+
+
+	rc = cam_irq_controller_find_event_handle(controller, handle,
+		&evt_handler);
+	if (rc)
+		goto end;
+
+	list_del_init(&evt_handler->list_node);
+	list_del_init(&evt_handler->th_list_node);
+
+	__cam_irq_controller_disable_irq_evt(controller, evt_handler);
+	cam_irq_controller_clear_irq(controller, evt_handler);
+
+	kfree(evt_handler->evt_bit_mask_arr);
+	kfree(evt_handler);
+
+end:
+	cam_irq_controller_unlock_irqrestore(controller, flags);
+
+	return rc;
+}
+
 /**
  * cam_irq_controller_match_bit_mask()
  *
@@ -833,7 +891,8 @@ void cam_irq_controller_disable_all(void *priv)
 
 	for (i = 0; i < controller->num_registers; i++) {
 		irq_register = &controller->irq_register_arr[i];
-		memset(irq_register->top_half_enable_mask, 0, CAM_IRQ_PRIORITY_MAX);
+		memset(irq_register->top_half_enable_mask, 0,
+			 sizeof(irq_register->top_half_enable_mask));
 		irq_register->aggr_mask = 0;
 		cam_io_w_mb(0x0, controller->mem_base + irq_register->mask_reg_offset);
 		cam_io_w_mb(controller->clear_all_bitmask, controller->mem_base +

+ 17 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_IRQ_CONTROLLER_H_
@@ -201,6 +201,7 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
  * cam_irq_controller_unsubscribe_irq()
  *
  * @brief:               Unsubscribe to IRQ events previously subscribed to.
+ *                       Masks out the correspondings events from source
  *
  * @irq_controller:      Pointer to IRQ Controller that controls this event IRQ
  * @handle:              Handle returned on successful subscribe used to
@@ -212,6 +213,21 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
 int cam_irq_controller_unsubscribe_irq(void *irq_controller,
 	uint32_t handle);
 
+/*
+ * cam_irq_controller_unsubscribe_irq_evt()
+ *
+ * @brief:               Unsubscribe to IRQ event payloads previously subscribed to
+ *
+ * @irq_controller:      Pointer to IRQ Controller that controls this event IRQ
+ * @handle:              Handle returned on successful subscribe used to
+ *                       identify the handler object
+ *
+ * @return:              0: Success
+ *                       Negative: Failure
+ */
+int cam_irq_controller_unsubscribe_irq_evt(void *irq_controller,
+	uint32_t handle);
+
 /*
  * cam_irq_controller_deinit()
  *

+ 279 - 58
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -807,29 +807,20 @@ static int cam_ife_csid_ver2_stop_csi2_in_err(
 	return 0;
 }
 
-static int cam_ife_csid_ver2_disable_csi2(
-	struct cam_ife_csid_ver2_hw  *csid_hw)
+static inline void cam_ife_csid_ver2_maskout_rx_irqs(
+	struct cam_ife_csid_ver2_hw *csid_hw)
 {
-	const struct cam_ife_csid_ver2_reg_info *csid_reg;
-	struct cam_hw_soc_info                  *soc_info;
-	int rc = 0;
-
-	soc_info = &csid_hw->hw_info->soc_info;
-	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
-			csid_hw->core_info->csid_reg;
-	CAM_DBG(CAM_ISP, "CSID:%u Disable csi2 rx",
-		csid_hw->hw_intf->hw_idx);
-
-	if (!csid_hw->flags.rx_enabled) {
-		CAM_DBG(CAM_ISP, "CSID:%u Rx already disabled",
-			csid_hw->hw_intf->hw_idx);
-		return 0;
-	}
+	int rc;
 
 	if (csid_hw->rx_cfg.irq_handle) {
 		rc = cam_irq_controller_unsubscribe_irq(
 			csid_hw->rx_irq_controller,
 			csid_hw->rx_cfg.irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe rx info irq for CSID:%u rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+
 		csid_hw->rx_cfg.irq_handle = 0;
 	}
 
@@ -837,6 +828,11 @@ static int cam_ife_csid_ver2_disable_csi2(
 		rc = cam_irq_controller_unsubscribe_irq(
 			csid_hw->rx_irq_controller,
 			csid_hw->rx_cfg.err_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe rx err irq for CSID:%u rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+
 		csid_hw->rx_cfg.err_irq_handle = 0;
 	}
 
@@ -844,11 +840,85 @@ static int cam_ife_csid_ver2_disable_csi2(
 		rc = cam_irq_controller_unsubscribe_irq(
 			csid_hw->top_irq_controller,
 			csid_hw->rx_cfg.top_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe rx irq in top for CSID:%u rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+
 		csid_hw->rx_cfg.irq_handle = 0;
+		cam_irq_controller_unregister_dependent(csid_hw->top_irq_controller,
+			csid_hw->rx_irq_controller);
+	}
+}
+
+static inline void cam_ife_csid_ver2_disable_rx_evts(
+	struct cam_ife_csid_ver2_hw *csid_hw)
+{
+	int rc;
+
+	if (csid_hw->rx_cfg.irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->rx_irq_controller,
+			csid_hw->rx_cfg.irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe rx info irq evt for CSID:%u rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		csid_hw->rx_cfg.irq_handle = 0;
+	}
+
+	if (csid_hw->rx_cfg.err_irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->rx_irq_controller,
+			csid_hw->rx_cfg.err_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe rx err irq evt for CSID:%u rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		csid_hw->rx_cfg.err_irq_handle = 0;
+	}
+
+	if (csid_hw->rx_cfg.top_irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->top_irq_controller,
+			csid_hw->rx_cfg.top_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe rx irq evt in top for CSID:%u rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
 
+		csid_hw->rx_cfg.irq_handle = 0;
 		cam_irq_controller_unregister_dependent(csid_hw->top_irq_controller,
 			csid_hw->rx_irq_controller);
 	}
+}
+
+
+static int cam_ife_csid_ver2_disable_csi2(
+	bool maskout_irqs,
+	struct cam_ife_csid_ver2_hw *csid_hw)
+{
+	const struct cam_ife_csid_ver2_reg_info *csid_reg;
+	struct cam_hw_soc_info                  *soc_info;
+
+	soc_info = &csid_hw->hw_info->soc_info;
+	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
+			csid_hw->core_info->csid_reg;
+	CAM_DBG(CAM_ISP, "CSID:%u Disable csi2 rx",
+		csid_hw->hw_intf->hw_idx);
+
+	if (!csid_hw->flags.rx_enabled) {
+		CAM_DBG(CAM_ISP, "CSID:%u Rx already disabled",
+			csid_hw->hw_intf->hw_idx);
+		return 0;
+	}
+
+	if (maskout_irqs)
+		cam_ife_csid_ver2_maskout_rx_irqs(csid_hw);
+	else
+		cam_ife_csid_ver2_disable_rx_evts(csid_hw);
 
 	csid_hw->flags.rx_enabled = false;
 
@@ -2268,11 +2338,13 @@ static int cam_ife_csid_ver2_internal_reset(
 	uint32_t val = 0;
 	struct cam_ife_csid_ver2_reg_info *csid_reg;
 	struct cam_hw_soc_info                *soc_info;
+	const struct cam_ife_csid_csi2_rx_reg_info *csi2_reg;
 	void __iomem *mem_base;
 	int rc = 0;
 
 	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
 			csid_hw->core_info->csid_reg;
+	csi2_reg = csid_reg->csi2_reg;
 
 	soc_info = &csid_hw->hw_info->soc_info;
 	mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
@@ -2283,6 +2355,12 @@ static int cam_ife_csid_ver2_internal_reset(
 		return -EINVAL;
 	}
 
+	/* Input cut off prior to SW reset */
+	if (rst_cmd == CAM_IFE_CSID_RESET_CMD_SW_RST) {
+		cam_io_w_mb(0x0, mem_base + csi2_reg->cfg0_addr);
+		cam_io_w_mb(0x0, mem_base + csi2_reg->cfg1_addr);
+	}
+
 	if (csid_hw->sync_mode == CAM_ISP_HW_SYNC_SLAVE &&
 		rst_cmd == CAM_IFE_CSID_RESET_CMD_HW_RST)
 		goto wait_only;
@@ -2379,64 +2457,157 @@ int cam_ife_csid_ver2_reset(void *hw_priv,
 	return rc;
 }
 
-static int cam_ife_csid_ver2_disable_path(
-	struct cam_ife_csid_ver2_hw     *csid_hw,
-	struct cam_isp_resource_node    *res)
+static inline void cam_ife_csid_ver2_maskout_path_irqs(
+	int32_t res_id,
+	struct cam_ife_csid_ver2_hw *csid_hw,
+	struct cam_ife_csid_ver2_path_cfg *path_cfg)
 {
-	const struct cam_ife_csid_ver2_reg_info *csid_reg;
-	struct cam_ife_csid_ver2_path_cfg       *path_cfg;
-	int                                      rc = 0;
+	int rc;
 
-	if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
-		CAM_ERR(CAM_ISP,
-			"CSID:%u path res type:%d res_id:%d Invalid state:%d",
-			csid_hw->hw_intf->hw_idx,
-			res->res_type, res->res_id, res->res_state);
-		return -EINVAL;
+	if (path_cfg->err_irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq(
+			csid_hw->path_irq_controller[res_id],
+				path_cfg->err_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path err irq CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		path_cfg->err_irq_handle = 0;
 	}
 
-	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
-		CAM_DBG(CAM_ISP, "CSID:%u Invalid res id%d",
-			csid_hw->hw_intf->hw_idx, res->res_id);
-		return -EINVAL;
+	if (path_cfg->irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq(
+			csid_hw->path_irq_controller[res_id],
+			path_cfg->irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path info irq CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		path_cfg->irq_handle = 0;
 	}
 
-	path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
-	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
-			csid_hw->core_info->csid_reg;
+	if (path_cfg->discard_irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq(
+			csid_hw->path_irq_controller[res_id],
+			path_cfg->discard_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path discard irq CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		path_cfg->discard_irq_handle = 0;
+	}
 
 	if (path_cfg->top_irq_handle) {
 		rc = cam_irq_controller_unsubscribe_irq(
 			csid_hw->top_irq_controller,
 			path_cfg->top_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path irq in top CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
 		path_cfg->top_irq_handle = 0;
 
 		rc = cam_irq_controller_unregister_dependent(
 			csid_hw->top_irq_controller,
-			csid_hw->path_irq_controller[res->res_id]);
+			csid_hw->path_irq_controller[res_id]);
 	}
+}
 
-	if (path_cfg->irq_handle) {
-		rc = cam_irq_controller_unsubscribe_irq(
-			csid_hw->path_irq_controller[res->res_id],
-			path_cfg->irq_handle);
-		path_cfg->irq_handle = 0;
-	}
+static inline void cam_ife_csid_ver2_disable_path_irqs_evts(
+	int32_t res_id,
+	struct cam_ife_csid_ver2_hw *csid_hw,
+	struct cam_ife_csid_ver2_path_cfg *path_cfg)
+{
+	int rc;
 
 	if (path_cfg->err_irq_handle) {
-		rc = cam_irq_controller_unsubscribe_irq(
-			csid_hw->path_irq_controller[res->res_id],
-			path_cfg->err_irq_handle);
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->path_irq_controller[res_id],
+				path_cfg->err_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path err irq evt CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
 		path_cfg->err_irq_handle = 0;
 	}
 
+	if (path_cfg->irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->path_irq_controller[res_id],
+			path_cfg->irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path info irq evt CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		path_cfg->irq_handle = 0;
+	}
+
 	if (path_cfg->discard_irq_handle) {
-		rc = cam_irq_controller_unsubscribe_irq(
-			csid_hw->path_irq_controller[res->res_id],
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->path_irq_controller[res_id],
 			path_cfg->discard_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path discard irq evt CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
 		path_cfg->discard_irq_handle = 0;
 	}
 
+	if (path_cfg->top_irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq_evt(
+			csid_hw->top_irq_controller,
+			path_cfg->top_irq_handle);
+		if (rc)
+			CAM_WARN(CAM_ISP,
+				"Failed to unsubscribe path irq in top evt CSID:%u rc: %d",
+				csid_hw->hw_intf->hw_idx, rc);
+
+		path_cfg->top_irq_handle = 0;
+
+		rc = cam_irq_controller_unregister_dependent(
+			csid_hw->top_irq_controller,
+			csid_hw->path_irq_controller[res_id]);
+	}
+}
+
+static int cam_ife_csid_ver2_disable_path(
+	bool                             maskout_irqs,
+	struct cam_ife_csid_ver2_hw     *csid_hw,
+	struct cam_isp_resource_node    *res)
+{
+	struct cam_ife_csid_ver2_path_cfg       *path_cfg;
+	int                                      rc = 0;
+
+	if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
+		CAM_ERR(CAM_ISP,
+			"CSID:%u path res type:%d res_id:%d Invalid state:%d",
+			csid_hw->hw_intf->hw_idx,
+			res->res_type, res->res_id, res->res_state);
+		return -EINVAL;
+	}
+
+	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
+		CAM_DBG(CAM_ISP, "CSID:%u Invalid res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_id);
+		return -EINVAL;
+	}
+
+	path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
+
+	if (maskout_irqs)
+		cam_ife_csid_ver2_maskout_path_irqs(res->res_id,
+			csid_hw, path_cfg);
+	else
+		cam_ife_csid_ver2_disable_path_irqs_evts(res->res_id,
+			csid_hw, path_cfg);
+
 	/* Reset frame drop fields at stream off */
 	path_cfg->discard_init_frames = false;
 	path_cfg->skip_discard_frame_cfg = false;
@@ -4596,7 +4767,7 @@ static int cam_ife_csid_ver2_disable_core(
 	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
 			csid_hw->core_info->csid_reg;
 	top_reg = csid_reg->top_reg;
-	cam_ife_csid_ver2_disable_csi2(csid_hw);
+	cam_ife_csid_ver2_disable_csi2(true, csid_hw);
 
 	/* Disable the top IRQ interrupt */
 	cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
@@ -4696,7 +4867,7 @@ int cam_ife_csid_ver2_deinit_hw(void *hw_priv,
 	case CAM_IFE_PIX_PATH_RES_RDI_2:
 	case CAM_IFE_PIX_PATH_RES_RDI_3:
 	case CAM_IFE_PIX_PATH_RES_RDI_4:
-		rc = cam_ife_csid_ver2_disable_path(csid_hw, res);
+		rc = cam_ife_csid_ver2_disable_path(true, csid_hw, res);
 		break;
 	default:
 		CAM_ERR(CAM_ISP, "CSID:%u Invalid res type%d",
@@ -4991,6 +5162,45 @@ end:
 	return rc;
 }
 
+static void cam_ife_csid_ver2_maskout_all_irqs(
+	struct cam_ife_csid_ver2_hw *csid_hw,
+	struct cam_csid_hw_stop_args *csid_stop)
+{
+	int i;
+	struct cam_hw_soc_info *soc_info;
+	const struct cam_ife_csid_ver2_reg_info *csid_reg;
+	const struct cam_ife_csid_csi2_rx_reg_info *csi2_reg;
+	const struct cam_ife_csid_ver2_path_reg_info *path_reg = NULL;
+	void __iomem *mem_base;
+	struct cam_isp_resource_node           *res;
+
+	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
+		csid_hw->core_info->csid_reg;
+	csi2_reg  = csid_reg->csi2_reg;
+	soc_info = &csid_hw->hw_info->soc_info;
+	mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
+
+	/* Disable rx */
+	if (!csid_hw->flags.offline_mode)
+		cam_io_w_mb(0x0, mem_base + csi2_reg->irq_mask_addr);
+
+	for (i = 0; i < csid_stop->num_res; i++) {
+		res = csid_stop->node_res[i];
+		path_reg = csid_reg->path_reg[res->res_id];
+
+		/* Disable path */
+		cam_io_w_mb(0x0, mem_base + path_reg->irq_mask_addr);
+	}
+
+	/* Disable buf done */
+	cam_io_w_mb(0x0, mem_base +
+		csid_reg->cmn_reg->buf_done_irq_mask_addr);
+
+	/* Disable top except rst_done */
+	cam_io_w_mb(csid_reg->cmn_reg->top_reset_irq_mask,
+		mem_base + csid_reg->cmn_reg->top_irq_mask_addr);
+}
+
 int cam_ife_csid_ver2_stop(void *hw_priv,
 	void *stop_args, uint32_t arg_size)
 {
@@ -5039,6 +5249,7 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 				(void *)&halt_resume_info);
 	}
 
+	/* Issue a halt & reset to ensure there is no HW activity post the halt block */
 	reset.reset_type = (csid_hw->flags.fatal_err_detected) ? CAM_IFE_CSID_RESET_GLOBAL :
 		CAM_IFE_CSID_RESET_PATH;
 	cam_ife_csid_ver2_reset(hw_priv, &reset,
@@ -5046,10 +5257,14 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 
 	atomic_set(&csid_hw->discard_frame_per_path, 0);
 	mutex_lock(&csid_hw->hw_info->hw_mutex);
+
+	/* Mask out all irqs from HW */
+	cam_ife_csid_ver2_maskout_all_irqs(csid_hw, csid_stop);
+
 	for (i = 0; i < csid_stop->num_res; i++) {
 
 		res = csid_stop->node_res[i];
-		rc = cam_ife_csid_ver2_disable_path(csid_hw, res);
+		rc = cam_ife_csid_ver2_disable_path(false, csid_hw, res);
 		res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
 		CAM_DBG(CAM_ISP, "CSID:%u res_type %d Resource[id:%d name:%s]",
 			csid_hw->hw_intf->hw_idx,
@@ -5079,7 +5294,7 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 		csid_hw->top_info_irq_handle = 0;
 	}
 
-	cam_ife_csid_ver2_disable_csi2(csid_hw);
+	cam_ife_csid_ver2_disable_csi2(false, csid_hw);
 	if (csid_hw->debug_info.test_bus_enabled)
 		cam_ife_csid_ver2_testbus_config(csid_hw, 0x0);
 
@@ -6303,7 +6518,8 @@ static int cam_ife_csid_hw_init_irq(
 	soc_info = &csid_hw->hw_info->soc_info;
 	mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
 
-	rc = cam_irq_controller_init("csid_top", mem_base, csid_reg->top_irq_reg_info,
+	snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid%d_top", csid_hw->hw_intf->hw_idx);
+	rc = cam_irq_controller_init(name, mem_base, csid_reg->top_irq_reg_info,
 		&csid_hw->top_irq_controller);
 
 	if (rc) {
@@ -6313,7 +6529,8 @@ static int cam_ife_csid_hw_init_irq(
 		return rc;
 	}
 
-	rc = cam_irq_controller_init("csid_rx", mem_base, csid_reg->rx_irq_reg_info,
+	snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid%d_rx", csid_hw->hw_intf->hw_idx);
+	rc = cam_irq_controller_init(name, mem_base, csid_reg->rx_irq_reg_info,
 		&csid_hw->rx_irq_controller);
 
 	if (rc) {
@@ -6322,7 +6539,8 @@ static int cam_ife_csid_hw_init_irq(
 		goto deinit_controller;
 	}
 
-	rc = cam_irq_controller_init("csid_buf_done", mem_base, csid_reg->buf_done_irq_reg_info,
+	snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid%d_buf_done", csid_hw->hw_intf->hw_idx);
+	rc = cam_irq_controller_init(name, mem_base, csid_reg->buf_done_irq_reg_info,
 		&csid_hw->buf_done_irq_controller);
 
 	if (rc) {
@@ -6332,7 +6550,8 @@ static int cam_ife_csid_hw_init_irq(
 	}
 
 	if (csid_reg->cmn_reg->num_pix) {
-		rc = cam_irq_controller_init("csid_ipp", mem_base,
+		snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid%d_ipp", csid_hw->hw_intf->hw_idx);
+		rc = cam_irq_controller_init(name, mem_base,
 			csid_reg->path_irq_reg_info[CAM_IFE_PIX_PATH_RES_IPP],
 			&csid_hw->path_irq_controller[CAM_IFE_PIX_PATH_RES_IPP]);
 
@@ -6344,7 +6563,8 @@ static int cam_ife_csid_hw_init_irq(
 	}
 
 	if (csid_reg->cmn_reg->num_ppp) {
-		rc = cam_irq_controller_init("csid_ppp", mem_base,
+		snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid%d_ppp", csid_hw->hw_intf->hw_idx);
+		rc = cam_irq_controller_init(name, mem_base,
 			csid_reg->path_irq_reg_info[CAM_IFE_PIX_PATH_RES_PPP],
 			&csid_hw->path_irq_controller[CAM_IFE_PIX_PATH_RES_PPP]);
 
@@ -6357,7 +6577,8 @@ static int cam_ife_csid_hw_init_irq(
 	}
 
 	for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
-		snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid_rdi%d", i);
+		snprintf(name, CAM_CSID_IRQ_CTRL_NAME_LEN, "csid%d_rdi%d",
+			csid_hw->hw_intf->hw_idx, i);
 		rc = cam_irq_controller_init(name, mem_base,
 			csid_reg->path_irq_reg_info[CAM_IFE_PIX_PATH_RES_RDI_0 + i],
 			&csid_hw->path_irq_controller[CAM_IFE_PIX_PATH_RES_RDI_0 + i]);