Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8e3a419 authored by Harsh Shah's avatar Harsh Shah Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Avoid locking in IRQ context



Check if the thread is IRQ handler to avoid deadlock
trying to lock. The interrupt handler currently holds
the lock, so any other API being called from IRQ context
should not try to lock, else there will be recursion
leading to deadlock.

Change-Id: I6f70234b430286c94a0b558ebeb5b4393c06d995
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
parent b81eb44c
Loading
Loading
Loading
Loading
+29 −12
Original line number Diff line number Diff line
@@ -239,7 +239,8 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
	int                         i;
	int                         rc = 0;
	uint32_t                    irq_mask;
	unsigned long               flags;
	unsigned long               flags = 0;
	bool                        need_lock;

	if (!controller || !handler_priv || !evt_bit_mask_arr) {
		CAM_ERR(CAM_ISP,
@@ -301,6 +302,8 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
	if (controller->hdl_idx > 0x3FFFFFFF)
		controller->hdl_idx = 1;

	need_lock = !in_irq();
	if (need_lock)
		write_lock_irqsave(&controller->rw_lock, flags);
	for (i = 0; i < controller->num_registers; i++) {
		controller->irq_register_arr[i].top_half_enable_mask[priority]
@@ -313,6 +316,7 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
		cam_io_w_mb(irq_mask, controller->mem_base +
			controller->irq_register_arr[i].mask_reg_offset);
	}
	if (need_lock)
		write_unlock_irqrestore(&controller->rw_lock, flags);

	list_add_tail(&evt_handler->list_node,
@@ -334,11 +338,12 @@ int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
	struct cam_irq_controller  *controller  = irq_controller;
	struct cam_irq_evt_handler *evt_handler = NULL;
	struct cam_irq_evt_handler *evt_handler_temp;
	unsigned long               flags;
	unsigned long               flags = 0;
	unsigned int                i;
	uint32_t                    irq_mask;
	uint32_t                    found = 0;
	int                         rc = -EINVAL;
	bool                        need_lock;

	if (!controller)
		return rc;
@@ -356,6 +361,8 @@ int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
	if (!found)
		return rc;

	need_lock = !in_irq();
	if (need_lock)
		write_lock_irqsave(&controller->rw_lock, flags);
	for (i = 0; i < controller->num_registers; i++) {
		controller->irq_register_arr[i].
@@ -370,6 +377,7 @@ int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
		cam_io_w_mb(irq_mask, controller->mem_base +
		controller->irq_register_arr[i].mask_reg_offset);
	}
	if (need_lock)
		write_unlock_irqrestore(&controller->rw_lock, flags);

	return rc;
@@ -380,11 +388,12 @@ int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
	struct cam_irq_controller  *controller  = irq_controller;
	struct cam_irq_evt_handler *evt_handler = NULL;
	struct cam_irq_evt_handler *evt_handler_temp;
	unsigned long               flags;
	unsigned long               flags = 0;
	unsigned int                i;
	uint32_t                    irq_mask;
	uint32_t                    found = 0;
	int                         rc = -EINVAL;
	bool                        need_lock;

	if (!controller)
		return rc;
@@ -402,6 +411,8 @@ int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
	if (!found)
		return rc;

	need_lock = !in_irq();
	if (need_lock)
		write_lock_irqsave(&controller->rw_lock, flags);
	for (i = 0; i < controller->num_registers; i++) {
		controller->irq_register_arr[i].
@@ -429,6 +440,7 @@ int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
				controller->mem_base +
				controller->global_clear_offset);
	}
	if (need_lock)
		write_unlock_irqrestore(&controller->rw_lock, flags);

	return rc;
@@ -443,8 +455,9 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller,
	uint32_t                    i;
	uint32_t                    found = 0;
	uint32_t                    irq_mask;
	unsigned long               flags;
	unsigned long               flags = 0;
	int                         rc = -EINVAL;
	bool                        need_lock;

	list_for_each_entry_safe(evt_handler, evt_handler_temp,
		&controller->evt_handler_list_head, list_node) {
@@ -458,7 +471,10 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller,
		}
	}

	need_lock = !in_irq();

	if (found) {
		if (need_lock)
			write_lock_irqsave(&controller->rw_lock, flags);
		for (i = 0; i < controller->num_registers; i++) {
			controller->irq_register_arr[i].
@@ -485,6 +501,7 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller,
					controller->mem_base +
					controller->global_clear_offset);
		}
		if (need_lock)
			write_unlock_irqrestore(&controller->rw_lock, flags);

		kfree(evt_handler->evt_bit_mask_arr);