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

Commit 92aa0b1f authored by Lloyd Atkinson's avatar Lloyd Atkinson Committed by Abhinav Kumar
Browse files

drm/msm/sde: fix register debug range printing



Add checks to sde debug facility to reject poorly formed
register block ranges. Add names for dsc and vbif register
blocks. Register the vbif hw block under the vbif base register.
Fix the names of the printed register blocks to be 0 based as
expected. Fix the DSC register length initialization. Sort
register ranges before printing. Register mdp top block
address before dumping the sde debug bus.

Change-Id: I0179d59543de52537937abcc7d556f79569e9c55
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
Signed-off-by: default avatarAbhinav Kumar <abhinavk@codeaurora.org>
parent abd41176
Loading
Loading
Loading
Loading
+38 −26
Original line number Diff line number Diff line
@@ -719,7 +719,8 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
	sblk->maxdwnscale = MAX_SSPP_DOWNSCALE;
	sblk->format_list = plane_formats_yuv;
	sspp->id = SSPP_VIG0 + *vig_count;
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u", sspp->id);
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u",
			sspp->id - SSPP_VIG0);
	sspp->clk_ctrl = SDE_CLK_CTRL_VIG0 + *vig_count;
	sspp->type = SSPP_TYPE_VIG;
	set_bit(SDE_SSPP_QOS, &sspp->features);
@@ -736,7 +737,7 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
		sblk->scaler_blk.len = PROP_VALUE_ACCESS(prop_value,
			VIG_QSEED_LEN, 0);
		snprintf(sblk->scaler_blk.name, SDE_HW_BLK_NAME_LEN,
				"sspp_scaler%u", sspp->id);
				"sspp_scaler%u", sspp->id - SSPP_VIG0);
	} else if (sde_cfg->qseed_type == SDE_SSPP_SCALER_QSEED3) {
		set_bit(SDE_SSPP_SCALER_QSEED3, &sspp->features);
		sblk->scaler_blk.id = SDE_SSPP_SCALER_QSEED3;
@@ -745,12 +746,12 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
		sblk->scaler_blk.len = PROP_VALUE_ACCESS(prop_value,
			VIG_QSEED_LEN, 0);
		snprintf(sblk->scaler_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_scaler%u", sspp->id);
			"sspp_scaler%u", sspp->id - SSPP_VIG0);
	}

	sblk->csc_blk.id = SDE_SSPP_CSC;
	snprintf(sblk->csc_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_csc%u", sspp->id);
			"sspp_csc%u", sspp->id - SSPP_VIG0);
	if (sde_cfg->csc_type == SDE_SSPP_CSC) {
		set_bit(SDE_SSPP_CSC, &sspp->features);
		sblk->csc_blk.base = PROP_VALUE_ACCESS(prop_value,
@@ -763,7 +764,7 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,

	sblk->hsic_blk.id = SDE_SSPP_HSIC;
	snprintf(sblk->hsic_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_hsic%u", sspp->id);
			"sspp_hsic%u", sspp->id - SSPP_VIG0);
	if (prop_exists[VIG_HSIC_PROP]) {
		sblk->hsic_blk.base = PROP_VALUE_ACCESS(prop_value,
			VIG_HSIC_PROP, 0);
@@ -775,7 +776,7 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,

	sblk->memcolor_blk.id = SDE_SSPP_MEMCOLOR;
	snprintf(sblk->memcolor_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_memcolor%u", sspp->id);
			"sspp_memcolor%u", sspp->id - SSPP_VIG0);
	if (prop_exists[VIG_MEMCOLOR_PROP]) {
		sblk->memcolor_blk.base = PROP_VALUE_ACCESS(prop_value,
			VIG_MEMCOLOR_PROP, 0);
@@ -787,7 +788,7 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,

	sblk->pcc_blk.id = SDE_SSPP_PCC;
	snprintf(sblk->pcc_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_pcc%u", sspp->id);
			"sspp_pcc%u", sspp->id - SSPP_VIG0);
	if (prop_exists[VIG_PCC_PROP]) {
		sblk->pcc_blk.base = PROP_VALUE_ACCESS(prop_value,
			VIG_PCC_PROP, 0);
@@ -807,7 +808,8 @@ static void _sde_sspp_setup_rgb(struct sde_mdss_cfg *sde_cfg,
	sblk->maxdwnscale = MAX_SSPP_DOWNSCALE;
	sblk->format_list = plane_formats;
	sspp->id = SSPP_RGB0 + *rgb_count;
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u", sspp->id);
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u",
			sspp->id - SSPP_VIG0);
	sspp->clk_ctrl = SDE_CLK_CTRL_RGB0 + *rgb_count;
	sspp->type = SSPP_TYPE_RGB;
	set_bit(SDE_SSPP_QOS, &sspp->features);
@@ -824,7 +826,7 @@ static void _sde_sspp_setup_rgb(struct sde_mdss_cfg *sde_cfg,
		sblk->scaler_blk.len = PROP_VALUE_ACCESS(prop_value,
			RGB_SCALER_LEN, 0);
		snprintf(sblk->scaler_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_scaler%u", sspp->id);
			"sspp_scaler%u", sspp->id - SSPP_VIG0);
	} else if (sde_cfg->qseed_type == SDE_SSPP_SCALER_QSEED3) {
		set_bit(SDE_SSPP_SCALER_RGB, &sspp->features);
		sblk->scaler_blk.id = SDE_SSPP_SCALER_QSEED3;
@@ -833,7 +835,7 @@ static void _sde_sspp_setup_rgb(struct sde_mdss_cfg *sde_cfg,
		sblk->scaler_blk.len = PROP_VALUE_ACCESS(prop_value,
			SSPP_SCALE_SIZE, 0);
		snprintf(sblk->scaler_blk.name, SDE_HW_BLK_NAME_LEN,
			"sspp_scaler%u", sspp->id);
			"sspp_scaler%u", sspp->id - SSPP_VIG0);
	}

	sblk->pcc_blk.id = SDE_SSPP_PCC;
@@ -857,7 +859,8 @@ static void _sde_sspp_setup_cursor(struct sde_mdss_cfg *sde_cfg,
	sblk->maxdwnscale = SSPP_UNITY_SCALE;
	sblk->format_list = cursor_formats;
	sspp->id = SSPP_CURSOR0 + *cursor_count;
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u", sspp->id);
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u",
			sspp->id - SSPP_VIG0);
	sspp->clk_ctrl = SDE_CLK_CTRL_CURSOR0 + *cursor_count;
	sspp->type = SSPP_TYPE_CURSOR;
	(*cursor_count)++;
@@ -874,7 +877,8 @@ static void _sde_sspp_setup_dma(struct sde_mdss_cfg *sde_cfg,
	sspp->id = SSPP_DMA0 + *dma_count;
	sspp->clk_ctrl = SDE_CLK_CTRL_DMA0 + *dma_count;
	sspp->type = SSPP_TYPE_DMA;
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u", sspp->id);
	snprintf(sspp->name, SDE_HW_BLK_NAME_LEN, "sspp_%u",
			sspp->id - SSPP_VIG0);
	set_bit(SDE_SSPP_QOS, &sspp->features);
	(*dma_count)++;
	snprintf(sspp->name, sizeof(sspp->name), "dma%d", *dma_count-1);
@@ -978,8 +982,6 @@ static int sde_sspp_parse_dt(struct device_node *np,

		set_bit(SDE_SSPP_SRC, &sspp->features);
		sblk->src_blk.id = SDE_SSPP_SRC;
		snprintf(sblk->src_blk.name, SDE_HW_BLK_NAME_LEN, "sspp_src_%u",
				sblk->src_blk.id);

		of_property_read_string_index(np,
				sspp_prop[SSPP_TYPE].prop_name, i, &type);
@@ -1104,7 +1106,8 @@ static int sde_ctl_parse_dt(struct device_node *np,
		ctl->base = PROP_VALUE_ACCESS(prop_value, HW_OFF, i);
		ctl->len = PROP_VALUE_ACCESS(prop_value, HW_LEN, 0);
		ctl->id = CTL_0 + i;
		snprintf(ctl->name, SDE_HW_BLK_NAME_LEN, "ctl_%u", ctl->id);
		snprintf(ctl->name, SDE_HW_BLK_NAME_LEN, "ctl_%u",
				ctl->id - CTL_0);

		if (i < MAX_SPLIT_DISPLAY_CTL)
			set_bit(SDE_CTL_SPLIT_DISPLAY, &ctl->features);
@@ -1196,7 +1199,8 @@ static int sde_mixer_parse_dt(struct device_node *np,
		mixer->base = PROP_VALUE_ACCESS(prop_value, MIXER_OFF, i);
		mixer->len = PROP_VALUE_ACCESS(prop_value, MIXER_LEN, 0);
		mixer->id = LM_0 + i;
		snprintf(mixer->name, SDE_HW_BLK_NAME_LEN, "lm_%u", mixer->id);
		snprintf(mixer->name, SDE_HW_BLK_NAME_LEN, "lm_%u",
				mixer->id - LM_0);

		if (!prop_exists[MIXER_LEN])
			mixer->len = DEFAULT_SDE_HW_BLOCK_LEN;
@@ -1284,7 +1288,8 @@ static int sde_intf_parse_dt(struct device_node *np,
		intf->base = PROP_VALUE_ACCESS(prop_value, INTF_OFF, i);
		intf->len = PROP_VALUE_ACCESS(prop_value, INTF_LEN, 0);
		intf->id = INTF_0 + i;
		snprintf(intf->name, SDE_HW_BLK_NAME_LEN, "intf_%u", intf->id);
		snprintf(intf->name, SDE_HW_BLK_NAME_LEN, "intf_%u",
				intf->id - INTF_0);

		if (!prop_exists[INTF_LEN])
			intf->len = DEFAULT_SDE_HW_BLOCK_LEN;
@@ -1365,7 +1370,8 @@ static int sde_wb_parse_dt(struct device_node *np,

		wb->base = PROP_VALUE_ACCESS(prop_value, WB_OFF, i);
		wb->id = WB_0 + PROP_VALUE_ACCESS(prop_value, WB_ID, i);
		snprintf(wb->name, SDE_HW_BLK_NAME_LEN, "wb_%u", wb->id);
		snprintf(wb->name, SDE_HW_BLK_NAME_LEN, "wb_%u",
				wb->id - WB_0);
		wb->clk_ctrl = SDE_CLK_CTRL_WB0 +
			PROP_VALUE_ACCESS(prop_value, WB_ID, i);
		wb->xin_id = PROP_VALUE_ACCESS(prop_value, WB_XIN_ID, i);
@@ -1601,7 +1607,8 @@ static int sde_dspp_parse_dt(struct device_node *np,
		dspp->base = PROP_VALUE_ACCESS(prop_value, DSPP_OFF, i);
		dspp->len = PROP_VALUE_ACCESS(prop_value, DSPP_SIZE, 0);
		dspp->id = DSPP_0 + i;
		snprintf(dspp->name, SDE_HW_BLK_NAME_LEN, "dspp_%u", dspp->id);
		snprintf(dspp->name, SDE_HW_BLK_NAME_LEN, "dspp_%u",
				dspp->id - DSPP_0);

		sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
		if (!sblk) {
@@ -1671,7 +1678,8 @@ static int sde_cdm_parse_dt(struct device_node *np,
		cdm = sde_cfg->cdm + i;
		cdm->base = PROP_VALUE_ACCESS(prop_value, HW_OFF, i);
		cdm->id = CDM_0 + i;
		snprintf(cdm->name, SDE_HW_BLK_NAME_LEN, "cdm_%u", cdm->id);
		snprintf(cdm->name, SDE_HW_BLK_NAME_LEN, "cdm_%u",
				cdm->id - CDM_0);
		cdm->len = PROP_VALUE_ACCESS(prop_value, HW_LEN, 0);

		/* intf3 and wb2 for cdm block */
@@ -1737,6 +1745,8 @@ static int sde_vbif_parse_dt(struct device_node *np,
		vbif->base = PROP_VALUE_ACCESS(prop_value, VBIF_OFF, i);
		vbif->len = vbif_len;
		vbif->id = VBIF_0 + PROP_VALUE_ACCESS(prop_value, VBIF_ID, i);
		snprintf(vbif->name, SDE_HW_BLK_NAME_LEN, "vbif_%u",
				vbif->id - VBIF_0);

		SDE_DEBUG("vbif:%d\n", vbif->id - VBIF_0);

@@ -1864,19 +1874,21 @@ static int sde_pp_parse_dt(struct device_node *np,

		pp->base = PROP_VALUE_ACCESS(prop_value, PP_OFF, i);
		pp->id = PINGPONG_0 + i;
		snprintf(pp->name, SDE_HW_BLK_NAME_LEN, "pingpong_%u", pp->id);
		snprintf(pp->name, SDE_HW_BLK_NAME_LEN, "pingpong_%u",
				pp->id - PINGPONG_0);
		pp->len = PROP_VALUE_ACCESS(prop_value, PP_LEN, 0);

		sblk->te.base = PROP_VALUE_ACCESS(prop_value, TE_OFF, i);
		sblk->te.id = SDE_PINGPONG_TE;
		snprintf(sblk->te.name, SDE_HW_BLK_NAME_LEN, "te_%u", pp->id);
		snprintf(sblk->te.name, SDE_HW_BLK_NAME_LEN, "te_%u",
				pp->id - PINGPONG_0);
		set_bit(SDE_PINGPONG_TE, &pp->features);

		sblk->te2.base = PROP_VALUE_ACCESS(prop_value, TE2_OFF, i);
		if (sblk->te2.base) {
			sblk->te2.id = SDE_PINGPONG_TE2;
			snprintf(sblk->te2.name, SDE_HW_BLK_NAME_LEN, "te2_%u",
					pp->id);
					pp->id - PINGPONG_0);
			set_bit(SDE_PINGPONG_TE2, &pp->features);
			set_bit(SDE_PINGPONG_SPLIT, &pp->features);
		}
@@ -1888,7 +1900,7 @@ static int sde_pp_parse_dt(struct device_node *np,
		if (sblk->dsc.base) {
			sblk->dsc.id = SDE_PINGPONG_DSC;
			snprintf(sblk->dsc.name, SDE_HW_BLK_NAME_LEN, "dsc_%u",
					pp->id);
					sblk->dsc.id - PINGPONG_0);
			set_bit(SDE_PINGPONG_DSC, &pp->features);
		}
	}
@@ -2020,12 +2032,12 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	cfg->mdss[0].base = MDSS_BASE_OFFSET;
	cfg->mdss[0].id = MDP_TOP;
	snprintf(cfg->mdss[0].name, SDE_HW_BLK_NAME_LEN, "mdss_%u",
			cfg->mdss[0].id);
			cfg->mdss[0].id - MDP_TOP);

	cfg->mdp_count = 1;
	cfg->mdp[0].id = MDP_TOP;
	snprintf(cfg->mdp[0].name, SDE_HW_BLK_NAME_LEN, "top_%u",
		cfg->mdp[0].id);
		cfg->mdp[0].id - MDP_TOP);
	cfg->mdp[0].base = PROP_VALUE_ACCESS(prop_value, SDE_OFF, 0);
	cfg->mdp[0].len = PROP_VALUE_ACCESS(prop_value, SDE_LEN, 0);
	if (!prop_exists[SDE_LEN])
+3 −2
Original line number Diff line number Diff line
@@ -946,8 +946,9 @@ struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
	if (cfg->sblk->scaler_blk.len)
		sde_dbg_reg_register_dump_range(SDE_DBG_NAME,
			cfg->sblk->scaler_blk.name,
			cfg->sblk->scaler_blk.base,
			cfg->sblk->scaler_blk.base + cfg->sblk->scaler_blk.len,
			hw_pipe->hw.blk_off + cfg->sblk->scaler_blk.base,
			hw_pipe->hw.blk_off + cfg->sblk->scaler_blk.base +
				cfg->sblk->scaler_blk.len,
			hw_pipe->hw.xin_id);

	return hw_pipe;
+1 −0
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx,
	sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name,
			mdp->hw.blk_off, mdp->hw.blk_off + mdp->hw.length,
			mdp->hw.xin_id);
	sde_dbg_set_sde_top_offset(mdp->hw.blk_off);

	return mdp;
}
+1 −2
Original line number Diff line number Diff line
@@ -158,8 +158,7 @@ struct sde_hw_vbif *sde_hw_vbif_init(enum sde_vbif idx,
	c->cap = cfg;
	_setup_vbif_ops(&c->ops, c->cap->features);

	sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name, c->hw.blk_off,
			c->hw.blk_off + c->hw.length, c->hw.xin_id);
	/* no need to register sub-range in sde dbg, dump entire vbif io base */

	return c;
}
+98 −38
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/uaccess.h>
#include <linux/dma-buf.h>
#include <linux/slab.h>
#include <linux/list_sort.h>

#include "sde_dbg.h"
#include "sde/sde_hw_catalog.h"
@@ -41,7 +42,7 @@
#define DBGBUS_NAME_SDE		"sde"
#define DBGBUS_NAME_VBIF_RT	"vbif_rt"

/* offsets from sde_base address for the debug buses */
/* offsets from sde top address for the debug buses */
#define DBGBUS_SSPP0	0x188
#define DBGBUS_SSPP1	0x298
#define DBGBUS_DSPP	0x348
@@ -54,6 +55,9 @@
#define MMSS_VBIF_TEST_BUS_OUT_CTRL	0x210
#define MMSS_VBIF_TEST_BUS_OUT		0x230

/* print debug ranges in groups of 4 u32s */
#define REG_DUMP_ALIGN		16

/**
 * struct sde_dbg_reg_offset - tracking for start and end of region
 * @start: start offset
@@ -135,6 +139,7 @@ struct sde_dbg_debug_bus_common {
struct sde_dbg_sde_debug_bus {
	struct sde_dbg_debug_bus_common cmn;
	struct sde_debug_bus_entry *entries;
	u32 top_blk_off;
};

struct sde_dbg_vbif_debug_bus {
@@ -978,16 +983,17 @@ static inline void _sde_dbg_enable_power(int enable)
 * _sde_dump_reg - helper function for dumping rotator register set content
 * @dump_name: register set name
 * @reg_dump_flag: dumping flag controlling in-log/memory dump location
 * @base_addr: starting address of io region for calculating offsets to print
 * @addr: starting address offset for dumping
 * @len_bytes: range of the register set
 * @dump_mem: output buffer for memory dump location option
 * @from_isr: whether being called from isr context
 */
static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
		char __iomem *addr, size_t len_bytes, u32 **dump_mem,
		bool from_isr)
		char __iomem *base_addr, char __iomem *addr, size_t len_bytes,
		u32 **dump_mem, bool from_isr)
{
	u32 in_log, in_mem, len_align_16, len_bytes_aligned;
	u32 in_log, in_mem, len_align, len_padded;
	u32 *dump_addr = NULL;
	char __iomem *end_addr;
	int i;
@@ -998,28 +1004,33 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
	in_log = (reg_dump_flag & SDE_DBG_DUMP_IN_LOG);
	in_mem = (reg_dump_flag & SDE_DBG_DUMP_IN_MEM);

	pr_debug("reg_dump_flag=%d in_log=%d in_mem=%d\n",
		reg_dump_flag, in_log, in_mem);
	pr_debug("%s: reg_dump_flag=%d in_log=%d in_mem=%d\n",
		dump_name, reg_dump_flag, in_log, in_mem);

	if (!in_log && !in_mem)
		return;

	len_align_16 = (len_bytes + 15) / 16;
	len_bytes_aligned = len_align_16 * 16;
	if (in_log)
		dev_info(sde_dbg_base.dev, "%s: start_offset 0x%lx len 0x%zx\n",
				dump_name, addr - base_addr, len_bytes);

	len_align = (len_bytes + REG_DUMP_ALIGN - 1) / REG_DUMP_ALIGN;
	len_padded = len_align * REG_DUMP_ALIGN;
	end_addr = addr + len_bytes;

	if (in_mem) {
		if (dump_mem && !(*dump_mem)) {
			phys_addr_t phys = 0;
			*dump_mem = dma_alloc_coherent(sde_dbg_base.dev,
					len_bytes_aligned, &phys, GFP_KERNEL);
					len_padded, &phys, GFP_KERNEL);
		}

		if (dump_mem && *dump_mem) {
			dump_addr = *dump_mem;
			pr_info("%s: start_addr:0x%pK end_addr:0x%pK reg_addr=0x%pK\n",
				dump_name, dump_addr,
				dump_addr + len_bytes_aligned, addr);
			dev_info(sde_dbg_base.dev,
				"%s: start_addr:0x%pK len:0x%x reg_offset=0x%lx\n",
				dump_name, dump_addr, len_padded,
				addr - base_addr);
		} else {
			in_mem = 0;
			pr_err("dump_mem: kzalloc fails!\n");
@@ -1029,7 +1040,7 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
	if (!from_isr)
		_sde_dbg_enable_power(true);

	for (i = 0; i < len_align_16; i++) {
	for (i = 0; i < len_align; i++) {
		u32 x0, x4, x8, xc;

		x0 = (addr < end_addr) ? readl_relaxed(addr + 0x0) : 0;
@@ -1038,8 +1049,9 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
		xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + 0xc) : 0;

		if (in_log)
			pr_info("%pK : %08x %08x %08x %08x\n", addr, x0, x4, x8,
				xc);
			dev_info(sde_dbg_base.dev,
					"0x%lx : %08x %08x %08x %08x\n",
					addr - base_addr, x0, x4, x8, xc);

		if (dump_addr) {
			dump_addr[i * 4] = x0;
@@ -1048,7 +1060,7 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
			dump_addr[i * 4 + 3] = xc;
		}

		addr += 16;
		addr += REG_DUMP_ALIGN;
	}

	if (!from_isr)
@@ -1077,6 +1089,20 @@ static u32 _sde_dbg_get_dump_range(struct sde_dbg_reg_offset *range_node,
	return length;
}

static int _sde_dump_reg_range_cmp(void *priv, struct list_head *a,
		struct list_head *b)
{
	struct sde_dbg_reg_range *ar, *br;

	if (!a || !b)
		return 0;

	ar = container_of(a, struct sde_dbg_reg_range, head);
	br = container_of(b, struct sde_dbg_reg_range, head);

	return ar->offset.start - br->offset.start;
}

/**
 * _sde_dump_reg_by_ranges - dump ranges or full range of the register blk base
 * @dbg: register blk base structure
@@ -1094,10 +1120,13 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg,
		return;
	}

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

	/* If there is a list to dump the registers by ranges, use the ranges */
	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) {
			len = _sde_dbg_get_dump_range(&range_node->offset,
				dbg->max_offset);
@@ -1107,18 +1136,20 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg,
				addr, range_node->offset.start,
				range_node->offset.end);

			_sde_dump_reg((const char *)range_node->range_name,
				reg_dump_flag, addr, len, &range_node->reg_dump,
				false);
			_sde_dump_reg(range_node->range_name, reg_dump_flag,
					dbg->base, addr, len,
					&range_node->reg_dump, false);
		}
	} else {
		/* If there is no list to dump ranges, dump all registers */
		pr_info("Ranges not found, will dump full registers\n");
		pr_info("base:0x%pK len:0x%zx\n", dbg->base, dbg->max_offset);
		dev_info(sde_dbg_base.dev,
				"Ranges not found, will dump full registers\n");
		dev_info(sde_dbg_base.dev, "base:0x%pK len:0x%zx\n", dbg->base,
				dbg->max_offset);
		addr = dbg->base;
		len = dbg->max_offset;
		_sde_dump_reg((const char *)dbg->name, reg_dump_flag, addr,
			len, &dbg->reg_dump, false);
		_sde_dump_reg(dbg->name, reg_dump_flag, dbg->base, addr, len,
				&dbg->reg_dump, false);
	}
}

@@ -1198,7 +1229,7 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)
			reg_base_head)
		if (strlen(reg_base->name) &&
			!strcmp(reg_base->name, bus->cmn.name))
			mem_base = reg_base->base;
			mem_base = reg_base->base + bus->top_blk_off;

	if (!mem_base) {
		pr_err("unable to find mem_base for %s\n", bus->cmn.name);
@@ -1216,7 +1247,8 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)
	if (!in_log && !in_mem)
		return;

	pr_info("======== start %s dump =========\n", bus->cmn.name);
	dev_info(sde_dbg_base.dev, "======== start %s dump =========\n",
			bus->cmn.name);

	if (in_mem) {
		if (!(*dump_mem))
@@ -1225,8 +1257,9 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)

		if (*dump_mem) {
			dump_addr = *dump_mem;
			pr_info("%s: start_addr:0x%pK end_addr:0x%pK\n",
				__func__, dump_addr, dump_addr + list_size);
			dev_info(sde_dbg_base.dev,
				"%s: start_addr:0x%pK len:0x%x\n",
				__func__, dump_addr, list_size);
		} else {
			in_mem = false;
			pr_err("dump_mem: allocation fails\n");
@@ -1248,9 +1281,10 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)
		status = readl_relaxed(mem_base + offset);

		if (in_log)
			pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n",
				head->wr_addr, head->block_id, head->test_id,
				status);
			dev_info(sde_dbg_base.dev,
					"waddr=0x%x blk=%d tst=%d val=0x%x\n",
					head->wr_addr, head->block_id,
					head->test_id, status);

		if (dump_addr && in_mem) {
			dump_addr[i*4]     = head->wr_addr;
@@ -1265,7 +1299,8 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)
	}
	_sde_dbg_enable_power(false);

	pr_info("======== end %s dump =========\n", bus->cmn.name);
	dev_info(sde_dbg_base.dev, "======== end %s dump =========\n",
			bus->cmn.name);
}

static void _sde_dbg_dump_vbif_debug_bus_entry(
@@ -1295,7 +1330,8 @@ static void _sde_dbg_dump_vbif_debug_bus_entry(
				*dump_addr++ = val;
			}
			if (in_log)
				pr_err("testpoint:%x arb/xin id=%d index=%d val=0x%x\n",
				dev_info(sde_dbg_base.dev,
					"testpoint:%x arb/xin id=%d index=%d val=0x%x\n",
					head->block_bus_addr, i, j, val);
		}
	}
@@ -1334,7 +1370,8 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus)
	list_size = bus->cmn.entries_size;
	dump_mem = &bus->cmn.dumped_content;

	pr_info("======== start %s dump =========\n", bus->cmn.name);
	dev_info(sde_dbg_base.dev, "======== start %s dump =========\n",
			bus->cmn.name);

	if (!dump_mem || !dbg_bus || !bus_size || !list_size)
		return;
@@ -1361,8 +1398,9 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus)

		if (*dump_mem) {
			dump_addr = *dump_mem;
			pr_info("%s: start_addr:0x%pK end_addr:0x%pK\n",
				__func__, dump_addr, dump_addr + list_size);
			dev_info(sde_dbg_base.dev,
				"%s: start_addr:0x%pK len:0x%x\n",
				__func__, dump_addr, list_size);
		} else {
			in_mem = false;
			pr_err("dump_mem: allocation fails\n");
@@ -1393,7 +1431,8 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus)

	_sde_dbg_enable_power(false);

	pr_info("======== end %s dump =========\n", bus->cmn.name);
	dev_info(sde_dbg_base.dev, "======== end %s dump =========\n",
			bus->cmn.name);
}

/**
@@ -1995,6 +2034,21 @@ void sde_dbg_reg_register_dump_range(const char *base_name,
		return;
	}

	if (!range_name || strlen(range_name) == 0) {
		pr_err("%pS: bad range name, base_name %s, offset_start 0x%X, end 0x%X\n",
				__builtin_return_address(0), base_name,
				offset_start, offset_end);
		return;
	}

	if (offset_end - offset_start < REG_DUMP_ALIGN ||
			offset_start > offset_end) {
		pr_err("%pS: bad range, base_name %s, range_name %s, offset_start 0x%X, end 0x%X\n",
				__builtin_return_address(0), base_name,
				range_name, offset_start, offset_end);
		return;
	}

	range = kzalloc(sizeof(*range), GFP_KERNEL);
	if (!range)
		return;
@@ -2005,6 +2059,12 @@ void sde_dbg_reg_register_dump_range(const char *base_name,
	range->xin_id = xin_id;
	list_add_tail(&range->head, &reg_base->sub_range_list);

	pr_debug("%s start: 0x%X end: 0x%X\n", range->range_name,
	pr_debug("base %s, range %s, start 0x%X, end 0x%X\n",
			base_name, range->range_name,
			range->offset.start, range->offset.end);
}

void sde_dbg_set_sde_top_offset(u32 blk_off)
{
	sde_dbg_base.dbgbus_sde.top_blk_off = blk_off;
}
Loading