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

Commit ec6d1399 authored by Avaneesh Kumar Dwivedi's avatar Avaneesh Kumar Dwivedi
Browse files

soc: qcom: Add SSR minidump provision for subsystem ramdump



Minidump is concise and bare minimum dump to enable technology
teams to debug most of subsystem issues. This change adds required
driver code changes to provide support of subsystem minidump.

Increase PIL timeout to give MBA more time for encryption
and decryption for modem segments.

Change-Id: I1d04a9306ce507bc610777bc476197f26c1e18ac
Signed-off-by: default avatarAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>
parent 9a78128f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@ USB Diag Cookies:
Memory region used to store USB PID and serial numbers to be used by
bootloader in download mode.

SSR Minidump Offset
-------------------
-Compatible: "qcom,msm-imem-minidump"
-reg: start address and size of ssr imem region

Required properties:
-compatible: "qcom,msm-imem-diag-dload"
-reg: start address and size of USB Diag download mode region in imem
@@ -115,4 +120,9 @@ Example:
			compatible = "qcom,msm-imem-emergency_download_mode";
			reg = <0xfe0 12>;
		};

		ss_mdump@b88 {
			compatible = "qcom,msm-imem-minidump";
			reg = <0xb88 28>;
		};
	};
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ Optional properties:
		    wordline clamp, and compiler memory clamp during MSS restart.
- qcom,qdsp6v56-1-10: Boolean- Present if the qdsp version is v56 1.10
- qcom,override-acc-1: Override the default ACC settings with this value if present.
- qcom,minidump-id: Unique id for each subsystem

One child node to represent the MBA image may be specified, when the MBA image
needs to be loaded in a specifically carved out memory region.
+107 −1
Original line number Diff line number Diff line
@@ -55,7 +55,9 @@
#endif

#define PIL_NUM_DESC		10
#define NUM_OF_ENCRYPTED_KEY	3
static void __iomem *pil_info_base;
static void __iomem *pil_minidump_base;

/**
 * proxy_timeout - Override for proxy vote timeouts
@@ -77,6 +79,18 @@ struct pil_mdt {
	struct elf32_phdr phdr[];
};

/**
 * struct boot_minidump_smem_region - Representation of SMEM TOC
 * @region_name: Name of modem segment to be dumped
 * @region_base_address: Where segment start from
 * @region_size: Size of segment to be dumped
 */
struct boot_minidump_smem_region {
	char region_name[16];
	u64 region_base_address;
	u64 region_size;
};

/**
 * struct pil_seg - memory map representing one segment
 * @next: points to next seg mentor NULL if last segment
@@ -131,11 +145,67 @@ struct pil_priv {
	phys_addr_t region_end;
	void *region;
	struct pil_image_info __iomem *info;
	struct md_ssr_ss_info __iomem *minidump;
	int minidump_id;
	int id;
	int unvoted_flag;
	size_t region_size;
};

static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
{
	struct boot_minidump_smem_region __iomem *region_info;
	struct ramdump_segment *ramdump_segs, *s;
	struct pil_priv *priv = desc->priv;
	void __iomem *subsys_smem_base;
	void __iomem *offset;
	int ss_mdump_seg_cnt;
	int ret, i;

	memcpy(&offset, &priv->minidump, sizeof(priv->minidump));
	offset = offset + sizeof(priv->minidump->md_ss_smem_regions_baseptr);
	/* There are 3 encryption keys which also need to be dumped */
	ss_mdump_seg_cnt = readb_relaxed(offset) +
				NUM_OF_ENCRYPTED_KEY;

	subsys_smem_base = ioremap(__raw_readl(priv->minidump),
				   ss_mdump_seg_cnt * sizeof(*region_info));
	region_info =
		(struct boot_minidump_smem_region __iomem *)subsys_smem_base;
	ramdump_segs = kcalloc(ss_mdump_seg_cnt,
			       sizeof(*ramdump_segs), GFP_KERNEL);
	if (!ramdump_segs)
		return -ENOMEM;

	if (desc->subsys_vmid > 0)
		ret = pil_assign_mem_to_linux(desc, priv->region_start,
			(priv->region_end - priv->region_start));

	s = ramdump_segs;
	for (i = 0; i < ss_mdump_seg_cnt; i++) {
		memcpy(&offset, &region_info, sizeof(region_info));
		memcpy(&s->name, &region_info, sizeof(region_info));
		offset = offset + sizeof(region_info->region_name);
		s->address = __raw_readl(offset);
		offset = offset + sizeof(region_info->region_base_address);
		s->size = __raw_readl(offset);
		s++;
		region_info++;
	}
	ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt);
	kfree(ramdump_segs);
	if (ret)
		pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n",
			__func__, desc->name, ret);
	writel_relaxed(0, &priv->minidump->md_ss_smem_regions_baseptr);
	writeb_relaxed(1, &priv->minidump->md_ss_ssr_cause);

	if (desc->subsys_vmid > 0)
		ret = pil_assign_mem_to_subsys(desc, priv->region_start,
			(priv->region_end - priv->region_start));
	return ret;
}

/**
 * pil_do_ramdump() - Ramdump an image
 * @desc: descriptor from pil_desc_init()
@@ -151,6 +221,9 @@ int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev)
	int count = 0, ret;
	struct ramdump_segment *ramdump_segs, *s;

	if (priv->minidump && (__raw_readl(priv->minidump) > 0))
		return pil_do_minidump(desc, ramdump_dev);

	list_for_each_entry(seg, &priv->segs, list)
		count++;

@@ -1011,9 +1084,10 @@ bool is_timeout_disabled(void)
int pil_desc_init(struct pil_desc *desc)
{
	struct pil_priv *priv;
	int ret;
	void __iomem *addr;
	int ret, ss_imem_offset_mdump;
	char buf[sizeof(priv->info->name)];
	struct device_node *ofnode = desc->dev->of_node;

	if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
				"Invalid proxy voting. Ignoring\n"))
@@ -1036,6 +1110,22 @@ int pil_desc_init(struct pil_desc *desc)
		strlcpy(buf, desc->name, sizeof(buf));
		__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
	}
	if (of_property_read_u32(ofnode, "qcom,minidump-id",
		&priv->minidump_id))
		pr_debug("minidump-id not found for %s\n", desc->name);
	else {
		ss_imem_offset_mdump =
			sizeof(struct md_ssr_ss_info) * priv->minidump_id;
		if (pil_minidump_base) {
			/* Add 0x4 to get start of struct md_ssr_ss_info base
			 * from struct md_ssr_toc for any subsystem,
			 * struct md_ssr_ss_info is actually the pointer
			 * of ToC in smem for any subsystem.
			 */
			addr = pil_minidump_base + ss_imem_offset_mdump + 0x4;
			priv->minidump = (struct md_ssr_ss_info __iomem *)addr;
		}
	}

	ret = pil_parse_devicetree(desc);
	if (ret)
@@ -1144,6 +1234,20 @@ static int __init msm_pil_init(void)
	for (i = 0; i < resource_size(&res)/sizeof(u32); i++)
		writel_relaxed(0, pil_info_base + (i * sizeof(u32)));

	np = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-minidump");
	if (!np) {
		pr_warn("pil: failed to find qcom,msm-imem-minidump node\n");
		goto out;
	} else {
		pil_minidump_base = of_iomap(np, 0);
		if (!pil_minidump_base) {
			pr_err("unable to map pil minidump imem offset\n");
			goto out;
		}
	}
	for (i = 0; i < sizeof(struct md_ssr_toc)/sizeof(u32); i++)
		writel_relaxed(0, pil_minidump_base + (i * sizeof(u32)));
	writel_relaxed(1, pil_minidump_base);
out:
	return register_pm_notifier(&pil_pm_notifier);
}
@@ -1154,6 +1258,8 @@ static void __exit msm_pil_exit(void)
	unregister_pm_notifier(&pil_pm_notifier);
	if (pil_info_base)
		iounmap(pil_info_base);
	if (pil_minidump_base)
		iounmap(pil_minidump_base);
}
module_exit(msm_pil_exit);

+28 −0
Original line number Diff line number Diff line
@@ -71,6 +71,34 @@ struct pil_image_info {
	__le32 size;
} __attribute__((__packed__));

#define MAX_NUM_OF_SS 3

/**
 * struct md_ssr_ss_info - Info in imem about smem ToC
 * @md_ss_smem_regions_baseptr: Start physical address of SMEM TOC
 * @md_ss_num_of_regions: number of segments that need to be dumped
 * @md_ss_encryption_status: status of encryption of segments
 * @md_ss_ssr_cause: ssr cause enum
 */
struct md_ssr_ss_info {
	u32 md_ss_smem_regions_baseptr;
	u8 md_ss_num_of_regions;
	u8 md_ss_encryption_status;
	u8 md_ss_ssr_cause;
	u8 reserved;
};

/**
 * struct md_ssr_toc - Wrapper of struct md_ssr_ss_info
 * @md_ssr_toc_init: flag to indicate to MSS SW about imem init done
 * @md_ssr_ss: Instance of struct md_ssr_ss_info for a subsystem
 */
struct md_ssr_toc /* Shared IMEM ToC struct */
{
	u32 md_ssr_toc_init;
	struct md_ssr_ss_info	md_ssr_ss[MAX_NUM_OF_SS];
};

/**
 * struct pil_reset_ops - PIL operations
 * @init_image: prepare an image for authentication
+8 −1
Original line number Diff line number Diff line
@@ -80,6 +80,8 @@
#define MSS_PDC_OFFSET			8
#define MSS_PDC_MASK			BIT(MSS_PDC_OFFSET)

/* Timeout value for MBA boot when minidump is enabled */
#define MBA_ENCRYPTION_TIMEOUT	3000
enum scm_cmd {
	PAS_MEM_SETUP_CMD = 2,
};
@@ -298,7 +300,12 @@ static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv)
	struct device *dev = drv->desc.dev;
	int ret;
	u32 status;
	u64 val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000;
	u64 val;

	if (of_property_read_bool(dev->of_node, "qcom,minidump-id"))
		pbl_mba_boot_timeout_ms = MBA_ENCRYPTION_TIMEOUT;

	val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000;

	/* Wait for PBL completion. */
	ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
Loading