Loading drivers/cam_core/cam_context_utils.c +1 −0 Original line number Diff line number Diff line Loading @@ -615,6 +615,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/cam_core/cam_hw_mgr_intf.h +3 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,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 @@ -267,6 +269,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/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +104 −5 Original line number Diff line number Diff line Loading @@ -3056,11 +3056,63 @@ static int cam_icp_retry_wait_for_abort( 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 @@ -3196,6 +3248,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 @@ -3803,6 +3856,11 @@ 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 @@ -4852,6 +4910,46 @@ static void cam_icp_mgr_flush_info_dump( } } 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_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; Loading @@ -4876,9 +4974,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: mutex_lock(&hw_mgr->hw_mgr_mutex); Loading @@ -4887,7 +4986,7 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) mutex_unlock(&hw_mgr->hw_mgr_mutex); cam_icp_mgr_flush_info_dump(flush_args, ctx_data->ctx_id); cam_icp_mgr_abort_handle(ctx_data); cam_icp_mgr_enqueue_abort(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); } Loading drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,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 @@ -253,6 +254,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/cam_smmu/cam_smmu_api.c +3 −1 Original line number Diff line number Diff line Loading @@ -296,6 +296,7 @@ static void cam_smmu_page_fault_work(struct work_struct *work) buf_info); } } cam_smmu_dump_cb_info(idx); kfree(payload); } Loading Loading @@ -432,8 +433,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/cam_core/cam_context_utils.c +1 −0 Original line number Diff line number Diff line Loading @@ -615,6 +615,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/cam_core/cam_hw_mgr_intf.h +3 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,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 @@ -267,6 +269,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/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +104 −5 Original line number Diff line number Diff line Loading @@ -3056,11 +3056,63 @@ static int cam_icp_retry_wait_for_abort( 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 @@ -3196,6 +3248,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 @@ -3803,6 +3856,11 @@ 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 @@ -4852,6 +4910,46 @@ static void cam_icp_mgr_flush_info_dump( } } 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_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; Loading @@ -4876,9 +4974,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: mutex_lock(&hw_mgr->hw_mgr_mutex); Loading @@ -4887,7 +4986,7 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) mutex_unlock(&hw_mgr->hw_mgr_mutex); cam_icp_mgr_flush_info_dump(flush_args, ctx_data->ctx_id); cam_icp_mgr_abort_handle(ctx_data); cam_icp_mgr_enqueue_abort(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); } Loading
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,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 @@ -253,6 +254,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/cam_smmu/cam_smmu_api.c +3 −1 Original line number Diff line number Diff line Loading @@ -296,6 +296,7 @@ static void cam_smmu_page_fault_work(struct work_struct *work) buf_info); } } cam_smmu_dump_cb_info(idx); kfree(payload); } Loading Loading @@ -432,8 +433,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