Răsfoiți Sursa

msm: camera: common: Add wrapper for presil locking

Presil IRQ handling requires running in a workqueue, with
wait for acknowledgement in io operations. This busy wait
should be done while holding a mutex lock as opposed to
spinlock in usual irq context. Add wrapper to switch from
spinlock to mutex for presil mode in irq controller and
cdm. Add the hw lock wrapper in hw interface header.

CRs-Fixed: 2932495
Change-Id: I7600eb1e6ae8746a39e76f6cb3a2652b255f2ddd
Signed-off-by: Suraj Dongre <[email protected]>
Signed-off-by: Mukund Madhusudan Atre <[email protected]>
Suraj Dongre 3 ani în urmă
părinte
comite
1d86110d7b

+ 13 - 12
drivers/cam_cdm/cam_cdm_hw_core.c

@@ -1552,10 +1552,10 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
 	CAM_DBG(CAM_CDM, "Got irq hw_version 0x%x from %s%u",
 		cdm_core->hw_version, soc_info->label_name,
 		soc_info->index);
-	spin_lock(&cdm_hw->hw_lock);
+	cam_hw_util_hw_lock(cdm_hw);
 	if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
 		CAM_DBG(CAM_CDM, "CDM is in power down state");
-		spin_unlock(&cdm_hw->hw_lock);
+		cam_hw_util_hw_unlock(cdm_hw);
 		return IRQ_HANDLED;
 	}
 	if (cdm_core->hw_version >= CAM_CDM_VERSION_2_1) {
@@ -1596,7 +1596,8 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
 		CAM_ERR(CAM_CDM, "Failed to read %s%u HW IRQ data",
 				soc_info->label_name,
 				soc_info->index);
-	spin_unlock(&cdm_hw->hw_lock);
+
+	cam_hw_util_hw_unlock(cdm_hw);
 
 	for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) {
 		if (!irq_status[i])
@@ -2112,7 +2113,7 @@ int cam_hw_cdm_init(void *hw_priv,
 	struct cam_hw_soc_info *soc_info = NULL;
 	struct cam_cdm *cdm_core = NULL;
 	int rc, i, reset_hw_hdl = 0x0;
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	if (!hw_priv)
 		return -EINVAL;
@@ -2127,9 +2128,9 @@ int cam_hw_cdm_init(void *hw_priv,
 			soc_info->label_name, soc_info->index);
 		goto end;
 	}
-	spin_lock_irqsave(&cdm_hw->hw_lock, flags);
+	flags = cam_hw_util_hw_lock_irqsave(cdm_hw);
 	cdm_hw->hw_state = CAM_HW_STATE_POWER_UP;
-	spin_unlock_irqrestore(&cdm_hw->hw_lock, flags);
+	cam_hw_util_hw_unlock_irqrestore(cdm_hw, flags);
 
 	CAM_DBG(CAM_CDM, "Enable soc done for %s%d",
 		soc_info->label_name, soc_info->index);
@@ -2170,9 +2171,9 @@ int cam_hw_cdm_init(void *hw_priv,
 
 disable_return:
 	rc = -EIO;
-	spin_lock_irqsave(&cdm_hw->hw_lock, flags);
+	flags = cam_hw_util_hw_lock_irqsave(cdm_hw);
 	cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
-	spin_unlock_irqrestore(&cdm_hw->hw_lock, flags);
+	cam_hw_util_hw_unlock_irqrestore(cdm_hw, flags);
 	cam_soc_util_disable_platform_resource(soc_info, true, true);
 end:
 	return rc;
@@ -2188,7 +2189,7 @@ int cam_hw_cdm_deinit(void *hw_priv,
 	int rc = 0, i;
 	uint32_t reset_val = 1;
 	long time_left;
-	unsigned long                             flags;
+	unsigned long flags = 0;
 
 	if (!hw_priv)
 		return -EINVAL;
@@ -2250,9 +2251,9 @@ int cam_hw_cdm_deinit(void *hw_priv,
 	for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++)
 		mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock);
 
-	spin_lock_irqsave(&cdm_hw->hw_lock, flags);
+	flags = cam_hw_util_hw_lock_irqsave(cdm_hw);
 	cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
-	spin_unlock_irqrestore(&cdm_hw->hw_lock, flags);
+	cam_hw_util_hw_unlock_irqrestore(cdm_hw, flags);
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc) {
 		CAM_ERR(CAM_CDM, "disable platform failed for %s%u",
@@ -2306,7 +2307,7 @@ static int cam_hw_cdm_component_bind(struct device *dev,
 	cdm_hw_intf->hw_type = CAM_HW_CDM;
 	cdm_hw->open_count = 0;
 	mutex_init(&cdm_hw->hw_mutex);
-	spin_lock_init(&cdm_hw->hw_lock);
+	cam_hw_util_init_hw_lock(cdm_hw);
 	init_completion(&cdm_hw->hw_complete);
 
 	rc = cam_hw_cdm_soc_get_dt_properties(cdm_hw, msm_cam_hw_cdm_dt_match);

+ 7 - 1
drivers/cam_core/cam_hw.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_HW_H_
@@ -30,6 +30,8 @@ enum cam_hw_state {
  * @soc_info:              Platform SOC properties for hardware
  * @node_info:             Private HW data related to nodes
  * @core_info:             Private HW data related to core logic
+ * @presil_hw_lock:        Mutex lock used for presil in place of hw_lock,
+ *                         for drivers like CDM
  *
  */
 struct cam_hw_info {
@@ -41,6 +43,10 @@ struct cam_hw_info {
 	struct cam_hw_soc_info          soc_info;
 	void                           *node_info;
 	void                           *core_info;
+
+#ifdef CONFIG_CAM_PRESIL
+	struct mutex                    presil_hw_lock;
+#endif
 };
 
 #endif /* _CAM_HW_H_ */

+ 63 - 0
drivers/cam_core/cam_hw_intf.h

@@ -7,6 +7,7 @@
 #define _CAM_HW_INTF_H_
 
 #include <linux/types.h>
+#include "cam_hw.h"
 
 /*
  * This file declares Constants, Enums, Structures and APIs to be used as
@@ -86,4 +87,66 @@ struct cam_hw_intf {
 typedef int (*cam_hw_mgr_event_cb_func)(void *priv, uint32_t evt_id,
 	void *evt_data);
 
+#ifdef CONFIG_CAM_PRESIL
+static inline void cam_hw_util_init_hw_lock(struct cam_hw_info *hw_info)
+{
+	mutex_init(&hw_info->presil_hw_lock);
+}
+
+static inline unsigned long cam_hw_util_hw_lock_irqsave(struct cam_hw_info *hw_info)
+{
+	mutex_lock(&hw_info->presil_hw_lock);
+
+	return 0;
+}
+
+static inline void cam_hw_util_hw_unlock_irqrestore(struct cam_hw_info *hw_info,
+	unsigned long flags)
+{
+	mutex_unlock(&hw_info->presil_hw_lock);
+}
+
+static inline void cam_hw_util_hw_lock(struct cam_hw_info *hw_info)
+{
+	mutex_lock(&hw_info->presil_hw_lock);
+}
+
+static inline void cam_hw_util_hw_unlock(struct cam_hw_info *hw_info)
+{
+	mutex_unlock(&hw_info->presil_hw_lock);
+}
+#else
+static inline void cam_hw_util_init_hw_lock(struct cam_hw_info *hw_info)
+{
+	spin_lock_init(&hw_info->hw_lock);
+}
+
+static inline unsigned long cam_hw_util_hw_lock_irqsave(struct cam_hw_info *hw_info)
+{
+	unsigned long flags = 0;
+
+	if (!in_irq())
+		spin_lock_irqsave(&hw_info->hw_lock, flags);
+
+	return flags;
+}
+
+static inline void cam_hw_util_hw_unlock_irqrestore(struct cam_hw_info *hw_info,
+	unsigned long flags)
+{
+	if (!in_irq())
+		spin_unlock_irqrestore(&hw_info->hw_lock, flags);
+}
+
+static inline void cam_hw_util_hw_lock(struct cam_hw_info *hw_info)
+{
+	spin_lock(&hw_info->hw_lock);
+}
+
+static inline void cam_hw_util_hw_unlock(struct cam_hw_info *hw_info)
+{
+	spin_unlock(&hw_info->hw_lock);
+}
+#endif /* CONFIG_CAM_PRESIL */
+
 #endif /* _CAM_HW_INTF_H_ */

+ 93 - 36
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c

@@ -11,6 +11,7 @@
 #include "cam_io_util.h"
 #include "cam_irq_controller.h"
 #include "cam_debug_util.h"
+#include "cam_common_util.h"
 
 /**
  * struct cam_irq_evt_handler:
@@ -94,12 +95,13 @@ struct cam_irq_register_obj {
  * @th_list_head:           List of handlers sorted by priority
  * @hdl_idx:                Unique identity of handler assigned on Subscribe.
  *                          Used to Unsubscribe.
- * @lock:                   Lock for use by controller
  * @th_payload:             Payload structure to be passed to top half handler
  * @is_dependent:           Flag to indicate is this controller is dependent on another controller
  * @dependent_controller:   Array of controllers that depend on this controller
  * @delayed_global_clear:   Flag to indicate if this controller issues global clear after dependent
  *                          controllers are handled
+ * @lock:                   Lock to be used by controller, Use mutex lock in presil mode,
+ *                          and spinlock in regular case
  */
 struct cam_irq_controller {
 	const char                     *name;
@@ -113,13 +115,84 @@ struct cam_irq_controller {
 	struct list_head                evt_handler_list_head;
 	struct list_head                th_list_head[CAM_IRQ_PRIORITY_MAX];
 	uint32_t                        hdl_idx;
-	spinlock_t                      lock;
 	struct cam_irq_th_payload       th_payload;
 	bool                            is_dependent;
 	struct cam_irq_controller      *dependent_controller[CAM_IRQ_MAX_DEPENDENTS];
 	bool                            delayed_global_clear;
+
+#ifdef CONFIG_CAM_PRESIL
+	struct mutex                    lock;
+#else
+	spinlock_t                      lock;
+#endif
 };
 
+#ifdef CONFIG_CAM_PRESIL
+static inline void cam_irq_controller_lock_init(struct cam_irq_controller *controller)
+{
+	mutex_init(&controller->lock);
+}
+
+static inline unsigned long cam_irq_controller_lock_irqsave(
+	struct cam_irq_controller *controller)
+{
+	mutex_lock(&controller->lock);
+
+	return 0;
+}
+
+static inline void cam_irq_controller_unlock_irqrestore(
+	struct cam_irq_controller *controller, unsigned long flags)
+{
+	mutex_unlock(&controller->lock);
+}
+
+static inline void cam_irq_controller_lock(struct cam_irq_controller *controller)
+{
+	mutex_lock(&controller->lock);
+}
+
+static inline void cam_irq_controller_unlock(struct cam_irq_controller *controller)
+{
+	mutex_unlock(&controller->lock);
+}
+#else
+static inline void cam_irq_controller_lock_init(struct cam_irq_controller *controller)
+{
+	spin_lock_init(&controller->lock);
+}
+
+static inline unsigned long cam_irq_controller_lock_irqsave(
+	struct cam_irq_controller *controller)
+{
+	unsigned long flags = 0;
+
+	if (!in_irq())
+		spin_lock_irqsave(&controller->lock, flags);
+
+	return flags;
+}
+
+static inline void cam_irq_controller_unlock_irqrestore(
+	struct cam_irq_controller *controller, unsigned long flags)
+{
+	if (!in_irq())
+		spin_unlock_irqrestore(&controller->lock, flags);
+}
+
+static inline void cam_irq_controller_lock(struct cam_irq_controller *controller)
+{
+	spin_lock(&controller->lock);
+}
+
+static inline void cam_irq_controller_unlock(struct cam_irq_controller *controller)
+{
+	spin_unlock(&controller->lock);
+}
+#endif
+
+
+
 int cam_irq_controller_unregister_dependent(void *primary_controller, void *secondary_controller)
 {
 	struct cam_irq_controller *ctrl_primary, *ctrl_secondary;
@@ -200,25 +273,6 @@ int cam_irq_controller_register_dependent(void *primary_controller, void *second
 	return 0;
 }
 
-static inline unsigned long cam_irq_controller_lock(
-	struct cam_irq_controller *controller)
-{
-	unsigned long flags = 0;
-
-	if (!in_irq())
-		spin_lock_irqsave(&controller->lock, flags);
-
-	return flags;
-}
-
-static inline void cam_irq_controller_unlock(
-	struct cam_irq_controller *controller,
-	unsigned long flags)
-{
-	if (!in_irq())
-		spin_unlock_irqrestore(&controller->lock, flags);
-}
-
 static inline void cam_irq_controller_clear_irq(
 	struct cam_irq_controller  *controller,
 	struct cam_irq_evt_handler *evt_handler)
@@ -358,7 +412,7 @@ int cam_irq_controller_init(const char       *name,
 	for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++)
 		INIT_LIST_HEAD(&controller->th_list_head[i]);
 
-	spin_lock_init(&controller->lock);
+	cam_irq_controller_lock_init(controller);
 
 	controller->hdl_idx = 1;
 	*irq_controller = controller;
@@ -506,7 +560,7 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
 	if (controller->hdl_idx > 0x3FFFFFFF)
 		controller->hdl_idx = 1;
 
-	flags = cam_irq_controller_lock(controller);
+	flags = cam_irq_controller_lock_irqsave(controller);
 
 	__cam_irq_controller_enable_irq(controller, evt_handler);
 
@@ -515,7 +569,7 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
 	list_add_tail(&evt_handler->th_list_node,
 		&controller->th_list_head[priority]);
 
-	cam_irq_controller_unlock(controller, flags);
+	cam_irq_controller_unlock_irqrestore(controller, flags);
 
 	return evt_handler->index;
 
@@ -554,7 +608,7 @@ int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
 	if (!controller)
 		return rc;
 
-	flags = cam_irq_controller_lock(controller);
+	flags = cam_irq_controller_lock_irqsave(controller);
 
 	rc = cam_irq_controller_find_event_handle(controller, handle,
 		&evt_handler);
@@ -565,7 +619,7 @@ int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
 	__cam_irq_controller_enable_irq(controller, evt_handler);
 
 end:
-	cam_irq_controller_unlock(controller, flags);
+	cam_irq_controller_unlock_irqrestore(controller, flags);
 
 	return rc;
 }
@@ -580,7 +634,7 @@ int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
 	if (!controller)
 		return rc;
 
-	flags = cam_irq_controller_lock(controller);
+	flags = cam_irq_controller_lock_irqsave(controller);
 
 	rc = cam_irq_controller_find_event_handle(controller, handle,
 		&evt_handler);
@@ -592,7 +646,7 @@ int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
 	cam_irq_controller_clear_irq(controller, evt_handler);
 
 end:
-	cam_irq_controller_unlock(controller, flags);
+	cam_irq_controller_unlock_irqrestore(controller, flags);
 
 	return rc;
 }
@@ -605,7 +659,7 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller,
 	unsigned long               flags = 0;
 	int                         rc = 0;
 
-	flags = cam_irq_controller_lock(controller);
+	flags = cam_irq_controller_lock_irqsave(controller);
 
 
 	rc = cam_irq_controller_find_event_handle(controller, handle,
@@ -623,7 +677,7 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller,
 	kfree(evt_handler);
 
 end:
-	cam_irq_controller_unlock(controller, flags);
+	cam_irq_controller_unlock_irqrestore(controller, flags);
 
 	return rc;
 }
@@ -824,9 +878,9 @@ static void cam_irq_controller_read_registers(struct cam_irq_controller *control
 			dep_controller = controller->dependent_controller[j];
 			CAM_DBG(CAM_IRQ_CTRL, "Reading dependent registers for %s",
 				dep_controller->name);
-			spin_lock(&dep_controller->lock);
+			cam_irq_controller_lock(dep_controller);
 			__cam_irq_controller_read_registers(dep_controller);
-			spin_unlock(&dep_controller->lock);
+			cam_irq_controller_unlock(dep_controller);
 		}
 	}
 
@@ -875,11 +929,14 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv, int evt_grp)
 	CAM_DBG(CAM_IRQ_CTRL,
 		"Locking: %s IRQ Controller: [%pK], lock handle: %pK",
 		controller->name, controller, &controller->lock);
-	spin_lock(&controller->lock);
+	cam_irq_controller_lock(controller);
+
 	if (!controller->is_dependent)
 		cam_irq_controller_read_registers(controller);
+
 	cam_irq_controller_process_th(controller, evt_grp);
-	spin_unlock(&controller->lock);
+
+	cam_irq_controller_unlock(controller);
 	CAM_DBG(CAM_IRQ_CTRL,
 		"Unlocked: %s IRQ Controller: %pK, lock handle: %pK",
 		controller->name, controller, &controller->lock);
@@ -899,7 +956,7 @@ int cam_irq_controller_update_irq(void *irq_controller, uint32_t handle,
 	if (!controller)
 		return rc;
 
-	flags = cam_irq_controller_lock(controller);
+	flags = cam_irq_controller_lock_irqsave(controller);
 
 	rc = cam_irq_controller_find_event_handle(controller, handle,
 		&evt_handler);
@@ -918,7 +975,7 @@ int cam_irq_controller_update_irq(void *irq_controller, uint32_t handle,
 	cam_irq_controller_clear_irq(controller, evt_handler);
 
 end:
-	cam_irq_controller_unlock(controller, flags);
+	cam_irq_controller_unlock_irqrestore(controller, flags);
 
 	return rc;
 }