Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba1d3a03 authored by Camera Software Integration's avatar Camera Software Integration Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: req_mgr: LDAR Debug framework implementation" into camera-kernel.lnx.3.1

parents 2ff04ea2 2c397b51
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -230,6 +230,34 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx,
	return rc;
}

int cam_context_handle_crm_dump_req(struct cam_context *ctx,
	struct cam_req_mgr_dump_info *dump)
{
	int rc = 0;

	if (!ctx) {
		CAM_ERR(CAM_CORE, "Invalid Context");
		return -EINVAL;
	}
	if (!ctx->state_machine) {
		CAM_ERR(CAM_CORE, "Context %s ctx_id %d is not ready",
			ctx->dev_name, ctx->ctx_id);
		return -EINVAL;
	}
	mutex_lock(&ctx->ctx_mutex);

	if (ctx->state_machine[ctx->state].crm_ops.dump_req)
		rc = ctx->state_machine[ctx->state].crm_ops.dump_req(ctx,
			dump);
	else
		CAM_ERR(CAM_CORE, "No crm dump req for %s dev %d, state %d",
			ctx->dev_name, ctx->dev_hdl, ctx->state);

	mutex_unlock(&ctx->ctx_mutex);

	return rc;
}

int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
	uint32_t buf_info)
{
@@ -524,6 +552,43 @@ int cam_context_handle_info_dump(void *context,
	return rc;
}

int cam_context_handle_dump_dev(struct cam_context *ctx,
	struct cam_dump_req_cmd *cmd)
{
	int rc = 0;

	if (!ctx) {
		CAM_ERR(CAM_CORE, "Invalid Context");
		return -EINVAL;
	}

	if (!ctx->state_machine) {
		CAM_ERR(CAM_CORE, "Context %s ctx_id %d is not ready",
			ctx->dev_name, ctx->ctx_id);
		return -EINVAL;
	}

	if (!cmd) {
		CAM_ERR(CAM_CORE,
			"Context %s ctx_id %d Invalid dump command payload",
			ctx->dev_name, ctx->ctx_id);
		return -EINVAL;
	}

	mutex_lock(&ctx->ctx_mutex);
	CAM_DBG(CAM_CORE, "dump device in dev %d, name %s state %d",
		ctx->dev_hdl, ctx->dev_name, ctx->state);
	if (ctx->state_machine[ctx->state].ioctl_ops.dump_dev)
		rc = ctx->state_machine[ctx->state].ioctl_ops.dump_dev(
			ctx, cmd);
	else
		CAM_WARN(CAM_CORE, "No dump device in dev %d, name %s state %d",
			ctx->dev_hdl, ctx->dev_name, ctx->state);
	mutex_unlock(&ctx->ctx_mutex);

	return rc;
}

int cam_context_init(struct cam_context *ctx,
	const char *dev_name,
	uint64_t dev_id,
+49 −0
Original line number Diff line number Diff line
@@ -23,6 +23,12 @@ struct cam_context;
#define CAM_CTX_CFG_MAX              20
#define CAM_CTX_RES_MAX              20

/* max tag  dump header string length*/
#define CAM_CTXT_DUMP_TAG_MAX_LEN 32

/* Number of words to be dumped for context*/
#define CAM_CTXT_DUMP_NUM_WORDS 10

/**
 * enum cam_ctx_state -  context top level states
 *
@@ -86,6 +92,7 @@ struct cam_ctx_request {
 * @flush_dev:             Function pointer for flush device
 * @acquire_hw:            Function pointer for acquire hw
 * @release_hw:            Function pointer for release hw
 * @dump_dev:              Function pointer for dump dev
 *
 */
struct cam_ctx_ioctl_ops {
@@ -103,6 +110,8 @@ struct cam_ctx_ioctl_ops {
			struct cam_flush_dev_cmd *cmd);
	int (*acquire_hw)(struct cam_context *ctx, void *args);
	int (*release_hw)(struct cam_context *ctx, void *args);
	int (*dump_dev)(struct cam_context *ctx,
			struct cam_dump_req_cmd *cmd);
};

/**
@@ -114,6 +123,7 @@ struct cam_ctx_ioctl_ops {
 * @apply_req:             Apply setting for the context
 * @flush_req:             Flush request to remove request ids
 * @process_evt:           Handle event notification from CRM.(optional)
 * @dump_req:              Dump information for the issue request
 *
 */
struct cam_ctx_crm_ops {
@@ -129,6 +139,8 @@ struct cam_ctx_crm_ops {
			struct cam_req_mgr_flush_request *flush);
	int (*process_evt)(struct cam_context *ctx,
			struct cam_req_mgr_link_evt_data *evt_data);
	int (*dump_req)(struct cam_context *ctx,
			struct cam_req_mgr_dump_info *dump);
};


@@ -219,6 +231,19 @@ struct cam_context {
	uint32_t                     last_flush_req;
};

/**
 * struct cam_context_dump_header -  Function for context dump header
 *
 * @tag         :    Tag for context dump header
 * @size        :    Size of data
 * @word_size   :    Word size of data
 */
struct cam_context_dump_header {
	uint8_t   tag[CAM_CTXT_DUMP_TAG_MAX_LEN];
	uint64_t  size;
	uint32_t  word_size;
};

/**
 * cam_context_shutdown()
 *
@@ -301,6 +326,18 @@ int cam_context_handle_crm_flush_req(struct cam_context *ctx,
int cam_context_handle_crm_process_evt(struct cam_context *ctx,
	struct cam_req_mgr_link_evt_data *process_evt);

/**
 * cam_context_handle_crm_dump_req()
 *
 * @brief:        Handle CRM dump request
 *
 * @ctx:          Object pointer for cam_context
 * @dump:         Dump request command payload
 *
 */
int cam_context_handle_crm_dump_req(struct cam_context *ctx,
	struct cam_req_mgr_dump_info *dump);

/**
 * cam_context_dump_pf_info()
 *
@@ -410,6 +447,18 @@ int cam_context_handle_start_dev(struct cam_context *ctx,
int cam_context_handle_stop_dev(struct cam_context *ctx,
		struct cam_start_stop_dev_cmd *cmd);

/**
 * cam_context_handle_dump_dev()
 *
 * @brief:        Handle dump device command
 *
 * @ctx:          Object pointer for cam_context
 * @cmd:          Dump device command payload
 *
 */
int cam_context_handle_dump_dev(struct cam_context *ctx,
	struct cam_dump_req_cmd *cmd);

/**
 * cam_context_handle_info_dump()
 *
+127 −0
Original line number Diff line number Diff line
@@ -1046,3 +1046,130 @@ int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx)
end:
	return rc;
}

static int cam_context_dump_context(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;

	if (!ctx || !dump_args) {
		CAM_ERR(CAM_CORE, "Invalid parameters %pK %pK",
			ctx, dump_args);
		return -EINVAL;
	}

	spin_lock_bh(&ctx->lock);
	if (list_empty(&ctx->active_req_list)) {
		CAM_ERR(CAM_CTXT, "[%s][%d] no active request",
			ctx->dev_name, ctx->ctx_id);
		spin_unlock_bh(&ctx->lock);
		return -EIO;
	}
	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,
		&cpu_addr, &buf_len);
	if (rc) {
		CAM_ERR(CAM_CTXT, "Invalid hdl %u rc %d",
			dump_args->buf_handle, rc);
		return rc;
	}
	if (dump_args->offset >= buf_len) {
		CAM_WARN(CAM_CTXT, "dump buffer overshoot offset %zu len %zu",
			dump_args->offset, buf_len);
		return -ENOSPC;
	}

	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);

	if (remain_len < min_len) {
		CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u",
			remain_len, min_len);
		return -ENOSPC;
	}
	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);
	hdr->word_size = sizeof(uint64_t);
	addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
	start = addr;
	*addr++ = ctx->ctx_id;
	*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;
	}
	*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;
}

int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
	struct cam_dump_req_cmd *cmd)
{
	int                     rc = 0;
	struct cam_hw_dump_args dump_args;

	if (!ctx || !cmd) {
		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd);
		return -EINVAL;
	}
	if (!ctx->hw_mgr_intf) {
		CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready",
			ctx->dev_name, ctx->ctx_id);
		return -EFAULT;
	}
	memset(&dump_args, 0, sizeof(dump_args));
	if (ctx->hw_mgr_intf->hw_dump) {
		dump_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
		dump_args.buf_handle = cmd->buf_handle;
		dump_args.offset = cmd->offset;
		dump_args.request_id = cmd->issue_req_id;
		dump_args.error_type = cmd->error_type;
		rc  = ctx->hw_mgr_intf->hw_dump(
			ctx->hw_mgr_intf->hw_mgr_priv,
			&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;
		}
		/* 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 {
		CAM_DBG(CAM_CTXT, "%s hw dump not registered", ctx->dev_name);
	}
	return rc;
}
+2 −1
Original line number Diff line number Diff line
@@ -30,5 +30,6 @@ 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);
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);
#endif /* _CAM_CONTEXT_UTILS_H_ */
+19 −0
Original line number Diff line number Diff line
@@ -300,6 +300,23 @@ struct cam_hw_reset_args {
	void                           *ctxt_to_hw_map;
};

/**
 * struct cam_hw_dump_args - Dump arguments
 *
 * @request_id:            request_id
 * @offset:                Buffer offset. This is updated by the drivers.
 * @buf_handle:            Buffer handle
 * @error_type:            Error type, to be used to extend dump information
 * @ctxt_to_hw_map:        HW context from the acquire
 */
struct cam_hw_dump_args {
	uint64_t          request_id;
	size_t            offset;
	uint32_t          buf_handle;
	uint32_t          error_type;
	void             *ctxt_to_hw_map;
};

/* enum cam_hw_mgr_command - Hardware manager command type */
enum cam_hw_mgr_command {
	CAM_HW_MGR_CMD_INTERNAL,
@@ -355,6 +372,7 @@ struct cam_hw_cmd_args {
 * @hw_close:                  Function pointer for HW deinit
 * @hw_flush:                  Function pointer for HW flush
 * @hw_reset:                  Function pointer for HW reset
 * @hw_dump:                   Function pointer for HW dump
 *
 */
struct cam_hw_mgr_intf {
@@ -376,6 +394,7 @@ struct cam_hw_mgr_intf {
	int (*hw_close)(void *hw_priv, void *hw_close_args);
	int (*hw_flush)(void *hw_priv, void *hw_flush_args);
	int (*hw_reset)(void *hw_priv, void *hw_reset_args);
	int (*hw_dump)(void *hw_priv, void *hw_dump_args);
};

#endif /* _CAM_HW_MGR_INTF_H_ */
Loading