Forráskód Böngészése

msm: camera: isp: Differentiate between page fault and bus overflow

When a page fault is encountered by IFE/SFE, as a side affect
a bus overflow is also seen, which results in CSID overflow.
In this change, CSID driver registers a callback with CPAS,
and on camnoc slave error irq notification CSID will
skip processing the overflow. This will avoid resetting
the SFE/IFE pipeline and all necessary logs for PF debug
will be available. With this change kernel will post only
one error event to userland for PF as opposed to two
for PF and bus overflow.

CRs-Fixed: 3175797
Change-Id: I9789314452075e2b943cf08b19002a645eafb16b
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 3 éve
szülő
commit
6099cf407d

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_common.h

@@ -331,6 +331,8 @@ struct cam_ife_csid_debug_info {
  * @offline_mode:           flag to indicate if csid in offline mode
  * @rdi_lcr_en:             flag to indicate if RDI to lcr is enabled
  * @sfe_en:                 flag to indicate if SFE is enabled
+ * @pf_err_detected:        flag to indicate if camnoc has encountered
+ *                          error - page fault
  */
 struct cam_ife_csid_hw_flags {
 	bool                  device_enabled;
@@ -345,6 +347,7 @@ struct cam_ife_csid_hw_flags {
 	bool                  offline_mode;
 	bool                  rdi_lcr_en;
 	bool                  sfe_en;
+	bool                  pf_err_detected;
 };
 
 /*

+ 1 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c

@@ -4724,7 +4724,7 @@ int cam_ife_csid_hw_ver1_init(struct cam_hw_intf  *hw_intf,
 		init_completion(&ife_csid_hw->irq_complete[i]);
 
 	rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info,
-			cam_ife_csid_irq, ife_csid_hw, is_custom);
+			cam_ife_csid_irq, NULL, ife_csid_hw, is_custom);
 	if (rc < 0) {
 		CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc",
 			hw_intf->hw_idx);

+ 35 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -58,6 +58,31 @@ static void cam_ife_csid_ver2_print_debug_reg_status(
 	struct cam_ife_csid_ver2_hw *csid_hw,
 	struct cam_isp_resource_node    *res);
 
+static bool cam_ife_csid_ver2_cpas_cb(
+	uint32_t handle, void *user_data, struct cam_cpas_irq_data *irq_data)
+{
+	bool handled = false;
+	struct cam_ife_csid_ver2_hw *csid_hw = (struct cam_ife_csid_ver2_hw *)user_data;
+
+	if (!csid_hw || !irq_data)
+		return false;
+
+	switch (irq_data->irq_type) {
+	case CAM_CAMNOC_IRQ_SLAVE_ERROR:
+		if (irq_data->u.slave_err.errlog0_low.err_code == CAM_CAMNOC_ADDRESS_DECODE_ERROR) {
+			csid_hw->flags.pf_err_detected = true;
+			CAM_DBG(CAM_ISP, "CPAS address decode error rxved for CSID[%u]",
+				csid_hw->hw_intf->hw_idx);
+		}
+		handled = true;
+		break;
+	default:
+		break;
+	}
+
+	return handled;
+}
+
 static bool cam_ife_csid_ver2_disable_sof_retime(
 	struct cam_ife_csid_ver2_hw     *csid_hw,
 	struct cam_isp_resource_node    *res)
@@ -1000,6 +1025,13 @@ static int cam_ife_csid_ver2_handle_event_err(
 		return 0;
 	}
 
+	/*
+	 * If PF is encountered skip notifying error to ctx, PF
+	 * handler will do the necessary notifications
+	 */
+	if (csid_hw->flags.pf_err_detected)
+		return 0;
+
 	evt.hw_idx   = csid_hw->hw_intf->hw_idx;
 	evt.reg_val  = irq_status;
 	evt.hw_type  = CAM_ISP_HW_TYPE_CSID;
@@ -2791,6 +2823,7 @@ int cam_ife_csid_ver2_release(void *hw_priv,
 			sizeof(struct cam_ife_csid_ver2_top_cfg));
 		memset(&csid_hw->debug_info, 0,
 			sizeof(struct cam_ife_csid_debug_info));
+		csid_hw->flags.pf_err_detected = false;
 		csid_hw->token = NULL;
 	}
 
@@ -4544,6 +4577,7 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 		cam_ife_csid_ver2_testbus_config(csid_hw, 0x0);
 
 	csid_hw->debug_info.test_bus_enabled = false;
+	csid_hw->flags.pf_err_detected = false;
 	mutex_unlock(&csid_hw->hw_info->hw_mutex);
 
 	return rc;
@@ -5794,7 +5828,7 @@ int cam_ife_csid_hw_ver2_init(struct cam_hw_intf *hw_intf,
 	atomic_set(&csid_hw->discard_frame_per_path, 0);
 
 	rc = cam_ife_csid_init_soc_resources(&csid_hw->hw_info->soc_info,
-			cam_ife_csid_irq, csid_hw, is_custom);
+			cam_ife_csid_irq, cam_ife_csid_ver2_cpas_cb, csid_hw, is_custom);
 	if (rc < 0) {
 		CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc",
 			hw_intf->hw_idx);

+ 6 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c

@@ -1,10 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #include <linux/slab.h>
 #include "cam_ife_csid_soc.h"
-#include "cam_cpas_api.h"
 #include "cam_debug_util.h"
 
 static int cam_ife_csid_get_dt_properties(struct cam_hw_soc_info *soc_info)
@@ -64,7 +64,8 @@ static int cam_ife_csid_request_platform_resource(
 }
 
 int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
-	irq_handler_t csid_irq_handler, void *irq_data, bool is_custom)
+	irq_handler_t csid_irq_handler, cam_cpas_client_cb_func cpas_cb,
+	void *data, bool is_custom)
 {
 	int rc = 0;
 	struct cam_cpas_register_params   cpas_register_param;
@@ -83,7 +84,7 @@ int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
 	/* Need to see if we want post process the clock list */
 
 	rc = cam_ife_csid_request_platform_resource(soc_info, csid_irq_handler,
-		irq_data);
+		data);
 	if (rc < 0) {
 		CAM_ERR(CAM_ISP,
 			"Error Request platform resources failed rc=%d", rc);
@@ -100,6 +101,8 @@ int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
 
 	cpas_register_param.cell_index = soc_info->index;
 	cpas_register_param.dev = soc_info->dev;
+	cpas_register_param.cam_cpas_client_cb = cpas_cb;
+	cpas_register_param.userdata = data;
 	rc = cam_cpas_register_client(&cpas_register_param);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);

+ 10 - 5
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h

@@ -1,12 +1,15 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_IFE_CSID_SOC_H_
 #define _CAM_IFE_CSID_SOC_H_
 
 #include "cam_isp_hw.h"
+#include "cam_cpas_api.h"
+
 
 /*
  * struct cam_csid_soc_private:
@@ -16,17 +19,17 @@
  * @cpas_handle:             Handle returned on registering with CPAS driver.
  *                           This handle is used for all further interface
  *                           with CPAS.
- * @rt_wrapper_base:        Base address of the RT-Wrapper if the hw is in rt-wrapper
+ * @rt_wrapper_base:         Base address of the RT-Wrapper if the hw is in rt-wrapper
+ * @max_width:               Maxinum allowed width
  * @is_ife_csid_lite:        Flag to indicate Whether a full csid or a Lite csid
  * @max_width_enabled:       Flag to enable max width restriction
- * @max_width:               Maxinum allowed width
  */
 struct cam_csid_soc_private {
 	uint32_t cpas_handle;
 	uint32_t rt_wrapper_base;
+	uint32_t max_width;
 	bool     is_ife_csid_lite;
 	bool     max_width_enabled;
-	uint32_t max_width;
 };
 
 /**
@@ -46,12 +49,14 @@ struct csid_device_soc_info {
  *
  * @soc_info:              soc info structure pointer
  * @csid_irq_handler:      irq handler function to be registered
- * @irq_data:              irq data for the callback function
+ * @cpas_cb:               handler for cpas cb
+ * @data:                  data for the callback functions
  * @is_custom:             for custom csid hw
  *
  */
 int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
-	irq_handler_t csid_irq_handler, void *irq_data, bool is_custom);
+	irq_handler_t csid_irq_handler, cam_cpas_client_cb_func cpas_cb,
+	void *data, bool is_custom);
 
 
 /**