Commit 42123e81 authored by Kai Ye's avatar Kai Ye Committed by Herbert Xu
Browse files

crypto: hisilicon/hpre - support last word dumping



1. Add some debugging registers.
2. Add last word dumping function during hpre engine controller reset.

Signed-off-by: default avatarKai Ye <yekai13@huawei.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 8a88d091
Loading
Loading
Loading
Loading
+112 −20
Original line number Diff line number Diff line
@@ -36,6 +36,12 @@
#define HPRE_DATA_WUSER_CFG		0x301040
#define HPRE_INT_MASK			0x301400
#define HPRE_INT_STATUS			0x301800
#define HPRE_HAC_INT_MSK		0x301400
#define HPRE_HAC_RAS_CE_ENB		0x301410
#define HPRE_HAC_RAS_NFE_ENB		0x301414
#define HPRE_HAC_RAS_FE_ENB		0x301418
#define HPRE_HAC_INT_SET		0x301500
#define HPRE_RNG_TIMEOUT_NUM		0x301A34
#define HPRE_CORE_INT_ENABLE		0
#define HPRE_CORE_INT_DISABLE		GENMASK(21, 0)
#define HPRE_RDCHN_INI_ST		0x301a00
@@ -212,8 +218,6 @@ static const struct debugfs_reg32 hpre_com_dfx_regs[] = {
	{"READ_CLR_EN     ",  HPRE_CTRL_CNT_CLR_CE},
	{"AXQOS           ",  HPRE_VFG_AXQOS},
	{"AWUSR_CFG       ",  HPRE_AWUSR_FP_CFG},
	{"QM_ARUSR_MCFG1           ",  QM_ARUSER_M_CFG_1},
	{"QM_AWUSR_MCFG1           ",  QM_AWUSER_M_CFG_1},
	{"BD_ENDIAN       ",  HPRE_BD_ENDIAN},
	{"ECC_CHECK_CTRL  ",  HPRE_ECC_BYPASS},
	{"RAS_INT_WIDTH   ",  HPRE_RAS_WIDTH_CFG},
@@ -223,6 +227,12 @@ static const struct debugfs_reg32 hpre_com_dfx_regs[] = {
	{"DATA_ARUSER     ",  HPRE_DATA_RUSER_CFG},
	{"DATA_AWUSER     ",  HPRE_DATA_WUSER_CFG},
	{"INT_STATUS      ",  HPRE_INT_STATUS},
	{"INT_MASK        ",  HPRE_HAC_INT_MSK},
	{"RAS_CE_ENB      ",  HPRE_HAC_RAS_CE_ENB},
	{"RAS_NFE_ENB     ",  HPRE_HAC_RAS_NFE_ENB},
	{"RAS_FE_ENB      ",  HPRE_HAC_RAS_FE_ENB},
	{"INT_SET         ",  HPRE_HAC_INT_SET},
	{"RNG_TIMEOUT_NUM ",  HPRE_RNG_TIMEOUT_NUM},
};

static const char *hpre_dfx_files[HPRE_DFX_FILE_NUM] = {
@@ -1023,6 +1033,82 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
	return hisi_qm_init(qm);
}

static int hpre_show_last_regs_init(struct hisi_qm *qm)
{
	int cluster_dfx_regs_num =  ARRAY_SIZE(hpre_cluster_dfx_regs);
	int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs);
	u8 clusters_num = hpre_cluster_num(qm);
	struct qm_debug *debug = &qm->debug;
	void __iomem *io_base;
	int i, j, idx;

	debug->last_words = kcalloc(cluster_dfx_regs_num * clusters_num +
			com_dfx_regs_num, sizeof(unsigned int), GFP_KERNEL);
	if (!debug->last_words)
		return -ENOMEM;

	for (i = 0; i < com_dfx_regs_num; i++)
		debug->last_words[i] = readl_relaxed(qm->io_base +
						hpre_com_dfx_regs[i].offset);

	for (i = 0; i < clusters_num; i++) {
		io_base = qm->io_base + hpre_cluster_offsets[i];
		for (j = 0; j < cluster_dfx_regs_num; j++) {
			idx = com_dfx_regs_num + i * cluster_dfx_regs_num + j;
			debug->last_words[idx] = readl_relaxed(
				io_base + hpre_cluster_dfx_regs[j].offset);
		}
	}

	return 0;
}

static void hpre_show_last_regs_uninit(struct hisi_qm *qm)
{
	struct qm_debug *debug = &qm->debug;

	if (qm->fun_type == QM_HW_VF || !debug->last_words)
		return;

	kfree(debug->last_words);
	debug->last_words = NULL;
}

static void hpre_show_last_dfx_regs(struct hisi_qm *qm)
{
	int cluster_dfx_regs_num =  ARRAY_SIZE(hpre_cluster_dfx_regs);
	int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs);
	u8 clusters_num = hpre_cluster_num(qm);
	struct qm_debug *debug = &qm->debug;
	struct pci_dev *pdev = qm->pdev;
	void __iomem *io_base;
	int i, j, idx;
	u32 val;

	if (qm->fun_type == QM_HW_VF || !debug->last_words)
		return;

	/* dumps last word of the debugging registers during controller reset */
	for (i = 0; i < com_dfx_regs_num; i++) {
		val = readl_relaxed(qm->io_base + hpre_com_dfx_regs[i].offset);
		if (debug->last_words[i] != val)
			pci_info(pdev, "Common_core:%s \t= 0x%08x => 0x%08x\n",
			  hpre_com_dfx_regs[i].name, debug->last_words[i], val);
	}

	for (i = 0; i < clusters_num; i++) {
		io_base = qm->io_base + hpre_cluster_offsets[i];
		for (j = 0; j <  cluster_dfx_regs_num; j++) {
			val = readl_relaxed(io_base +
					     hpre_cluster_dfx_regs[j].offset);
			idx = com_dfx_regs_num + i * cluster_dfx_regs_num + j;
			if (debug->last_words[idx] != val)
				pci_info(pdev, "cluster-%d:%s \t= 0x%08x => 0x%08x\n",
				i, hpre_cluster_dfx_regs[j].name, debug->last_words[idx], val);
		}
	}
}

static void hpre_log_hw_error(struct hisi_qm *qm, u32 err_sts)
{
	const struct hpre_hw_error *err = hpre_hw_errors;
@@ -1081,6 +1167,7 @@ static const struct hisi_qm_err_ini hpre_err_ini = {
	.open_axi_master_ooo	= hpre_open_axi_master_ooo,
	.open_sva_prefetch	= hpre_open_sva_prefetch,
	.close_sva_prefetch	= hpre_close_sva_prefetch,
	.show_last_dfx_regs	= hpre_show_last_dfx_regs,
	.err_info_init		= hpre_err_info_init,
};

@@ -1098,8 +1185,11 @@ static int hpre_pf_probe_init(struct hpre *hpre)
	qm->err_ini = &hpre_err_ini;
	qm->err_ini->err_info_init(qm);
	hisi_qm_dev_err_init(qm);
	ret = hpre_show_last_regs_init(qm);
	if (ret)
		pci_err(qm->pdev, "Failed to init last word regs!\n");

	return 0;
	return ret;
}

static int hpre_probe_init(struct hpre *hpre)
@@ -1185,6 +1275,7 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	hisi_qm_stop(qm, QM_NORMAL);

err_with_err_init:
	hpre_show_last_regs_uninit(qm);
	hisi_qm_dev_err_uninit(qm);

err_with_qm_init:
@@ -1215,6 +1306,7 @@ static void hpre_remove(struct pci_dev *pdev)
	if (qm->fun_type == QM_HW_PF) {
		hpre_cnt_regs_clear(qm);
		qm->debug.curr_qm_qp_num = 0;
		hpre_show_last_regs_uninit(qm);
		hisi_qm_dev_err_uninit(qm);
	}