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

Commit 0fdb29e6 authored by Dhaval Patel's avatar Dhaval Patel
Browse files

msm: mdss: register smmu context fault handler



Smmu context fault handler provides the fault iova
information but does not provide any information about
xin client. This patch registers the context fault
handler in MDSS software to get the vmid/xin client
information. It also dumps the registers for source
associated with respective vmid client.

Change-Id: I2a833a4b5e81e36f4d7af23a3968c9755424b7a7
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 0b20839e
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -393,6 +393,10 @@ Optional properties:
				Note that each tag matches with one of the
				regs-dump entries in the same order as they
				are defined.
- qcom,regs-dump-xin-id-mdp:	Array of VBIF clients ids (xins) corresponding
				to mdp block. Xin id property is not valid for mdp
				internal blocks like ctl, lm, dspp. It should set
				to 0xff for such blocks.

Fudge Factors:			Fudge factors are used to boost demand for
				resources like bus bandswidth, clk rate etc. to
@@ -618,6 +622,8 @@ Subnode properties:
			"qcom,smmu_arm_mdp_sec"	- arm smmu context bank device for
						secure mdp domain.
- gdsc-mmagic-mdss-supply: Phandle for mmagic mdss supply regulator device node.
- reg :			offset and length of the register set for the device.
- reg-names :		names to refer to register sets related to this device
- clocks:		List of Phandles for clock device nodes
			needed by the device.
- clock-names:		List of clock names needed by the device.
@@ -640,6 +646,8 @@ Example:
		interrupts = <0 72 0>;
		interrupt-controller;
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		vdd-supply = <&gdsc_mdss>;
		batfet-supply = <&pm8941_chg_batif>;
		vdd-cx-supply = <&pm8841_s2_corner>;
@@ -779,6 +787,7 @@ Example:
		qcom,mdss-prefill-fbc-lines = <2>;
		qcom,mdss-idle-power-collapse-enabled;

		qcom,regs-dump-xin-id-mdp = <0xff 0xff 0xff 0xff 0x0 0x0>;
		mdss_fb0: qcom,mdss_fb_primary {
			cell-index = <0>;
			compatible = "qcom,mdss-fb";
@@ -826,6 +835,8 @@ Example:
		smmu_mdp_sec: qcom,smmu_mdp_sec_cb {
			compatible = "qcom,smmu_mdp_sec";
			iommus = <&mdp_smmu 1>;
			reg = <0xd09000 0x000d00>,
			reg-names = "mmu_cb";
			gdsc-mmagic-mdss-supply = <&gdsc_mmagic_mdss>;
			clocks = <&clock_mmss clk_smmu_mdp_ahb_clk>,
				<&clock_mmss clk_smmu_mdp_axi_clk>;
+1 −0
Original line number Diff line number Diff line
@@ -200,6 +200,7 @@ struct mdss_smmu_client {
	struct reg_bus_client *reg_bus_clt;
	bool domain_attached;
	bool handoff_pending;
	char __iomem *mmu_base;
};

struct mdss_mdp_qseed3_lut_tbl {
+41 −16
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#define PANEL_CMD_MIN_TX_COUNT 2
#define PANEL_DATA_NODE_LEN 80

#define INVALID_XIN_ID     0xFF

static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00};

static int panel_debug_base_open(struct inode *inode, struct file *file)
@@ -630,12 +632,37 @@ error:
}

static int parse_dt_xlog_dump_list(const u32 *arr, int count,
	struct list_head *xlog_dump_list, int total_names,
	struct platform_device *pdev, const char *name_prop)
	struct list_head *xlog_dump_list, struct platform_device *pdev,
	const char *name_prop, const char *xin_prop)
{
	struct range_dump_node *xlog_node;
	u32 len;
	int i;
	int i, total_names, total_xin_ids, rc;
	u32 *offsets = NULL;

	/* Get the property with the name of the ranges */
	total_names = of_property_count_strings(pdev->dev.of_node,
		name_prop);
	if (total_names < 0) {
		pr_warn("dump names not found. rc=%d\n", total_names);
		total_names = 0;
	}

	of_find_property(pdev->dev.of_node, xin_prop, &total_xin_ids);
	if (total_xin_ids > 0) {
		total_xin_ids /= sizeof(u32);
		offsets = kcalloc(total_xin_ids, sizeof(u32), GFP_KERNEL);
		if (offsets) {
			rc = of_property_read_u32_array(pdev->dev.of_node,
				xin_prop, offsets, total_xin_ids);
			if (rc)
				total_xin_ids = 0;
		} else {
			total_xin_ids = 0;
		}
	} else {
		total_xin_ids = 0;
	}

	for (i = 0, len = count * 2; i < len; i += 2) {
		xlog_node = kzalloc(sizeof(*xlog_node), GFP_KERNEL);
@@ -644,34 +671,33 @@ static int parse_dt_xlog_dump_list(const u32 *arr, int count,

		xlog_node->offset.start = be32_to_cpu(arr[i]);
		xlog_node->offset.end = be32_to_cpu(arr[i + 1]);

		parse_dump_range_name(pdev->dev.of_node, total_names, i/2,
			xlog_node->range_name,
			ARRAY_SIZE(xlog_node->range_name), name_prop);

		if ((i / 2) < total_xin_ids)
			xlog_node->xin_id = offsets[i / 2];
		else
			xlog_node->xin_id = INVALID_XIN_ID;

		list_add_tail(&xlog_node->head, xlog_dump_list);
	}

	kfree(offsets);
	return 0;
}

void mdss_debug_register_dump_range(struct platform_device *pdev,
	struct mdss_debug_base *blk_base, const char *ranges_prop,
	const char *name_prop)
	const char *name_prop, const char *xin_prop)
{
	int total_dump_names, mdp_len;
	int mdp_len;
	const u32 *mdp_arr;

	if (!blk_base || !ranges_prop || !name_prop)
		return;

	/* Get the property with the name of the ranges */
	total_dump_names = of_property_count_strings(pdev->dev.of_node,
		name_prop);
	if (total_dump_names < 0) {
		pr_warn("dump names not found. rc=%d\n", total_dump_names);
		total_dump_names = 0;
	}

	mdp_arr = of_get_property(pdev->dev.of_node, ranges_prop,
			&mdp_len);
	if (!mdp_arr) {
@@ -680,9 +706,8 @@ void mdss_debug_register_dump_range(struct platform_device *pdev,
	} else {
		/* 2 is the number of entries per row to calculate the rows */
		mdp_len /= 2 * sizeof(u32);
		parse_dt_xlog_dump_list(mdp_arr, mdp_len,
			&blk_base->dump_list, total_dump_names, pdev,
				name_prop);
		parse_dt_xlog_dump_list(mdp_arr, mdp_len, &blk_base->dump_list,
			pdev, name_prop, xin_prop);
	}
}

+13 −2
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ struct range_dump_node {
	u32 *reg_dump; /* address for the mem dump */
	char range_name[40]; /* name of this range */
	struct dump_offset offset; /* range to dump */
	uint32_t xin_id; /* client xin id */
};

#define DEFINE_MDSS_DEBUGFS_SEQ_FOPS(__prefix)				\
@@ -143,7 +144,7 @@ int mdss_debug_register_base(const char *name, void __iomem *base,
	size_t max_offset, struct mdss_debug_base **dbg_blk);
void mdss_debug_register_dump_range(struct platform_device *pdev,
	struct mdss_debug_base *blk_base, const char *ranges_prop,
	const char *name_prop);
	const char *name_prop, const char *xin_prop);
int panel_debug_register_base(const char *name, void __iomem *base,
				    size_t max_offset);
int mdss_misr_set(struct mdss_data_type *mdata,
@@ -162,8 +163,13 @@ void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id,
int mdss_create_xlog_debug(struct mdss_debug_data *mdd);
void mdss_xlog(const char *name, int line, int flag, ...);
void mdss_xlog_tout_handler_default(bool queue, const char *name, ...);
u32 get_dump_range(struct dump_offset *range_node, size_t max_offset);
void mdss_dump_reg(const char *dump_name, u32 reg_dump_flag, char *addr,
	int len, u32 **dump_mem, bool from_isr);
void mdss_mdp_debug_mid(u32 mid);
#else
struct mdss_debug_base;
struct dump_offset;

static inline int mdss_debugfs_init(struct mdss_data_type *mdata) { return 0; }
static inline int mdss_debugfs_remove(struct mdss_data_type *mdata)
@@ -174,7 +180,7 @@ static inline int mdss_debug_register_base(const char *name, void __iomem *base,
	size_t max_offset, struct mdss_debug_base **dbg_blk) { return 0; }
static inline void mdss_debug_register_dump_range(struct platform_device *pdev,
	struct mdss_debug_base *blk_base, const char *ranges_prop,
	const char *name_prop) { }
	const char *name_prop, const char *xin_prop) { }
static inline int panel_debug_register_base(const char *name,
					void __iomem *base,
					size_t max_offset)
@@ -203,6 +209,11 @@ static inline void mdss_xlog(const char *name, int line, int flag, ...) { }
static inline void mdss_dsi_debug_check_te(struct mdss_panel_data *pdata) { }
static inline void mdss_xlog_tout_handler_default(bool queue,
	const char *name, ...) { }
u32 get_dump_range(struct dump_offset *range_node, size_t max_offset)
	{ return 0; }
void mdss_dump_reg(const char *dump_name, u32 reg_dump_flag, char *addr,
	int len, u32 **dump_mem, bool from_isr) { }
void mdss_mdp_debug_mid(u32 mid) { }
#endif

int mdss_dump_misr_data(char **buf, u32 size);
+12 −7
Original line number Diff line number Diff line
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -405,8 +405,8 @@ static void mdss_dump_vbif_debug_bus(u32 bus_dump_flag,
	pr_info("========End VBIF Debug bus=========\n");
}

static void mdss_dump_reg(const char *dump_name, u32 reg_dump_flag,
	char *addr, int len, u32 **dump_mem)
void mdss_dump_reg(const char *dump_name, u32 reg_dump_flag, char *addr,
	int len, u32 **dump_mem, bool from_isr)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	bool in_log, in_mem;
@@ -440,7 +440,9 @@ static void mdss_dump_reg(const char *dump_name, u32 reg_dump_flag,
		}
	}

	if (!from_isr)
		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);

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

@@ -462,6 +464,8 @@ static void mdss_dump_reg(const char *dump_name, u32 reg_dump_flag,

		addr += 16;
	}

	if (!from_isr)
		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
}

@@ -491,7 +495,8 @@ static void mdss_dump_reg_by_ranges(struct mdss_debug_base *dbg,
				addr, xlog_node->offset.start,
				xlog_node->offset.end);
			mdss_dump_reg((const char *)xlog_node->range_name,
				reg_dump_flag, addr, len, &xlog_node->reg_dump);
				reg_dump_flag, addr, len, &xlog_node->reg_dump,
				false);
		}
	} else {
		/* If there is no list to dump ranges, dump all registers */
@@ -500,7 +505,7 @@ static void mdss_dump_reg_by_ranges(struct mdss_debug_base *dbg,
		addr = dbg->base;
		len = dbg->max_offset;
		mdss_dump_reg((const char *)dbg->name, reg_dump_flag, addr,
			len, &dbg->reg_dump);
			len, &dbg->reg_dump, false);
	}
}

Loading