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

Commit aa53e68c authored by Alan Kwong's avatar Alan Kwong
Browse files

drm/msm: clean up inline rotator register dump



Add inline rotator register dump to sde dump so that
when inline use case causes panic, inline rotator hw
state is captured for analysis. Update sequence number
for proper tracking and output events as hex number to
trace log so that it is compatible with evtlog dump format.

Change-Id: I8a1be9e7442b2fa9b65af620db56c98f39882455
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent de85fcd6
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -61,6 +61,16 @@ static struct sde_rot_cfg *_rot_offset(enum sde_rot rot,
	return ERR_PTR(-EINVAL);
}

/**
 * _sde_hw_rot_reg_dump - perform register dump
 * @ptr: private pointer to rotator platform device
 * return: None
 */
static void _sde_hw_rot_reg_dump(void *ptr)
{
	sde_rotator_inline_reg_dump((struct platform_device *) ptr);
}

/**
 * sde_hw_rot_start - start rotator before any commit
 * @hw: Pointer to rotator hardware driver
@@ -78,6 +88,10 @@ static int sde_hw_rot_start(struct sde_hw_rot *hw)

	pdev = hw->caps->pdev;

	rc = sde_dbg_reg_register_cb(hw->name, _sde_hw_rot_reg_dump, pdev);
	if (rc)
		SDE_ERROR("failed to register debug dump %d\n", rc);

	hw->rot_ctx = sde_rotator_inline_open(pdev);
	if (IS_ERR_OR_NULL(hw->rot_ctx)) {
		rc = PTR_ERR(hw->rot_ctx);
@@ -95,13 +109,16 @@ static int sde_hw_rot_start(struct sde_hw_rot *hw)
 */
static void sde_hw_rot_stop(struct sde_hw_rot *hw)
{
	if (!hw) {
	if (!hw || !hw->caps || !hw->caps->pdev) {
		SDE_ERROR("invalid parameter\n");
		return;
	}

	sde_rotator_inline_release(hw->rot_ctx);
	hw->rot_ctx = NULL;

	sde_dbg_reg_unregister_cb(hw->name, _sde_hw_rot_reg_dump,
			hw->caps->pdev);
}

/**
@@ -576,6 +593,7 @@ static int sde_hw_rot_commit(struct sde_hw_rot *hw, struct sde_hw_rot_cmd *data,
		return -EINVAL;
	}

	rot_cmd.sequence_id = data->sequence_id;
	rot_cmd.video_mode = data->video_mode;
	rot_cmd.fps = data->fps;

@@ -899,6 +917,7 @@ struct sde_hw_rot *sde_hw_rot_init(enum sde_rot idx,
	c->idx = idx;
	c->caps = cfg;
	_setup_rot_ops(&c->ops, c->caps->features);
	snprintf(c->name, ARRAY_SIZE(c->name), "sde_rot_%d", idx - ROT_0);

	rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_ROT, idx, &sde_hw_rot_ops);
	if (rc) {
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#include "sde_hw_util.h"
#include "sde_hw_blk.h"

#define SDE_HW_ROT_NAME_SIZE	80

struct sde_hw_rot;

/**
@@ -137,6 +139,7 @@ struct sde_hw_rot_ops {
struct sde_hw_rot {
	struct sde_hw_blk base;
	struct sde_hw_blk_reg_map hw;
	char name[SDE_HW_ROT_NAME_SIZE];
	int idx;
	const struct sde_rot_cfg *caps;
	struct sde_hw_rot_ops ops;
+1 −1
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ TRACE_EVENT(sde_evtlog,
			memset(&__entry->data[cnt], 0,
				(SDE_TRACE_EVTLOG_SIZE - cnt) * sizeof(u32));
	),
	TP_printk("%d|%s:%d|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u",
	TP_printk("%d|%s:%d|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x",
			__entry->pid, __get_str(evtlog_tag),
			__entry->tag_id,
			__entry->data[0], __entry->data[1],
+62 −3
Original line number Diff line number Diff line
@@ -106,6 +106,8 @@ struct sde_dbg_reg_range {
 * @buf: buffer used for manual register dumping
 * @buf_len:  buffer length used for manual register dumping
 * @reg_dump: address for the mem dump if no ranges used
 * @cb: callback for external dump function, null if not defined
 * @cb_ptr: private pointer to callback function
 */
struct sde_dbg_reg_base {
	struct list_head reg_base_head;
@@ -118,6 +120,8 @@ struct sde_dbg_reg_base {
	char *buf;
	size_t buf_len;
	u32 *reg_dump;
	void (*cb)(void *ptr);
	void *cb_ptr;
};

struct sde_debug_bus_entry {
@@ -2144,16 +2148,17 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg,
	size_t len;
	struct sde_dbg_reg_range *range_node;

	if (!dbg || !dbg->base) {
	if (!dbg || !(dbg->base || dbg->cb)) {
		pr_err("dbg base is null!\n");
		return;
	}

	dev_info(sde_dbg_base.dev, "%s:=========%s DUMP=========\n", __func__,
			dbg->name);

	if (dbg->cb) {
		dbg->cb(dbg->cb_ptr);
	/* If there is a list to dump the registers by ranges, use the ranges */
	if (!list_empty(&dbg->sub_range_list)) {
	} else if (!list_empty(&dbg->sub_range_list)) {
		/* sort the list by start address first */
		list_sort(NULL, &dbg->sub_range_list, _sde_dump_reg_range_cmp);
		list_for_each_entry(range_node, &dbg->sub_range_list, head) {
@@ -3179,6 +3184,60 @@ int sde_dbg_reg_register_base(const char *name, void __iomem *base,
	return 0;
}

int sde_dbg_reg_register_cb(const char *name, void (*cb)(void *), void *ptr)
{
	struct sde_dbg_base *dbg_base = &sde_dbg_base;
	struct sde_dbg_reg_base *reg_base;

	if (!name || !strlen(name)) {
		pr_err("no debug name provided\n");
		return -EINVAL;
	}

	reg_base = kzalloc(sizeof(*reg_base), GFP_KERNEL);
	if (!reg_base)
		return -ENOMEM;

	strlcpy(reg_base->name, name, sizeof(reg_base->name));
	reg_base->base = NULL;
	reg_base->max_offset = 0;
	reg_base->off = 0;
	reg_base->cnt = DEFAULT_BASE_REG_CNT;
	reg_base->reg_dump = NULL;
	reg_base->cb = cb;
	reg_base->cb_ptr = ptr;

	/* Initialize list to make sure check for null list will be valid */
	INIT_LIST_HEAD(&reg_base->sub_range_list);

	pr_debug("%s cb: %pK cb_ptr: %pK\n", reg_base->name,
			reg_base->cb, reg_base->cb_ptr);

	list_add(&reg_base->reg_base_head, &dbg_base->reg_base_list);

	return 0;
}

void sde_dbg_reg_unregister_cb(const char *name, void (*cb)(void *), void *ptr)
{
	struct sde_dbg_base *dbg_base = &sde_dbg_base;
	struct sde_dbg_reg_base *reg_base;

	if (!dbg_base)
		return;

	list_for_each_entry(reg_base, &dbg_base->reg_base_list, reg_base_head) {
		if (strlen(reg_base->name) &&
			!strcmp(reg_base->name, name)) {
			pr_debug("%s cb: %pK cb_ptr: %pK\n", reg_base->name,
					reg_base->cb, reg_base->cb_ptr);
			list_del(&reg_base->reg_base_head);
			kfree(reg_base);
			break;
		}
	}
}

void sde_dbg_reg_register_dump_range(const char *base_name,
		const char *range_name, u32 offset_start, u32 offset_end,
		uint32_t xin_id)
+20 −0
Original line number Diff line number Diff line
@@ -250,6 +250,26 @@ void sde_dbg_dump(bool queue_work, const char *name, ...);
int sde_dbg_reg_register_base(const char *name, void __iomem *base,
		size_t max_offset);

/**
 * sde_dbg_reg_register_cb - register a hw register callback for later
 *	dumping.
 * @name:	name of base region
 * @cb:		callback of external region
 * @cb_ptr:	private pointer of external region
 * Returns:	0 or -ERROR
 */
int sde_dbg_reg_register_cb(const char *name, void (*cb)(void *), void *ptr);

/**
 * sde_dbg_reg_unregister_cb - register a hw unregister callback for later
 *	dumping.
 * @name:	name of base region
 * @cb:		callback of external region
 * @cb_ptr:	private pointer of external region
 * Returns:	None
 */
void sde_dbg_reg_unregister_cb(const char *name, void (*cb)(void *), void *ptr);

/**
 * sde_dbg_reg_register_dump_range - register a hw register sub-region for
 *	later register dumping associated with base specified by