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

Commit 80b5c096 authored by Camera Software Integration's avatar Camera Software Integration Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: ife: check cdm hang in the ife config timeout" into camera-kernel.lnx.1.0

parents a908dbc7 370b0928
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_CDM_H_
@@ -52,6 +52,7 @@ enum cam_cdm_hw_process_intf_cmd {
	CAM_CDM_HW_INTF_CMD_RELEASE,
	CAM_CDM_HW_INTF_CMD_SUBMIT_BL,
	CAM_CDM_HW_INTF_CMD_RESET_HW,
	CAM_CDM_HW_INTF_CMD_HANG_DETECT,
	CAM_CDM_HW_INTF_CMD_INVALID,
};

@@ -217,6 +218,7 @@ struct cam_cdm {
	atomic_t bl_done;
	struct cam_cdm_hw_mem gen_irq;
	uint32_t cpas_handle;
	atomic_t work_record;
};

/* struct cam_cdm_private_dt_data - CDM hw custom dt data */
+26 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/delay.h>
@@ -579,6 +579,31 @@ int cam_cdm_process_cmd(void *hw_priv,
			*((uint32_t *)cmd_args));
		break;
	}
	case CAM_CDM_HW_INTF_CMD_HANG_DETECT: {
		uint32_t *handle = cmd_args;
		int idx;
		struct cam_cdm_client *client;

		if (sizeof(uint32_t) != arg_size) {
			CAM_ERR(CAM_CDM,
				"Invalid CDM cmd %d size=%x for handle=%x",
				cmd, arg_size, *handle);
				return -EINVAL;
		}

		idx = CAM_CDM_GET_CLIENT_IDX(*handle);
		mutex_lock(&cdm_hw->hw_mutex);
		client = core->clients[idx];
		if ((!client) || (*handle != client->handle)) {
			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x",
				client, *handle);
			mutex_unlock(&cdm_hw->hw_mutex);
			break;
		}
		rc = cam_hw_cdm_hang_detect(cdm_hw, *handle);
		mutex_unlock(&cdm_hw->hw_mutex);
		break;
	}
	default:
		CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd);
		break;
+2 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_CDM_CORE_COMMON_H_
@@ -37,6 +37,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw,
	struct cam_cdm_hw_intf_cmd_submit_bl *req,
	struct cam_cdm_client *client);
int cam_hw_cdm_hang_detect(struct cam_hw_info *cdm_hw, uint32_t handle);
struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag(
	uint32_t tag, struct list_head *bl_list);
void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
+27 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/delay.h>
@@ -563,6 +563,10 @@ static void cam_hw_cdm_work(struct work_struct *work)
			CAM_DBG(CAM_CDM, "inline IRQ data=0x%x",
				payload->irq_data);
			mutex_lock(&cdm_hw->hw_mutex);

			if (atomic_read(&core->work_record))
				atomic_dec(&core->work_record);

			list_for_each_entry_safe(node, tnode,
					&core->bl_request_list, entry) {
				if (node->request_type ==
@@ -689,6 +693,9 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
		payload->hw = cdm_hw;
		INIT_WORK((struct work_struct *)&payload->work,
			cam_hw_cdm_work);
		if (payload->irq_status &
			CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK)
			atomic_inc(&cdm_core->work_record);
		work_status = queue_work(cdm_core->work_queue, &payload->work);
		if (work_status == false) {
			CAM_ERR(CAM_CDM, "Failed to queue work for irq=0x%x",
@@ -700,6 +707,22 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
	return IRQ_HANDLED;
}

int cam_hw_cdm_hang_detect(struct cam_hw_info *cdm_hw, uint32_t handle)
{
	struct cam_cdm *cdm_core = NULL;
	int rc = -1;

	cdm_core = (struct cam_cdm *)cdm_hw->core_info;

	if (atomic_read(&cdm_core->work_record)) {
		CAM_WARN(CAM_CDM,
			"workqueue got delayed, work_record :%u",
			 atomic_read(&cdm_core->work_record));
		rc = 0;
	}
	return rc;
}

int cam_hw_cdm_alloc_genirq_mem(void *hw_priv)
{
	struct cam_hw_info *cdm_hw = hw_priv;
@@ -775,6 +798,7 @@ int cam_hw_cdm_init(void *hw_priv,
	CAM_DBG(CAM_CDM, "Enable soc done");

/* Before triggering the reset to HW, clear the reset complete */
	atomic_set(&cdm_core->work_record, 0);
	atomic_set(&cdm_core->error, 0);
	atomic_set(&cdm_core->bl_done, 0);
	reinit_completion(&cdm_core->reset_complete);
@@ -824,6 +848,7 @@ int cam_hw_cdm_deinit(void *hw_priv,

	soc_info = &cdm_hw->soc_info;
	cdm_core = cdm_hw->core_info;
	atomic_set(&cdm_core->work_record, 0);
	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
	if (rc) {
		CAM_ERR(CAM_CDM, "disable platform failed");
@@ -888,6 +913,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev)
		cdm_core->flags = CAM_CDM_FLAG_PRIVATE_CDM;

	cdm_core->bl_tag = 0;
	atomic_set(&cdm_core->work_record, 0);
	cdm_core->id = cam_hw_cdm_get_id_by_name(cdm_core->name);
	if (cdm_core->id >= CAM_CDM_MAX) {
		CAM_ERR(CAM_CDM, "Failed to get CDM HW name for %s",
+28 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/delay.h>
@@ -379,6 +379,33 @@ int cam_cdm_reset_hw(uint32_t handle)
}
EXPORT_SYMBOL(cam_cdm_reset_hw);

int cam_cdm_detect_hang_error(uint32_t handle)
{
	uint32_t hw_index;
	int rc = -EINVAL;
	struct cam_hw_intf *hw;

	if (get_cdm_mgr_refcount()) {
		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
		rc = -EPERM;
		return rc;
	}

	hw_index = CAM_CDM_GET_HW_IDX(handle);
	if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) {
		hw = cdm_mgr.nodes[hw_index].device;
		if (hw && hw->hw_ops.process_cmd)
			rc = hw->hw_ops.process_cmd(hw->hw_priv,
				CAM_CDM_HW_INTF_CMD_HANG_DETECT,
				&handle,
				sizeof(handle));
	}
	put_cdm_mgr_refcount();

	return rc;
}
EXPORT_SYMBOL(cam_cdm_detect_hang_error);

int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw,
	struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
	uint32_t *index)
Loading