Loading drivers/cam_cdm/cam_cdm.h +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_ Loading Loading @@ -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, }; Loading Loading @@ -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 */ Loading drivers/cam_cdm/cam_cdm_core_common.c +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> Loading Loading @@ -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; Loading drivers/cam_cdm/cam_cdm_core_common.h +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_ Loading Loading @@ -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, Loading drivers/cam_cdm/cam_cdm_hw_core.c +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> Loading Loading @@ -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 == Loading Loading @@ -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", Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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", Loading drivers/cam_cdm/cam_cdm_intf.c +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> Loading Loading @@ -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 Loading
drivers/cam_cdm/cam_cdm.h +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_ Loading Loading @@ -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, }; Loading Loading @@ -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 */ Loading
drivers/cam_cdm/cam_cdm_core_common.c +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> Loading Loading @@ -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; Loading
drivers/cam_cdm/cam_cdm_core_common.h +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_ Loading Loading @@ -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, Loading
drivers/cam_cdm/cam_cdm_hw_core.c +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> Loading Loading @@ -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 == Loading Loading @@ -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", Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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", Loading
drivers/cam_cdm/cam_cdm_intf.c +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> Loading Loading @@ -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