Loading drivers/media/platform/msm/camera/cam_core/cam_context_utils.c +1 −0 Original line number Diff line number Diff line Loading @@ -642,6 +642,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) ctx->dev_name, ctx->ctx_id); flush_args.num_req_pending = 0; flush_args.last_flush_req = ctx->last_flush_req; while (true) { spin_lock(&ctx->lock); if (list_empty(&temp_list)) { Loading drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h +3 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,8 @@ struct cam_hw_config_args { * @num_req_active: Num request to flush, valid when flush type is REQ * @flush_req_active: Request active pointers to flush * @flush_type: The flush type * @last_flush_req: last flush req_id notified to hw_mgr for the * given stream * */ struct cam_hw_flush_args { Loading @@ -244,6 +246,7 @@ struct cam_hw_flush_args { uint32_t num_req_active; void *flush_req_active[20]; enum flush_type_t flush_type; uint32_t last_flush_req; }; /** Loading drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +133 −4 Original line number Diff line number Diff line Loading @@ -2672,11 +2672,93 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hw_mgr->a5_jtag_debug); } static int cam_icp_retry_wait_for_abort( struct cam_icp_hw_ctx_data *ctx_data) { int retry_cnt = 1; unsigned long rem_jiffies; int timeout = 1000; CAM_WARN(CAM_ICP, "FW timeout in abort ctx: %u retry_left: %d", ctx_data->ctx_id, retry_cnt); while (retry_cnt > 0) { rem_jiffies = wait_for_completion_timeout( &ctx_data->wait_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { retry_cnt--; if (retry_cnt > 0) { CAM_WARN(CAM_ICP, "FW timeout in abort ctx: %u retry_left: %u", ctx_data->ctx_id, retry_cnt); continue; } } if (retry_cnt > 0) return 0; } return -ETIMEDOUT; } static int cam_icp_mgr_abort_handle_wq( void *priv, void *data) { int rc; size_t packet_size; struct hfi_cmd_work_data *task_data = NULL; struct cam_icp_hw_ctx_data *ctx_data; struct hfi_cmd_ipebps_async *abort_cmd; if (!data || !priv) { CAM_ERR(CAM_ICP, "Invalid params %pK %pK", data, priv); return -EINVAL; } task_data = (struct hfi_cmd_work_data *)data; ctx_data = (struct cam_icp_hw_ctx_data *)task_data->data; packet_size = sizeof(struct hfi_cmd_ipebps_async) + sizeof(struct hfi_cmd_abort) - sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct); abort_cmd = kzalloc(packet_size, GFP_KERNEL); CAM_DBG(CAM_ICP, "abort pkt size = %d", (int) packet_size); if (!abort_cmd) { rc = -ENOMEM; return rc; } abort_cmd->size = packet_size; abort_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT; if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_ABORT; else abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_ABORT; abort_cmd->num_fw_handles = 1; abort_cmd->fw_handles[0] = ctx_data->fw_handle; abort_cmd->user_data1 = PTR_TO_U64(ctx_data); abort_cmd->user_data2 = (uint64_t)0x0; rc = hfi_write_cmd(abort_cmd); if (rc) { kfree(abort_cmd); return rc; } CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK ctx_id %d", ctx_data->fw_handle, ctx_data, ctx_data->ctx_id); kfree(abort_cmd); return rc; } static int cam_icp_mgr_abort_handle( struct cam_icp_hw_ctx_data *ctx_data) { int rc = 0; unsigned long rem_jiffies; unsigned long rem_jiffies = 0; size_t packet_size; int timeout = 1000; struct hfi_cmd_ipebps_async *abort_cmd; Loading Loading @@ -2808,6 +2890,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) hw_mgr->ctx_data[ctx_id].fw_handle = 0; hw_mgr->ctx_data[ctx_id].scratch_mem_size = 0; hw_mgr->ctx_data[ctx_id].last_flush_req = 0; for (i = 0; i < CAM_FRAME_CMD_MAX; i++) clear_bit(i, hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); kfree(hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); Loading Loading @@ -3415,6 +3498,10 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd"); } if (req_id <= ctx_data->last_flush_req) CAM_WARN(CAM_ICP, "Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u", req_id, ctx_data->last_flush_req, ctx_data->ctx_id); rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args); if (rc) goto config_err; Loading Loading @@ -4433,6 +4520,46 @@ static int cam_icp_mgr_flush_req(struct cam_icp_hw_ctx_data *ctx_data, return 0; } static int cam_icp_mgr_enqueue_abort( struct cam_icp_hw_ctx_data *ctx_data) { int timeout = 1000, rc; unsigned long rem_jiffies = 0; struct hfi_cmd_work_data *task_data; struct crm_workq_task *task; task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); if (!task) { CAM_ERR(CAM_ICP, "no empty task"); return -ENOMEM; } reinit_completion(&ctx_data->wait_complete); task_data = (struct hfi_cmd_work_data *)task->payload; task_data->data = (void *)ctx_data; task_data->type = ICP_WORKQ_TASK_CMD_TYPE; task->process_cb = cam_icp_mgr_abort_handle_wq; cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, CRM_TASK_PRIORITY_0); rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { rc = cam_icp_retry_wait_for_abort(ctx_data); if (rc) { CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command ctx: %u", ctx_data->ctx_id); cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); cam_hfi_queue_dump(); return rc; } } CAM_DBG(CAM_ICP, "Abort after flush is success"); return 0; } static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args) { struct cam_hw_dump_args *dump_args = hw_dump_args; Loading Loading @@ -4550,8 +4677,10 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) return -EINVAL; } CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d", ctx_data->ctx_id, flush_args->flush_type); ctx_data->last_flush_req = flush_args->last_flush_req; CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d last_flush_req %u", ctx_data->ctx_id, flush_args->flush_type, ctx_data->last_flush_req); switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: Loading @@ -4559,7 +4688,7 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) if (!atomic_read(&hw_mgr->recovery) && flush_args->num_req_active) { mutex_unlock(&hw_mgr->hw_mgr_mutex); cam_icp_mgr_abort_handle(ctx_data); cam_icp_mgr_enqueue_abort(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); } Loading drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -219,6 +219,7 @@ struct cam_ctx_clk_info { * @watch_dog: watchdog timer handle * @watch_dog_reset_counter: Counter for watch dog reset * @icp_dev_io_info: io config resource * @last_flush_req: last flush req for this ctx */ struct cam_icp_hw_ctx_data { void *context_priv; Loading @@ -239,6 +240,7 @@ struct cam_icp_hw_ctx_data { struct cam_req_mgr_timer *watch_dog; uint32_t watch_dog_reset_counter; struct cam_icp_acquire_dev_info icp_dev_io_info; uint64_t last_flush_req; }; /** Loading drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c +3 −2 Original line number Diff line number Diff line /* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -410,8 +410,9 @@ static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr) if (closest_mapping) { buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd); CAM_INFO(CAM_SMMU, "Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x", "Closest map fd %d 0x%lx %llu-%llu 0x%lx-0x%lx buf=%pK mem %0x", closest_mapping->ion_fd, current_addr, mapping->len, closest_mapping->len, (unsigned long)closest_mapping->paddr, (unsigned long)closest_mapping->paddr + mapping->len, closest_mapping->buf, Loading Loading
drivers/media/platform/msm/camera/cam_core/cam_context_utils.c +1 −0 Original line number Diff line number Diff line Loading @@ -642,6 +642,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) ctx->dev_name, ctx->ctx_id); flush_args.num_req_pending = 0; flush_args.last_flush_req = ctx->last_flush_req; while (true) { spin_lock(&ctx->lock); if (list_empty(&temp_list)) { Loading
drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h +3 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,8 @@ struct cam_hw_config_args { * @num_req_active: Num request to flush, valid when flush type is REQ * @flush_req_active: Request active pointers to flush * @flush_type: The flush type * @last_flush_req: last flush req_id notified to hw_mgr for the * given stream * */ struct cam_hw_flush_args { Loading @@ -244,6 +246,7 @@ struct cam_hw_flush_args { uint32_t num_req_active; void *flush_req_active[20]; enum flush_type_t flush_type; uint32_t last_flush_req; }; /** Loading
drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +133 −4 Original line number Diff line number Diff line Loading @@ -2672,11 +2672,93 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hw_mgr->a5_jtag_debug); } static int cam_icp_retry_wait_for_abort( struct cam_icp_hw_ctx_data *ctx_data) { int retry_cnt = 1; unsigned long rem_jiffies; int timeout = 1000; CAM_WARN(CAM_ICP, "FW timeout in abort ctx: %u retry_left: %d", ctx_data->ctx_id, retry_cnt); while (retry_cnt > 0) { rem_jiffies = wait_for_completion_timeout( &ctx_data->wait_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { retry_cnt--; if (retry_cnt > 0) { CAM_WARN(CAM_ICP, "FW timeout in abort ctx: %u retry_left: %u", ctx_data->ctx_id, retry_cnt); continue; } } if (retry_cnt > 0) return 0; } return -ETIMEDOUT; } static int cam_icp_mgr_abort_handle_wq( void *priv, void *data) { int rc; size_t packet_size; struct hfi_cmd_work_data *task_data = NULL; struct cam_icp_hw_ctx_data *ctx_data; struct hfi_cmd_ipebps_async *abort_cmd; if (!data || !priv) { CAM_ERR(CAM_ICP, "Invalid params %pK %pK", data, priv); return -EINVAL; } task_data = (struct hfi_cmd_work_data *)data; ctx_data = (struct cam_icp_hw_ctx_data *)task_data->data; packet_size = sizeof(struct hfi_cmd_ipebps_async) + sizeof(struct hfi_cmd_abort) - sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct); abort_cmd = kzalloc(packet_size, GFP_KERNEL); CAM_DBG(CAM_ICP, "abort pkt size = %d", (int) packet_size); if (!abort_cmd) { rc = -ENOMEM; return rc; } abort_cmd->size = packet_size; abort_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT; if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_ABORT; else abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_ABORT; abort_cmd->num_fw_handles = 1; abort_cmd->fw_handles[0] = ctx_data->fw_handle; abort_cmd->user_data1 = PTR_TO_U64(ctx_data); abort_cmd->user_data2 = (uint64_t)0x0; rc = hfi_write_cmd(abort_cmd); if (rc) { kfree(abort_cmd); return rc; } CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK ctx_id %d", ctx_data->fw_handle, ctx_data, ctx_data->ctx_id); kfree(abort_cmd); return rc; } static int cam_icp_mgr_abort_handle( struct cam_icp_hw_ctx_data *ctx_data) { int rc = 0; unsigned long rem_jiffies; unsigned long rem_jiffies = 0; size_t packet_size; int timeout = 1000; struct hfi_cmd_ipebps_async *abort_cmd; Loading Loading @@ -2808,6 +2890,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) hw_mgr->ctx_data[ctx_id].fw_handle = 0; hw_mgr->ctx_data[ctx_id].scratch_mem_size = 0; hw_mgr->ctx_data[ctx_id].last_flush_req = 0; for (i = 0; i < CAM_FRAME_CMD_MAX; i++) clear_bit(i, hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); kfree(hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); Loading Loading @@ -3415,6 +3498,10 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd"); } if (req_id <= ctx_data->last_flush_req) CAM_WARN(CAM_ICP, "Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u", req_id, ctx_data->last_flush_req, ctx_data->ctx_id); rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args); if (rc) goto config_err; Loading Loading @@ -4433,6 +4520,46 @@ static int cam_icp_mgr_flush_req(struct cam_icp_hw_ctx_data *ctx_data, return 0; } static int cam_icp_mgr_enqueue_abort( struct cam_icp_hw_ctx_data *ctx_data) { int timeout = 1000, rc; unsigned long rem_jiffies = 0; struct hfi_cmd_work_data *task_data; struct crm_workq_task *task; task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); if (!task) { CAM_ERR(CAM_ICP, "no empty task"); return -ENOMEM; } reinit_completion(&ctx_data->wait_complete); task_data = (struct hfi_cmd_work_data *)task->payload; task_data->data = (void *)ctx_data; task_data->type = ICP_WORKQ_TASK_CMD_TYPE; task->process_cb = cam_icp_mgr_abort_handle_wq; cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, CRM_TASK_PRIORITY_0); rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { rc = cam_icp_retry_wait_for_abort(ctx_data); if (rc) { CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command ctx: %u", ctx_data->ctx_id); cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); cam_hfi_queue_dump(); return rc; } } CAM_DBG(CAM_ICP, "Abort after flush is success"); return 0; } static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args) { struct cam_hw_dump_args *dump_args = hw_dump_args; Loading Loading @@ -4550,8 +4677,10 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) return -EINVAL; } CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d", ctx_data->ctx_id, flush_args->flush_type); ctx_data->last_flush_req = flush_args->last_flush_req; CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d last_flush_req %u", ctx_data->ctx_id, flush_args->flush_type, ctx_data->last_flush_req); switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: Loading @@ -4559,7 +4688,7 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) if (!atomic_read(&hw_mgr->recovery) && flush_args->num_req_active) { mutex_unlock(&hw_mgr->hw_mgr_mutex); cam_icp_mgr_abort_handle(ctx_data); cam_icp_mgr_enqueue_abort(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); } Loading
drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -219,6 +219,7 @@ struct cam_ctx_clk_info { * @watch_dog: watchdog timer handle * @watch_dog_reset_counter: Counter for watch dog reset * @icp_dev_io_info: io config resource * @last_flush_req: last flush req for this ctx */ struct cam_icp_hw_ctx_data { void *context_priv; Loading @@ -239,6 +240,7 @@ struct cam_icp_hw_ctx_data { struct cam_req_mgr_timer *watch_dog; uint32_t watch_dog_reset_counter; struct cam_icp_acquire_dev_info icp_dev_io_info; uint64_t last_flush_req; }; /** Loading
drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c +3 −2 Original line number Diff line number Diff line /* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -410,8 +410,9 @@ static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr) if (closest_mapping) { buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd); CAM_INFO(CAM_SMMU, "Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x", "Closest map fd %d 0x%lx %llu-%llu 0x%lx-0x%lx buf=%pK mem %0x", closest_mapping->ion_fd, current_addr, mapping->len, closest_mapping->len, (unsigned long)closest_mapping->paddr, (unsigned long)closest_mapping->paddr + mapping->len, closest_mapping->buf, Loading