diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index fd903f3364..128edaf3e5 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1224,16 +1224,14 @@ static void cam_hw_cdm_work(struct work_struct *work) } -static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, - struct device *dev, unsigned long iova, int flags, void *token, - uint32_t buf_info) +static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; int i; - if (token) { - cdm_hw = (struct cam_hw_info *)token; + if (pf_info->token) { + cdm_hw = (struct cam_hw_info *)pf_info->token; core = (struct cam_cdm *)cdm_hw->core_info; set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); mutex_lock(&cdm_hw->hw_mutex); @@ -1254,9 +1252,9 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, mutex_unlock(&core->bl_fifo[i].fifo_lock); mutex_unlock(&cdm_hw->hw_mutex); CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n", - (void *)iova); + (void *)pf_info->iova); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT, - (void *)iova); + (void *)pf_info->iova); clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "Invalid token"); diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 4b3078ad79..5fc9387e33 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -287,8 +287,8 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx, return rc; } -int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, - uint32_t buf_info) +int cam_context_dump_pf_info(struct cam_context *ctx, + struct cam_smmu_pf_info *pf_info) { int rc = 0; @@ -301,7 +301,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, (ctx->state < CAM_CTX_STATE_MAX)) { if (ctx->state_machine[ctx->state].pagefault_ops) { rc = ctx->state_machine[ctx->state].pagefault_ops( - ctx, iova, buf_info); + ctx, pf_info); } else { CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", ctx->dev_hdl, ctx->state); diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index c959edb8a2..10bc72b89a 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -11,6 +11,7 @@ #include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" +#include "cam_smmu_api.h" /* Forward declarations */ struct cam_context; @@ -360,12 +361,11 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx, * @brief: Handle dump active request request command * * @ctx: Object pointer for cam_context - * @iova: Page fault address - * @buf_info: Information about closest memory handle + * @pf_info: Smmu page fault info * */ -int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, - uint32_t buf_info); +int cam_context_dump_pf_info(struct cam_context *ctx, + struct cam_smmu_pf_info *pf_info); /** * cam_context_handle_acquire_dev() diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index beb28f89d8..86f1bf43af 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -998,8 +998,8 @@ end: } int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, - struct cam_packet *packet, unsigned long iova, uint32_t buf_info, - bool *mem_found) + struct cam_packet *packet, bool *mem_found, bool *ctx_found, + uint32_t *resource_type, struct cam_smmu_pf_info *pf_info) { int rc = 0; struct cam_hw_cmd_args cmd_args; @@ -1021,9 +1021,14 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO; cmd_args.u.pf_args.pf_data.packet = packet; - cmd_args.u.pf_args.iova = iova; - cmd_args.u.pf_args.buf_info = buf_info; + cmd_args.u.pf_args.iova = pf_info->iova; + cmd_args.u.pf_args.buf_info = pf_info->buf_info; cmd_args.u.pf_args.mem_found = mem_found; + cmd_args.u.pf_args.ctx_found = ctx_found; + cmd_args.u.pf_args.resource_type = resource_type; + cmd_args.u.pf_args.bid = pf_info->bid; + cmd_args.u.pf_args.pid = pf_info->pid; + cmd_args.u.pf_args.mid = pf_info->mid; ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &cmd_args); } diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h index 4aeb7dd338..559c4e254b 100644 --- a/drivers/cam_core/cam_context_utils.h +++ b/drivers/cam_core/cam_context_utils.h @@ -7,6 +7,7 @@ #define _CAM_CONTEXT_UTILS_H_ #include +#include "cam_smmu_api.h" int cam_context_buf_done_from_hw(struct cam_context *ctx, void *done_event_data, uint32_t evt_id); @@ -27,8 +28,9 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx); int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, - struct cam_packet *packet, unsigned long iova, uint32_t buf_info, - bool *mem_found); + struct cam_packet *packet, bool *mem_found, bool *ctx_found, + uint32_t *resource_type, + struct cam_smmu_pf_info *pf_info); int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx); int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 9c243f19a8..2389327863 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -9,6 +9,8 @@ #include #include #include +#include "cam_smmu_api.h" + /* * This file declares Constants, Enums, Structures and APIs to be used as * Interface between HW Manager and Context. @@ -44,8 +46,8 @@ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, void *evt_data); /* hardware page fault callback function type */ -typedef int (*cam_hw_pagefault_cb_func)(void *context, unsigned long iova, - uint32_t buf_info); +typedef int (*cam_hw_pagefault_cb_func)(void *context, + struct cam_smmu_pf_info *pf_info); /* ctx dump callback function type */ typedef int (*cam_ctx_info_dump_cb_func)(void *context, @@ -295,6 +297,11 @@ struct cam_hw_flush_args { * fault occurred * @mem_found: If fault memory found in current * request + * @ctx_found If fault pid found in context acquired hardware + * @resource_type Resource type of the port which caused pf + * @bid: Indicate the bus id + * @pid: Indicates unique hw group ports + * @mid: Indicates port id of the camera hw * */ struct cam_hw_dump_pf_args { @@ -302,6 +309,11 @@ struct cam_hw_dump_pf_args { unsigned long iova; uint32_t buf_info; bool *mem_found; + bool *ctx_found; + uint32_t *resource_type; + uint32_t bid; + uint32_t pid; + uint32_t mid; }; /** diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index d8f18a8220..e2d94ef3c5 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -14,6 +14,7 @@ #include "cam_cpas_hw_intf.h" #include "cam_cpas_soc.h" #include "cam_req_mgr_dev.h" +#include "cam_smmu_api.h" static uint cam_min_camnoc_ib_bw; module_param(cam_min_camnoc_ib_bw, uint, 0644); @@ -1431,6 +1432,8 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, } CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); + + cam_smmu_reset_cb_page_fault_cnt(); cpas_hw->hw_state = CAM_HW_STATE_POWER_UP; } diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index af3c7b907a..d1a3444084 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -25,22 +25,20 @@ static struct cam_custom_dev g_custom_dev; static void cam_custom_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) + struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { + if (!pf_info || !pf_info->token) { CAM_ERR(CAM_CUSTOM, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static const struct of_device_id cam_custom_dt_match[] = { diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index c2edab7d3f..064236f007 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -22,15 +22,16 @@ static const char icp_dev_name[] = "cam-icp"; -static int cam_icp_context_dump_active_request(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_icp_context_dump_active_request(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + uint32_t resource_type = 0; int rc = 0; - bool b_mem_found = false; + bool b_mem_found = false, b_ctx_found = false; if (!ctx) { CAM_ERR(CAM_ICP, "Invalid ctx"); @@ -52,7 +53,7 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova, CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &b_mem_found); + &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ICP, "Failed to dump pf info"); diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index ee7fe5132d..8c79bbbde5 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -50,23 +50,20 @@ static const struct of_device_id cam_icp_dt_match[] = { {} }; -static void cam_icp_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) +static void cam_icp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { - CAM_ERR(CAM_ICP, "invalid token in page handler cb"); + if (!pf_info || !pf_info->token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static int cam_icp_subdev_open(struct v4l2_subdev *sd, diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index c1e9b968cd..3ed41d95f7 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -28,8 +28,8 @@ static struct cam_isp_ctx_debug isp_ctx_debug; div_u64_rem(atomic64_add_return(1, head),\ max_entries, (ret)) -static int cam_isp_context_dump_requests(void *data, unsigned long iova, - uint32_t buf_info); +static int cam_isp_context_dump_requests(void *data, + struct cam_smmu_pf_info *pf_info); static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); @@ -5423,9 +5423,8 @@ static struct cam_ctx_ops }, }; - -static int cam_isp_context_dump_requests(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_isp_context_dump_requests(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; @@ -5434,7 +5433,10 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, struct cam_isp_ctx_req *req_isp = NULL; struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; - bool mem_found = false; + struct cam_req_mgr_message req_msg; + struct cam_isp_context *ctx_isp; + uint32_t resource_type = 0; + bool mem_found = false, ctx_found = false, send_error = false; int rc = 0; struct cam_isp_context *isp_ctx = @@ -5457,13 +5459,12 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &mem_found); + &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); - if (mem_found) - CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", - req->request_id, rc); + if (ctx_found) + send_error = true; } CAM_INFO(CAM_ISP, "Iterating over wait_list of isp ctx %d state %d", @@ -5477,13 +5478,12 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, CAM_INFO(CAM_ISP, "Wait List: req_id : %lld ", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &mem_found); + &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); - if (mem_found) - CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", - req->request_id, rc); + if (ctx_found) + send_error = true; } /* @@ -5508,15 +5508,57 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &mem_found); + &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); - if (mem_found) - CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", - req->request_id, rc); + if (ctx_found) + send_error = true; } + if (resource_type) { + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + if (ctx_isp->isp_device_type == CAM_IFE_DEVICE_TYPE) + CAM_ERR(CAM_ISP, + "Page fault on resource id:%s (0x%x) ctx id:%d frame id:%d reported id:%lld applied id:%lld", + __cam_isp_resource_handle_id_to_type( + resource_type), + resource_type, ctx->ctx_id, ctx_isp->frame_id, + ctx_isp->reported_req_id, + ctx_isp->last_applied_req_id); + else + CAM_ERR(CAM_ISP, + "Page fault on resource id:%s (0x%x) ctx id:%d frame id:%d reported id:%lld applied id:%lld", + __cam_isp_tfe_resource_handle_id_to_type( + resource_type), + resource_type, ctx->ctx_id, ctx_isp->frame_id, + ctx_isp->reported_req_id, + ctx_isp->last_applied_req_id); + + } + + if (send_error) { + CAM_INFO(CAM_ISP, + "page fault notifying to umd ctx %u session_hdl:%d device_hdl:%d link_hdl:%d", + ctx->ctx_id, ctx->session_hdl, + ctx->dev_hdl, ctx->link_hdl); + + req_msg.session_hdl = ctx->session_hdl; + req_msg.u.err_msg.device_hdl = ctx->dev_hdl; + req_msg.u.err_msg.error_type = + CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT; + req_msg.u.err_msg.link_hdl = ctx->link_hdl; + req_msg.u.err_msg.request_id = 0; + req_msg.u.err_msg.resource_size = 0x0; + + if (cam_req_mgr_notify_message(&req_msg, + V4L_EVENT_CAM_REQ_MGR_ERROR, + V4L_EVENT_CAM_REQ_MGR_EVENT)) + CAM_ERR(CAM_ISP, + "could not send page fault notification ctx %u session_hdl:%d device_hdl:%d link_hdl:%d", + ctx->ctx_id, ctx->session_hdl, + ctx->dev_hdl, ctx->link_hdl); + } return rc; } diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 778621bcdb..10aa46ffc0 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -22,23 +22,20 @@ static struct cam_isp_dev g_isp_dev; -static void cam_isp_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) +static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { + if (!pf_info || !pf_info->token) { CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static const struct of_device_id cam_isp_dt_match[] = { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c41af53f91..00a6fd9fc1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1527,7 +1527,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( continue; hw_intf = ife_hw_mgr->ife_devices[ - csid_res->hw_res[i]->hw_intf->hw_idx]; + csid_res->hw_res[i]->hw_intf->hw_idx]->hw_intf; if (i == CAM_ISP_HW_SPLIT_LEFT && ife_src_res->is_dual_isp) { @@ -2348,7 +2348,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_bus_rd( if (!ife_hw_mgr->ife_devices[j]) continue; - hw_intf = ife_hw_mgr->ife_devices[j]; + hw_intf = ife_hw_mgr->ife_devices[j]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -2379,7 +2379,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_bus_rd( if (j == ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx) continue; - hw_intf = ife_hw_mgr->ife_devices[j]; + hw_intf = ife_hw_mgr->ife_devices[j]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -2463,7 +2463,7 @@ static int cam_ife_hw_mgr_acquire_offline_res_ife_camif( vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; hw_intf = ife_hw_mgr->ife_devices[ - ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx]; + ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -2493,7 +2493,7 @@ static int cam_ife_hw_mgr_acquire_offline_res_ife_camif( vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE; hw_intf = ife_hw_mgr->ife_devices[ - ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx]; + ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -4163,10 +4163,10 @@ static int cam_ife_mgr_reset_vfe_hw(struct cam_ife_hw_mgr *hw_mgr, if (!hw_mgr->ife_devices[i]) continue; - if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + if (hw_idx != hw_mgr->ife_devices[i]->hw_intf->hw_idx) continue; CAM_DBG(CAM_ISP, "VFE (id = %d) reset", hw_idx); - vfe_hw_intf = hw_mgr->ife_devices[i]; + vfe_hw_intf = hw_mgr->ife_devices[i]->hw_intf; vfe_hw_intf->hw_ops.reset(vfe_hw_intf->hw_priv, &vfe_reset_type, sizeof(vfe_reset_type)); break; @@ -4188,12 +4188,15 @@ static int cam_ife_mgr_unmask_bus_wr_irq(struct cam_ife_hw_mgr *hw_mgr, } for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) { - if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + if (!hw_mgr->ife_devices[i]) + continue; + + if (hw_idx != hw_mgr->ife_devices[i]->hw_intf->hw_idx) continue; CAM_DBG(CAM_ISP, "Unmask VFE:%d BUS_WR IRQ", hw_idx); - vfe_hw_intf = hw_mgr->ife_devices[i]; + vfe_hw_intf = hw_mgr->ife_devices[i]->hw_intf; vfe_hw_intf->hw_ops.process_cmd(vfe_hw_intf->hw_priv, CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, @@ -4632,6 +4635,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->dsp_enabled = false; ctx->is_fe_enabled = false; ctx->is_offline = false; + ctx->pf_mid_found = false; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; @@ -6421,42 +6425,43 @@ static int cam_ife_mgr_sof_irq_debug( return rc; } -static void cam_ife_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) +static void cam_ife_mgr_print_io_bufs(struct cam_ife_hw_mgr *hw_mgr, + uint32_t res_id, struct cam_packet *packet, + bool *ctx_found, struct cam_ife_hw_mgr_ctx *ctx) { - 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; + int32_t mmu_hdl, iommu_hdl, sec_mmu_hdl; + dma_addr_t iova_addr; + size_t src_buf_size; + int i, j, rc = 0; - if (mem_found) - *mem_found = false; + iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl; + sec_mmu_hdl = hw_mgr->mgr_common.img_iommu_hdl_secure; 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++) { + if (io_cfg[i].resource_type != res_id) + continue; + else + break; + } + + if (i == packet->num_io_configs) { + *ctx_found = false; + CAM_ERR(CAM_ISP, + "getting io port for mid resource id failed ctx id:%d req id:%lld res id:0x%x", + ctx->ctx_index, packet->header.request_id, + res_id); + return; + } + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { if (!io_cfg[i].mem_handle[j]) break; - if (pf_buf_info && - GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == - GET_FD_FROM_HANDLE(pf_buf_info)) { - CAM_INFO(CAM_ISP, - "Found PF at port: 0x%x mem 0x%x fd: 0x%x", - io_cfg[i].resource_type, - io_cfg[i].mem_handle[j], - pf_buf_info); - if (mem_found) - *mem_found = true; - } - CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d", io_cfg[i].resource_type, io_cfg[i].fence, @@ -6476,7 +6481,6 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, } if ((iova_addr & 0xFFFFFFFF) != iova_addr) { CAM_ERR(CAM_ISP, "Invalid mapped address"); - rc = -EINVAL; continue; } @@ -6492,7 +6496,185 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, io_cfg[i].offsets[j], io_cfg[i].mem_handle[j]); } +} + +static void cam_ife_mgr_pf_dump(uint32_t res_id, + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_event_info event_info; + uint32_t res_id_out; + int i, rc = 0; + + /* dump the registers */ + rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, + CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, NULL, false); + if (rc) + CAM_ERR(CAM_ISP, + "Reg dump on pf failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + + + /* dump the acquire data */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_LOG_ACQUIRE_DATA, + hw_mgr_res->hw_res[i], + sizeof(void *)); + if (rc) + CAM_ERR(CAM_ISP, + "csid acquire data dump failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } } + + event_info.res_id = res_id; + res_id_out = res_id & 0xFF; + + if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid out resource id :%x", + res_id); + return; + } + + hw_mgr_res = &ctx->res_list_ife_out[res_id_out]; + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)&event_info, + sizeof(struct cam_isp_hw_event_info)); + } + } +} + +static void cam_ife_mgr_dump_pf_data( + struct cam_ife_hw_mgr *hw_mgr, + struct cam_hw_cmd_args *hw_cmd_args) +{ + struct cam_ife_hw_mgr_ctx *ctx; + + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_get_cmd_update cmd_update; + struct cam_isp_hw_get_res_for_mid get_res; + struct cam_packet *packet; + uint32_t hw_id; + uint32_t *resource_type; + bool *ctx_found, hw_id_found = false; + int i, j, rc = 0; + + ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map; + + packet = hw_cmd_args->u.pf_args.pf_data.packet; + ctx_found = hw_cmd_args->u.pf_args.ctx_found; + resource_type = hw_cmd_args->u.pf_args.resource_type; + + if ((*ctx_found) && (*resource_type)) + goto outportlog; + + if (ctx->pf_mid_found) + goto outportlog; + + if (!g_ife_hw_mgr.hw_pid_support) + goto mid_check; + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (!hw_mgr->ife_devices[i]) + continue; + + for (j = 0; j < g_ife_hw_mgr.ife_devices[i]->num_hw_pid; j++) { + if (g_ife_hw_mgr.ife_devices[i]->hw_pid[j] == + hw_cmd_args->u.pf_args.pid) { + hw_id_found = true; + hw_id = i; + break; + } + } + if (hw_id_found) + break; + } + + if (i == CAM_IFE_HW_NUM_MAX) { + CAM_INFO(CAM_ISP, + "PID:%d is not matching with any IFE HW PIDs ctx id:%d", + hw_cmd_args->u.pf_args.pid, ctx->ctx_index); + return; + } + + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == hw_id) { + *ctx_found = true; + break; + } + } + + if (!(*ctx_found)) { + CAM_INFO(CAM_ISP, + "This context does not cause pf:pid:%d hw id:%d ctx_id:%d", + hw_cmd_args->u.pf_args.pid, hw_id, ctx->ctx_index); + return; + } + +mid_check: + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + hw_mgr_res = &ctx->res_list_ife_out[i]; + if (!hw_mgr_res->hw_res[0]) + continue; + + break; + } + + if (i >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, + "NO valid outport resources ctx id:%d req id:%lld", + ctx->ctx_index, packet->header.request_id); + return; + } + + get_res.mid = hw_cmd_args->u.pf_args.mid; + cmd_update.res = hw_mgr_res->hw_res[0]; + cmd_update.cmd_type = CAM_ISP_HW_CMD_GET_RES_FOR_MID; + cmd_update.data = (void *) &get_res; + + /* get resource id for given mid */ + rc = hw_mgr_res->hw_res[0]->hw_intf->hw_ops.process_cmd( + hw_mgr_res->hw_res[0]->hw_intf->hw_priv, + cmd_update.cmd_type, &cmd_update, + sizeof(struct cam_isp_hw_get_cmd_update)); + + if (rc) { + CAM_ERR(CAM_ISP, + "getting mid port resource id failed ctx id:%d req id:%lld", + ctx->ctx_index, packet->header.request_id); + return; + } + + CAM_ERR(CAM_ISP, + "Page fault on resource id:(0x%x) ctx id:%d req id:%lld", + get_res.out_res_id, ctx->ctx_index, packet->header.request_id); + *resource_type = get_res.out_res_id; + ctx->pf_mid_found = true; + + cam_ife_mgr_pf_dump(get_res.out_res_id, ctx); + +outportlog: + cam_ife_mgr_print_io_bufs(hw_mgr, *resource_type, packet, + ctx_found, ctx); + } static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) @@ -6567,12 +6749,8 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) } break; case CAM_HW_MGR_CMD_DUMP_PF_INFO: - cam_ife_mgr_print_io_bufs( - hw_cmd_args->u.pf_args.pf_data.packet, - hw_mgr->mgr_common.img_iommu_hdl, - hw_mgr->mgr_common.img_iommu_hdl_secure, - hw_cmd_args->u.pf_args.buf_info, - hw_cmd_args->u.pf_args.mem_found); + cam_ife_mgr_dump_pf_data(hw_mgr, hw_cmd_args); + break; case CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH: if (ctx->last_dump_flush_req_id == ctx->applied_req_id) @@ -7548,9 +7726,9 @@ static int cam_ife_hw_mgr_sort_dev_with_caps( for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (!ife_hw_mgr->ife_devices[i]) continue; - if (ife_hw_mgr->ife_devices[i]->hw_ops.get_hw_caps) { - ife_hw_mgr->ife_devices[i]->hw_ops.get_hw_caps( - ife_hw_mgr->ife_devices[i]->hw_priv, + if (ife_hw_mgr->ife_devices[i]->hw_intf->hw_ops.get_hw_caps) { + ife_hw_mgr->ife_devices[i]->hw_intf->hw_ops.get_hw_caps( + ife_hw_mgr->ife_devices[i]->hw_intf->hw_priv, &ife_hw_mgr->ife_dev_caps[i], sizeof(ife_hw_mgr->ife_dev_caps[i])); } @@ -7671,7 +7849,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) rc = cam_vfe_hw_init(&g_ife_hw_mgr.ife_devices[i], i); if (!rc) { struct cam_hw_intf *ife_device = - g_ife_hw_mgr.ife_devices[i]; + g_ife_hw_mgr.ife_devices[i]->hw_intf; struct cam_hw_info *vfe_hw = (struct cam_hw_info *) ife_device->hw_priv; @@ -7690,6 +7868,10 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) "reg_map: mem base = %pK cam_base = 0x%llx", (void __iomem *)soc_info->reg_map[0].mem_base, (uint64_t) soc_info->reg_map[0].mem_cam_base); + + if (g_ife_hw_mgr.ife_devices[i]->num_hw_pid) + g_ife_hw_mgr.hw_pid_support = true; + } else { g_ife_hw_mgr.cdm_reg_map[i] = NULL; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 15adc1713c..010c7dda16 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -99,6 +99,7 @@ struct cam_ife_hw_mgr_debug { * @dsp_enabled Indicate whether dsp is enabled in this context * @hw_enabled Array to indicate active HW * @internal_cdm Indicate whether context uses internal CDM + * @pf_mid_found in page fault, mid found for this ctx. */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -154,6 +155,7 @@ struct cam_ife_hw_mgr_ctx { bool is_offline; bool dsp_enabled; bool internal_cdm; + bool pf_mid_found; }; /** @@ -172,13 +174,15 @@ struct cam_ife_hw_mgr_ctx { * @ife_dev_caps ife device capability per core * @work q work queue for IFE hw manager * @debug_cfg debug configuration + * @ctx_lock context lock * @support_consumed_addr indicate whether hw supports last consumed address + * @hw_pid_support hw pid support for this target */ struct cam_ife_hw_mgr { struct cam_isp_hw_mgr mgr_common; struct cam_hw_intf *tpg_devices[CAM_TOP_TPG_HW_NUM_MAX]; struct cam_hw_intf *csid_devices[CAM_IFE_CSID_HW_NUM_MAX]; - struct cam_hw_intf *ife_devices[CAM_IFE_HW_NUM_MAX]; + struct cam_isp_hw_intf_data *ife_devices[CAM_IFE_HW_NUM_MAX]; struct cam_soc_reg_map *cdm_reg_map[CAM_IFE_HW_NUM_MAX]; struct mutex ctx_mutex; @@ -194,6 +198,7 @@ struct cam_ife_hw_mgr { struct cam_ife_hw_mgr_debug debug_cfg; spinlock_t ctx_lock; bool support_consumed_addr; + bool hw_pid_support; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index dd85eb45d4..1ec669eca3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4118,6 +4118,55 @@ static int cam_ife_csid_dump_hw( return 0; } +static int cam_ife_csid_log_acquire_data( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_isp_resource_node *res = + (struct cam_isp_resource_node *)cmd_args; + struct cam_ife_csid_path_cfg *path_data; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg; + const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + uint32_t byte_cnt_ping, byte_cnt_pong; + + path_data = (struct cam_ife_csid_path_cfg *)res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d invalid res id:%d res type: %d state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_type, + res->res_state); + return -EINVAL; + } + + /* Dump all the acquire data for this hardware */ + CAM_INFO(CAM_ISP, + "CSID:%d res id:%d type:%d state:%d in f:%d out f:%d st pix:%d end pix:%d st line:%d end line:%d h bin:%d qcfa bin:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_type, + res->res_type, path_data->in_format, path_data->out_format, + path_data->start_pixel, path_data->end_pixel, + path_data->start_line, path_data->end_line, + path_data->horizontal_bin, path_data->qcfa_bin); + + if (res->res_id >= CAM_IFE_PIX_PATH_RES_RDI_0 && + res->res_id <= CAM_IFE_PIX_PATH_RES_RDI_3) { + rdi_reg = csid_reg->rdi_reg[res->res_id]; + /* read total number of bytes transmitted through RDI */ + byte_cnt_ping = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_byte_cntr_ping_addr); + byte_cnt_pong = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_byte_cntr_pong_addr); + CAM_INFO(CAM_ISP, + "CSID:%d res id:%d byte cnt val ping:%d pong:%d", + csid_hw->hw_intf->hw_idx, res->res_id, + byte_cnt_ping, byte_cnt_pong); + } + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -4164,6 +4213,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG: rc = cam_ife_csid_set_sensor_dimension(csid_hw, cmd_args); break; + case CAM_IFE_CSID_LOG_ACQUIRE_DATA: + rc = cam_ife_csid_log_acquire_data(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index a399d2fdc4..bd866c6202 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -212,6 +212,7 @@ enum cam_ife_csid_cmd_type { CAM_IFE_CSID_SOF_IRQ_DEBUG, CAM_IFE_CSID_SET_CONFIG, CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, + CAM_IFE_CSID_LOG_ACQUIRE_DATA, CAM_IFE_CSID_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 9181fdc2eb..03e76b627d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -15,6 +15,8 @@ /* Maximum length of tag while dumping */ #define CAM_ISP_HW_DUMP_TAG_MAX_LEN 32 +/* Max isp hw pid values number */ +#define CAM_ISP_HW_MAX_PID_VAL 4 /* * struct cam_isp_timestamp: * @@ -121,6 +123,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_FE_TRIGGER_CMD, CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + CAM_ISP_HW_CMD_GET_RES_FOR_MID, CAM_ISP_HW_CMD_MAX, }; @@ -233,6 +236,20 @@ struct cam_isp_hw_get_wm_update { struct cam_buf_io_cfg *io_cfg; }; +/* + * struct cam_isp_hw_get_res_for_mid: + * + * @Brief: Get the out resource id for given mid + * + * @mid: Mid number of hw outport numb + * @out_res_id: Out resource id + * + */ +struct cam_isp_hw_get_res_for_mid { + uint32_t mid; + uint32_t out_res_id; +}; + /* * struct cam_isp_hw_get_cmd_update: * @@ -308,4 +325,19 @@ struct cam_isp_hw_dump_header { uint32_t word_size; }; +/** + * struct cam_isp_hw_intf_data - ISP hw intf data + * + * @Brief: isp hw intf pointer and pid list data + * + * @isp_hw_intf: Isp hw intf pointer + * @num_hw_pid: Number of pids for this hw + * @isp_hw_pid: Isp hw pid values + * + */ +struct cam_isp_hw_intf_data { + struct cam_hw_intf *hw_intf; + uint32_t num_hw_pid; + uint32_t hw_pid[CAM_ISP_HW_MAX_PID_VAL]; +}; #endif /* _CAM_ISP_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index adb33444cf..bd2c808bf1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -389,7 +389,8 @@ struct cam_vfe_generic_ubwc_config { * successful initialization * @hw_idx: Index of VFE HW */ -int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx); +int cam_vfe_hw_init(struct cam_isp_hw_intf_data **vfe_hw, + uint32_t hw_idx); /* * cam_vfe_put_evt_payload() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 8eaca71f1e..1581902964 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -616,6 +616,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c index 1dfa48cbfb..4be7e8e8de 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c @@ -14,8 +14,7 @@ #include "cam_vfe_soc.h" #include "cam_debug_util.h" -static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX]; - +static struct cam_isp_hw_intf_data cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX]; static char vfe_dev_name[8]; static int cam_vfe_component_bind(struct device *dev, @@ -28,6 +27,8 @@ static int cam_vfe_component_bind(struct device *dev, struct cam_vfe_hw_info *hw_info = NULL; int rc = 0; struct platform_device *pdev = to_platform_device(dev); + struct cam_vfe_soc_private *vfe_soc_priv; + uint32_t i; vfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!vfe_hw_intf) { @@ -109,7 +110,13 @@ static int cam_vfe_component_bind(struct device *dev, init_completion(&vfe_hw->hw_complete); if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) - cam_vfe_hw_list[vfe_hw_intf->hw_idx] = vfe_hw_intf; + cam_vfe_hw_list[vfe_hw_intf->hw_idx].hw_intf = vfe_hw_intf; + + vfe_soc_priv = vfe_hw->soc_info.soc_private; + cam_vfe_hw_list[vfe_hw_intf->hw_idx].num_hw_pid = vfe_soc_priv->num_pid; + for (i = 0; i < vfe_soc_priv->num_pid; i++) + cam_vfe_hw_list[vfe_hw_intf->hw_idx].hw_pid[i] = + vfe_soc_priv->pid[i]; cam_vfe_init_hw(vfe_hw, NULL, 0); cam_vfe_deinit_hw(vfe_hw, NULL, 0); @@ -150,7 +157,7 @@ static void cam_vfe_component_unbind(struct device *dev, vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx); if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) - cam_vfe_hw_list[vfe_hw_intf->hw_idx] = NULL; + cam_vfe_hw_list[vfe_hw_intf->hw_idx].hw_intf = NULL; vfe_hw = vfe_hw_intf->hw_priv; if (!vfe_hw) { @@ -207,15 +214,17 @@ int cam_vfe_remove(struct platform_device *pdev) return 0; } -int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx) +int cam_vfe_hw_init(struct cam_isp_hw_intf_data **vfe_hw_intf, + uint32_t hw_idx) { int rc = 0; - if (cam_vfe_hw_list[hw_idx]) { - *vfe_hw = cam_vfe_hw_list[hw_idx]; + if (cam_vfe_hw_list[hw_idx].hw_intf) { + *vfe_hw_intf = &cam_vfe_hw_list[hw_idx]; rc = 0; } else { - *vfe_hw = NULL; + CAM_ERR(CAM_ISP, "inval param"); + *vfe_hw_intf = NULL; rc = -ENODEV; } return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 61b7efe5bf..6b1bb46b94 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -36,7 +36,7 @@ static bool cam_vfe_cpas_cb(uint32_t client_handle, void *userdata, static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) { - int rc = 0, num_ubwc_cfg = 0, i = 0; + int rc = 0, num_ubwc_cfg = 0, i = 0, num_pid = 0; struct device_node *of_node = NULL; struct platform_device *pdev = NULL; struct cam_vfe_soc_private *vfe_soc_private; @@ -55,7 +55,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) if (strnstr(soc_info->compatible, "lite", strlen(soc_info->compatible)) != NULL) { vfe_soc_private->is_ife_lite = true; - goto end; + goto pid; } switch (soc_info->hw_version) { @@ -69,7 +69,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) CAM_ERR(CAM_ISP, "wrong num_ubwc_cfg: %d", num_ubwc_cfg); rc = num_ubwc_cfg; - goto end; + goto pid; } for (i = 0; i < num_ubwc_cfg; i++) { @@ -86,8 +86,24 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) default: break; } +pid: + /* set some default values */ + vfe_soc_private->num_pid = 0; + + num_pid = of_property_count_u32_elems(pdev->dev.of_node, "cam_hw_pid"); + CAM_DBG(CAM_CPAS, "vfe:%d pid count %d", soc_info->index, num_pid); + + if (num_pid <= 0 || num_pid > CAM_ISP_HW_MAX_PID_VAL) + goto end; + + for (i = 0; i < num_pid; i++) + of_property_read_u32_index(pdev->dev.of_node, "cam_hw_pid", i, + &vfe_soc_private->pid[i]); + + vfe_soc_private->num_pid = num_pid; end: + return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h index eef0207962..cb76b84790 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h @@ -25,6 +25,8 @@ * @ubwc_static_ctrl: UBWC static control configuration * @is_ife_lite: Flag to indicate full vs lite IFE * @ife_clk_src: IFE source clock + * @num_pid: Number of pids of ife + * @pid: IFE pid values list */ struct cam_vfe_soc_private { uint32_t cpas_handle; @@ -35,6 +37,8 @@ struct cam_vfe_soc_private { uint32_t ubwc_static_ctrl[UBWC_STATIC_CONFIG_MAX]; bool is_ife_lite; uint64_t ife_clk_src; + uint32_t num_pid; + uint32_t pid[CAM_ISP_HW_MAX_PID_VAL]; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index bda439a4c9..bd0390e04a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1176,60 +1176,77 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .mid[0] = 8, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_4, + .mid[0] = 9, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_5, + .mid[0] = 10, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL, .max_width = 4096, .max_height = 4096, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 32, + .mid[1] = 33, + .mid[2] = 34, + .mid[3] = 35, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 16, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 17, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 11, + .mid[1] = 12, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FD, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 20, + .mid[1] = 21, + .mid[2] = 22, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_PDAF, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 25, + .mid[1] = 26, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 40, }, { .vfe_out_type = @@ -1237,6 +1254,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 41, }, { .vfe_out_type = @@ -1244,72 +1262,88 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 42, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 43, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 44, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 45, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 46, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 47, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 48, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, .max_width = 4096, .max_height = 4096, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 36, + .mid[1] = 37, + .mid[2] = 38, + .mid[3] = 39, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 18, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 19, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .mid[0] = 23, + .mid[1] = 24, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LCR, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .mid[0] = 27, }, }, .comp_done_shift = 6, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 730af4c945..5478bb021d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -373,24 +373,28 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 16, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .mid[0] = 17, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .mid[0] = 18, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .mid[0] = 19, }, }, .comp_done_shift = 4, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index a5bb5b8621..69a69817b5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -180,6 +180,7 @@ struct cam_vfe_bus_ver2_vfe_out_data { struct cam_cdm_utils_ops *cdm_util_ops; uint32_t secure_mode; void *priv; + uint32_t mid[CAM_VFE_BUS_VER2_MAX_MID_PER_PORT]; }; struct cam_vfe_bus_ver2_priv { @@ -2431,7 +2432,7 @@ static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, { struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; - int rc = 0; + int rc = 0, i; int32_t vfe_out_type = ver2_hw_info->vfe_out_hw_info[index].vfe_out_type; @@ -2481,6 +2482,9 @@ static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf; vfe_out->irq_handle = 0; + for (i = 0; i < CAM_VFE_BUS_VER2_MAX_MID_PER_PORT; i++) + rsrc_data->mid[i] = ver2_hw_info->vfe_out_hw_info[index].mid[i]; + return 0; } @@ -3576,6 +3580,50 @@ int cam_vfe_bus_dump_wm_data(void *priv, void *cmd_args, uint32_t arg_size) return 0; } +static int cam_vfe_bus_get_res_for_mid( + struct cam_vfe_bus_ver2_priv *bus_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_vfe_out_data *out_data = NULL; + struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; + struct cam_isp_hw_get_res_for_mid *get_res = NULL; + int i, j; + + get_res = (struct cam_isp_hw_get_res_for_mid *)cmd_update->data; + if (!get_res) { + CAM_ERR(CAM_ISP, + "invalid get resource for mid paramas"); + return -EINVAL; + } + + for (i = 0; i < bus_priv->num_out; i++) { + out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + bus_priv->vfe_out[i].res_priv; + + if (!out_data) + continue; + + for (j = 0; j < CAM_VFE_BUS_VER2_MAX_MID_PER_PORT; j++) { + if (out_data->mid[j] == get_res->mid) + goto end; + } + } + + if (i == bus_priv->num_out) { + CAM_ERR(CAM_ISP, + "mid:%d does not match with any out resource", + get_res->mid); + get_res->out_res_id = 0; + return -EINVAL; + } + +end: + CAM_INFO(CAM_ISP, "match mid :%d out resource:0x%x found", + get_res->mid, bus_priv->vfe_out[i].res_id); + get_res->out_res_id = bus_priv->vfe_out[i].res_id; + return 0; +} + static int cam_vfe_bus_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -3636,6 +3684,10 @@ static int cam_vfe_bus_process_cmd( *support_consumed_addr = bus_priv->common_data.support_consumed_addr; break; + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index cfb8dda17d..a9d4168c90 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -10,6 +10,7 @@ #include "cam_vfe_bus.h" #define CAM_VFE_BUS_VER2_MAX_CLIENTS 24 +#define CAM_VFE_BUS_VER2_MAX_MID_PER_PORT 4 enum cam_vfe_bus_ver2_vfe_core_id { CAM_VFE_BUS_VER2_VFE_CORE_0, @@ -167,6 +168,7 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info { enum cam_vfe_bus_ver2_vfe_out_type vfe_out_type; uint32_t max_width; uint32_t max_height; + uint32_t mid[CAM_VFE_BUS_VER2_MAX_MID_PER_PORT]; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 727febe397..3e8ddb7385 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -177,6 +177,7 @@ struct cam_vfe_bus_ver3_vfe_out_data { struct cam_cdm_utils_ops *cdm_util_ops; uint32_t secure_mode; void *priv; + uint32_t mid[CAM_VFE_BUS_VER3_MAX_MID_PER_PORT]; }; struct cam_vfe_bus_ver3_priv { @@ -2641,7 +2642,7 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, { struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; - int rc = 0; + int rc = 0, i; int32_t vfe_out_type = ver3_hw_info->vfe_out_hw_info[index].vfe_out_type; @@ -2694,6 +2695,10 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, vfe_out->hw_intf = ver3_bus_priv->common_data.hw_intf; vfe_out->irq_handle = 0; + for (i = 0; i < CAM_VFE_BUS_VER3_MAX_MID_PER_PORT; i++) + rsrc_data->mid[i] = ver3_hw_info->vfe_out_hw_info[index].mid[i]; + + return 0; } @@ -2735,7 +2740,9 @@ static int cam_vfe_bus_ver3_print_dimensions( struct cam_isp_resource_node *rsrc_node = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_vfe_bus_ver3_common_data *common_data = NULL; int i, wm_idx; + uint32_t addr_status0, addr_status1, addr_status2, addr_status3; rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; @@ -2748,6 +2755,16 @@ static int cam_vfe_bus_ver3_print_dimensions( return -EINVAL; } wm_data = bus_priv->bus_client[wm_idx].res_priv; + common_data = rsrc_data->common_data; + addr_status0 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_0); + addr_status1 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_1); + addr_status2 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_2); + addr_status3 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_3); + CAM_INFO(CAM_ISP, "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", wm_data->common_data->core_index, wm_idx, @@ -2757,6 +2774,14 @@ static int cam_vfe_bus_ver3_print_dimensions( wm_data->en_cfg, wm_data->acquired_width, wm_data->acquired_height); + CAM_INFO(CAM_ISP, + "hw:%d WM:%d last consumed address:0x%x last frame addr:0x%x fifo cnt:0x%x current client address:0x%x", + common_data->hw_intf->hw_idx, + wm_data->index, + addr_status0, + addr_status1, + addr_status2, + addr_status3); } return 0; } @@ -3689,6 +3714,50 @@ static int cam_vfe_bus_ver3_deinit_hw(void *hw_priv, return rc; } +static int cam_vfe_bus_get_res_for_mid( + struct cam_vfe_bus_ver3_priv *bus_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_vfe_out_data *out_data = NULL; + struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; + struct cam_isp_hw_get_res_for_mid *get_res = NULL; + int i, j; + + get_res = (struct cam_isp_hw_get_res_for_mid *)cmd_update->data; + if (!get_res) { + CAM_ERR(CAM_ISP, + "invalid get resource for mid paramas"); + return -EINVAL; + } + + for (i = 0; i < bus_priv->num_out; i++) { + out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + bus_priv->vfe_out[i].res_priv; + + if (!out_data) + continue; + + for (j = 0; j < CAM_VFE_BUS_VER3_MAX_MID_PER_PORT; j++) { + if (out_data->mid[j] == get_res->mid) + goto end; + } + } + + if (i == bus_priv->num_out) { + CAM_ERR(CAM_ISP, + "mid:%d does not match with any out resource", + get_res->mid); + get_res->out_res_id = 0; + return -EINVAL; + } + +end: + CAM_INFO(CAM_ISP, "match mid :%d out resource:0x%x found", + get_res->mid, bus_priv->vfe_out[i].res_id); + get_res->out_res_id = bus_priv->vfe_out[i].res_id; + return 0; +} + static int __cam_vfe_bus_ver3_process_cmd(void *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -3766,6 +3835,10 @@ static int cam_vfe_bus_ver3_process_cmd( *support_consumed_addr = bus_priv->common_data.support_consumed_addr; break; + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index 7b39c97f45..e713b26f6d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -12,6 +12,7 @@ #define CAM_VFE_BUS_VER3_MAX_CLIENTS 26 #define CAM_VFE_BUS_VER3_MAX_SUB_GRPS 6 +#define CAM_VFE_BUS_VER3_MAX_MID_PER_PORT 4 enum cam_vfe_bus_ver3_vfe_core_id { CAM_VFE_BUS_VER3_VFE_CORE_0, @@ -160,6 +161,7 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { uint32_t max_width; uint32_t max_height; uint32_t source_group; + uint32_t mid[CAM_VFE_BUS_VER3_MAX_MID_PER_PORT]; }; /* diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index b28f8b6672..511da77d34 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -16,17 +16,18 @@ static const char jpeg_dev_name[] = "cam-jpeg"; -static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_jpeg_context_dump_active_request(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + uint32_t resource_type = 0; int rc = 0; int closest_port; - bool b_mem_found = false; + bool b_mem_found = false, b_ctx_found = false; if (!ctx) { @@ -44,7 +45,7 @@ static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &b_mem_found); + &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_JPEG, "Failed to dump pf info"); diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 76a055b891..f627e8850d 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -22,22 +22,20 @@ static struct cam_jpeg_dev g_jpeg_dev; static void cam_jpeg_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) + struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { - CAM_ERR(CAM_JPEG, "invalid token in page handler cb"); + if (!pf_info || !pf_info->token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static const struct of_device_id cam_jpeg_dt_match[] = { diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index 0ff45243ed..1c6b940f9b 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -23,15 +23,16 @@ static const char ope_dev_name[] = "cam-ope"; -static int cam_ope_context_dump_active_request(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_ope_context_dump_active_request(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + uint32_t resource_type = 0; int rc = 0; - bool b_mem_found = false; + bool b_mem_found = false, b_ctx_found = false; if (!ctx) { CAM_ERR(CAM_OPE, "Invalid ctx"); @@ -54,7 +55,7 @@ static int cam_ope_context_dump_active_request(void *data, unsigned long iova, CAM_INFO(CAM_OPE, "req_id : %lld", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &b_mem_found); + &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_OPE, "Failed to dump pf info"); diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index 3ac839a474..df9de9993a 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -46,22 +46,20 @@ struct cam_ope_subdev { static struct cam_ope_subdev g_ope_dev; static void cam_ope_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) + struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { - CAM_ERR(CAM_OPE, "invalid token in page handler cb"); + if (!pf_info || !pf_info->token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static int cam_ope_subdev_open(struct v4l2_subdev *sd, diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 7376c2964f..4e6ee1b10d 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -47,7 +47,7 @@ div_u64_rem(atomic64_add_return(1, head),\ CAM_SMMU_MONITOR_MAX_ENTRIES, (ret)) -static int g_num_pf_handled = 4; +static int g_num_pf_handled = 1; module_param(g_num_pf_handled, int, 0644); struct cam_fw_alloc_info icp_fw; @@ -145,7 +145,7 @@ struct cam_context_bank_info { int handle; enum cam_smmu_ops_param state; - cam_smmu_client_page_fault_handler handler[CAM_SMMU_CB_MAX]; + void (*handler[CAM_SMMU_CB_MAX]) (struct cam_smmu_pf_info *pf_info); void *token[CAM_SMMU_CB_MAX]; int cb_count; int secure_count; @@ -363,6 +363,8 @@ static void cam_smmu_page_fault_work(struct work_struct *work) int idx; struct cam_smmu_work_payload *payload; uint32_t buf_info; + struct iommu_fault_ids fault_ids = {0, 0, 0}; + struct cam_smmu_pf_info pf_info; mutex_lock(&iommu_cb_set.payload_list_lock); if (list_empty(&iommu_cb_set.payload_list)) { @@ -377,21 +379,33 @@ static void cam_smmu_page_fault_work(struct work_struct *work) list_del(&payload->list); mutex_unlock(&iommu_cb_set.payload_list_lock); + + if ((iommu_get_fault_ids(payload->domain, &fault_ids))) + CAM_ERR(CAM_SMMU, + "Error: Can not get smmu fault ids"); + + CAM_ERR(CAM_SMMU, "smmu fault ids bid:%d pid:%d mid:%d", + fault_ids.bid, fault_ids.pid, fault_ids.mid); + /* Dereference the payload to call the handler */ idx = payload->idx; buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova); if (buf_info != 0) CAM_INFO(CAM_SMMU, "closest buf 0x%x idx %d", buf_info, idx); + pf_info.domain = payload->domain; + pf_info.dev = payload->dev; + pf_info.iova = payload->iova; + pf_info.flags = payload->flags; + pf_info.buf_info = buf_info; + pf_info.bid = fault_ids.bid; + pf_info.pid = fault_ids.pid; + pf_info.mid = fault_ids.mid; + for (j = 0; j < CAM_SMMU_CB_MAX; j++) { if ((iommu_cb_set.cb_info[idx].handler[j])) { - iommu_cb_set.cb_info[idx].handler[j]( - payload->domain, - payload->dev, - payload->iova, - payload->flags, - iommu_cb_set.cb_info[idx].token[j], - buf_info); + pf_info.token = iommu_cb_set.cb_info[idx].token[j]; + iommu_cb_set.cb_info[idx].handler[j](&pf_info); } } cam_smmu_dump_cb_info(idx); @@ -565,7 +579,7 @@ end: } void cam_smmu_set_client_page_fault_handler(int handle, - cam_smmu_client_page_fault_handler handler_cb, void *token) + void (*handler_cb)(struct cam_smmu_pf_info *pf_info), void *token) { int idx, i = 0; @@ -726,6 +740,15 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, return -EINVAL; } +void cam_smmu_reset_cb_page_fault_cnt(void) +{ + int idx; + + for (idx = 0; idx < iommu_cb_set.cb_num; idx++) + iommu_cb_set.cb_info[idx].pf_count = 0; + +} + static int cam_smmu_translate_dir_to_iommu_dir( enum cam_smmu_map_dir dir) { diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index 19d96e4e24..df1cbdf58f 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -43,8 +43,7 @@ enum cam_smmu_region_id { }; /** - * @brief : Callback function type that gets called back on cam - * smmu page fault. + * @brief : cam_smmu_pf_info * * @param domain : Iommu domain received in iommu page fault handler * @param dev : Device received in iommu page fault handler @@ -52,10 +51,22 @@ enum cam_smmu_region_id { * @param flags : Flags received in iommu page fault handler * @param token : Userdata given during callback registration * @param buf_info : Closest mapped buffer info + * @bid : bus id + * @pid : unique id for hw group of ports + * @mid : port id of hw */ -typedef void (*cam_smmu_client_page_fault_handler)(struct iommu_domain *domain, - struct device *dev, unsigned long iova, int flags, void *token, - uint32_t buf_info); + +struct cam_smmu_pf_info { + struct iommu_domain *domain; + struct device *dev; + unsigned long iova; + int flags; + void *token; + uint32_t buf_info; + uint32_t bid; + uint32_t pid; + uint32_t mid; +}; /** * @brief : Structure to store region information @@ -234,7 +245,7 @@ int cam_smmu_find_index_by_handle(int hdl); * @param token: It is input param when trigger page fault handler */ void cam_smmu_set_client_page_fault_handler(int handle, - cam_smmu_client_page_fault_handler handler_cb, void *token); + void (*handler_cb)(struct cam_smmu_pf_info *pf_info), void *token); /** * @brief : Unregisters smmu fault handler for client @@ -403,6 +414,13 @@ int cam_smmu_get_io_region_info(int32_t smmu_hdl, dma_addr_t *iova, size_t *len, dma_addr_t *discard_iova_start, size_t *discard_iova_len); +/** + * @brief : API to reset the call context bank page fault count + * This should be done on the starting of new camera open + * @return void. + */ +void cam_smmu_reset_cb_page_fault_cnt(void); + /** * @brief : API to register SMMU hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. @@ -413,4 +431,5 @@ int cam_smmu_init_module(void); * @brief : API to remove SMMU Hw from platform framework. */ void cam_smmu_exit_module(void); + #endif /* _CAM_SMMU_API_H_ */ diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 58071bc341..dfa698bd19 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -424,6 +424,7 @@ struct cam_mem_cache_ops_cmd { * @CAM_REQ_MGR_ERROR_TYPE_BUFFER: Buffer was not filled, not fatal * @CAM_REQ_MGR_ERROR_TYPE_RECOVERY: Fatal error, can be recovered * @CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE: SOF freeze, can be recovered + * @CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT: page fault, can be recovered */ #define CAM_REQ_MGR_ERROR_TYPE_DEVICE 0 #define CAM_REQ_MGR_ERROR_TYPE_REQUEST 1 @@ -431,7 +432,7 @@ struct cam_mem_cache_ops_cmd { #define CAM_REQ_MGR_ERROR_TYPE_RECOVERY 3 #define CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE 4 #define CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY 5 - +#define CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT 6 /** * struct cam_req_mgr_error_msg