Merge "msm: camera: common: Add Minidump changes for NRT devices" into camera-kernel.lnx.5.0
Цей коміт міститься в:

зафіксовано
Gerrit - the friendly Code Review server

коміт
946cfd80fe
@@ -341,6 +341,27 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_context_mini_dump_from_hw(struct cam_context *ctx,
|
||||
void *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!ctx->state_machine) {
|
||||
CAM_ERR(CAM_CORE, "Context [id %d name:%s] is not ready", ctx->ctx_id,
|
||||
ctx->dev_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ctx->state >= CAM_CTX_AVAILABLE) && (ctx->state < CAM_CTX_STATE_MAX)) {
|
||||
if (ctx->state_machine[ctx->state].mini_dump_ops)
|
||||
rc = ctx->state_machine[ctx->state].mini_dump_ops(ctx, args);
|
||||
else
|
||||
CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d",
|
||||
ctx->dev_hdl, ctx->state);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_context_dump_pf_info(struct cam_context *ctx,
|
||||
struct cam_smmu_pf_info *pf_info)
|
||||
{
|
||||
|
@@ -168,6 +168,7 @@ struct cam_ctx_crm_ops {
|
||||
* @dumpinfo_ops: Function to be invoked for dumping any
|
||||
* context info
|
||||
* @recovery_ops: Function to be invoked to try hardware recovery
|
||||
* @mini_dump_ops: Function for mini dump
|
||||
*
|
||||
*/
|
||||
struct cam_ctx_ops {
|
||||
@@ -177,6 +178,7 @@ struct cam_ctx_ops {
|
||||
cam_hw_pagefault_cb_func pagefault_ops;
|
||||
cam_ctx_info_dump_cb_func dumpinfo_ops;
|
||||
cam_ctx_recovery_cb_func recovery_ops;
|
||||
cam_ctx_mini_dump_cb_func mini_dump_ops;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -218,6 +220,7 @@ struct cam_ctx_ops {
|
||||
* @hw_updater_entry: Hw update entry
|
||||
* @in_map_entries: In map update entry
|
||||
* @out_map_entries: Out map entry
|
||||
* @mini dump cb: Mini dump cb
|
||||
*
|
||||
*/
|
||||
struct cam_context {
|
||||
@@ -262,6 +265,7 @@ struct cam_context {
|
||||
struct cam_hw_update_entry *hw_update_entry;
|
||||
struct cam_hw_fence_map_entry *in_map_entries;
|
||||
struct cam_hw_fence_map_entry *out_map_entries;
|
||||
cam_ctx_mini_dump_cb_func mini_dump_cb;
|
||||
|
||||
};
|
||||
|
||||
@@ -408,6 +412,18 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx,
|
||||
int cam_context_handle_crm_dump_req(struct cam_context *ctx,
|
||||
struct cam_req_mgr_dump_info *dump);
|
||||
|
||||
/**
|
||||
* cam_context_mini_dump_from_hw()
|
||||
*
|
||||
* @brief: Handle mini dump request command
|
||||
*
|
||||
* @ctx: Object pointer for cam_context
|
||||
* @args: Args to be passed
|
||||
*
|
||||
*/
|
||||
int cam_context_mini_dump_from_hw(struct cam_context *ctx,
|
||||
void *args);
|
||||
|
||||
/**
|
||||
* cam_context_dump_pf_info()
|
||||
*
|
||||
|
@@ -615,6 +615,7 @@ int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx,
|
||||
param.context_data = ctx;
|
||||
param.ctx_id = ctx->ctx_id;
|
||||
param.event_cb = ctx->irq_cb_intf;
|
||||
param.mini_dump_cb = ctx->mini_dump_cb;
|
||||
param.num_acq = cmd->num_resources;
|
||||
param.acquire_info = cmd->resource_hdl;
|
||||
|
||||
@@ -1318,3 +1319,154 @@ err:
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __cam_context_req_mini_dump(struct cam_ctx_request *req,
|
||||
uint8_t *start_addr, uint8_t *end_addr,
|
||||
unsigned long *bytes_updated)
|
||||
{
|
||||
struct cam_hw_req_mini_dump *req_md;
|
||||
struct cam_buf_io_cfg *io_cfg;
|
||||
struct cam_packet *packet = NULL;
|
||||
unsigned long bytes_written = 0;
|
||||
unsigned long bytes_required = 0;
|
||||
|
||||
bytes_required = sizeof(*req_md);
|
||||
if (start_addr + bytes_written + bytes_required > end_addr)
|
||||
goto end;
|
||||
|
||||
req_md = (struct cam_hw_req_mini_dump *)start_addr;
|
||||
|
||||
req_md->num_fence_map_in = req->num_in_map_entries;
|
||||
req_md->num_fence_map_out = req->num_out_map_entries;
|
||||
req_md->num_in_acked = atomic_read(&req->num_in_acked);
|
||||
req_md->num_out_acked = req->num_out_acked;
|
||||
req_md->request_id = req->request_id;
|
||||
bytes_written += bytes_required;
|
||||
|
||||
if (req->num_out_map_entries) {
|
||||
bytes_required = sizeof(struct cam_hw_fence_map_entry) *
|
||||
req->num_out_map_entries;
|
||||
if (start_addr + bytes_written + bytes_required > end_addr)
|
||||
goto end;
|
||||
|
||||
req_md->fence_map_out = (struct cam_hw_fence_map_entry *)
|
||||
(start_addr + bytes_written);
|
||||
memcpy(req_md->fence_map_out, req->out_map_entries, bytes_required);
|
||||
req_md->num_fence_map_out = req->num_out_map_entries;
|
||||
bytes_written += bytes_required;
|
||||
}
|
||||
|
||||
if (req->num_in_map_entries) {
|
||||
bytes_required = sizeof(struct cam_hw_fence_map_entry) *
|
||||
req->num_in_map_entries;
|
||||
if (start_addr + bytes_written + bytes_required > end_addr)
|
||||
goto end;
|
||||
|
||||
req_md->fence_map_in = (struct cam_hw_fence_map_entry *)
|
||||
(start_addr + bytes_written);
|
||||
memcpy(req_md->fence_map_in, req->in_map_entries, bytes_required);
|
||||
req_md->num_fence_map_in = req->num_in_map_entries;
|
||||
bytes_written += bytes_required;
|
||||
}
|
||||
|
||||
packet = (struct cam_packet *)req->pf_data.packet;
|
||||
if (packet && packet->num_io_configs) {
|
||||
bytes_required = packet->num_io_configs * sizeof(struct cam_buf_io_cfg);
|
||||
if (start_addr + bytes_written + bytes_required > end_addr)
|
||||
goto end;
|
||||
|
||||
io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
|
||||
packet->io_configs_offset / 4);
|
||||
req_md->io_cfg = (struct cam_buf_io_cfg *)(start_addr + bytes_written);
|
||||
memcpy(req_md->io_cfg, io_cfg, bytes_required);
|
||||
bytes_written += bytes_required;
|
||||
req_md->num_io_cfg = packet->num_io_configs;
|
||||
}
|
||||
|
||||
end:
|
||||
*bytes_updated = bytes_written;
|
||||
}
|
||||
|
||||
int cam_context_mini_dump(struct cam_context *ctx, void *args)
|
||||
{
|
||||
struct cam_hw_mini_dump_info *md;
|
||||
struct cam_ctx_request *req, *req_temp;
|
||||
struct cam_hw_mini_dump_args *md_args;
|
||||
uint8_t *start_addr;
|
||||
uint8_t *end_addr;
|
||||
unsigned long bytes_written = 0;
|
||||
unsigned long bytes_updated = 0;
|
||||
|
||||
if (!ctx || !args) {
|
||||
CAM_ERR(CAM_CTXT, "invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
md_args = (struct cam_hw_mini_dump_args *)args;
|
||||
if (md_args->len < sizeof(*md)) {
|
||||
md_args->bytes_written = 0;
|
||||
CAM_ERR(CAM_CTXT, "Insufficient len %lu, bytes_written %lu", md_args->len,
|
||||
md_args->bytes_written);
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_addr = (uint8_t *)md_args->start_addr;
|
||||
end_addr = start_addr + md_args->len;
|
||||
md = (struct cam_hw_mini_dump_info *)md_args->start_addr;
|
||||
md->ctx_id = ctx->ctx_id;
|
||||
md->last_flush_req = ctx->last_flush_req;
|
||||
md->hw_mgr_ctx_id = ctx->hw_mgr_ctx_id;
|
||||
md->dev_id = ctx->dev_id;
|
||||
md->link_hdl = ctx->link_hdl;
|
||||
md->state = ctx->state;
|
||||
md->session_hdl = ctx->session_hdl;
|
||||
md->dev_hdl = ctx->dev_hdl;
|
||||
scnprintf(md->name, CAM_HW_MINI_DUMP_DEV_NAME_LEN, ctx->dev_name);
|
||||
bytes_written += sizeof(*md);
|
||||
|
||||
if (!list_empty(&ctx->active_req_list)) {
|
||||
md->active_list = (struct cam_hw_req_mini_dump *)
|
||||
(start_addr + bytes_written);
|
||||
list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
|
||||
bytes_updated = 0;
|
||||
__cam_context_req_mini_dump(req,
|
||||
(uint8_t *)&md->active_list[md->active_cnt++],
|
||||
end_addr, &bytes_updated);
|
||||
if ((start_addr + bytes_written + bytes_updated >= end_addr))
|
||||
goto end;
|
||||
bytes_written += bytes_updated;
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_empty(&ctx->wait_req_list)) {
|
||||
md->wait_list = (struct cam_hw_req_mini_dump *)
|
||||
(start_addr + bytes_written);
|
||||
list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) {
|
||||
bytes_updated = 0;
|
||||
__cam_context_req_mini_dump(req,
|
||||
(uint8_t *)&md->wait_list[md->wait_cnt++],
|
||||
end_addr, &bytes_updated);
|
||||
if ((start_addr + bytes_written + bytes_updated >= end_addr))
|
||||
goto end;
|
||||
bytes_written += bytes_updated;
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_empty(&ctx->pending_req_list)) {
|
||||
md->pending_list = (struct cam_hw_req_mini_dump *)
|
||||
(start_addr + bytes_written);
|
||||
list_for_each_entry_safe(req, req_temp, &ctx->pending_req_list, list) {
|
||||
bytes_updated = 0;
|
||||
__cam_context_req_mini_dump(req,
|
||||
(uint8_t *)&md->pending_list[md->pending_cnt++],
|
||||
end_addr, &bytes_updated);
|
||||
if ((start_addr + bytes_written + bytes_updated >= end_addr))
|
||||
goto end;
|
||||
bytes_written += bytes_updated;
|
||||
}
|
||||
}
|
||||
end:
|
||||
md_args->bytes_written = bytes_written;
|
||||
CAM_INFO(CAM_CTXT, "Ctx %s bytes_written %lu", ctx->dev_name, md_args->bytes_written);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -36,4 +36,5 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
|
||||
struct cam_dump_req_cmd *cmd);
|
||||
size_t cam_context_parse_config_cmd(struct cam_context *ctx, struct cam_config_dev_cmd *cmd,
|
||||
struct cam_packet **packet);
|
||||
int cam_context_mini_dump(struct cam_context *ctx, void *args);
|
||||
#endif /* _CAM_CONTEXT_UTILS_H_ */
|
||||
|
@@ -26,6 +26,9 @@
|
||||
/* Maximum reg dump cmd buffer entries in a context */
|
||||
#define CAM_REG_DUMP_MAX_BUF_ENTRIES 10
|
||||
|
||||
/* max device name string length*/
|
||||
#define CAM_HW_MINI_DUMP_DEV_NAME_LEN 20
|
||||
|
||||
/**
|
||||
* enum cam_context_dump_id -
|
||||
* context dump type
|
||||
@@ -415,6 +418,73 @@ struct cam_hw_mini_dump_args {
|
||||
unsigned long bytes_written;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_hw_req_mini_dump - Mini dump context req
|
||||
*
|
||||
* @fence_map_out: Fence map out array
|
||||
* @fence_map_in: Fence map in array
|
||||
* @io_cfg: IO cfg.
|
||||
* @request_id: Request id
|
||||
* @num_fence_map_in: num of fence map in
|
||||
* @num_fence_map_in: num of fence map out
|
||||
* @num_io_cfg: num of io cfg
|
||||
* @num_in_acked: num in acked
|
||||
* @num_out_acked: num out acked
|
||||
* @status: Status
|
||||
* @flushed: whether request is flushed
|
||||
*
|
||||
*/
|
||||
struct cam_hw_req_mini_dump {
|
||||
struct cam_hw_fence_map_entry *fence_map_out;
|
||||
struct cam_hw_fence_map_entry *fence_map_in;
|
||||
struct cam_buf_io_cfg *io_cfg;
|
||||
uint64_t request_id;
|
||||
uint16_t num_fence_map_in;
|
||||
uint16_t num_fence_map_out;
|
||||
uint16_t num_io_cfg;
|
||||
uint16_t num_in_acked;
|
||||
uint16_t num_out_acked;
|
||||
uint8_t status;
|
||||
uint8_t flushed;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_hw_mini_dump_info - Mini dump context info
|
||||
*
|
||||
* @active_list: array of active req in context
|
||||
* @wait_list: array of wait req in context
|
||||
* @pending_list: array of pending req in context
|
||||
* @name: name of context
|
||||
* @dev_id: dev id.
|
||||
* @last_flush_req: last flushed request id
|
||||
* @refcount: kernel ref count
|
||||
* @ctx_id: Context id
|
||||
* @session_hdl: Session handle
|
||||
* @link_hdl: link handle
|
||||
* @dev_hdl: Dev hdl
|
||||
* @state: State of context
|
||||
* @hw_mgr_ctx_id: ctx id with hw mgr
|
||||
*
|
||||
*/
|
||||
struct cam_hw_mini_dump_info {
|
||||
struct cam_hw_req_mini_dump *active_list;
|
||||
struct cam_hw_req_mini_dump *wait_list;
|
||||
struct cam_hw_req_mini_dump *pending_list;
|
||||
char name[CAM_HW_MINI_DUMP_DEV_NAME_LEN];
|
||||
uint64_t dev_id;
|
||||
uint32_t last_flush_req;
|
||||
uint32_t refcount;
|
||||
uint32_t ctx_id;
|
||||
uint32_t active_cnt;
|
||||
uint32_t pending_cnt;
|
||||
uint32_t wait_cnt;
|
||||
int32_t session_hdl;
|
||||
int32_t link_hdl;
|
||||
int32_t dev_hdl;
|
||||
uint8_t state;
|
||||
uint8_t hw_mgr_ctx_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_hw_mgr_intf - HW manager interface
|
||||
*
|
||||
|
@@ -66,6 +66,25 @@ end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_context_mini_dump(void *priv, void *args)
|
||||
{
|
||||
int rc;
|
||||
struct cam_context *ctx;
|
||||
|
||||
if (!priv || !args) {
|
||||
CAM_ERR(CAM_ICP, "Invalid priv %pK args %pK", priv, args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx = (struct cam_context *)priv;
|
||||
rc = cam_context_mini_dump(ctx, args);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ICP, "ctx [id: %u name: %s] Mini Dump failed rc %d", ctx->dev_name,
|
||||
ctx->ctx_id, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_icp_acquire_dev_in_available(struct cam_context *ctx,
|
||||
struct cam_acquire_dev_cmd *cmd)
|
||||
{
|
||||
@@ -236,6 +255,7 @@ static struct cam_ctx_ops
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
},
|
||||
/* Acquired */
|
||||
{
|
||||
@@ -249,6 +269,7 @@ static struct cam_ctx_ops
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_icp_handle_buf_done_in_ready,
|
||||
.pagefault_ops = cam_icp_context_dump_active_request,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
@@ -262,6 +283,7 @@ static struct cam_ctx_ops
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_icp_handle_buf_done_in_ready,
|
||||
.pagefault_ops = cam_icp_context_dump_active_request,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
},
|
||||
/* Flushed */
|
||||
{
|
||||
@@ -273,6 +295,7 @@ static struct cam_ctx_ops
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_icp_context_dump_active_request,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -66,6 +66,19 @@ static void cam_icp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info)
|
||||
cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
|
||||
}
|
||||
|
||||
static void cam_icp_dev_mini_dump_cb(void *priv, void *args)
|
||||
{
|
||||
struct cam_context *ctx = NULL;
|
||||
|
||||
if (!priv || !args) {
|
||||
CAM_ERR(CAM_ICP, "Invalid param priv: %pK args %pK", priv, args);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = (struct cam_context *)priv;
|
||||
cam_context_mini_dump_from_hw(ctx, args);
|
||||
}
|
||||
|
||||
static int cam_icp_subdev_open(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
@@ -187,7 +200,7 @@ static int cam_icp_component_bind(struct device *dev,
|
||||
}
|
||||
|
||||
rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf,
|
||||
&iommu_hdl);
|
||||
&iommu_hdl, cam_icp_dev_mini_dump_cb);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ICP, "ICP HW manager init failed: %d", rc);
|
||||
goto hw_init_fail;
|
||||
|
@@ -8,6 +8,9 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define HFI_CMD_Q_MINI_DUMP_SIZE_IN_BYTES 4096
|
||||
#define HFI_MSG_Q_MINI_DUMP_SIZE_IN_BYTES 4096
|
||||
|
||||
/**
|
||||
* struct hfi_mem
|
||||
* @len: length of memory
|
||||
@@ -61,6 +64,19 @@ struct hfi_ops {
|
||||
void __iomem *(*iface_addr)(void *data);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hfi_mini_dump_info
|
||||
* @cmd_q: cmd queue
|
||||
* @msg_q: msg queue
|
||||
* @msg_q_state: msg queue state
|
||||
* @cmd_q_state: cmd queue state
|
||||
*/
|
||||
struct hfi_mini_dump_info {
|
||||
uint32_t cmd_q[HFI_CMD_Q_MINI_DUMP_SIZE_IN_BYTES];
|
||||
uint32_t msg_q[HFI_MSG_Q_MINI_DUMP_SIZE_IN_BYTES];
|
||||
bool msg_q_state;
|
||||
bool cmd_q_state;
|
||||
};
|
||||
/**
|
||||
* hfi_write_cmd() - function for hfi write
|
||||
* @cmd_ptr: pointer to command data for hfi write
|
||||
@@ -163,5 +179,9 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem);
|
||||
*/
|
||||
void cam_hfi_queue_dump(void);
|
||||
|
||||
/**
|
||||
* cam_hfi_mini_dump() - utility function for mini dump
|
||||
*/
|
||||
void cam_hfi_mini_dump(struct hfi_mini_dump_info *dst);
|
||||
|
||||
#endif /* _HFI_INTF_H_ */
|
||||
|
@@ -87,6 +87,32 @@ static void hfi_queue_dump(uint32_t *dwords, int count)
|
||||
rows * 4, dwords[0], dwords[1], dwords[2]);
|
||||
}
|
||||
|
||||
void cam_hfi_mini_dump(struct hfi_mini_dump_info *dst)
|
||||
{
|
||||
struct hfi_mem_info *hfi_mem = &g_hfi->map;
|
||||
struct hfi_qtbl *qtbl;
|
||||
struct hfi_q_hdr *q_hdr;
|
||||
uint32_t *dwords;
|
||||
int num_dwords;
|
||||
|
||||
if (!hfi_mem) {
|
||||
CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues");
|
||||
return;
|
||||
}
|
||||
|
||||
qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
|
||||
q_hdr = &qtbl->q_hdr[Q_CMD];
|
||||
dwords = (uint32_t *)hfi_mem->cmd_q.kva;
|
||||
num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
|
||||
memcpy(dst->cmd_q, dwords, ICP_CMD_Q_SIZE_IN_BYTES);
|
||||
|
||||
q_hdr = &qtbl->q_hdr[Q_MSG];
|
||||
dwords = (uint32_t *)hfi_mem->msg_q.kva;
|
||||
memcpy(dst->msg_q, dwords, ICP_CMD_Q_SIZE_IN_BYTES);
|
||||
dst->msg_q_state = g_hfi->msg_q_state;
|
||||
dst->cmd_q_state = g_hfi->cmd_q_state;
|
||||
}
|
||||
|
||||
void cam_hfi_queue_dump(void)
|
||||
{
|
||||
struct hfi_mem_info *hfi_mem = &g_hfi->map;
|
||||
|
@@ -178,6 +178,37 @@ static int cam_a5_fw_dump(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_a5_fw_mini_dump(
|
||||
struct cam_icp_hw_dump_args *dump_args,
|
||||
struct cam_a5_device_core_info *core_info)
|
||||
{
|
||||
u8 *dest;
|
||||
u8 *src;
|
||||
|
||||
if (!core_info || !dump_args) {
|
||||
CAM_ERR(CAM_ICP, "invalid params %pK %pK", core_info, dump_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!core_info->fw_kva_addr || !dump_args->cpu_addr) {
|
||||
CAM_ERR(CAM_ICP, "invalid params %pK, 0x%zx", core_info->fw_kva_addr,
|
||||
dump_args->cpu_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dump_args->buf_len < core_info->fw_buf_len) {
|
||||
CAM_WARN(CAM_ICP, "Insufficient Len %lu fw_len %llu",
|
||||
dump_args->buf_len, core_info->fw_buf_len);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dest = (u8 *)dump_args->cpu_addr;
|
||||
src = (u8 *)core_info->fw_kva_addr;
|
||||
memcpy_fromio(dest, src, core_info->fw_buf_len);
|
||||
dump_args->offset = core_info->fw_buf_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_a5_init_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -706,6 +737,13 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
rc = cam_a5_fw_dump(dump_args, core_info);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAM_ICP_CMD_HW_MINI_DUMP: {
|
||||
struct cam_icp_hw_dump_args *dump_args = cmd_args;
|
||||
|
||||
rc = cam_a5_fw_mini_dump(dump_args, core_info);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -3711,6 +3711,132 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long cam_icp_hw_mgr_mini_dump_cb(void *dst, unsigned long len)
|
||||
{
|
||||
struct cam_icp_hw_mini_dump_info *md;
|
||||
struct cam_icp_hw_ctx_mini_dump *ctx_md;
|
||||
struct cam_icp_hw_ctx_data *ctx;
|
||||
struct cam_icp_hw_mgr *hw_mgr;
|
||||
struct cam_hw_mini_dump_args hw_dump_args;
|
||||
struct cam_icp_hw_dump_args icp_dump_args;
|
||||
struct cam_hw_intf *icp_dev_intf = NULL;
|
||||
uint32_t i = 0, j = 0;
|
||||
unsigned long dumped_len = 0;
|
||||
unsigned long remain_len = len;
|
||||
int rc = 0;
|
||||
|
||||
if (!dst || len < sizeof(*md)) {
|
||||
CAM_ERR(CAM_ICP, "Invalid params dst %pk len %lu", dst, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
md = (struct cam_icp_hw_mini_dump_info *)dst;
|
||||
md->num_context = 0;
|
||||
hw_mgr = &icp_hw_mgr;
|
||||
cam_hfi_mini_dump(&md->hfi_info);
|
||||
memcpy(&md->hfi_mem_info, &hw_mgr->hfi_mem,
|
||||
sizeof(struct icp_hfi_mem_info));
|
||||
md->recovery = atomic_read(&hw_mgr->recovery);
|
||||
md->icp_booted = hw_mgr->icp_booted;
|
||||
md->icp_resumed = hw_mgr->icp_resumed;
|
||||
md->ipe_clk_state = hw_mgr->ipe_clk_state;
|
||||
md->ipe_clk_state = hw_mgr->ipe_clk_state;
|
||||
md->bps_clk_state = hw_mgr->bps_clk_state;
|
||||
md->disable_ubwc_comp = hw_mgr->disable_ubwc_comp;
|
||||
md->ipe0_enable = hw_mgr->ipe0_enable;
|
||||
md->ipe1_enable = hw_mgr->ipe1_enable;
|
||||
md->bps_enable = hw_mgr->bps_enable;
|
||||
md->icp_pc_flag = hw_mgr->icp_pc_flag;
|
||||
md->ipe_bps_pc_flag = hw_mgr->ipe_bps_pc_flag;
|
||||
md->icp_use_pil = hw_mgr->icp_use_pil;
|
||||
dumped_len += sizeof(*md);
|
||||
remain_len = len - dumped_len;
|
||||
for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
|
||||
ctx = &hw_mgr->ctx_data[i];
|
||||
if (ctx->state == CAM_ICP_CTX_STATE_FREE ||
|
||||
ctx->state == CAM_ICP_CTX_STATE_RELEASE)
|
||||
continue;
|
||||
|
||||
if (remain_len < sizeof(*ctx_md))
|
||||
goto end;
|
||||
|
||||
md->num_context++;
|
||||
ctx_md = (struct cam_icp_hw_ctx_mini_dump *)
|
||||
((uint8_t *)dst + dumped_len);
|
||||
md->ctx[i] = ctx_md;
|
||||
ctx_md->state = ctx->state;
|
||||
ctx_md->ctx_id = ctx->ctx_id;
|
||||
memcpy(ctx_md->ctx_id_string, ctx->ctx_id_string,
|
||||
strlen(ctx->ctx_id_string));
|
||||
if (ctx->icp_dev_acquire_info) {
|
||||
ctx_md->acquire.secure_mode =
|
||||
ctx->icp_dev_acquire_info->secure_mode;
|
||||
ctx_md->acquire.dev_type =
|
||||
ctx->icp_dev_acquire_info->dev_type;
|
||||
ctx_md->acquire.num_out_res =
|
||||
ctx->icp_dev_acquire_info->num_out_res;
|
||||
memcpy(&ctx_md->acquire.in_res,
|
||||
&ctx->icp_dev_acquire_info->in_res,
|
||||
sizeof(struct cam_icp_res_info));
|
||||
memcpy(ctx_md->acquire.out_res,
|
||||
ctx->icp_dev_acquire_info->out_res,
|
||||
sizeof(ctx->icp_dev_acquire_info->out_res));
|
||||
} else {
|
||||
memset(&ctx_md->acquire, 0,
|
||||
sizeof(struct cam_icp_mini_dump_acquire_info));
|
||||
}
|
||||
|
||||
memcpy(ctx_md->hfi_frame.request_id, ctx->hfi_frame_process.request_id,
|
||||
sizeof(ctx->hfi_frame_process.request_id));
|
||||
memcpy(ctx_md->hfi_frame.in_resource, ctx->hfi_frame_process.in_resource,
|
||||
sizeof(ctx->hfi_frame_process.in_resource));
|
||||
memcpy(ctx_md->hfi_frame.submit_timestamp,
|
||||
ctx->hfi_frame_process.submit_timestamp,
|
||||
sizeof(ctx->hfi_frame_process.submit_timestamp));
|
||||
memcpy(ctx_md->hfi_frame.num_out_res, ctx->hfi_frame_process.num_out_resources,
|
||||
sizeof(ctx->hfi_frame_process.num_out_resources));
|
||||
memcpy(ctx_md->hfi_frame.out_res, ctx->hfi_frame_process.out_resource,
|
||||
sizeof(ctx->hfi_frame_process.out_resource));
|
||||
for (j = 0; j < CAM_FRAME_CMD_MAX; j++) {
|
||||
ctx_md->hfi_frame.fw_process_flag[j] =
|
||||
ctx->hfi_frame_process.fw_process_flag[j];
|
||||
}
|
||||
|
||||
dumped_len += sizeof(*ctx_md);
|
||||
remain_len = len - dumped_len;
|
||||
hw_dump_args.len = remain_len;
|
||||
hw_dump_args.bytes_written = 0;
|
||||
hw_dump_args.start_addr = (void *)((uint8_t *)dst + dumped_len);
|
||||
hw_mgr->mini_dump_cb(ctx->context_priv, &hw_dump_args);
|
||||
if (dumped_len + hw_dump_args.bytes_written >= len)
|
||||
goto end;
|
||||
|
||||
ctx_md->hw_ctx = hw_dump_args.start_addr;
|
||||
dumped_len += hw_dump_args.bytes_written;
|
||||
remain_len = len - dumped_len;
|
||||
}
|
||||
|
||||
/* Dump fw image */
|
||||
if (!hw_mgr->icp_use_pil) {
|
||||
icp_dump_args.cpu_addr = (uintptr_t)((uint8_t *)dst + dumped_len);
|
||||
icp_dump_args.offset = 0;
|
||||
icp_dump_args.buf_len = remain_len;
|
||||
icp_dev_intf = hw_mgr->icp_dev_intf;
|
||||
rc = icp_dev_intf->hw_ops.process_cmd(
|
||||
icp_dev_intf->hw_priv,
|
||||
CAM_ICP_CMD_HW_MINI_DUMP, &icp_dump_args,
|
||||
sizeof(struct cam_icp_hw_dump_args));
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
dumped_len += icp_dump_args.offset;
|
||||
md->fw_img = (void *)icp_dump_args.cpu_addr;
|
||||
remain_len = len - dumped_len;
|
||||
}
|
||||
end:
|
||||
return dumped_len;
|
||||
}
|
||||
|
||||
static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr)
|
||||
{
|
||||
struct cam_hw_intf *icp_dev_intf = NULL;
|
||||
@@ -6351,7 +6477,7 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
|
||||
}
|
||||
|
||||
int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
int *iommu_hdl)
|
||||
int *iommu_hdl, cam_icp_mini_dump_cb mini_dump_cb)
|
||||
{
|
||||
int i, rc = 0;
|
||||
struct cam_hw_mgr_intf *hw_mgr_intf;
|
||||
@@ -6380,6 +6506,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
hw_mgr_intf->hw_dump = cam_icp_mgr_hw_dump;
|
||||
|
||||
icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
icp_hw_mgr.mini_dump_cb = mini_dump_cb;
|
||||
mutex_init(&icp_hw_mgr.hw_mgr_mutex);
|
||||
spin_lock_init(&icp_hw_mgr.hw_mgr_lock);
|
||||
|
||||
@@ -6445,6 +6572,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
*iommu_hdl = icp_hw_mgr.iommu_hdl;
|
||||
|
||||
init_completion(&icp_hw_mgr.icp_complete);
|
||||
cam_common_register_mini_dump_cb(
|
||||
cam_icp_hw_mgr_mini_dump_cb, "cam_icp");
|
||||
return rc;
|
||||
|
||||
icp_wq_create_failed:
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_a5_hw_intf.h"
|
||||
#include "hfi_session_defs.h"
|
||||
#include "hfi_intf.h"
|
||||
#include "cam_req_mgr_workq.h"
|
||||
#include "cam_mem_mgr.h"
|
||||
#include "cam_smmu_api.h"
|
||||
@@ -75,6 +76,8 @@
|
||||
*/
|
||||
#define CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD 300000
|
||||
|
||||
struct hfi_mini_dump_info;
|
||||
|
||||
/**
|
||||
* struct icp_hfi_mem_info
|
||||
* @qtbl: Memory info of queue table
|
||||
@@ -321,6 +324,7 @@ struct cam_icp_clk_info {
|
||||
* @devices: Devices of ICP hardware manager
|
||||
* @ctx_data: Context data
|
||||
* @icp_caps: ICP capabilities
|
||||
* @mini_dump_cb: Mini dump cb
|
||||
* @icp_booted: Processor is booted i.e. firmware loaded
|
||||
* @icp_resumed: Processor is powered on
|
||||
* @iommu_hdl: Non secure IOMMU handle
|
||||
@@ -372,6 +376,7 @@ struct cam_icp_hw_mgr {
|
||||
struct cam_hw_intf **devices[CAM_ICP_DEV_MAX];
|
||||
struct cam_icp_hw_ctx_data ctx_data[CAM_ICP_CTX_MAX];
|
||||
struct cam_icp_query_cap_cmd icp_caps;
|
||||
cam_icp_mini_dump_cb mini_dump_cb;
|
||||
|
||||
bool icp_booted;
|
||||
bool icp_resumed;
|
||||
@@ -415,6 +420,99 @@ struct cam_icp_hw_mgr {
|
||||
atomic_t recovery;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_icp_mini_dump_acquire_info - ICP mini dump device info
|
||||
*
|
||||
* @in_res: resource info used for clock and bandwidth calculation
|
||||
* @out_res: output resource
|
||||
* @num_out_res: number of output resources
|
||||
* @dev_type: device type (IPE_RT/IPE_NON_RT/BPS)
|
||||
* @secure_mode: camera mode (secure/non secure)
|
||||
*/
|
||||
struct cam_icp_mini_dump_acquire_info {
|
||||
struct cam_icp_res_info out_res[ICP_MAX_OUTPUT_SUPPORTED];
|
||||
struct cam_icp_res_info in_res;
|
||||
uint16_t num_out_res;
|
||||
uint8_t dev_type;
|
||||
uint8_t secure_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hfi_frame_process_info
|
||||
* @request_id: Request id list
|
||||
* @num_out_res: Number of out syncs
|
||||
* @out_res: Out sync info
|
||||
* @in_resource: In sync info
|
||||
* @submit_timestamp: Submit timestamp to hw
|
||||
* @fw_process_flag: Frame process flag
|
||||
*/
|
||||
struct hfi_frame_mini_dump_info {
|
||||
uint64_t request_id[CAM_FRAME_CMD_MAX];
|
||||
uint32_t num_out_res[CAM_FRAME_CMD_MAX];
|
||||
uint32_t out_res[CAM_FRAME_CMD_MAX][CAM_MAX_OUT_RES];
|
||||
uint32_t in_resource[CAM_FRAME_CMD_MAX];
|
||||
ktime_t submit_timestamp[CAM_FRAME_CMD_MAX];
|
||||
uint8_t fw_process_flag[CAM_FRAME_CMD_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_icp_hw_ctx_mini_dump
|
||||
* @acquire: Acquire device info
|
||||
* @hfi_frame: Frame command
|
||||
* @hw_ctx: Context private data
|
||||
* @state: context state
|
||||
* @ctx_id_string: Context id string
|
||||
* @ctx_id: Context Id
|
||||
*/
|
||||
struct cam_icp_hw_ctx_mini_dump {
|
||||
struct cam_icp_mini_dump_acquire_info acquire;
|
||||
struct hfi_frame_mini_dump_info hfi_frame;
|
||||
void *hw_ctx;
|
||||
char ctx_id_string[128];
|
||||
uint8_t state;
|
||||
uint8_t ctx_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_icp_hw_mini_dump_info
|
||||
*
|
||||
* @ctx: Context for minidump
|
||||
* @hfi_info: hfi info
|
||||
* @hfi_mem_info: hfi mem info
|
||||
* @fw_img: FW image
|
||||
* @recovery: To indicate if recovery is on
|
||||
* @icp_booted: Indicate if ICP is booted
|
||||
* @icp_resumed: Indicate if ICP is resumed
|
||||
* @ipe_clk_state: IPE Clk state
|
||||
* @bps_clk_state: BPS clk state
|
||||
* @disable_ubwc_comp: Indicate if ubws comp is disabled
|
||||
* @ipe0_enable: Is IPE0 enabled
|
||||
* @ipe1_enable: Is IPE1 enabled
|
||||
* @bps_enable: Is BPS enabled
|
||||
* @icp_pc_flag: Is ICP PC enabled
|
||||
* @ipe_bps_pc_flag: Is IPE BPS PC enabled
|
||||
* @icp_use_pil: Is PIL used
|
||||
*/
|
||||
struct cam_icp_hw_mini_dump_info {
|
||||
struct cam_icp_hw_ctx_mini_dump *ctx[CAM_ICP_CTX_MAX];
|
||||
struct hfi_mini_dump_info hfi_info;
|
||||
struct icp_hfi_mem_info hfi_mem_info;
|
||||
void *fw_img;
|
||||
uint32_t recovery;
|
||||
uint32_t num_context;
|
||||
bool icp_booted;
|
||||
bool icp_resumed;
|
||||
bool ipe_clk_state;
|
||||
bool bps_clk_state;
|
||||
bool disable_ubwc_comp;
|
||||
bool ipe0_enable;
|
||||
bool ipe1_enable;
|
||||
bool bps_enable;
|
||||
bool icp_pc_flag;
|
||||
bool ipe_bps_pc_flag;
|
||||
bool icp_use_pil;
|
||||
};
|
||||
|
||||
static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args);
|
||||
static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args);
|
||||
static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr);
|
||||
|
@@ -42,6 +42,7 @@ enum cam_icp_cmd_type {
|
||||
CAM_ICP_CMD_PC_PREP,
|
||||
CAM_ICP_CMD_CLK_UPDATE,
|
||||
CAM_ICP_CMD_HW_DUMP,
|
||||
CAM_ICP_CMD_HW_MINI_DUMP,
|
||||
CAM_ICP_CMD_MAX,
|
||||
};
|
||||
|
||||
|
@@ -30,8 +30,12 @@
|
||||
#define CAM_ICP_DUMP_TAG_MAX_LEN 32
|
||||
#define CAM_ICP_DUMP_NUM_WORDS 5
|
||||
|
||||
typedef void(*cam_icp_mini_dump_cb)(void *priv,
|
||||
void *args);
|
||||
|
||||
int cam_icp_hw_mgr_init(struct device_node *of_node,
|
||||
uint64_t *hw_mgr_hdl, int *iommu_hdl);
|
||||
uint64_t *hw_mgr_hdl, int *iommu_hdl,
|
||||
cam_icp_mini_dump_cb mini_dump_cb);
|
||||
|
||||
void cam_icp_hw_mgr_deinit(void);
|
||||
|
||||
|
@@ -777,6 +777,38 @@ static int __cam_lx7_update_clk_rate(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lx7_fw_mini_dump(
|
||||
struct cam_lx7_core_info *core_info,
|
||||
struct cam_icp_hw_dump_args *args)
|
||||
{
|
||||
u8 *dest;
|
||||
u8 *src;
|
||||
struct cam_icp_hw_dump_args *dump_args = args;
|
||||
|
||||
if (!core_info || !dump_args) {
|
||||
CAM_ERR(CAM_ICP, "invalid params %pK %pK", core_info, dump_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!core_info->fw_params.fw_kva_addr || !dump_args->cpu_addr) {
|
||||
CAM_ERR(CAM_ICP, "invalid params %pK, 0x%zx",
|
||||
core_info->fw_params.fw_kva_addr, dump_args->cpu_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dump_args->buf_len < core_info->fw_params.fw_buf_len) {
|
||||
CAM_WARN(CAM_ICP, "Insufficient Len %lu fw_len %llu",
|
||||
dump_args->buf_len, core_info->fw_params.fw_buf_len);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dest = (u8 *)dump_args->cpu_addr;
|
||||
src = (u8 *)core_info->fw_params.fw_kva_addr;
|
||||
memcpy_fromio(dest, src, core_info->fw_params.fw_buf_len);
|
||||
dump_args->offset = core_info->fw_params.fw_buf_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_lx7_process_cmd(void *priv, uint32_t cmd_type,
|
||||
void *args, uint32_t arg_size)
|
||||
{
|
||||
@@ -829,6 +861,10 @@ int cam_lx7_process_cmd(void *priv, uint32_t cmd_type,
|
||||
/* Not supported for lx7 */
|
||||
rc = 0;
|
||||
break;
|
||||
case CAM_ICP_CMD_HW_MINI_DUMP: {
|
||||
rc = __cam_lx7_fw_mini_dump(lx7_info->core_info, args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CAM_ERR(CAM_ICP, "invalid command type=%u", cmd_type);
|
||||
break;
|
||||
|
@@ -56,6 +56,24 @@ static int cam_jpeg_context_dump_active_request(void *data,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_jpeg_context_mini_dump(void *priv, void *args)
|
||||
{
|
||||
int rc;
|
||||
struct cam_context *ctx;
|
||||
|
||||
if (!priv || args) {
|
||||
CAM_ERR(CAM_ICP, "Invalid param priv %pK args %pK", priv, args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx = (struct cam_context *)priv;
|
||||
rc = cam_context_mini_dump(ctx, args);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_JPEG, "Mini Dump failed %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_jpeg_ctx_acquire_dev_in_available(struct cam_context *ctx,
|
||||
struct cam_acquire_dev_cmd *cmd)
|
||||
{
|
||||
@@ -151,6 +169,7 @@ static struct cam_ctx_ops
|
||||
},
|
||||
.crm_ops = { },
|
||||
.irq_ops = NULL,
|
||||
.mini_dump_ops = cam_jpeg_context_mini_dump,
|
||||
},
|
||||
/* Acquired */
|
||||
{
|
||||
@@ -164,6 +183,7 @@ static struct cam_ctx_ops
|
||||
.crm_ops = { },
|
||||
.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
|
||||
.pagefault_ops = cam_jpeg_context_dump_active_request,
|
||||
.mini_dump_ops = cam_jpeg_context_mini_dump,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
|
@@ -38,6 +38,19 @@ static void cam_jpeg_dev_iommu_fault_handler(
|
||||
cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
|
||||
}
|
||||
|
||||
static void cam_jpeg_dev_mini_dump_cb(void *priv, void *args)
|
||||
{
|
||||
struct cam_context *ctx = NULL;
|
||||
|
||||
if (!priv || !args) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid param priv %pK %pK args", priv, args);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = (struct cam_context *)priv;
|
||||
cam_context_mini_dump_from_hw(ctx, args);
|
||||
}
|
||||
|
||||
static const struct of_device_id cam_jpeg_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,cam-jpeg"
|
||||
@@ -123,7 +136,8 @@ static int cam_jpeg_dev_component_bind(struct device *dev,
|
||||
node = (struct cam_node *)g_jpeg_dev.sd.token;
|
||||
|
||||
rc = cam_jpeg_hw_mgr_init(pdev->dev.of_node,
|
||||
(uint64_t *)&hw_mgr_intf, &iommu_hdl);
|
||||
(uint64_t *)&hw_mgr_intf, &iommu_hdl,
|
||||
cam_jpeg_dev_mini_dump_cb);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_JPEG, "Can not initialize JPEG HWmanager %d", rc);
|
||||
goto unregister;
|
||||
|
@@ -1421,7 +1421,7 @@ static int cam_jpeg_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
|
||||
mutex_unlock(&ctx_data->ctx_mutex);
|
||||
|
||||
hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb;
|
||||
|
||||
hw_mgr->ctx_data[ctx_id].mini_dump_cb = args->mini_dump_cb;
|
||||
|
||||
if (copy_to_user((void __user *)args->acquire_info,
|
||||
&jpeg_dev_acquire_info,
|
||||
@@ -1971,8 +1971,83 @@ static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static unsigned long cam_jpeg_hw_mgr_mini_dump_cb(void *dst, unsigned long len)
|
||||
{
|
||||
struct cam_jpeg_hw_mini_dump_req *md_req;
|
||||
struct cam_jpeg_hw_mgr_mini_dump *md;
|
||||
struct cam_jpeg_hw_ctx_mini_dump *ctx_md;
|
||||
struct cam_jpeg_hw_ctx_data *ctx;
|
||||
struct cam_jpeg_hw_mgr *hw_mgr;
|
||||
struct cam_jpeg_hw_cfg_req *req;
|
||||
struct cam_hw_mini_dump_args hw_dump_args;
|
||||
uint32_t dev_type;
|
||||
uint32_t i = 0;
|
||||
unsigned long dumped_len = 0;
|
||||
unsigned long remain_len = len;
|
||||
|
||||
if (!dst || len < sizeof(*md)) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid params dst %pk len %lu", dst, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
md = (struct cam_jpeg_hw_mgr_mini_dump *)dst;
|
||||
md->num_context = 0;
|
||||
hw_mgr = &g_jpeg_hw_mgr;
|
||||
for (i = 0; i < CAM_JPEG_RES_TYPE_MAX; i++) {
|
||||
if (hw_mgr->devices[i][0]->hw_ops.process_cmd) {
|
||||
hw_mgr->devices[i][0]->hw_ops.process_cmd(
|
||||
hw_mgr->devices[i][0]->hw_priv,
|
||||
CAM_JPEG_CMD_MINI_DUMP,
|
||||
&md->core[i],
|
||||
sizeof(struct cam_jpeg_mini_dump_core_info));
|
||||
}
|
||||
}
|
||||
|
||||
dumped_len += sizeof(*md);
|
||||
remain_len = len - dumped_len;
|
||||
for (i = 0; i < CAM_JPEG_CTX_MAX; i++) {
|
||||
ctx = &hw_mgr->ctx_data[i];
|
||||
if (!ctx->in_use)
|
||||
continue;
|
||||
|
||||
if (remain_len < sizeof(*ctx_md))
|
||||
goto end;
|
||||
|
||||
md->num_context++;
|
||||
ctx_md = (struct cam_jpeg_hw_ctx_mini_dump *)
|
||||
((uint8_t *)dst + dumped_len);
|
||||
md->ctx[i] = ctx_md;
|
||||
ctx_md->in_use = ctx->in_use;
|
||||
memcpy(&ctx_md->acquire_info, &ctx->jpeg_dev_acquire_info,
|
||||
sizeof(struct cam_jpeg_acquire_dev_info));
|
||||
dev_type = ctx->jpeg_dev_acquire_info.dev_type;
|
||||
req = hw_mgr->dev_hw_cfg_args[dev_type][0];
|
||||
if (req) {
|
||||
md_req = &md->cfg_req[dev_type];
|
||||
memcpy(&md_req->submit_timestamp, &req->submit_timestamp,
|
||||
sizeof(ktime_t));
|
||||
md_req->req_id = req->req_id;
|
||||
md_req->dev_type = req->dev_type;
|
||||
md_req->num_hw_entry_processed = req->num_hw_entry_processed;
|
||||
}
|
||||
|
||||
hw_dump_args.len = remain_len;
|
||||
hw_dump_args.bytes_written = 0;
|
||||
hw_dump_args.start_addr = (void *)((uint8_t *)dst + dumped_len);
|
||||
hw_mgr->mini_dump_cb(ctx->context_priv, &hw_dump_args);
|
||||
if (dumped_len + hw_dump_args.bytes_written >= len)
|
||||
goto end;
|
||||
|
||||
dumped_len += hw_dump_args.bytes_written;
|
||||
remain_len = len - dumped_len;
|
||||
}
|
||||
|
||||
end:
|
||||
return dumped_len;
|
||||
}
|
||||
|
||||
int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
int *iommu_hdl)
|
||||
int *iommu_hdl, cam_jpeg_mini_dump_cb mini_dump_cb)
|
||||
{
|
||||
int i, rc;
|
||||
uint32_t num_dev;
|
||||
@@ -2048,6 +2123,8 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.incr = 0;
|
||||
g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.reserved = 0;
|
||||
|
||||
g_jpeg_hw_mgr.mini_dump_cb = mini_dump_cb;
|
||||
|
||||
rc = cam_jpeg_setup_workqs();
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_JPEG, "setup work qs failed %d", rc);
|
||||
@@ -2057,6 +2134,8 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
if (iommu_hdl)
|
||||
*iommu_hdl = g_jpeg_hw_mgr.iommu_hdl;
|
||||
|
||||
cam_common_register_mini_dump_cb(cam_jpeg_hw_mgr_mini_dump_cb, "CAM_JPEG");
|
||||
|
||||
return rc;
|
||||
|
||||
cdm_iommu_failed:
|
||||
|
@@ -103,6 +103,7 @@ struct cam_jpeg_hw_cfg_req {
|
||||
* @in_use: Flag for context usage
|
||||
* @wait_complete: Completion info
|
||||
* @cdm_cmd: Cdm cmd submitted for that context.
|
||||
* @mini_dump_cb: Mini dump cb
|
||||
*/
|
||||
struct cam_jpeg_hw_ctx_data {
|
||||
void *context_priv;
|
||||
@@ -112,6 +113,7 @@ struct cam_jpeg_hw_ctx_data {
|
||||
bool in_use;
|
||||
struct completion wait_complete;
|
||||
struct cam_cdm_bl_request *cdm_cmd;
|
||||
cam_ctx_mini_dump_cb_func mini_dump_cb;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -138,6 +140,7 @@ struct cam_jpeg_hw_ctx_data {
|
||||
* @free_req_list: Free nodes for above list
|
||||
* @req_list: Nodes of hw update list
|
||||
* @num_pid: num of pids supported in the device
|
||||
* @mini_dump_cb: Mini dump cb
|
||||
*/
|
||||
struct cam_jpeg_hw_mgr {
|
||||
struct mutex hw_mgr_mutex;
|
||||
@@ -167,6 +170,49 @@ struct cam_jpeg_hw_mgr {
|
||||
struct list_head free_req_list;
|
||||
struct cam_jpeg_hw_cfg_req req_list[CAM_JPEG_HW_CFG_Q_MAX];
|
||||
uint32_t num_pid[CAM_JPEG_DEV_TYPE_MAX];
|
||||
cam_jpeg_mini_dump_cb mini_dump_cb;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_jpeg_hw_mini_dump_req
|
||||
*
|
||||
* @submit_timestamp: Time stamp of request submit
|
||||
* @req_id: Request Id
|
||||
* @dev_type: Dev type
|
||||
* @num_hw_entry_processed: Num of hw entry processed
|
||||
*/
|
||||
struct cam_jpeg_hw_mini_dump_req {
|
||||
ktime_t submit_timestamp;
|
||||
uintptr_t req_id;
|
||||
uint32_t dev_type;
|
||||
uint32_t num_hw_entry_processed;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_jpeg_hw_ctx_mini_dump
|
||||
*
|
||||
* @acquire_info: Acquire info
|
||||
* @hw_ctx: hw context info
|
||||
* @in_use: flag to indicate if in use
|
||||
*/
|
||||
struct cam_jpeg_hw_ctx_mini_dump {
|
||||
struct cam_jpeg_acquire_dev_info acquire_info;
|
||||
struct cam_hw_mini_dump_info hw_ctx;
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_jpeg_hw_mgr_mini_dump
|
||||
*
|
||||
* @ctx: Context info array
|
||||
* @cfg_req: Cfg req
|
||||
* @core: core info
|
||||
* @num_context: Num of context
|
||||
*/
|
||||
struct cam_jpeg_hw_mgr_mini_dump {
|
||||
struct cam_jpeg_hw_ctx_mini_dump *ctx[CAM_JPEG_CTX_MAX];
|
||||
struct cam_jpeg_hw_mini_dump_req cfg_req[CAM_JPEG_DEV_TYPE_MAX];
|
||||
struct cam_jpeg_mini_dump_core_info core[CAM_JPEG_RES_TYPE_MAX];
|
||||
uint32_t num_context;
|
||||
};
|
||||
#endif /* CAM_JPEG_HW_MGR_H */
|
||||
|
@@ -56,12 +56,24 @@ struct cam_jpeg_match_pid_args {
|
||||
uint32_t match_res;
|
||||
};
|
||||
|
||||
struct cam_jpeg_mini_dump_core_info {
|
||||
uint32_t framedone;
|
||||
uint32_t resetdone;
|
||||
uint32_t iserror;
|
||||
uint32_t stopdone;
|
||||
uint32_t open_count;
|
||||
int32_t ref_count;
|
||||
uint32_t core_state;
|
||||
uint32_t hw_state;
|
||||
};
|
||||
|
||||
enum cam_jpeg_cmd_type {
|
||||
CAM_JPEG_CMD_CDM_CFG,
|
||||
CAM_JPEG_CMD_SET_IRQ_CB,
|
||||
CAM_JPEG_CMD_HW_DUMP,
|
||||
CAM_JPEG_CMD_GET_NUM_PID,
|
||||
CAM_JPEG_CMD_MATCH_PID_MID,
|
||||
CAM_JPEG_CMD_MINI_DUMP,
|
||||
CAM_JPEG_CMD_MAX,
|
||||
};
|
||||
|
||||
|
@@ -33,7 +33,10 @@ struct cam_jpeg_request_data {
|
||||
uint32_t thumbnail_threshold_size;
|
||||
};
|
||||
|
||||
typedef void (*cam_jpeg_mini_dump_cb)(void *priv, void *dst);
|
||||
|
||||
int cam_jpeg_hw_mgr_init(struct device_node *of_node,
|
||||
uint64_t *hw_mgr_hdl, int *iommu_hdl);
|
||||
uint64_t *hw_mgr_hdl, int *iommu_hdl,
|
||||
cam_jpeg_mini_dump_cb mini_dump_cb);
|
||||
|
||||
#endif /* CAM_JPEG_HW_MGR_INTF_H */
|
||||
|
@@ -369,6 +369,32 @@ int cam_jpeg_dma_stop_hw(void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_jpeg_dma_mini_dump(struct cam_hw_info *dev, void *args) {
|
||||
|
||||
struct cam_jpeg_mini_dump_core_info *md;
|
||||
struct cam_jpeg_dma_device_hw_info *hw_info;
|
||||
struct cam_jpeg_dma_device_core_info *core_info;
|
||||
|
||||
if (!dev || !args) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid params dev %pK args %pK", dev, args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core_info = (struct cam_jpeg_dma_device_core_info *)dev->core_info;
|
||||
hw_info = core_info->jpeg_dma_hw_info;
|
||||
md = (struct cam_jpeg_mini_dump_core_info *)args;
|
||||
|
||||
md->framedone = hw_info->int_status.framedone;
|
||||
md->resetdone = hw_info->int_status.resetdone;
|
||||
md->iserror = hw_info->int_status.iserror;
|
||||
md->stopdone = hw_info->int_status.stopdone;
|
||||
md->open_count = dev->open_count;
|
||||
md->hw_state = dev->hw_state;
|
||||
md->ref_count = core_info->ref_count;
|
||||
md->core_state = core_info->core_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -456,6 +482,9 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
match_pid_mid->pid_match_found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case CAM_JPEG_CMD_MINI_DUMP:
|
||||
rc = cam_jpeg_dma_mini_dump(jpeg_dma_dev, cmd_args);
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
|
@@ -496,6 +496,32 @@ int cam_jpeg_enc_hw_dump(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_jpeg_enc_mini_dump(struct cam_hw_info *dev, void *args) {
|
||||
|
||||
struct cam_jpeg_mini_dump_core_info *md;
|
||||
struct cam_jpeg_enc_device_hw_info *hw_info;
|
||||
struct cam_jpeg_enc_device_core_info *core_info;
|
||||
|
||||
if (!dev || !args) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid params priv %pK args %pK", dev, args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core_info = (struct cam_jpeg_enc_device_core_info *)dev->core_info;
|
||||
hw_info = core_info->jpeg_enc_hw_info;
|
||||
md = (struct cam_jpeg_mini_dump_core_info *)args;
|
||||
|
||||
md->framedone = hw_info->int_status.framedone;
|
||||
md->resetdone = hw_info->int_status.resetdone;
|
||||
md->iserror = hw_info->int_status.iserror;
|
||||
md->stopdone = hw_info->int_status.stopdone;
|
||||
md->open_count = dev->open_count;
|
||||
md->hw_state = dev->hw_state;
|
||||
md->ref_count = core_info->ref_count;
|
||||
md->core_state = core_info->core_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -590,6 +616,11 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
}
|
||||
|
||||
break;
|
||||
case CAM_JPEG_CMD_MINI_DUMP:
|
||||
{
|
||||
rc = cam_jpeg_enc_mini_dump(jpeg_enc_dev, cmd_args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
|
Посилання в новій задачі
Заблокувати користувача