diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 128edaf3e5..d3c00193d9 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1085,6 +1085,9 @@ static void cam_hw_cdm_reset_cleanup( &core->bl_fifo[i].bl_request_list, entry) { if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) { + CAM_DBG(CAM_CDM, + "Notifying client %d for tag %d", + node->client_hdl, node->bl_tag); if (flush_hw) cam_cdm_notify_clients(cdm_hw, (node->client_hdl == handle) ? @@ -1145,6 +1148,17 @@ static void cam_hw_cdm_work(struct work_struct *work) if (core->bl_fifo[payload->fifo_idx].work_record) core->bl_fifo[payload->fifo_idx].work_record--; + if (list_empty(&core->bl_fifo[payload->fifo_idx] + .bl_request_list)) { + CAM_INFO(CAM_CDM, + "Fifo list empty, idx %d tag %d arb %d", + payload->fifo_idx, payload->irq_data, + core->arbitration); + mutex_unlock(&core->bl_fifo[payload->fifo_idx] + .fifo_lock); + return; + } + if (core->bl_fifo[payload->fifo_idx] .last_bl_tag_done != payload->irq_data) { @@ -1174,7 +1188,7 @@ static void cam_hw_cdm_work(struct work_struct *work) } } } else { - CAM_DBG(CAM_CDM, + CAM_INFO(CAM_CDM, "Skip GenIRQ, tag 0x%x fifo %d", payload->irq_data, payload->fifo_idx); } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 05b5924003..7d207060d3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -78,6 +78,7 @@ struct cam_tfe_bus_common_data { struct cam_tfe_bus_wm_resource_data { uint32_t index; + uint32_t out_id; struct cam_tfe_bus_common_data *common_data; struct cam_tfe_bus_reg_offset_bus_client *hw_regs; @@ -631,6 +632,7 @@ static int cam_tfe_bus_acquire_wm( rsrc_data->height = out_port_info->height; rsrc_data->stride = out_port_info->stride; rsrc_data->mode = out_port_info->wm_mode; + rsrc_data->out_id = tfe_out_res_id; /* * Store the acquire width, height separately. For frame based ports @@ -644,14 +646,16 @@ static int cam_tfe_bus_acquire_wm( /* Set WM offset value to default */ rsrc_data->offset = 0; - if (rsrc_data->index > 6) { + if ((rsrc_data->index > 6) && + (tfe_out_res_id != CAM_TFE_BUS_TFE_OUT_PDAF)) { /* WM 7-9 refers to RDI 0/ RDI 1/RDI 2 */ rc = cam_tfe_bus_acquire_rdi_wm(rsrc_data); if (rc) return rc; - } else if (rsrc_data->index == 0 || rsrc_data->index == 1) { - /* WM 0 FULL_OUT */ + } else if (rsrc_data->index == 0 || rsrc_data->index == 1 || + (tfe_out_res_id == CAM_TFE_BUS_TFE_OUT_PDAF)) { + /* WM 0 FULL_OUT WM 1 IDEAL RAW WM9 for pdaf */ switch (rsrc_data->format) { case CAM_FORMAT_MIPI_RAW_8: rsrc_data->pack_fmt = 0x1; @@ -747,9 +751,14 @@ static int cam_tfe_bus_start_wm(struct cam_isp_resource_node *wm_res) /* Configure stride for RDIs on full TFE and TFE lite */ if ((rsrc_data->index > 6) && - (rsrc_data->mode != CAM_ISP_TFE_WM_LINE_BASED_MODE)) + ((rsrc_data->mode != CAM_ISP_TFE_WM_LINE_BASED_MODE) && + (rsrc_data->out_id != CAM_TFE_BUS_TFE_OUT_PDAF))) { cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + rsrc_data->hw_regs->image_cfg_2)); + CAM_DBG(CAM_ISP, "WM:%d configure stride reg :0x%x", + rsrc_data->index, + rsrc_data->stride); + } /* Enable WM */ cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + @@ -1183,9 +1192,9 @@ static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; enum cam_tfe_bus_tfe_out_id tfe_out_res_id; enum cam_tfe_bus_comp_grp_id comp_grp_id; - int rc = -ENODEV; + int i, rc = -ENODEV; uint32_t secure_caps = 0, mode; - uint32_t i, format, num_wm, client_done_mask = 0; + uint32_t format, num_wm, client_done_mask = 0; if (!bus_priv || !acquire_args) { CAM_ERR(CAM_ISP, "Invalid Param"); @@ -1310,10 +1319,10 @@ static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, release_wm: for (i--; i >= 0; i--) - cam_tfe_bus_release_wm(bus_priv, - rsrc_data->wm_res[i]); + cam_tfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]); - cam_tfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); + if (rsrc_data->comp_grp) + cam_tfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); return rc; } @@ -1918,7 +1927,8 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, wm_data->index, reg_val_pair[j-1]); if ((wm_data->index < 7) || ((wm_data->index >= 7) && - (wm_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE))) { + (wm_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE)) || + (wm_data->out_id == CAM_TFE_BUS_TFE_OUT_PDAF)) { CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_2, io_cfg->planes[i].plane_stride); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index c1914ec976..088652dab4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -1933,23 +1933,6 @@ static int cam_tfe_camif_resource_start( return -ENODEV; } - /* Camif module config */ - val = cam_io_r(rsrc_data->mem_base + - rsrc_data->camif_reg->module_cfg); - val &= ~(rsrc_data->reg_data->pixel_pattern_mask); - val |= (rsrc_data->pix_pattern << - rsrc_data->reg_data->pixel_pattern_shift); - val |= (1 << rsrc_data->reg_data->module_enable_shift); - val |= (1 << rsrc_data->reg_data->pix_out_enable_shift); - if (rsrc_data->camif_pd_enable) - val |= (1 << rsrc_data->reg_data->pdaf_output_enable_shift); - - cam_io_w_mb(val, rsrc_data->mem_base + - rsrc_data->camif_reg->module_cfg); - - CAM_DBG(CAM_ISP, "TFE:%d camif module config val:%d", - core_info->core_index, val); - /* Config tfe core*/ val = 0; if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index 1c6b940f9b..d82b4ba84a 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -123,6 +123,18 @@ static int __cam_ope_flush_dev_in_ready(struct cam_context *ctx, return rc; } +static int __cam_ope_dump_dev_in_ready(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc; + + rc = cam_context_dump_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_OPE, "Failed to dump device"); + + return rc; +} + static int __cam_ope_config_dev_in_ready(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { @@ -206,6 +218,7 @@ static struct cam_ctx_ops .start_dev = __cam_ope_start_dev_in_acquired, .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, + .dump_dev = __cam_ope_dump_dev_in_ready, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -218,6 +231,7 @@ static struct cam_ctx_ops .release_dev = __cam_ope_release_dev_in_ready, .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, + .dump_dev = __cam_ope_dump_dev_in_ready, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 8dfff457a6..ca17328d41 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -96,12 +96,19 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) task_data = (struct ope_cmd_work_data *)data; cdm_cmd = task_data->data; - CAM_DBG(CAM_OPE, - "cam_cdm_submit_bls: handle 0x%x, ctx_id %d req %d cookie %d", - ctx_data->ope_cdm.cdm_handle, ctx_data->ctx_id, - task_data->req_id, cdm_cmd->cookie); + if (!cdm_cmd) { + CAM_ERR(CAM_OPE, "Invalid params%pK", cdm_cmd); + return -EINVAL; + } mutex_lock(&hw_mgr->hw_mgr_mutex); + if (ctx_data->ctx_state != OPE_CTX_STATE_ACQUIRED) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_OPE, "ctx id :%u is not in use", + ctx_data->ctx_id); + return -EINVAL; + } + if (task_data->req_id <= ctx_data->last_flush_req) { CAM_WARN(CAM_OPE, "request %lld has been flushed, reject packet", @@ -110,6 +117,11 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) return -EINVAL; } + CAM_DBG(CAM_OPE, + "cam_cdm_submit_bls: handle 0x%x, ctx_id %d req %d cookie %d", + ctx_data->ope_cdm.cdm_handle, ctx_data->ctx_id, + task_data->req_id, cdm_cmd->cookie); + if (task_data->req_id > ctx_data->last_flush_req) ctx_data->last_flush_req = 0; @@ -536,13 +548,21 @@ static int cam_ope_dump_bls(struct cam_ope_request *ope_req, struct cam_ope_hang_dump *dump) { struct cam_cdm_bl_request *cdm_cmd; - int i; + size_t size; + int i, rc; + dma_addr_t iova_addr; cdm_cmd = ope_req->cdm_cmd; for (i = 0; i < cdm_cmd->cmd_arrary_count; i++) { + rc = cam_mem_get_io_buf(cdm_cmd->cmd[i].bl_addr.mem_handle, + ope_hw_mgr->iommu_hdl, &iova_addr, &size); + if (rc) { + CAM_ERR(CAM_OPE, "get io buf fail 0x%x", + cdm_cmd->cmd[i].bl_addr.mem_handle); + return rc; + } dump->bl_entries[dump->num_bls].base = - (uint32_t)cdm_cmd->cmd[i].bl_addr.hw_iova + - cdm_cmd->cmd[i].offset; + (uint32_t)iova_addr + cdm_cmd->cmd[i].offset; dump->bl_entries[dump->num_bls].len = cdm_cmd->cmd[i].len; dump->bl_entries[dump->num_bls].arbitration = cdm_cmd->cmd[i].arbitrate; @@ -568,6 +588,7 @@ static void cam_ope_dump_req_data(struct cam_ope_request *ope_req) ope_req->ope_debug_buf.offset); return; } + dump = (struct cam_ope_hang_dump *)ope_req->ope_debug_buf.cpu_addr; memset(dump, 0, sizeof(struct cam_ope_hang_dump)); dump->num_bufs = 0; @@ -1013,8 +1034,11 @@ static int cam_ope_get_lower_clk_rate(struct cam_ope_hw_mgr *hw_mgr, i = cam_ope_get_actual_clk_rate_idx(ctx_data, base_clk); - if (i > 0) - return ctx_data->clk_info.clk_rate[i - 1]; + while (i > 0) { + if (ctx_data->clk_info.clk_rate[i - 1]) + return ctx_data->clk_info.clk_rate[i - 1]; + i--; + } CAM_DBG(CAM_OPE, "Already clk at lower level"); @@ -1028,8 +1052,11 @@ static int cam_ope_get_next_clk_rate(struct cam_ope_hw_mgr *hw_mgr, i = cam_ope_get_actual_clk_rate_idx(ctx_data, base_clk); - if (i < CAM_MAX_VOTE - 1) - return ctx_data->clk_info.clk_rate[i + 1]; + while (i < CAM_MAX_VOTE - 1) { + if (ctx_data->clk_info.clk_rate[i + 1]) + return ctx_data->clk_info.clk_rate[i + 1]; + i++; + } CAM_DBG(CAM_OPE, "Already clk at higher level"); @@ -1520,6 +1547,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, struct cam_hw_done_event_data buf_data; struct timespec64 ts; uint32_t evt_id = CAM_CTX_EVT_ID_SUCCESS; + bool dump_flag = true; if (!userdata) { CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); @@ -1581,8 +1609,10 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id, ctx->ctx_id); CAM_ERR(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", ope_req->request_id); - if (status != CAM_CDM_CB_STATUS_HW_FLUSH) + if (status != CAM_CDM_CB_STATUS_HW_FLUSH) { cam_ope_dump_req_data(ope_req); + dump_flag = false; + } rc = cam_ope_mgr_reset_hw(); evt_id = CAM_CTX_EVT_ID_ERROR; @@ -1598,6 +1628,9 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, buf_data.evt_param = CAM_SYNC_OPE_EVENT_UNKNOWN; } + if (ope_hw_mgr->dump_req_data_enable && dump_flag) + cam_ope_dump_req_data(ope_req); + ctx->req_cnt--; buf_data.request_id = ope_req->request_id; @@ -1779,15 +1812,14 @@ static void cam_ope_mgr_print_stripe_info(uint32_t batch, { CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d: E", batch, io_buf, plane, stripe); - CAM_DBG(CAM_OPE, "width: %d s_w: %u s_h: %u s_s: %u", - stripe_info->width, stripe_info->width, - stripe_info->height, stripe_info->stride); + CAM_DBG(CAM_OPE, "width: %d s_h: %u s_s: %u", + stripe_info->width, stripe_info->height, + stripe_info->stride); CAM_DBG(CAM_OPE, "s_xinit = %u iova = %x s_loc = %u", - stripe_info->s_location, stripe_info->x_init, - iova_addr); - CAM_DBG(CAM_OPE, "s_off = %u s_format = %u s_len = %u", + stripe_info->x_init, iova_addr, stripe_info->s_location); + CAM_DBG(CAM_OPE, "s_off = %u s_format = %u s_len = %u d_bus %d", stripe_info->offset, stripe_info->format, - stripe_info->len); + stripe_info->len, stripe_info->disable_bus); CAM_DBG(CAM_OPE, "s_align = %u s_pack = %u s_unpack = %u", stripe_info->alignment, stripe_info->pack_format, stripe_info->unpack_format); @@ -1827,29 +1859,15 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, in_frame_set = &in_frame_process->frame_set[i]; for (j = 0; j < in_frame_set->num_io_bufs; j++) { in_io_buf = &in_frame_set->io_buf[j]; - CAM_DBG(CAM_OPE, "i:%d j:%d dir: %x rsc: %u plane: %d", - i, j, in_io_buf->direction, - in_io_buf->resource_type, - in_io_buf->num_planes); for (k = 0; k < in_io_buf->num_planes; k++) { - CAM_DBG(CAM_OPE, "i:%d j:%d k:%d numstripe: %d", - i, j, k, in_io_buf->num_stripes[k]); - CAM_DBG(CAM_OPE, "m_hdl: %d len: %d", - in_io_buf->mem_handle[k], - in_io_buf->length[k]); + if (!in_io_buf->num_stripes[k]) { + CAM_ERR(CAM_OPE, "Null num_stripes"); + return -EINVAL; + } for (l = 0; l < in_io_buf->num_stripes[k]; l++) { in_stripe_info = &in_io_buf->stripe_info[k][l]; - CAM_DBG(CAM_OPE, "i:%d j:%d k:%d l:%d", - i, j, k, l); - CAM_DBG(CAM_OPE, "%d s_loc:%d w:%d", - in_stripe_info->x_init, - in_stripe_info->stripe_location, - in_stripe_info->width); - CAM_DBG(CAM_OPE, "s_off: %d d_bus: %d", - in_stripe_info->offset, - in_stripe_info->disable_bus); } } } @@ -1907,9 +1925,6 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, unpack_format = 0; } - CAM_DBG(CAM_OPE, "i:%d j:%d dir:%d rsc type:%d fmt:%d", - i, j, io_buf->direction, io_buf->resource_type, - io_buf->format); for (k = 0; k < in_io_buf->num_planes; k++) { io_buf->num_stripes[k] = in_io_buf->num_stripes[k]; @@ -1936,6 +1951,11 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, return -EINVAL; } iova_addr += in_io_buf->plane_offset[k]; + CAM_DBG(CAM_OPE, + "E rsc %d stripes %d dir %d plane %d", + in_io_buf->resource_type, + in_io_buf->direction, + in_io_buf->num_stripes[k], k); for (l = 0; l < in_io_buf->num_stripes[k]; l++) { in_stripe_info = @@ -1966,6 +1986,11 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, cam_ope_mgr_print_stripe_info(i, j, k, l, stripe_info, iova_addr); } + CAM_DBG(CAM_OPE, + "X rsc %d stripes %d dir %d plane %d", + in_io_buf->resource_type, + in_io_buf->direction, + in_io_buf->num_stripes[k], k); } } } @@ -2491,6 +2516,9 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) struct cam_ope_dev_clk_update clk_update; struct cam_ope_dev_bw_update *bw_update; struct cam_ope_set_irq_cb irq_cb; + struct cam_hw_info *dev = NULL; + struct cam_hw_soc_info *soc_info = NULL; + int32_t idx; if ((!hw_priv) || (!hw_acquire_args)) { CAM_ERR(CAM_OPE, "Invalid args: %x %x", @@ -2579,8 +2607,14 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } } - hw_mgr->clk_info.base_clk = 600000000; - hw_mgr->clk_info.curr_clk = 600000000; + dev = (struct cam_hw_info *)hw_mgr->ope_dev_intf[0]->hw_priv; + soc_info = &dev->soc_info; + idx = soc_info->src_clk_idx; + + hw_mgr->clk_info.base_clk = + soc_info->clk_rate[CAM_TURBO_VOTE][idx]; + hw_mgr->clk_info.curr_clk = + soc_info->clk_rate[CAM_TURBO_VOTE][idx]; hw_mgr->clk_info.threshold = 5; hw_mgr->clk_info.over_clked = 0; @@ -2607,7 +2641,11 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } for (i = 0; i < ope_hw_mgr->num_ope; i++) { - clk_update.clk_rate = 600000000; + dev = (struct cam_hw_info *)hw_mgr->ope_dev_intf[i]->hw_priv; + soc_info = &dev->soc_info; + idx = soc_info->src_clk_idx; + clk_update.clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][idx]; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_CLK_UPDATE, &clk_update, sizeof(clk_update)); @@ -3302,6 +3340,7 @@ static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args) cdm_cmd->cookie = ope_req->req_idx; cam_ope_mgr_ope_clk_update(hw_mgr, ctx_data, ope_req->req_idx); + ctx_data->req_list[ope_req->req_idx]->submit_timestamp = ktime_get(); if (ope_req->request_id <= ctx_data->last_flush_req) CAM_WARN(CAM_OPE, @@ -3327,6 +3366,112 @@ config_err: return rc; } +static void cam_ope_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + dma_addr_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_OPE, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_OPE, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, + "get src buf address fail rc %d mem %x", + rc, io_cfg[i].mem_handle[j]); + continue; + } + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { + CAM_ERR(CAM_OPE, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_OPE, + "pln %d dir %d w %d h %d s %u sh %u sz %d addr 0x%x off 0x%x memh %x", + j, io_cfg[i].direction, + io_cfg[i].planes[j].width, + io_cfg[i].planes[j].height, + io_cfg[i].planes[j].plane_stride, + io_cfg[i].planes[j].slice_height, + (int32_t)src_buf_size, + (unsigned int)iova_addr, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + + iova_addr += io_cfg[i].offsets[j]; + + } + } + cam_packet_dump_patch_info(packet, ope_hw_mgr->iommu_hdl, + ope_hw_mgr->iommu_sec_hdl); +} + +static int cam_ope_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_ope_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_OPE, "Invalid arguments"); + return -EINVAL; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_ope_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->iommu_hdl, + hw_mgr->iommu_sec_hdl, + hw_cmd_args->u.pf_args.buf_info, + hw_cmd_args->u.pf_args.mem_found); + + break; + default: + CAM_ERR(CAM_OPE, "Invalid cmd"); + } + + return rc; +} + static int cam_ope_mgr_hw_open_u(void *hw_priv, void *fw_download_args) { struct cam_ope_hw_mgr *hw_mgr; @@ -3429,6 +3574,76 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data, return rc; } +static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) +{ + struct cam_ope_ctx *ctx_data; + struct cam_ope_hw_mgr *hw_mgr = hw_priv; + struct cam_hw_dump_args *dump_args; + int idx; + ktime_t cur_time; + struct timespec64 cur_ts, req_ts; + uint64_t diff; + + if ((!hw_priv) || (!hw_dump_args)) { + CAM_ERR(CAM_OPE, "Invalid params %pK %pK", + hw_priv, hw_dump_args); + return -EINVAL; + } + + dump_args = (struct cam_hw_dump_args *)hw_dump_args; + ctx_data = dump_args->ctxt_to_hw_map; + + if (!ctx_data) { + CAM_ERR(CAM_OPE, "Invalid context"); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + CAM_INFO(CAM_OPE, "Req %lld", dump_args->request_id); + for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) { + if (!ctx_data->req_list[idx]) + continue; + + if (ctx_data->req_list[idx]->request_id == + dump_args->request_id) + break; + } + + /* no matching request found */ + if (idx == CAM_CTX_REQ_MAX) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; + } + + cur_time = ktime_get(); + diff = ktime_us_delta(cur_time, + ctx_data->req_list[idx]->submit_timestamp); + cur_ts = ktime_to_timespec64(cur_time); + req_ts = ktime_to_timespec64(ctx_data->req_list[idx]->submit_timestamp); + + if (diff < (OPE_REQUEST_TIMEOUT * 1000)) { + CAM_INFO(CAM_OPE, "No Error req %llu %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; + } + + CAM_ERR(CAM_OPE, "Error req %llu %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; +} + static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; @@ -3683,6 +3898,40 @@ cmd_work_failed: return rc; } +static int cam_ope_create_debug_fs(void) +{ + ope_hw_mgr->dentry = debugfs_create_dir("camera_ope", + NULL); + + if (!ope_hw_mgr->dentry) { + CAM_ERR(CAM_OPE, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_bool("frame_dump_enable", + 0644, + ope_hw_mgr->dentry, + &ope_hw_mgr->frame_dump_enable)) { + CAM_ERR(CAM_OPE, + "failed to create dump_enable_debug"); + goto err; + } + + if (!debugfs_create_bool("dump_req_data_enable", + 0644, + ope_hw_mgr->dentry, + &ope_hw_mgr->dump_req_data_enable)) { + CAM_ERR(CAM_OPE, + "failed to create dump_enable_debug"); + goto err; + } + + return 0; +err: + debugfs_remove_recursive(ope_hw_mgr->dentry); + return -ENOMEM; +} + int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl) @@ -3716,10 +3965,11 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, hw_mgr_intf->hw_config = cam_ope_mgr_config_hw; hw_mgr_intf->hw_read = NULL; hw_mgr_intf->hw_write = NULL; - hw_mgr_intf->hw_cmd = NULL; + hw_mgr_intf->hw_cmd = cam_ope_mgr_cmd; hw_mgr_intf->hw_open = cam_ope_mgr_hw_open_u; hw_mgr_intf->hw_close = cam_ope_mgr_hw_close_u; hw_mgr_intf->hw_flush = cam_ope_mgr_hw_flush; + hw_mgr_intf->hw_dump = cam_ope_mgr_hw_dump; ope_hw_mgr->secure_mode = false; mutex_init(&ope_hw_mgr->hw_mgr_mutex); @@ -3787,6 +4037,8 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, if (rc) goto ope_wq_create_failed; + cam_ope_create_debug_fs(); + if (iommu_hdl) *iommu_hdl = ope_hw_mgr->iommu_hdl; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index 07ef8203bb..98d3587ac9 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -62,8 +62,6 @@ #define OPE_DEVICE_IDLE_TIMEOUT 400 #define OPE_REQUEST_TIMEOUT 200 - - /** * struct cam_ope_clk_bw_request_v2 * @budget_ns: Time required to process frame @@ -390,6 +388,7 @@ struct ope_io_buf { * @clk_info: Clock Info V1 * @clk_info_v2: Clock Info V2 * @hang_data: Debug data for HW error + * @submit_timestamp: Submit timestamp to hw */ struct cam_ope_request { uint64_t request_id; @@ -410,6 +409,7 @@ struct cam_ope_request { struct cam_ope_clk_bw_request clk_info; struct cam_ope_clk_bw_req_internal_v2 clk_info_v2; struct cam_hw_mgr_dump_pf_data hang_data; + ktime_t submit_timestamp; }; /** @@ -499,6 +499,9 @@ struct cam_ope_ctx { * @ope_dev_intf: OPE device interface * @cdm_reg_map: OPE CDM register map * @clk_info: OPE clock Info for HW manager + * @dentry: Pointer to OPE debugfs directory + * @frame_dump_enable: OPE frame setting dump enablement + * @dump_req_data_enable: OPE hang dump enablement */ struct cam_ope_hw_mgr { int32_t open_cnt; @@ -529,6 +532,9 @@ struct cam_ope_hw_mgr { struct cam_hw_intf *ope_dev_intf[OPE_DEV_MAX]; struct cam_soc_reg_map *cdm_reg_map[OPE_DEV_MAX][OPE_BASE_MAX]; struct cam_ope_clk_info clk_info; + struct dentry *dentry; + bool frame_dump_enable; + bool dump_req_data_enable; }; /** diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index d58d4dd5e9..0042675f18 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -193,13 +193,17 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, CAM_DBG(CAM_OPE, "req_idx = %d req_id = %lld KMDbuf %x offset %d", req_idx, ope_request->request_id, kmd_buf, prepare->kmd_buf_offset); - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; io_port_info = &bus_rd_ctx->io_port_info; rd_reg = ope_hw_info->bus_rd_reg; rd_reg_val = ope_hw_info->bus_rd_reg_val; - io_buf = ope_request->io_buf[batch_idx][io_idx]; + CAM_DBG(CAM_OPE, + "req_idx = %d req_id = %lld KMDbuf 0x%x offset %d rsc %d", + req_idx, ope_request->request_id, + kmd_buf, prepare->kmd_buf_offset, + io_buf->resource_type); CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d", batch_idx, io_idx, io_buf->direction); io_port_cdm = @@ -307,20 +311,15 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, sizeof(temp)); CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", batch_idx, io_idx, k, l); - for (m = 0; m < count; m++) - CAM_DBG(CAM_OPE, "%d:temp:%x", - m, temp_reg[m]); + for (m = 0; m < count; m += 2) + CAM_DBG(CAM_OPE, "%d: off: 0x%x val: 0x%x", + m, temp_reg[m], temp_reg[m+1]); CAM_DBG(CAM_OPE, "kmd_buf:%x offset:%d", - kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "%x count: %d size:%d", - temp_reg, count, header_size); - CAM_DBG(CAM_OPE, "RD cmdbufs:%d off:%d", - io_port_cdm->num_s_cmd_bufs[l], - io_port_cdm->s_cdm_info[l][idx].offset); - CAM_DBG(CAM_OPE, "len:%d", - io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "RD cmdbufs:%d off:%d len %d", + io_port_cdm->num_s_cmd_bufs[l], + io_port_cdm->s_cdm_info[l][idx].offset, + io_port_cdm->s_cdm_info[l][idx].len); count = 0; } } @@ -368,12 +367,13 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info, req_idx = prepare->req_idx; cdm_ops = ctx_data->ope_cdm.cdm_ops; - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; io_port_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; rd_reg = ope_hw_info->bus_rd_reg; - CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d", - kmd_buf, req_idx, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, + "kmd_buf = 0x%x req_idx = %d offset = %d rd_idx %d b %d", + kmd_buf, req_idx, prepare->kmd_buf_offset, rm_idx, batch_idx); io_port_cdm = &bus_rd_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; @@ -402,20 +402,11 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info, prepare->kmd_buf_offset += ((count + header_size) * sizeof(temp)); - CAM_DBG(CAM_OPE, "b:%d s:%d", - batch_idx, l); - CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", - kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", - count, temp_reg, header_size); - CAM_DBG(CAM_OPE, "header_size:%d", header_size); - CAM_DBG(CAM_OPE, "RD cmd bufs = %d", + CAM_DBG(CAM_OPE, "RD cmd bufs = %d", io_port_cdm->num_s_cmd_bufs[l]); - CAM_DBG(CAM_OPE, "off:%d len:%d", - io_port_cdm->s_cdm_info[l][idx].offset, + CAM_DBG(CAM_OPE, "stripe %d off:%d len:%d", + l, io_port_cdm->s_cdm_info[l][idx].offset, io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d s:%d", - batch_idx, l); count = 0; } @@ -464,7 +455,7 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, req_idx, ope_request->request_id); CAM_DBG(CAM_OPE, "KMD buf and offset = %x %d", kmd_buf, prepare->kmd_buf_offset); - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; io_port_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; memset(io_port_cdm_batch, 0, @@ -562,25 +553,15 @@ end: static int cam_ope_bus_rd_release(struct ope_hw *ope_hw_info, int32_t ctx_id, void *data) { - int rc = 0, i; - struct ope_acquire_dev_info *in_acquire; - struct ope_bus_rd_ctx *bus_rd_ctx; + int rc = 0; - if (ctx_id < 0) { + if (ctx_id < 0 || ctx_id >= OPE_CTX_MAX) { CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id); return -EINVAL; } - in_acquire = bus_rd->bus_rd_ctx[ctx_id].ope_acquire; - bus_rd->bus_rd_ctx[ctx_id].ope_acquire = NULL; - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; - bus_rd_ctx->num_in_ports = 0; - - for (i = 0; i < bus_rd_ctx->num_in_ports; i++) { - bus_rd_ctx->io_port_info.input_port_id[i] = 0; - bus_rd_ctx->io_port_info.input_format_type[i - 1] = 0; - bus_rd_ctx->io_port_info.pixel_pattern[i - 1] = 0; - } + vfree(bus_rd->bus_rd_ctx[ctx_id]); + bus_rd->bus_rd_ctx[ctx_id] = NULL; return rc; } @@ -597,15 +578,21 @@ static int cam_ope_bus_rd_acquire(struct ope_hw *ope_hw_info, int in_port_idx; - if (ctx_id < 0 || !data || !ope_hw_info) { + if (ctx_id < 0 || !data || !ope_hw_info || ctx_id >= OPE_CTX_MAX) { CAM_ERR(CAM_OPE, "Invalid data: %d %x %x", ctx_id, data, ope_hw_info); return -EINVAL; } - bus_rd->bus_rd_ctx[ctx_id].ope_acquire = data; + bus_rd->bus_rd_ctx[ctx_id] = vzalloc(sizeof(struct ope_bus_rd_ctx)); + if (!bus_rd->bus_rd_ctx[ctx_id]) { + CAM_ERR(CAM_OPE, "Out of memory"); + return -ENOMEM; + } + + bus_rd->bus_rd_ctx[ctx_id]->ope_acquire = data; in_acquire = data; - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; bus_rd_ctx->num_in_ports = in_acquire->num_in_res; bus_rd_ctx->security_flag = in_acquire->secure_mode; bus_rd_reg_val = ope_hw_info->bus_rd_reg_val; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h index 15a45a6bea..b461374c2a 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h @@ -132,7 +132,7 @@ struct ope_bus_rd_ctx { struct ope_bus_rd { struct ope_hw *ope_hw_info; struct ope_bus_in_port_to_rm in_port_to_rm[OPE_IN_RES_MAX]; - struct ope_bus_rd_ctx bus_rd_ctx[OPE_CTX_MAX]; + struct ope_bus_rd_ctx *bus_rd_ctx[OPE_CTX_MAX]; struct completion reset_complete; }; #endif /* OPE_BUS_RD_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c index bade41972a..df5cb89b1e 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c @@ -169,7 +169,7 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, int batch_idx, int io_idx, uint32_t *kmd_buf, uint32_t *num_stripes) { - int k, l, out_port_idx; + int k, l, m, out_port_idx; uint32_t idx; uint32_t num_wm_ports; uint32_t comb_idx; @@ -226,8 +226,8 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, prepare->kmd_buf_offset); io_buf = ope_request->io_buf[batch_idx][io_idx]; - CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d", - batch_idx, io_idx, io_buf->direction); + CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d rsc %d", + batch_idx, io_idx, io_buf->direction, io_buf->resource_type); io_port_cdm = &bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; @@ -335,19 +335,15 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", batch_idx, io_idx, k, l); + for (m = 0; m < count; m += 2) + CAM_DBG(CAM_OPE, "%d: off: 0x%x val: 0x%x", + m, temp_reg[m], temp_reg[m+1]); CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", - count, temp_reg, header_size); - CAM_DBG(CAM_OPE, "header_size:%d", header_size); - - CAM_DBG(CAM_OPE, "WR cmd bufs = %d", - io_port_cdm->num_s_cmd_bufs[l]); - CAM_DBG(CAM_OPE, "off:%d len:%d", + CAM_DBG(CAM_OPE, "WR cmd bufs = %d off:%d len:%d", + io_port_cdm->num_s_cmd_bufs[l], io_port_cdm->s_cdm_info[l][idx].offset, io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); count = 0; } } @@ -398,8 +394,9 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; wr_reg = ope_hw_info->bus_wr_reg; - CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d", - kmd_buf, req_idx, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, + "kmd_buf = %x req_idx = %d offset = %d out_idx %d b %d", + kmd_buf, req_idx, prepare->kmd_buf_offset, io_idx, batch_idx); io_port_cdm = &bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; @@ -409,8 +406,6 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, for (k = 0; k < num_wm_ports; k++) { for (l = 0; l < num_stripes; l++) { - CAM_DBG(CAM_OPE, "comb_idx = %d p_idx = %d s_idx = %d", - comb_idx, k, l); /* frame level info */ /* stripe level info */ wm_port_id = out_port_to_wm->wm_port_id[comb_idx][k]; @@ -436,21 +431,11 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, prepare->kmd_buf_offset += ((count + header_size) * sizeof(temp)); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); - CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", - kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", - count, temp_reg, header_size); - CAM_DBG(CAM_OPE, "header_size:%d", header_size); - CAM_DBG(CAM_OPE, "WR cmd bufs = %d", io_port_cdm->num_s_cmd_bufs[l]); - CAM_DBG(CAM_OPE, "off:%d len:%d", - io_port_cdm->s_cdm_info[l][idx].offset, + CAM_DBG(CAM_OPE, "s:%d off:%d len:%d", + l, io_port_cdm->s_cdm_info[l][idx].offset, io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); count = 0; } } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index 8a46b71241..dee7186aad 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -427,7 +427,7 @@ static int dump_dmi_cmd(uint32_t print_idx, return 0; } -static int dump_frame_direct(uint32_t print_idx, +static int dump_direct_cmd(uint32_t print_idx, uint32_t *print_ptr, struct ope_frame_process *frm_proc, int batch_idx, int cmd_buf_idx) @@ -569,7 +569,7 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, iova_addr, frm_proc->cmd_buf[i][j].length); print_ptr = (uint32_t *)cpu_addr; - dump_frame_direct(print_idx, print_ptr, + dump_direct_cmd(print_idx, print_ptr, frm_proc, i, j); } else { num_dmi = frm_proc->cmd_buf[i][j].length / @@ -581,21 +581,28 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, memcpy(temp, (const void *)print_ptr, sizeof(struct cdm_dmi_cmd)); dmi_cmd = (struct cdm_dmi_cmd *)temp; + if (!dmi_cmd->addr) { + CAM_ERR(CAM_OPE, "Null dmi cmd addr"); + return NULL; + } + kmd_buf = cdm_ops->cdm_write_dmi( kmd_buf, 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, dmi_cmd->addr, dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); + if (hw_mgr->frame_dump_enable) + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); print_ptr += sizeof(struct cdm_dmi_cmd) / sizeof(uint32_t); } CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); } - dump_frame_cmd(frm_proc, i, j, - iova_addr, kmd_buf, buf_len); + if (hw_mgr->frame_dump_enable) + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); } return kmd_buf; @@ -719,8 +726,9 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, iova_addr, frm_proc->cmd_buf[i][j].length); print_ptr = (uint32_t *)cpu_addr; - dump_frame_direct(print_idx, print_ptr, - frm_proc, i, j); + if (hw_mgr->frame_dump_enable) + dump_direct_cmd(print_idx, print_ptr, + frm_proc, i, j); } else { num_dmi = frm_proc->cmd_buf[i][j].length / sizeof(struct cdm_dmi_cmd); @@ -731,21 +739,30 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, memcpy(temp, (const void *)print_ptr, sizeof(struct cdm_dmi_cmd)); dmi_cmd = (struct cdm_dmi_cmd *)temp; + if (!dmi_cmd->addr) { + CAM_ERR(CAM_OPE, + "Null dmi cmd addr"); + return NULL; + } + kmd_buf = cdm_ops->cdm_write_dmi( kmd_buf, 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, dmi_cmd->addr, dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); + if (hw_mgr->frame_dump_enable) + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, + temp); print_ptr += sizeof(struct cdm_dmi_cmd) / sizeof(uint32_t); } CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); } - dump_frame_cmd(frm_proc, i, j, - iova_addr, kmd_buf, buf_len); + if (hw_mgr->frame_dump_enable) + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); } } return kmd_buf; @@ -817,15 +834,12 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, kmd_buf, iova_addr, frm_proc->cmd_buf[i][k].length); - print_ptr = (uint32_t *)cpu_addr; - CAM_DBG(CAM_OPE, "Stripe:%d direct:E", - stripe_idx); - for (print_idx = 0; print_idx < - frm_proc->cmd_buf[i][k].length / 4; - print_idx++) { - CAM_DBG(CAM_OPE, "%d: %x", print_idx, - print_ptr[print_idx]); - } + print_ptr = (uint32_t *)cpu_addr; + CAM_DBG(CAM_OPE, "Stripe:%d direct:E", + stripe_idx); + if (hw_mgr->frame_dump_enable) + dump_direct_cmd(print_idx, print_ptr, + frm_proc, i, k); CAM_DBG(CAM_OPE, "Stripe:%d direct:X", stripe_idx); } else if (frm_proc->cmd_buf[i][k].type == OPE_CMD_BUF_TYPE_INDIRECT) { @@ -837,18 +851,25 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, memcpy(temp, (const void *)print_ptr, sizeof(struct cdm_dmi_cmd)); dmi_cmd = (struct cdm_dmi_cmd *)temp; + if (!dmi_cmd->addr) { + CAM_ERR(CAM_OPE, "Null dmi cmd addr"); + return NULL; + } + kmd_buf = cdm_ops->cdm_write_dmi(kmd_buf, 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, dmi_cmd->addr, dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); + if (hw_mgr->frame_dump_enable) + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); print_ptr += sizeof(struct cdm_dmi_cmd) / sizeof(uint32_t); } CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx); } - dump_stripe_cmd(frm_proc, stripe_idx, i, k, - iova_addr, kmd_buf, buf_len); + if (hw_mgr->frame_dump_enable) + dump_stripe_cmd(frm_proc, stripe_idx, i, k, + iova_addr, kmd_buf, buf_len); } return kmd_buf; } @@ -1511,10 +1532,12 @@ static int cam_ope_dev_process_prepare(struct ope_hw *ope_hw, void *cmd_args) if (rc) goto end; - cam_ope_dev_create_kmd_buf(ope_dev_prepare_req->hw_mgr, - ope_dev_prepare_req->prepare_args, - ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, - ope_dev_prepare_req->kmd_buf_offset, ope_dev_prepare_req); + rc = cam_ope_dev_create_kmd_buf(ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, + ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, + ope_dev_prepare_req); end: return rc; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index e3c7cedaff..cb80739071 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -80,6 +80,7 @@ static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info, ope_hw_100.top_reg->base = core_info->ope_hw_info->ope_top_base; ope_hw_100.bus_rd_reg->base = core_info->ope_hw_info->ope_bus_rd_base; ope_hw_100.bus_wr_reg->base = core_info->ope_hw_info->ope_bus_wr_base; + ope_hw_100.pp_reg->base = core_info->ope_hw_info->ope_pp_base; return rc; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index ecff57eeb9..a54a2ec5b8 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -14,6 +14,7 @@ #define MAX_RD_CLIENTS 2 #define MAX_WR_CLIENTS 8 +#define MAX_PP_CLIENTS 29 #define OPE_CDM_BASE 0x0 #define OPE_TOP_BASE 0x1 @@ -386,6 +387,18 @@ struct cam_ope_debug_register { uint32_t offset; }; +struct cam_ope_bus_pp_client_reg { + uint32_t hw_status; +}; + +struct cam_ope_pp_reg { + void *base; + uint32_t offset; + + uint32_t num_clients; + struct cam_ope_bus_pp_client_reg pp_clients[MAX_PP_CLIENTS]; +}; + struct ope_hw { struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; @@ -400,6 +413,8 @@ struct ope_hw { struct cam_ope_qos_reg_val *qos_reg_val; struct cam_ope_common *common; + + struct cam_ope_pp_reg *pp_reg; }; struct hw_version_reg { diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index 95ae384161..727b43c685 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -554,6 +554,101 @@ static struct cam_ope_bus_wr_reg_val ope_bus_wr_reg_val = { }, }, }; + +static struct cam_ope_pp_reg ope_pp_reg = { + .offset = 0x800, + .num_clients = MAX_PP_CLIENTS, + .pp_clients = { + { + .hw_status = 0x4, + }, + { + .hw_status = 0x204, + }, + { + .hw_status = 0x404, + }, + { + .hw_status = 0x604, + }, + { + .hw_status = 0x804, + }, + { + .hw_status = 0xA04, + }, + { + .hw_status = 0xC04, + }, + { + .hw_status = 0xE04, + }, + { + .hw_status = 0x1004, + }, + { + .hw_status = 0x1204, + }, + { + .hw_status = 0x1404, + }, + { + .hw_status = 0x1604, + }, + { + .hw_status = 0x1804, + }, + { + .hw_status = 0x1A04, + }, + { + .hw_status = 0x1C04, + }, + { + .hw_status = 0x1E04, + }, + { + .hw_status = 0x2204, + }, + { + .hw_status = 0x2604, + }, + { + .hw_status = 0x2804, + }, + { + .hw_status = 0x2A04, + }, + { + .hw_status = 0x2C04, + }, + { + .hw_status = 0x2E04, + }, + { + .hw_status = 0x3004, + }, + { + .hw_status = 0x3204, + }, + { + .hw_status = 0x3404, + }, + { + .hw_status = 0x3604, + }, + { + .hw_status = 0x3804, + }, + { + .hw_status = 0x3A04, + }, + { + .hw_status = 0x3C04, + }, + }, +}; + static struct ope_hw ope_hw_100 = { .top_reg = &ope_top_reg, .top_reg_val = &ope_top_reg_val, @@ -561,6 +656,7 @@ static struct ope_hw ope_hw_100 = { .bus_rd_reg_val = &ope_bus_rd_reg_val, .bus_wr_reg = &ope_bus_wr_reg, .bus_wr_reg_val = &ope_bus_wr_reg_val, + .pp_reg = &ope_pp_reg, }; #endif /* CAM_OPE_HW_100_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index 1034e55feb..ee59b8d277 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -50,6 +50,7 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; uint32_t irq_mask, irq_status; + unsigned long flags; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -72,21 +73,37 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, rc = wait_for_completion_timeout( &ope_top_info.reset_complete, - msecs_to_jiffies(30)); + msecs_to_jiffies(60)); cam_io_w_mb(top_reg_val->debug_cfg_val, top_reg->base + top_reg->debug_cfg); if (!rc || rc < 0) { - CAM_ERR(CAM_OPE, "reset error result = %d", rc); - irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_mask); - irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_status); - CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x", - irq_mask, irq_status); - cam_ope_top_dump_debug_reg(ope_hw_info); - rc = -ETIMEDOUT; + spin_lock_irqsave(&ope_top_info.hw_lock, flags); + if (!completion_done(&ope_top_info.reset_complete)) { + CAM_DBG(CAM_OPE, + "IRQ delayed, checking the status registers"); + irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_mask); + irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_status); + if (irq_status & top_reg_val->rst_done) { + CAM_DBG(CAM_OPE, "ope reset done"); + cam_io_w_mb(irq_status, + top_reg->base + top_reg->irq_clear); + cam_io_w_mb(top_reg_val->irq_set_clear, + top_reg->base + top_reg->irq_cmd); + } else { + CAM_ERR(CAM_OPE, + "irq mask 0x%x irq status 0x%x", + irq_mask, irq_status); + cam_ope_top_dump_debug_reg(ope_hw_info); + rc = -ETIMEDOUT; + } + } else { + rc = 0; + } + spin_unlock_irqrestore(&ope_top_info.hw_lock, flags); } else { rc = 0; } @@ -137,6 +154,7 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, struct cam_ope_top_reg_val *top_reg_val; struct cam_ope_dev_init *dev_init = data; uint32_t irq_mask, irq_status; + unsigned long flags; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -160,25 +178,41 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, rc = wait_for_completion_timeout( &ope_top_info.reset_complete, - msecs_to_jiffies(30)); + msecs_to_jiffies(60)); cam_io_w_mb(top_reg_val->debug_cfg_val, top_reg->base + top_reg->debug_cfg); if (!rc || rc < 0) { - CAM_ERR(CAM_OPE, "reset error result = %d", rc); - irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_mask); - irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_status); - CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x", - irq_mask, irq_status); - cam_ope_top_dump_debug_reg(ope_hw_info); - rc = -ETIMEDOUT; + spin_lock_irqsave(&ope_top_info.hw_lock, flags); + if (!completion_done(&ope_top_info.reset_complete)) { + CAM_DBG(CAM_OPE, + "IRQ delayed, checking the status registers"); + irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_mask); + irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_status); + if (irq_status & top_reg_val->rst_done) { + CAM_DBG(CAM_OPE, "ope reset done"); + cam_io_w_mb(irq_status, + top_reg->base + top_reg->irq_clear); + cam_io_w_mb(top_reg_val->irq_set_clear, + top_reg->base + top_reg->irq_cmd); + } else { + CAM_ERR(CAM_OPE, + "irq mask 0x%x irq status 0x%x", + irq_mask, irq_status); + cam_ope_top_dump_debug_reg(ope_hw_info); + rc = -ETIMEDOUT; + } + } else { + CAM_DBG(CAM_OPE, "reset done"); + rc = 0; + } + spin_unlock_irqrestore(&ope_top_info.hw_lock, flags); } else { rc = 0; } - /* enable interrupt mask */ cam_io_w_mb(top_reg_val->irq_mask, ope_hw_info->top_reg->base + top_reg->irq_mask); @@ -197,6 +231,7 @@ static int cam_ope_top_probe(struct ope_hw *ope_hw_info, } ope_top_info.ope_hw_info = ope_hw_info; + spin_lock_init(&ope_top_info.hw_lock); return rc; } @@ -207,9 +242,12 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info, int rc = 0; uint32_t irq_status; uint32_t violation_status; + uint32_t pp_hw_status = 0; struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; + struct cam_ope_pp_reg *pp_reg; struct cam_ope_irq_data *irq_data = data; + int i; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -218,7 +256,9 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info, top_reg = ope_hw_info->top_reg; top_reg_val = ope_hw_info->top_reg_val; + pp_reg = ope_hw_info->pp_reg; + spin_lock(&ope_top_info.hw_lock); /* Read and Clear Top Interrupt status */ irq_status = cam_io_r_mb(top_reg->base + top_reg->irq_status); cam_io_w_mb(irq_status, @@ -237,7 +277,22 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info, top_reg->violation_status); irq_data->error = 1; CAM_ERR(CAM_OPE, "ope violation: %x", violation_status); + + for (i = 0; i < pp_reg->num_clients ; i++) { + pp_hw_status = 0; + pp_hw_status = + cam_io_r_mb(pp_reg->base + + pp_reg->pp_clients[i] + .hw_status); + + if (pp_hw_status) + CAM_ERR(CAM_OPE, + "ope pp hw_status offset 0x%x val 0x%x", + pp_reg->pp_clients[i].hw_status, + pp_hw_status); + } } + spin_unlock(&ope_top_info.hw_lock); return rc; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h index 428d66f7e9..57d90712bd 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h @@ -33,11 +33,13 @@ struct ope_top_ctx { * @top_ctx: OPE top context * @reset_complete: Reset complete flag * @ope_mutex: OPE hardware mutex + * @hw_lock: OPE hardware spinlock */ struct ope_top { struct ope_hw *ope_hw_info; struct ope_top_ctx top_ctx[OPE_CTX_MAX]; struct completion reset_complete; struct mutex ope_hw_mutex; + spinlock_t hw_lock; }; #endif /* OPE_TOP_H */