Loading drivers/cam_cdm/cam_cdm_hw_core.c +5 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "camera_main.h" #include "cam_trace.h" #include "cam_req_mgr_workq.h" #include "cam_common_util.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 #define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff Loading Loading @@ -1215,8 +1216,10 @@ static void cam_hw_cdm_work(struct work_struct *work) return; } cam_req_mgr_thread_switch_delay_detect( payload->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "CDM workq schedule", payload->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); if (payload->irq_status & Loading drivers/cam_cdm/cam_cdm_virtual_core.c +6 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include <linux/delay.h> Loading @@ -20,6 +20,7 @@ #include "cam_cdm_soc.h" #include "cam_io_util.h" #include "cam_req_mgr_workq.h" #include "cam_common_util.h" #define CAM_CDM_VIRTUAL_NAME "qcom,cam_virtual_cdm" Loading @@ -34,8 +35,10 @@ static void cam_virtual_cdm_work(struct work_struct *work) cdm_hw = payload->hw; core = (struct cam_cdm *)cdm_hw->core_info; cam_req_mgr_thread_switch_delay_detect( payload->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "Virtual CDM workq schedule", payload->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); if (payload->irq_status & 0x2) { struct cam_cdm_bl_cb_request_entry *node; Loading drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +5 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "cpastop_v680_100.h" #include "cpastop_v165_100.h" #include "cam_req_mgr_workq.h" #include "cam_common_util.h" struct cam_camnoc_info *camnoc_info; struct cam_cpas_camnoc_qchannel *qchannel_info; Loading Loading @@ -598,8 +599,10 @@ static void cam_cpastop_work(struct work_struct *work) return; } cam_req_mgr_thread_switch_delay_detect( payload->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "CPAS workq schedule", payload->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); cpas_hw = payload->hw; cpas_core = (struct cam_cpas *) cpas_hw->core_info; Loading drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c +25 −2 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-2019, 2021 The Linux Foundation. All rights reserved. */ #include <linux/slab.h> Loading @@ -11,6 +11,14 @@ #include "cam_tasklet_util.h" #include "cam_irq_controller.h" #include "cam_debug_util.h" #include "cam_common_util.h" /* Threshold for scheduling delay in ms */ #define CAM_TASKLET_SCHED_TIME_THRESHOLD 5 /* Threshold for execution delay in ms */ #define CAM_TASKLET_EXE_TIME_THRESHOLD 10 #define CAM_TASKLETQ_SIZE 256 Loading @@ -27,6 +35,7 @@ static void cam_tasklet_action(unsigned long data); * @handler_priv: Private data passed at event subscribe * @bottom_half_handler: Function pointer for event handler in bottom * half context * @tasklet_enqueue_ts: enqueue time of tasklet * */ struct cam_tasklet_queue_cmd { Loading @@ -34,6 +43,7 @@ struct cam_tasklet_queue_cmd { void *payload; void *handler_priv; CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; ktime_t tasklet_enqueue_ts; }; /** Loading Loading @@ -209,6 +219,7 @@ void cam_tasklet_enqueue_cmd( tasklet_cmd->bottom_half_handler = bottom_half_handler; tasklet_cmd->payload = evt_payload_priv; tasklet_cmd->handler_priv = handler_priv; tasklet_cmd->tasklet_enqueue_ts = ktime_get(); spin_lock_irqsave(&tasklet->tasklet_lock, flags); list_add_tail(&tasklet_cmd->list, &tasklet->used_cmd_list); Loading Loading @@ -322,12 +333,24 @@ static void cam_tasklet_action(unsigned long data) { struct cam_tasklet_info *tasklet_info = NULL; struct cam_tasklet_queue_cmd *tasklet_cmd = NULL; ktime_t curr_time; tasklet_info = (struct cam_tasklet_info *)data; while (!cam_tasklet_dequeue_cmd(tasklet_info, &tasklet_cmd)) { cam_common_util_thread_switch_delay_detect( "Tasklet schedule", tasklet_cmd->tasklet_enqueue_ts, CAM_TASKLET_SCHED_TIME_THRESHOLD); curr_time = ktime_get(); tasklet_cmd->bottom_half_handler(tasklet_cmd->handler_priv, tasklet_cmd->payload); cam_common_util_thread_switch_delay_detect( "Tasklet execution", curr_time, CAM_TASKLET_EXE_TIME_THRESHOLD); cam_tasklet_put_cmd(tasklet_info, (void **)(&tasklet_cmd)); } } drivers/cam_req_mgr/cam_req_mgr_workq.c +13 −25 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_workq.h" #include "cam_debug_util.h" #include "cam_common_util.h" #define WORKQ_ACQUIRE_LOCK(workq, flags) {\ if ((workq)->in_irq) \ Loading Loading @@ -94,6 +95,7 @@ void cam_req_mgr_process_workq(struct work_struct *w) struct crm_workq_task *task; int32_t i = CRM_TASK_PRIORITY_0; unsigned long flags = 0; ktime_t curr_time; if (!w) { CAM_ERR(CAM_CRM, "NULL task pointer can not schedule"); Loading @@ -102,7 +104,11 @@ void cam_req_mgr_process_workq(struct work_struct *w) workq = (struct cam_req_mgr_core_workq *) container_of(w, struct cam_req_mgr_core_workq, work); cam_req_mgr_thread_switch_delay_detect(workq->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "CRM workq schedule", workq->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); curr_time = ktime_get(); while (i < CRM_TASK_PRIORITY_MAX) { WORKQ_ACQUIRE_LOCK(workq, flags); while (!list_empty(&workq->task.process_head[i])) { Loading @@ -119,6 +125,10 @@ void cam_req_mgr_process_workq(struct work_struct *w) WORKQ_RELEASE_LOCK(workq, flags); i++; } cam_common_util_thread_switch_delay_detect( "CRM workq execution", curr_time, CAM_WORKQ_EXE_TIME_THRESHOLD); } int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, Loading Loading @@ -165,8 +175,8 @@ int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d", task, atomic_read(&workq->task.pending_cnt)); workq->workq_scheduled_ts = ktime_get(); queue_work(workq->job, &workq->work); workq->workq_scheduled_ts = ktime_get(); WORKQ_RELEASE_LOCK(workq, flags); end: return rc; Loading Loading @@ -267,25 +277,3 @@ void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq) *crm_workq = NULL; } } void cam_req_mgr_thread_switch_delay_detect(ktime_t workq_scheduled) { uint64_t diff; ktime_t cur_time; struct timespec64 cur_ts; struct timespec64 workq_scheduled_ts; cur_time = ktime_get(); diff = ktime_ms_delta(cur_time, workq_scheduled); workq_scheduled_ts = ktime_to_timespec64(workq_scheduled); cur_ts = ktime_to_timespec64(cur_time); if (diff > CAM_WORKQ_RESPONSE_TIME_THRESHOLD) { CAM_WARN_RATE_LIMIT(CAM_CRM, "Workq delay detected %ld:%06ld %ld:%06ld %ld:", workq_scheduled_ts.tv_sec, workq_scheduled_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC, diff); } } Loading
drivers/cam_cdm/cam_cdm_hw_core.c +5 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "camera_main.h" #include "cam_trace.h" #include "cam_req_mgr_workq.h" #include "cam_common_util.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 #define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff Loading Loading @@ -1215,8 +1216,10 @@ static void cam_hw_cdm_work(struct work_struct *work) return; } cam_req_mgr_thread_switch_delay_detect( payload->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "CDM workq schedule", payload->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); if (payload->irq_status & Loading
drivers/cam_cdm/cam_cdm_virtual_core.c +6 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include <linux/delay.h> Loading @@ -20,6 +20,7 @@ #include "cam_cdm_soc.h" #include "cam_io_util.h" #include "cam_req_mgr_workq.h" #include "cam_common_util.h" #define CAM_CDM_VIRTUAL_NAME "qcom,cam_virtual_cdm" Loading @@ -34,8 +35,10 @@ static void cam_virtual_cdm_work(struct work_struct *work) cdm_hw = payload->hw; core = (struct cam_cdm *)cdm_hw->core_info; cam_req_mgr_thread_switch_delay_detect( payload->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "Virtual CDM workq schedule", payload->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); if (payload->irq_status & 0x2) { struct cam_cdm_bl_cb_request_entry *node; Loading
drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +5 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "cpastop_v680_100.h" #include "cpastop_v165_100.h" #include "cam_req_mgr_workq.h" #include "cam_common_util.h" struct cam_camnoc_info *camnoc_info; struct cam_cpas_camnoc_qchannel *qchannel_info; Loading Loading @@ -598,8 +599,10 @@ static void cam_cpastop_work(struct work_struct *work) return; } cam_req_mgr_thread_switch_delay_detect( payload->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "CPAS workq schedule", payload->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); cpas_hw = payload->hw; cpas_core = (struct cam_cpas *) cpas_hw->core_info; Loading
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c +25 −2 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-2019, 2021 The Linux Foundation. All rights reserved. */ #include <linux/slab.h> Loading @@ -11,6 +11,14 @@ #include "cam_tasklet_util.h" #include "cam_irq_controller.h" #include "cam_debug_util.h" #include "cam_common_util.h" /* Threshold for scheduling delay in ms */ #define CAM_TASKLET_SCHED_TIME_THRESHOLD 5 /* Threshold for execution delay in ms */ #define CAM_TASKLET_EXE_TIME_THRESHOLD 10 #define CAM_TASKLETQ_SIZE 256 Loading @@ -27,6 +35,7 @@ static void cam_tasklet_action(unsigned long data); * @handler_priv: Private data passed at event subscribe * @bottom_half_handler: Function pointer for event handler in bottom * half context * @tasklet_enqueue_ts: enqueue time of tasklet * */ struct cam_tasklet_queue_cmd { Loading @@ -34,6 +43,7 @@ struct cam_tasklet_queue_cmd { void *payload; void *handler_priv; CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; ktime_t tasklet_enqueue_ts; }; /** Loading Loading @@ -209,6 +219,7 @@ void cam_tasklet_enqueue_cmd( tasklet_cmd->bottom_half_handler = bottom_half_handler; tasklet_cmd->payload = evt_payload_priv; tasklet_cmd->handler_priv = handler_priv; tasklet_cmd->tasklet_enqueue_ts = ktime_get(); spin_lock_irqsave(&tasklet->tasklet_lock, flags); list_add_tail(&tasklet_cmd->list, &tasklet->used_cmd_list); Loading Loading @@ -322,12 +333,24 @@ static void cam_tasklet_action(unsigned long data) { struct cam_tasklet_info *tasklet_info = NULL; struct cam_tasklet_queue_cmd *tasklet_cmd = NULL; ktime_t curr_time; tasklet_info = (struct cam_tasklet_info *)data; while (!cam_tasklet_dequeue_cmd(tasklet_info, &tasklet_cmd)) { cam_common_util_thread_switch_delay_detect( "Tasklet schedule", tasklet_cmd->tasklet_enqueue_ts, CAM_TASKLET_SCHED_TIME_THRESHOLD); curr_time = ktime_get(); tasklet_cmd->bottom_half_handler(tasklet_cmd->handler_priv, tasklet_cmd->payload); cam_common_util_thread_switch_delay_detect( "Tasklet execution", curr_time, CAM_TASKLET_EXE_TIME_THRESHOLD); cam_tasklet_put_cmd(tasklet_info, (void **)(&tasklet_cmd)); } }
drivers/cam_req_mgr/cam_req_mgr_workq.c +13 −25 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_workq.h" #include "cam_debug_util.h" #include "cam_common_util.h" #define WORKQ_ACQUIRE_LOCK(workq, flags) {\ if ((workq)->in_irq) \ Loading Loading @@ -94,6 +95,7 @@ void cam_req_mgr_process_workq(struct work_struct *w) struct crm_workq_task *task; int32_t i = CRM_TASK_PRIORITY_0; unsigned long flags = 0; ktime_t curr_time; if (!w) { CAM_ERR(CAM_CRM, "NULL task pointer can not schedule"); Loading @@ -102,7 +104,11 @@ void cam_req_mgr_process_workq(struct work_struct *w) workq = (struct cam_req_mgr_core_workq *) container_of(w, struct cam_req_mgr_core_workq, work); cam_req_mgr_thread_switch_delay_detect(workq->workq_scheduled_ts); cam_common_util_thread_switch_delay_detect( "CRM workq schedule", workq->workq_scheduled_ts, CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); curr_time = ktime_get(); while (i < CRM_TASK_PRIORITY_MAX) { WORKQ_ACQUIRE_LOCK(workq, flags); while (!list_empty(&workq->task.process_head[i])) { Loading @@ -119,6 +125,10 @@ void cam_req_mgr_process_workq(struct work_struct *w) WORKQ_RELEASE_LOCK(workq, flags); i++; } cam_common_util_thread_switch_delay_detect( "CRM workq execution", curr_time, CAM_WORKQ_EXE_TIME_THRESHOLD); } int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, Loading Loading @@ -165,8 +175,8 @@ int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d", task, atomic_read(&workq->task.pending_cnt)); workq->workq_scheduled_ts = ktime_get(); queue_work(workq->job, &workq->work); workq->workq_scheduled_ts = ktime_get(); WORKQ_RELEASE_LOCK(workq, flags); end: return rc; Loading Loading @@ -267,25 +277,3 @@ void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq) *crm_workq = NULL; } } void cam_req_mgr_thread_switch_delay_detect(ktime_t workq_scheduled) { uint64_t diff; ktime_t cur_time; struct timespec64 cur_ts; struct timespec64 workq_scheduled_ts; cur_time = ktime_get(); diff = ktime_ms_delta(cur_time, workq_scheduled); workq_scheduled_ts = ktime_to_timespec64(workq_scheduled); cur_ts = ktime_to_timespec64(cur_time); if (diff > CAM_WORKQ_RESPONSE_TIME_THRESHOLD) { CAM_WARN_RATE_LIMIT(CAM_CRM, "Workq delay detected %ld:%06ld %ld:%06ld %ld:", workq_scheduled_ts.tv_sec, workq_scheduled_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC, diff); } }