|
@@ -1217,19 +1217,17 @@ end:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-static int cam_context_dump_context(struct cam_context *ctx,
|
|
|
+static int cam_context_user_dump(struct cam_context *ctx,
|
|
|
struct cam_hw_dump_args *dump_args)
|
|
|
{
|
|
|
- int rc;
|
|
|
- int i;
|
|
|
- size_t buf_len;
|
|
|
- size_t remain_len;
|
|
|
- uint8_t *dst;
|
|
|
- uint64_t *addr, *start;
|
|
|
- uint32_t min_len;
|
|
|
- uintptr_t cpu_addr;
|
|
|
- struct cam_ctx_request *req;
|
|
|
- struct cam_context_dump_header *hdr;
|
|
|
+ int rc, i;
|
|
|
+ struct cam_ctx_request *req, *req_temp;
|
|
|
+ struct cam_context_dump_header *hdr;
|
|
|
+ uint8_t *dst;
|
|
|
+ uint64_t *addr, *start;
|
|
|
+ uint32_t min_len;
|
|
|
+ size_t buf_len, remain_len;
|
|
|
+ uintptr_t cpu_addr;
|
|
|
|
|
|
if (!ctx || !dump_args) {
|
|
|
CAM_ERR(CAM_CORE, "Invalid parameters %pK %pK",
|
|
@@ -1247,7 +1245,8 @@ static int cam_context_dump_context(struct cam_context *ctx,
|
|
|
req = list_first_entry(&ctx->active_req_list,
|
|
|
struct cam_ctx_request, list);
|
|
|
spin_unlock_bh(&ctx->lock);
|
|
|
- rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
|
|
|
+
|
|
|
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
|
|
|
&cpu_addr, &buf_len);
|
|
|
if (rc) {
|
|
|
CAM_ERR(CAM_CTXT, "Invalid hdl %u rc %d",
|
|
@@ -1261,38 +1260,111 @@ static int cam_context_dump_context(struct cam_context *ctx,
|
|
|
}
|
|
|
|
|
|
remain_len = buf_len - dump_args->offset;
|
|
|
- min_len = sizeof(struct cam_context_dump_header) +
|
|
|
- (CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries +
|
|
|
- (req->num_out_map_entries * 2)) * sizeof(uint64_t);
|
|
|
+ min_len = sizeof(struct cam_context_dump_header) +
|
|
|
+ (CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries +
|
|
|
+ (req->num_out_map_entries * 2)) * sizeof(uint64_t);
|
|
|
|
|
|
if (remain_len < min_len) {
|
|
|
CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u",
|
|
|
remain_len, min_len);
|
|
|
return -ENOSPC;
|
|
|
}
|
|
|
+
|
|
|
+ /* Dump context info */
|
|
|
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
|
|
hdr = (struct cam_context_dump_header *)dst;
|
|
|
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
|
|
- "%s_CTXT_DUMP:", ctx->dev_name);
|
|
|
+ "%s_CTX_INFO:", ctx->dev_name);
|
|
|
hdr->word_size = sizeof(uint64_t);
|
|
|
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
|
|
start = addr;
|
|
|
- *addr++ = ctx->ctx_id;
|
|
|
+ *addr++ = ctx->hw_mgr_ctx_id;
|
|
|
+ *addr++ = ctx->dev_id;
|
|
|
+ *addr++ = ctx->dev_hdl;
|
|
|
+ *addr++ = ctx->link_hdl;
|
|
|
+ *addr++ = ctx->session_hdl;
|
|
|
*addr++ = refcount_read(&(ctx->refcount.refcount));
|
|
|
*addr++ = ctx->last_flush_req;
|
|
|
*addr++ = ctx->state;
|
|
|
- *addr++ = req->num_out_map_entries;
|
|
|
- for (i = 0; i < req->num_out_map_entries; i++) {
|
|
|
- *addr++ = req->out_map_entries[i].resource_handle;
|
|
|
- *addr++ = req->out_map_entries[i].sync_id;
|
|
|
+ hdr->size = hdr->word_size * (addr - start);
|
|
|
+ dump_args->offset += hdr->size +
|
|
|
+ sizeof(struct cam_context_dump_header);
|
|
|
+
|
|
|
+ /* Dump pending request IDs */
|
|
|
+ dst = (uint8_t *)cpu_addr + dump_args->offset;
|
|
|
+ hdr = (struct cam_context_dump_header *)dst;
|
|
|
+ scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
|
|
+ "%s_OUT_FENCE_PENDING_REQUESTS:", ctx->dev_name);
|
|
|
+ hdr->word_size = sizeof(uint64_t);
|
|
|
+ addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
|
|
+ start = addr;
|
|
|
+ if (!list_empty(&ctx->wait_req_list)) {
|
|
|
+ list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) {
|
|
|
+ *addr++ = req->request_id;
|
|
|
+ }
|
|
|
}
|
|
|
- *addr++ = req->num_in_map_entries;
|
|
|
- for (i = 0; i < req->num_in_map_entries; i++)
|
|
|
- *addr++ = req->in_map_entries[i].sync_id;
|
|
|
hdr->size = hdr->word_size * (addr - start);
|
|
|
dump_args->offset += hdr->size +
|
|
|
sizeof(struct cam_context_dump_header);
|
|
|
- return rc;
|
|
|
+
|
|
|
+ /* Dump applied request IDs */
|
|
|
+ dst = (uint8_t *)cpu_addr + dump_args->offset;
|
|
|
+ hdr = (struct cam_context_dump_header *)dst;
|
|
|
+ scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
|
|
+ "%s_OUT_FENCE_APPLIED_REQUESTS:", ctx->dev_name);
|
|
|
+ hdr->word_size = sizeof(uint64_t);
|
|
|
+ addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
|
|
+ start = addr;
|
|
|
+ if (!list_empty(&ctx->pending_req_list)) {
|
|
|
+ list_for_each_entry_safe(req, req_temp, &ctx->pending_req_list, list) {
|
|
|
+ *addr++ = req->request_id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ hdr->size = hdr->word_size * (addr - start);
|
|
|
+ dump_args->offset += hdr->size +
|
|
|
+ sizeof(struct cam_context_dump_header);
|
|
|
+
|
|
|
+ /* Dump active request IDs */
|
|
|
+ dst = (uint8_t *)cpu_addr + dump_args->offset;
|
|
|
+ hdr = (struct cam_context_dump_header *)dst;
|
|
|
+ scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
|
|
+ "%s_OUT_FENCE_ACTIVE_REQUESTS:", ctx->dev_name);
|
|
|
+ hdr->word_size = sizeof(uint64_t);
|
|
|
+ addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
|
|
+ start = addr;
|
|
|
+ if (!list_empty(&ctx->active_req_list)) {
|
|
|
+ list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
|
|
|
+ *addr++ = req->request_id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ hdr->size = hdr->word_size * (addr - start);
|
|
|
+ dump_args->offset += hdr->size +
|
|
|
+ sizeof(struct cam_context_dump_header);
|
|
|
+
|
|
|
+ /* Dump active requests */
|
|
|
+ if (!list_empty(&ctx->active_req_list)) {
|
|
|
+ list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
|
|
|
+ for (i = 0; i < req->num_out_map_entries; i++) {
|
|
|
+ dst = (uint8_t *)cpu_addr + dump_args->offset;
|
|
|
+ hdr = (struct cam_context_dump_header *)dst;
|
|
|
+ scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
|
|
+ "%s_OUT_FENCE_REQUEST_ACTIVE.%d.%d.%d:",
|
|
|
+ ctx->dev_name,
|
|
|
+ req->out_map_entries[i].resource_handle,
|
|
|
+ &(req->out_map_entries[i].image_buf_addr),
|
|
|
+ req->out_map_entries[i].sync_id);
|
|
|
+ hdr->word_size = sizeof(uint64_t);
|
|
|
+ addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
|
|
+ start = addr;
|
|
|
+ *addr++ = req->request_id;
|
|
|
+ hdr->size = hdr->word_size * (addr - start);
|
|
|
+ dump_args->offset += hdr->size +
|
|
|
+ sizeof(struct cam_context_dump_header);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
|
|
@@ -1317,6 +1389,14 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
|
|
|
dump_args.offset = cmd->offset;
|
|
|
dump_args.request_id = cmd->issue_req_id;
|
|
|
dump_args.error_type = cmd->error_type;
|
|
|
+
|
|
|
+ rc = cam_context_user_dump(ctx, &dump_args);
|
|
|
+ if (rc) {
|
|
|
+ CAM_ERR(CAM_CTXT, "[%s][%d] handle[%u] failed",
|
|
|
+ ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
rc = ctx->hw_mgr_intf->hw_dump(
|
|
|
ctx->hw_mgr_intf->hw_mgr_priv,
|
|
|
&dump_args);
|
|
@@ -1325,17 +1405,9 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
|
|
|
ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
|
|
|
return rc;
|
|
|
}
|
|
|
- /* Offset will change if the issue request id is found with
|
|
|
- * the hw and has been lying with it beyond threshold time.
|
|
|
- * If offset does not change, do not dump the context
|
|
|
- * information as the current context has no problem with
|
|
|
- * the provided request id.
|
|
|
- */
|
|
|
+
|
|
|
+
|
|
|
if (dump_args.offset > cmd->offset) {
|
|
|
- cam_context_dump_context(ctx, &dump_args);
|
|
|
- CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %u",
|
|
|
- ctx->dev_name, ctx->ctx_id,
|
|
|
- dump_args.offset - cmd->offset);
|
|
|
cmd->offset = dump_args.offset;
|
|
|
}
|
|
|
} else {
|