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

Commit f6c4e703 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: Add SSR minidump provision for subsystem ramdump"

parents 110dab42 ec6d1399
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