162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2022 HiSilicon Limited. */
362306a36Sopenharmony_ci#include <linux/hisi_acc_qm.h>
462306a36Sopenharmony_ci#include "qm_common.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#define QM_DFX_BASE			0x0100000
762306a36Sopenharmony_ci#define QM_DFX_STATE1			0x0104000
862306a36Sopenharmony_ci#define QM_DFX_STATE2			0x01040C8
962306a36Sopenharmony_ci#define QM_DFX_COMMON			0x0000
1062306a36Sopenharmony_ci#define QM_DFX_BASE_LEN			0x5A
1162306a36Sopenharmony_ci#define QM_DFX_STATE1_LEN		0x2E
1262306a36Sopenharmony_ci#define QM_DFX_STATE2_LEN		0x11
1362306a36Sopenharmony_ci#define QM_DFX_COMMON_LEN		0xC3
1462306a36Sopenharmony_ci#define QM_DFX_REGS_LEN			4UL
1562306a36Sopenharmony_ci#define QM_DBG_TMP_BUF_LEN		22
1662306a36Sopenharmony_ci#define CURRENT_FUN_MASK		GENMASK(5, 0)
1762306a36Sopenharmony_ci#define CURRENT_Q_MASK			GENMASK(31, 16)
1862306a36Sopenharmony_ci#define QM_SQE_ADDR_MASK		GENMASK(7, 0)
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define QM_DFX_MB_CNT_VF		0x104010
2162306a36Sopenharmony_ci#define QM_DFX_DB_CNT_VF		0x104020
2262306a36Sopenharmony_ci#define QM_DFX_SQE_CNT_VF_SQN		0x104030
2362306a36Sopenharmony_ci#define QM_DFX_CQE_CNT_VF_CQN		0x104040
2462306a36Sopenharmony_ci#define QM_DFX_QN_SHIFT			16
2562306a36Sopenharmony_ci#define QM_DFX_CNT_CLR_CE		0x100118
2662306a36Sopenharmony_ci#define QM_DBG_WRITE_LEN		1024
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic const char * const qm_debug_file_name[] = {
2962306a36Sopenharmony_ci	[CURRENT_QM]   = "current_qm",
3062306a36Sopenharmony_ci	[CURRENT_Q]    = "current_q",
3162306a36Sopenharmony_ci	[CLEAR_ENABLE] = "clear_enable",
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistruct qm_dfx_item {
3562306a36Sopenharmony_ci	const char *name;
3662306a36Sopenharmony_ci	u32 offset;
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistruct qm_cmd_dump_item {
4062306a36Sopenharmony_ci	const char *cmd;
4162306a36Sopenharmony_ci	char *info_name;
4262306a36Sopenharmony_ci	int (*dump_fn)(struct hisi_qm *qm, char *cmd, char *info_name);
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic struct qm_dfx_item qm_dfx_files[] = {
4662306a36Sopenharmony_ci	{"err_irq", offsetof(struct qm_dfx, err_irq_cnt)},
4762306a36Sopenharmony_ci	{"aeq_irq", offsetof(struct qm_dfx, aeq_irq_cnt)},
4862306a36Sopenharmony_ci	{"abnormal_irq", offsetof(struct qm_dfx, abnormal_irq_cnt)},
4962306a36Sopenharmony_ci	{"create_qp_err", offsetof(struct qm_dfx, create_qp_err_cnt)},
5062306a36Sopenharmony_ci	{"mb_err", offsetof(struct qm_dfx, mb_err_cnt)},
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define CNT_CYC_REGS_NUM		10
5462306a36Sopenharmony_cistatic const struct debugfs_reg32 qm_dfx_regs[] = {
5562306a36Sopenharmony_ci	/* XXX_CNT are reading clear register */
5662306a36Sopenharmony_ci	{"QM_ECC_1BIT_CNT               ",  0x104000ull},
5762306a36Sopenharmony_ci	{"QM_ECC_MBIT_CNT               ",  0x104008ull},
5862306a36Sopenharmony_ci	{"QM_DFX_MB_CNT                 ",  0x104018ull},
5962306a36Sopenharmony_ci	{"QM_DFX_DB_CNT                 ",  0x104028ull},
6062306a36Sopenharmony_ci	{"QM_DFX_SQE_CNT                ",  0x104038ull},
6162306a36Sopenharmony_ci	{"QM_DFX_CQE_CNT                ",  0x104048ull},
6262306a36Sopenharmony_ci	{"QM_DFX_SEND_SQE_TO_ACC_CNT    ",  0x104050ull},
6362306a36Sopenharmony_ci	{"QM_DFX_WB_SQE_FROM_ACC_CNT    ",  0x104058ull},
6462306a36Sopenharmony_ci	{"QM_DFX_ACC_FINISH_CNT         ",  0x104060ull},
6562306a36Sopenharmony_ci	{"QM_DFX_CQE_ERR_CNT            ",  0x1040b4ull},
6662306a36Sopenharmony_ci	{"QM_DFX_FUNS_ACTIVE_ST         ",  0x200ull},
6762306a36Sopenharmony_ci	{"QM_ECC_1BIT_INF               ",  0x104004ull},
6862306a36Sopenharmony_ci	{"QM_ECC_MBIT_INF               ",  0x10400cull},
6962306a36Sopenharmony_ci	{"QM_DFX_ACC_RDY_VLD0           ",  0x1040a0ull},
7062306a36Sopenharmony_ci	{"QM_DFX_ACC_RDY_VLD1           ",  0x1040a4ull},
7162306a36Sopenharmony_ci	{"QM_DFX_AXI_RDY_VLD            ",  0x1040a8ull},
7262306a36Sopenharmony_ci	{"QM_DFX_FF_ST0                 ",  0x1040c8ull},
7362306a36Sopenharmony_ci	{"QM_DFX_FF_ST1                 ",  0x1040ccull},
7462306a36Sopenharmony_ci	{"QM_DFX_FF_ST2                 ",  0x1040d0ull},
7562306a36Sopenharmony_ci	{"QM_DFX_FF_ST3                 ",  0x1040d4ull},
7662306a36Sopenharmony_ci	{"QM_DFX_FF_ST4                 ",  0x1040d8ull},
7762306a36Sopenharmony_ci	{"QM_DFX_FF_ST5                 ",  0x1040dcull},
7862306a36Sopenharmony_ci	{"QM_DFX_FF_ST6                 ",  0x1040e0ull},
7962306a36Sopenharmony_ci	{"QM_IN_IDLE_ST                 ",  0x1040e4ull},
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic const struct debugfs_reg32 qm_vf_dfx_regs[] = {
8362306a36Sopenharmony_ci	{"QM_DFX_FUNS_ACTIVE_ST         ",  0x200ull},
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/* define the QM's dfx regs region and region length */
8762306a36Sopenharmony_cistatic struct dfx_diff_registers qm_diff_regs[] = {
8862306a36Sopenharmony_ci	{
8962306a36Sopenharmony_ci		.reg_offset = QM_DFX_BASE,
9062306a36Sopenharmony_ci		.reg_len = QM_DFX_BASE_LEN,
9162306a36Sopenharmony_ci	}, {
9262306a36Sopenharmony_ci		.reg_offset = QM_DFX_STATE1,
9362306a36Sopenharmony_ci		.reg_len = QM_DFX_STATE1_LEN,
9462306a36Sopenharmony_ci	}, {
9562306a36Sopenharmony_ci		.reg_offset = QM_DFX_STATE2,
9662306a36Sopenharmony_ci		.reg_len = QM_DFX_STATE2_LEN,
9762306a36Sopenharmony_ci	}, {
9862306a36Sopenharmony_ci		.reg_offset = QM_DFX_COMMON,
9962306a36Sopenharmony_ci		.reg_len = QM_DFX_COMMON_LEN,
10062306a36Sopenharmony_ci	},
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic struct hisi_qm *file_to_qm(struct debugfs_file *file)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	struct qm_debug *debug = file->debug;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	return container_of(debug, struct hisi_qm, debug);
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic ssize_t qm_cmd_read(struct file *filp, char __user *buffer,
11162306a36Sopenharmony_ci			   size_t count, loff_t *pos)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	char buf[QM_DBG_READ_LEN];
11462306a36Sopenharmony_ci	int len;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	len = scnprintf(buf, QM_DBG_READ_LEN, "%s\n",
11762306a36Sopenharmony_ci			"Please echo help to cmd to get help information");
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return simple_read_from_buffer(buffer, count, pos, buf, len);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic void dump_show(struct hisi_qm *qm, void *info,
12362306a36Sopenharmony_ci		     unsigned int info_size, char *info_name)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
12662306a36Sopenharmony_ci	u8 *info_curr = info;
12762306a36Sopenharmony_ci	u32 i;
12862306a36Sopenharmony_ci#define BYTE_PER_DW	4
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	dev_info(dev, "%s DUMP\n", info_name);
13162306a36Sopenharmony_ci	for (i = 0; i < info_size; i += BYTE_PER_DW, info_curr += BYTE_PER_DW) {
13262306a36Sopenharmony_ci		pr_info("DW%u: %02X%02X %02X%02X\n", i / BYTE_PER_DW,
13362306a36Sopenharmony_ci			*(info_curr + 3), *(info_curr + 2), *(info_curr + 1), *(info_curr));
13462306a36Sopenharmony_ci	}
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
14062306a36Sopenharmony_ci	struct qm_sqc *sqc, *sqc_curr;
14162306a36Sopenharmony_ci	dma_addr_t sqc_dma;
14262306a36Sopenharmony_ci	u32 qp_id;
14362306a36Sopenharmony_ci	int ret;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (!s)
14662306a36Sopenharmony_ci		return -EINVAL;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	ret = kstrtou32(s, 0, &qp_id);
14962306a36Sopenharmony_ci	if (ret || qp_id >= qm->qp_num) {
15062306a36Sopenharmony_ci		dev_err(dev, "Please input qp num (0-%u)", qm->qp_num - 1);
15162306a36Sopenharmony_ci		return -EINVAL;
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	sqc = hisi_qm_ctx_alloc(qm, sizeof(*sqc), &sqc_dma);
15562306a36Sopenharmony_ci	if (IS_ERR(sqc))
15662306a36Sopenharmony_ci		return PTR_ERR(sqc);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	ret = hisi_qm_mb(qm, QM_MB_CMD_SQC, sqc_dma, qp_id, 1);
15962306a36Sopenharmony_ci	if (ret) {
16062306a36Sopenharmony_ci		down_read(&qm->qps_lock);
16162306a36Sopenharmony_ci		if (qm->sqc) {
16262306a36Sopenharmony_ci			sqc_curr = qm->sqc + qp_id;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci			dump_show(qm, sqc_curr, sizeof(*sqc), "SOFT SQC");
16562306a36Sopenharmony_ci		}
16662306a36Sopenharmony_ci		up_read(&qm->qps_lock);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		goto free_ctx;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	dump_show(qm, sqc, sizeof(*sqc), name);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cifree_ctx:
17462306a36Sopenharmony_ci	hisi_qm_ctx_free(qm, sizeof(*sqc), sqc, &sqc_dma);
17562306a36Sopenharmony_ci	return 0;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
18162306a36Sopenharmony_ci	struct qm_cqc *cqc, *cqc_curr;
18262306a36Sopenharmony_ci	dma_addr_t cqc_dma;
18362306a36Sopenharmony_ci	u32 qp_id;
18462306a36Sopenharmony_ci	int ret;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	if (!s)
18762306a36Sopenharmony_ci		return -EINVAL;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	ret = kstrtou32(s, 0, &qp_id);
19062306a36Sopenharmony_ci	if (ret || qp_id >= qm->qp_num) {
19162306a36Sopenharmony_ci		dev_err(dev, "Please input qp num (0-%u)", qm->qp_num - 1);
19262306a36Sopenharmony_ci		return -EINVAL;
19362306a36Sopenharmony_ci	}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	cqc = hisi_qm_ctx_alloc(qm, sizeof(*cqc), &cqc_dma);
19662306a36Sopenharmony_ci	if (IS_ERR(cqc))
19762306a36Sopenharmony_ci		return PTR_ERR(cqc);
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	ret = hisi_qm_mb(qm, QM_MB_CMD_CQC, cqc_dma, qp_id, 1);
20062306a36Sopenharmony_ci	if (ret) {
20162306a36Sopenharmony_ci		down_read(&qm->qps_lock);
20262306a36Sopenharmony_ci		if (qm->cqc) {
20362306a36Sopenharmony_ci			cqc_curr = qm->cqc + qp_id;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci			dump_show(qm, cqc_curr, sizeof(*cqc), "SOFT CQC");
20662306a36Sopenharmony_ci		}
20762306a36Sopenharmony_ci		up_read(&qm->qps_lock);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		goto free_ctx;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	dump_show(qm, cqc, sizeof(*cqc), name);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cifree_ctx:
21562306a36Sopenharmony_ci	hisi_qm_ctx_free(qm, sizeof(*cqc), cqc, &cqc_dma);
21662306a36Sopenharmony_ci	return 0;
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic int qm_eqc_aeqc_dump(struct hisi_qm *qm, char *s, char *name)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
22262306a36Sopenharmony_ci	dma_addr_t xeqc_dma;
22362306a36Sopenharmony_ci	size_t size;
22462306a36Sopenharmony_ci	void *xeqc;
22562306a36Sopenharmony_ci	int ret;
22662306a36Sopenharmony_ci	u8 cmd;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	if (strsep(&s, " ")) {
22962306a36Sopenharmony_ci		dev_err(dev, "Please do not input extra characters!\n");
23062306a36Sopenharmony_ci		return -EINVAL;
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (!strcmp(name, "EQC")) {
23462306a36Sopenharmony_ci		cmd = QM_MB_CMD_EQC;
23562306a36Sopenharmony_ci		size = sizeof(struct qm_eqc);
23662306a36Sopenharmony_ci	} else {
23762306a36Sopenharmony_ci		cmd = QM_MB_CMD_AEQC;
23862306a36Sopenharmony_ci		size = sizeof(struct qm_aeqc);
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	xeqc = hisi_qm_ctx_alloc(qm, size, &xeqc_dma);
24262306a36Sopenharmony_ci	if (IS_ERR(xeqc))
24362306a36Sopenharmony_ci		return PTR_ERR(xeqc);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	ret = hisi_qm_mb(qm, cmd, xeqc_dma, 0, 1);
24662306a36Sopenharmony_ci	if (ret)
24762306a36Sopenharmony_ci		goto err_free_ctx;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	dump_show(qm, xeqc, size, name);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cierr_free_ctx:
25262306a36Sopenharmony_ci	hisi_qm_ctx_free(qm, size, xeqc, &xeqc_dma);
25362306a36Sopenharmony_ci	return ret;
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic int q_dump_param_parse(struct hisi_qm *qm, char *s,
25762306a36Sopenharmony_ci			      u32 *e_id, u32 *q_id, u16 q_depth)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
26062306a36Sopenharmony_ci	unsigned int qp_num = qm->qp_num;
26162306a36Sopenharmony_ci	char *presult;
26262306a36Sopenharmony_ci	int ret;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	presult = strsep(&s, " ");
26562306a36Sopenharmony_ci	if (!presult) {
26662306a36Sopenharmony_ci		dev_err(dev, "Please input qp number!\n");
26762306a36Sopenharmony_ci		return -EINVAL;
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	ret = kstrtou32(presult, 0, q_id);
27162306a36Sopenharmony_ci	if (ret || *q_id >= qp_num) {
27262306a36Sopenharmony_ci		dev_err(dev, "Please input qp num (0-%u)", qp_num - 1);
27362306a36Sopenharmony_ci		return -EINVAL;
27462306a36Sopenharmony_ci	}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	presult = strsep(&s, " ");
27762306a36Sopenharmony_ci	if (!presult) {
27862306a36Sopenharmony_ci		dev_err(dev, "Please input sqe number!\n");
27962306a36Sopenharmony_ci		return -EINVAL;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	ret = kstrtou32(presult, 0, e_id);
28362306a36Sopenharmony_ci	if (ret || *e_id >= q_depth) {
28462306a36Sopenharmony_ci		dev_err(dev, "Please input sqe num (0-%u)", q_depth - 1);
28562306a36Sopenharmony_ci		return -EINVAL;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	if (strsep(&s, " ")) {
28962306a36Sopenharmony_ci		dev_err(dev, "Please do not input extra characters!\n");
29062306a36Sopenharmony_ci		return -EINVAL;
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	return 0;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic int qm_sq_dump(struct hisi_qm *qm, char *s, char *name)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	u16 sq_depth = qm->qp_array->cq_depth;
29962306a36Sopenharmony_ci	void *sqe, *sqe_curr;
30062306a36Sopenharmony_ci	struct hisi_qp *qp;
30162306a36Sopenharmony_ci	u32 qp_id, sqe_id;
30262306a36Sopenharmony_ci	int ret;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	ret = q_dump_param_parse(qm, s, &sqe_id, &qp_id, sq_depth);
30562306a36Sopenharmony_ci	if (ret)
30662306a36Sopenharmony_ci		return ret;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	sqe = kzalloc(qm->sqe_size * sq_depth, GFP_KERNEL);
30962306a36Sopenharmony_ci	if (!sqe)
31062306a36Sopenharmony_ci		return -ENOMEM;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	qp = &qm->qp_array[qp_id];
31362306a36Sopenharmony_ci	memcpy(sqe, qp->sqe, qm->sqe_size * sq_depth);
31462306a36Sopenharmony_ci	sqe_curr = sqe + (u32)(sqe_id * qm->sqe_size);
31562306a36Sopenharmony_ci	memset(sqe_curr + qm->debug.sqe_mask_offset, QM_SQE_ADDR_MASK,
31662306a36Sopenharmony_ci	       qm->debug.sqe_mask_len);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	dump_show(qm, sqe_curr, qm->sqe_size, name);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	kfree(sqe);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	return 0;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic int qm_cq_dump(struct hisi_qm *qm, char *s, char *name)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	struct qm_cqe *cqe_curr;
32862306a36Sopenharmony_ci	struct hisi_qp *qp;
32962306a36Sopenharmony_ci	u32 qp_id, cqe_id;
33062306a36Sopenharmony_ci	int ret;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	ret = q_dump_param_parse(qm, s, &cqe_id, &qp_id, qm->qp_array->cq_depth);
33362306a36Sopenharmony_ci	if (ret)
33462306a36Sopenharmony_ci		return ret;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	qp = &qm->qp_array[qp_id];
33762306a36Sopenharmony_ci	cqe_curr = qp->cqe + cqe_id;
33862306a36Sopenharmony_ci	dump_show(qm, cqe_curr, sizeof(struct qm_cqe), name);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return 0;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic int qm_eq_aeq_dump(struct hisi_qm *qm, char *s, char *name)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
34662306a36Sopenharmony_ci	u16 xeq_depth;
34762306a36Sopenharmony_ci	size_t size;
34862306a36Sopenharmony_ci	void *xeqe;
34962306a36Sopenharmony_ci	u32 xeqe_id;
35062306a36Sopenharmony_ci	int ret;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (!s)
35362306a36Sopenharmony_ci		return -EINVAL;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	ret = kstrtou32(s, 0, &xeqe_id);
35662306a36Sopenharmony_ci	if (ret)
35762306a36Sopenharmony_ci		return -EINVAL;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	if (!strcmp(name, "EQE")) {
36062306a36Sopenharmony_ci		xeq_depth = qm->eq_depth;
36162306a36Sopenharmony_ci		size = sizeof(struct qm_eqe);
36262306a36Sopenharmony_ci	} else {
36362306a36Sopenharmony_ci		xeq_depth = qm->aeq_depth;
36462306a36Sopenharmony_ci		size = sizeof(struct qm_aeqe);
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	if (xeqe_id >= xeq_depth) {
36862306a36Sopenharmony_ci		dev_err(dev, "Please input eqe or aeqe num (0-%u)", xeq_depth - 1);
36962306a36Sopenharmony_ci		return -EINVAL;
37062306a36Sopenharmony_ci	}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	down_read(&qm->qps_lock);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (qm->eqe && !strcmp(name, "EQE")) {
37562306a36Sopenharmony_ci		xeqe = qm->eqe + xeqe_id;
37662306a36Sopenharmony_ci	} else if (qm->aeqe && !strcmp(name, "AEQE")) {
37762306a36Sopenharmony_ci		xeqe = qm->aeqe + xeqe_id;
37862306a36Sopenharmony_ci	} else {
37962306a36Sopenharmony_ci		ret = -EINVAL;
38062306a36Sopenharmony_ci		goto err_unlock;
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	dump_show(qm, xeqe, size, name);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cierr_unlock:
38662306a36Sopenharmony_ci	up_read(&qm->qps_lock);
38762306a36Sopenharmony_ci	return ret;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic int qm_dbg_help(struct hisi_qm *qm, char *s)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (strsep(&s, " ")) {
39562306a36Sopenharmony_ci		dev_err(dev, "Please do not input extra characters!\n");
39662306a36Sopenharmony_ci		return -EINVAL;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	dev_info(dev, "available commands:\n");
40062306a36Sopenharmony_ci	dev_info(dev, "sqc <num>\n");
40162306a36Sopenharmony_ci	dev_info(dev, "cqc <num>\n");
40262306a36Sopenharmony_ci	dev_info(dev, "eqc\n");
40362306a36Sopenharmony_ci	dev_info(dev, "aeqc\n");
40462306a36Sopenharmony_ci	dev_info(dev, "sq <num> <e>\n");
40562306a36Sopenharmony_ci	dev_info(dev, "cq <num> <e>\n");
40662306a36Sopenharmony_ci	dev_info(dev, "eq <e>\n");
40762306a36Sopenharmony_ci	dev_info(dev, "aeq <e>\n");
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	return 0;
41062306a36Sopenharmony_ci}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cistatic const struct qm_cmd_dump_item qm_cmd_dump_table[] = {
41362306a36Sopenharmony_ci	{
41462306a36Sopenharmony_ci		.cmd = "sqc",
41562306a36Sopenharmony_ci		.info_name = "SQC",
41662306a36Sopenharmony_ci		.dump_fn = qm_sqc_dump,
41762306a36Sopenharmony_ci	}, {
41862306a36Sopenharmony_ci		.cmd = "cqc",
41962306a36Sopenharmony_ci		.info_name = "CQC",
42062306a36Sopenharmony_ci		.dump_fn = qm_cqc_dump,
42162306a36Sopenharmony_ci	}, {
42262306a36Sopenharmony_ci		.cmd = "eqc",
42362306a36Sopenharmony_ci		.info_name = "EQC",
42462306a36Sopenharmony_ci		.dump_fn = qm_eqc_aeqc_dump,
42562306a36Sopenharmony_ci	}, {
42662306a36Sopenharmony_ci		.cmd = "aeqc",
42762306a36Sopenharmony_ci		.info_name = "AEQC",
42862306a36Sopenharmony_ci		.dump_fn = qm_eqc_aeqc_dump,
42962306a36Sopenharmony_ci	}, {
43062306a36Sopenharmony_ci		.cmd = "sq",
43162306a36Sopenharmony_ci		.info_name = "SQE",
43262306a36Sopenharmony_ci		.dump_fn = qm_sq_dump,
43362306a36Sopenharmony_ci	}, {
43462306a36Sopenharmony_ci		.cmd = "cq",
43562306a36Sopenharmony_ci		.info_name = "CQE",
43662306a36Sopenharmony_ci		.dump_fn = qm_cq_dump,
43762306a36Sopenharmony_ci	}, {
43862306a36Sopenharmony_ci		.cmd = "eq",
43962306a36Sopenharmony_ci		.info_name = "EQE",
44062306a36Sopenharmony_ci		.dump_fn = qm_eq_aeq_dump,
44162306a36Sopenharmony_ci	}, {
44262306a36Sopenharmony_ci		.cmd = "aeq",
44362306a36Sopenharmony_ci		.info_name = "AEQE",
44462306a36Sopenharmony_ci		.dump_fn = qm_eq_aeq_dump,
44562306a36Sopenharmony_ci	},
44662306a36Sopenharmony_ci};
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cistatic int qm_cmd_write_dump(struct hisi_qm *qm, const char *cmd_buf)
44962306a36Sopenharmony_ci{
45062306a36Sopenharmony_ci	struct device *dev = &qm->pdev->dev;
45162306a36Sopenharmony_ci	char *presult, *s, *s_tmp;
45262306a36Sopenharmony_ci	int table_size, i, ret;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	s = kstrdup(cmd_buf, GFP_KERNEL);
45562306a36Sopenharmony_ci	if (!s)
45662306a36Sopenharmony_ci		return -ENOMEM;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	s_tmp = s;
45962306a36Sopenharmony_ci	presult = strsep(&s, " ");
46062306a36Sopenharmony_ci	if (!presult) {
46162306a36Sopenharmony_ci		ret = -EINVAL;
46262306a36Sopenharmony_ci		goto err_buffer_free;
46362306a36Sopenharmony_ci	}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	if (!strcmp(presult, "help")) {
46662306a36Sopenharmony_ci		ret = qm_dbg_help(qm, s);
46762306a36Sopenharmony_ci		goto err_buffer_free;
46862306a36Sopenharmony_ci	}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	table_size = ARRAY_SIZE(qm_cmd_dump_table);
47162306a36Sopenharmony_ci	for (i = 0; i < table_size; i++) {
47262306a36Sopenharmony_ci		if (!strcmp(presult, qm_cmd_dump_table[i].cmd)) {
47362306a36Sopenharmony_ci			ret = qm_cmd_dump_table[i].dump_fn(qm, s,
47462306a36Sopenharmony_ci				qm_cmd_dump_table[i].info_name);
47562306a36Sopenharmony_ci			break;
47662306a36Sopenharmony_ci		}
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (i == table_size) {
48062306a36Sopenharmony_ci		dev_info(dev, "Please echo help\n");
48162306a36Sopenharmony_ci		ret = -EINVAL;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_cierr_buffer_free:
48562306a36Sopenharmony_ci	kfree(s_tmp);
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	return ret;
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_cistatic ssize_t qm_cmd_write(struct file *filp, const char __user *buffer,
49162306a36Sopenharmony_ci			    size_t count, loff_t *pos)
49262306a36Sopenharmony_ci{
49362306a36Sopenharmony_ci	struct hisi_qm *qm = filp->private_data;
49462306a36Sopenharmony_ci	char *cmd_buf, *cmd_buf_tmp;
49562306a36Sopenharmony_ci	int ret;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	if (*pos)
49862306a36Sopenharmony_ci		return 0;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	ret = hisi_qm_get_dfx_access(qm);
50162306a36Sopenharmony_ci	if (ret)
50262306a36Sopenharmony_ci		return ret;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/* Judge if the instance is being reset. */
50562306a36Sopenharmony_ci	if (unlikely(atomic_read(&qm->status.flags) == QM_STOP)) {
50662306a36Sopenharmony_ci		ret = 0;
50762306a36Sopenharmony_ci		goto put_dfx_access;
50862306a36Sopenharmony_ci	}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (count > QM_DBG_WRITE_LEN) {
51162306a36Sopenharmony_ci		ret = -ENOSPC;
51262306a36Sopenharmony_ci		goto put_dfx_access;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	cmd_buf = memdup_user_nul(buffer, count);
51662306a36Sopenharmony_ci	if (IS_ERR(cmd_buf)) {
51762306a36Sopenharmony_ci		ret = PTR_ERR(cmd_buf);
51862306a36Sopenharmony_ci		goto put_dfx_access;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	cmd_buf_tmp = strchr(cmd_buf, '\n');
52262306a36Sopenharmony_ci	if (cmd_buf_tmp) {
52362306a36Sopenharmony_ci		*cmd_buf_tmp = '\0';
52462306a36Sopenharmony_ci		count = cmd_buf_tmp - cmd_buf + 1;
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	ret = qm_cmd_write_dump(qm, cmd_buf);
52862306a36Sopenharmony_ci	if (ret) {
52962306a36Sopenharmony_ci		kfree(cmd_buf);
53062306a36Sopenharmony_ci		goto put_dfx_access;
53162306a36Sopenharmony_ci	}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	kfree(cmd_buf);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	ret = count;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ciput_dfx_access:
53862306a36Sopenharmony_ci	hisi_qm_put_dfx_access(qm);
53962306a36Sopenharmony_ci	return ret;
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_cistatic const struct file_operations qm_cmd_fops = {
54362306a36Sopenharmony_ci	.owner = THIS_MODULE,
54462306a36Sopenharmony_ci	.open = simple_open,
54562306a36Sopenharmony_ci	.read = qm_cmd_read,
54662306a36Sopenharmony_ci	.write = qm_cmd_write,
54762306a36Sopenharmony_ci};
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci/**
55062306a36Sopenharmony_ci * hisi_qm_regs_dump() - Dump registers's value.
55162306a36Sopenharmony_ci * @s: debugfs file handle.
55262306a36Sopenharmony_ci * @regset: accelerator registers information.
55362306a36Sopenharmony_ci *
55462306a36Sopenharmony_ci * Dump accelerator registers.
55562306a36Sopenharmony_ci */
55662306a36Sopenharmony_civoid hisi_qm_regs_dump(struct seq_file *s, struct debugfs_regset32 *regset)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(regset->dev);
55962306a36Sopenharmony_ci	struct hisi_qm *qm = pci_get_drvdata(pdev);
56062306a36Sopenharmony_ci	const struct debugfs_reg32 *regs = regset->regs;
56162306a36Sopenharmony_ci	int regs_len = regset->nregs;
56262306a36Sopenharmony_ci	int i, ret;
56362306a36Sopenharmony_ci	u32 val;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	ret = hisi_qm_get_dfx_access(qm);
56662306a36Sopenharmony_ci	if (ret)
56762306a36Sopenharmony_ci		return;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	for (i = 0; i < regs_len; i++) {
57062306a36Sopenharmony_ci		val = readl(regset->base + regs[i].offset);
57162306a36Sopenharmony_ci		seq_printf(s, "%s= 0x%08x\n", regs[i].name, val);
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	hisi_qm_put_dfx_access(qm);
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_qm_regs_dump);
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_cistatic int qm_regs_show(struct seq_file *s, void *unused)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	struct hisi_qm *qm = s->private;
58162306a36Sopenharmony_ci	struct debugfs_regset32 regset;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	if (qm->fun_type == QM_HW_PF) {
58462306a36Sopenharmony_ci		regset.regs = qm_dfx_regs;
58562306a36Sopenharmony_ci		regset.nregs = ARRAY_SIZE(qm_dfx_regs);
58662306a36Sopenharmony_ci	} else {
58762306a36Sopenharmony_ci		regset.regs = qm_vf_dfx_regs;
58862306a36Sopenharmony_ci		regset.nregs = ARRAY_SIZE(qm_vf_dfx_regs);
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	regset.base = qm->io_base;
59262306a36Sopenharmony_ci	regset.dev = &qm->pdev->dev;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	hisi_qm_regs_dump(s, &regset);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	return 0;
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(qm_regs);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_cistatic u32 current_q_read(struct hisi_qm *qm)
60262306a36Sopenharmony_ci{
60362306a36Sopenharmony_ci	return readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) >> QM_DFX_QN_SHIFT;
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_cistatic int current_q_write(struct hisi_qm *qm, u32 val)
60762306a36Sopenharmony_ci{
60862306a36Sopenharmony_ci	u32 tmp;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	if (val >= qm->debug.curr_qm_qp_num)
61162306a36Sopenharmony_ci		return -EINVAL;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	tmp = val << QM_DFX_QN_SHIFT |
61462306a36Sopenharmony_ci	      (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_FUN_MASK);
61562306a36Sopenharmony_ci	writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	tmp = val << QM_DFX_QN_SHIFT |
61862306a36Sopenharmony_ci	      (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_FUN_MASK);
61962306a36Sopenharmony_ci	writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	return 0;
62262306a36Sopenharmony_ci}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cistatic u32 clear_enable_read(struct hisi_qm *qm)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	return readl(qm->io_base + QM_DFX_CNT_CLR_CE);
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci/* rd_clr_ctrl 1 enable read clear, otherwise 0 disable it */
63062306a36Sopenharmony_cistatic int clear_enable_write(struct hisi_qm *qm, u32 rd_clr_ctrl)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	if (rd_clr_ctrl > 1)
63362306a36Sopenharmony_ci		return -EINVAL;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	writel(rd_clr_ctrl, qm->io_base + QM_DFX_CNT_CLR_CE);
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	return 0;
63862306a36Sopenharmony_ci}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_cistatic u32 current_qm_read(struct hisi_qm *qm)
64162306a36Sopenharmony_ci{
64262306a36Sopenharmony_ci	return readl(qm->io_base + QM_DFX_MB_CNT_VF);
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic int qm_get_vf_qp_num(struct hisi_qm *qm, u32 fun_num)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	u32 remain_q_num, vfq_num;
64862306a36Sopenharmony_ci	u32 num_vfs = qm->vfs_num;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	vfq_num = (qm->ctrl_qp_num - qm->qp_num) / num_vfs;
65162306a36Sopenharmony_ci	if (vfq_num >= qm->max_qp_num)
65262306a36Sopenharmony_ci		return qm->max_qp_num;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	remain_q_num = (qm->ctrl_qp_num - qm->qp_num) % num_vfs;
65562306a36Sopenharmony_ci	if (vfq_num + remain_q_num <= qm->max_qp_num)
65662306a36Sopenharmony_ci		return fun_num == num_vfs ? vfq_num + remain_q_num : vfq_num;
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	/*
65962306a36Sopenharmony_ci	 * if vfq_num + remain_q_num > max_qp_num, the last VFs,
66062306a36Sopenharmony_ci	 * each with one more queue.
66162306a36Sopenharmony_ci	 */
66262306a36Sopenharmony_ci	return fun_num + remain_q_num > num_vfs ? vfq_num + 1 : vfq_num;
66362306a36Sopenharmony_ci}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_cistatic int current_qm_write(struct hisi_qm *qm, u32 val)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	u32 tmp;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	if (val > qm->vfs_num)
67062306a36Sopenharmony_ci		return -EINVAL;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	/* According PF or VF Dev ID to calculation curr_qm_qp_num and store */
67362306a36Sopenharmony_ci	if (!val)
67462306a36Sopenharmony_ci		qm->debug.curr_qm_qp_num = qm->qp_num;
67562306a36Sopenharmony_ci	else
67662306a36Sopenharmony_ci		qm->debug.curr_qm_qp_num = qm_get_vf_qp_num(qm, val);
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	writel(val, qm->io_base + QM_DFX_MB_CNT_VF);
67962306a36Sopenharmony_ci	writel(val, qm->io_base + QM_DFX_DB_CNT_VF);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	tmp = val |
68262306a36Sopenharmony_ci	      (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_Q_MASK);
68362306a36Sopenharmony_ci	writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	tmp = val |
68662306a36Sopenharmony_ci	      (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_Q_MASK);
68762306a36Sopenharmony_ci	writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	return 0;
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic ssize_t qm_debug_read(struct file *filp, char __user *buf,
69362306a36Sopenharmony_ci			     size_t count, loff_t *pos)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	struct debugfs_file *file = filp->private_data;
69662306a36Sopenharmony_ci	enum qm_debug_file index = file->index;
69762306a36Sopenharmony_ci	struct hisi_qm *qm = file_to_qm(file);
69862306a36Sopenharmony_ci	char tbuf[QM_DBG_TMP_BUF_LEN];
69962306a36Sopenharmony_ci	u32 val;
70062306a36Sopenharmony_ci	int ret;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	ret = hisi_qm_get_dfx_access(qm);
70362306a36Sopenharmony_ci	if (ret)
70462306a36Sopenharmony_ci		return ret;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	mutex_lock(&file->lock);
70762306a36Sopenharmony_ci	switch (index) {
70862306a36Sopenharmony_ci	case CURRENT_QM:
70962306a36Sopenharmony_ci		val = current_qm_read(qm);
71062306a36Sopenharmony_ci		break;
71162306a36Sopenharmony_ci	case CURRENT_Q:
71262306a36Sopenharmony_ci		val = current_q_read(qm);
71362306a36Sopenharmony_ci		break;
71462306a36Sopenharmony_ci	case CLEAR_ENABLE:
71562306a36Sopenharmony_ci		val = clear_enable_read(qm);
71662306a36Sopenharmony_ci		break;
71762306a36Sopenharmony_ci	default:
71862306a36Sopenharmony_ci		goto err_input;
71962306a36Sopenharmony_ci	}
72062306a36Sopenharmony_ci	mutex_unlock(&file->lock);
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	hisi_qm_put_dfx_access(qm);
72362306a36Sopenharmony_ci	ret = scnprintf(tbuf, QM_DBG_TMP_BUF_LEN, "%u\n", val);
72462306a36Sopenharmony_ci	return simple_read_from_buffer(buf, count, pos, tbuf, ret);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_cierr_input:
72762306a36Sopenharmony_ci	mutex_unlock(&file->lock);
72862306a36Sopenharmony_ci	hisi_qm_put_dfx_access(qm);
72962306a36Sopenharmony_ci	return -EINVAL;
73062306a36Sopenharmony_ci}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_cistatic ssize_t qm_debug_write(struct file *filp, const char __user *buf,
73362306a36Sopenharmony_ci			      size_t count, loff_t *pos)
73462306a36Sopenharmony_ci{
73562306a36Sopenharmony_ci	struct debugfs_file *file = filp->private_data;
73662306a36Sopenharmony_ci	enum qm_debug_file index = file->index;
73762306a36Sopenharmony_ci	struct hisi_qm *qm = file_to_qm(file);
73862306a36Sopenharmony_ci	unsigned long val;
73962306a36Sopenharmony_ci	char tbuf[QM_DBG_TMP_BUF_LEN];
74062306a36Sopenharmony_ci	int len, ret;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	if (*pos != 0)
74362306a36Sopenharmony_ci		return 0;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	if (count >= QM_DBG_TMP_BUF_LEN)
74662306a36Sopenharmony_ci		return -ENOSPC;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	len = simple_write_to_buffer(tbuf, QM_DBG_TMP_BUF_LEN - 1, pos, buf,
74962306a36Sopenharmony_ci				     count);
75062306a36Sopenharmony_ci	if (len < 0)
75162306a36Sopenharmony_ci		return len;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	tbuf[len] = '\0';
75462306a36Sopenharmony_ci	if (kstrtoul(tbuf, 0, &val))
75562306a36Sopenharmony_ci		return -EFAULT;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	ret = hisi_qm_get_dfx_access(qm);
75862306a36Sopenharmony_ci	if (ret)
75962306a36Sopenharmony_ci		return ret;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	mutex_lock(&file->lock);
76262306a36Sopenharmony_ci	switch (index) {
76362306a36Sopenharmony_ci	case CURRENT_QM:
76462306a36Sopenharmony_ci		ret = current_qm_write(qm, val);
76562306a36Sopenharmony_ci		break;
76662306a36Sopenharmony_ci	case CURRENT_Q:
76762306a36Sopenharmony_ci		ret = current_q_write(qm, val);
76862306a36Sopenharmony_ci		break;
76962306a36Sopenharmony_ci	case CLEAR_ENABLE:
77062306a36Sopenharmony_ci		ret = clear_enable_write(qm, val);
77162306a36Sopenharmony_ci		break;
77262306a36Sopenharmony_ci	default:
77362306a36Sopenharmony_ci		ret = -EINVAL;
77462306a36Sopenharmony_ci	}
77562306a36Sopenharmony_ci	mutex_unlock(&file->lock);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	hisi_qm_put_dfx_access(qm);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	if (ret)
78062306a36Sopenharmony_ci		return ret;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	return count;
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic const struct file_operations qm_debug_fops = {
78662306a36Sopenharmony_ci	.owner = THIS_MODULE,
78762306a36Sopenharmony_ci	.open = simple_open,
78862306a36Sopenharmony_ci	.read = qm_debug_read,
78962306a36Sopenharmony_ci	.write = qm_debug_write,
79062306a36Sopenharmony_ci};
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_cistatic void dfx_regs_uninit(struct hisi_qm *qm,
79362306a36Sopenharmony_ci		struct dfx_diff_registers *dregs, int reg_len)
79462306a36Sopenharmony_ci{
79562306a36Sopenharmony_ci	int i;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	/* Setting the pointer is NULL to prevent double free */
79862306a36Sopenharmony_ci	for (i = 0; i < reg_len; i++) {
79962306a36Sopenharmony_ci		kfree(dregs[i].regs);
80062306a36Sopenharmony_ci		dregs[i].regs = NULL;
80162306a36Sopenharmony_ci	}
80262306a36Sopenharmony_ci	kfree(dregs);
80362306a36Sopenharmony_ci}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_cistatic struct dfx_diff_registers *dfx_regs_init(struct hisi_qm *qm,
80662306a36Sopenharmony_ci	const struct dfx_diff_registers *cregs, u32 reg_len)
80762306a36Sopenharmony_ci{
80862306a36Sopenharmony_ci	struct dfx_diff_registers *diff_regs;
80962306a36Sopenharmony_ci	u32 j, base_offset;
81062306a36Sopenharmony_ci	int i;
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	diff_regs = kcalloc(reg_len, sizeof(*diff_regs), GFP_KERNEL);
81362306a36Sopenharmony_ci	if (!diff_regs)
81462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	for (i = 0; i < reg_len; i++) {
81762306a36Sopenharmony_ci		if (!cregs[i].reg_len)
81862306a36Sopenharmony_ci			continue;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci		diff_regs[i].reg_offset = cregs[i].reg_offset;
82162306a36Sopenharmony_ci		diff_regs[i].reg_len = cregs[i].reg_len;
82262306a36Sopenharmony_ci		diff_regs[i].regs = kcalloc(QM_DFX_REGS_LEN, cregs[i].reg_len,
82362306a36Sopenharmony_ci					 GFP_KERNEL);
82462306a36Sopenharmony_ci		if (!diff_regs[i].regs)
82562306a36Sopenharmony_ci			goto alloc_error;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci		for (j = 0; j < diff_regs[i].reg_len; j++) {
82862306a36Sopenharmony_ci			base_offset = diff_regs[i].reg_offset +
82962306a36Sopenharmony_ci					j * QM_DFX_REGS_LEN;
83062306a36Sopenharmony_ci			diff_regs[i].regs[j] = readl(qm->io_base + base_offset);
83162306a36Sopenharmony_ci		}
83262306a36Sopenharmony_ci	}
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	return diff_regs;
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_cialloc_error:
83762306a36Sopenharmony_ci	while (i > 0) {
83862306a36Sopenharmony_ci		i--;
83962306a36Sopenharmony_ci		kfree(diff_regs[i].regs);
84062306a36Sopenharmony_ci	}
84162306a36Sopenharmony_ci	kfree(diff_regs);
84262306a36Sopenharmony_ci	return ERR_PTR(-ENOMEM);
84362306a36Sopenharmony_ci}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_cistatic int qm_diff_regs_init(struct hisi_qm *qm,
84662306a36Sopenharmony_ci		struct dfx_diff_registers *dregs, u32 reg_len)
84762306a36Sopenharmony_ci{
84862306a36Sopenharmony_ci	qm->debug.qm_diff_regs = dfx_regs_init(qm, qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
84962306a36Sopenharmony_ci	if (IS_ERR(qm->debug.qm_diff_regs))
85062306a36Sopenharmony_ci		return PTR_ERR(qm->debug.qm_diff_regs);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	qm->debug.acc_diff_regs = dfx_regs_init(qm, dregs, reg_len);
85362306a36Sopenharmony_ci	if (IS_ERR(qm->debug.acc_diff_regs)) {
85462306a36Sopenharmony_ci		dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
85562306a36Sopenharmony_ci		return PTR_ERR(qm->debug.acc_diff_regs);
85662306a36Sopenharmony_ci	}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	return 0;
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic void qm_last_regs_uninit(struct hisi_qm *qm)
86262306a36Sopenharmony_ci{
86362306a36Sopenharmony_ci	struct qm_debug *debug = &qm->debug;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	if (qm->fun_type == QM_HW_VF || !debug->qm_last_words)
86662306a36Sopenharmony_ci		return;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	kfree(debug->qm_last_words);
86962306a36Sopenharmony_ci	debug->qm_last_words = NULL;
87062306a36Sopenharmony_ci}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_cistatic int qm_last_regs_init(struct hisi_qm *qm)
87362306a36Sopenharmony_ci{
87462306a36Sopenharmony_ci	int dfx_regs_num = ARRAY_SIZE(qm_dfx_regs);
87562306a36Sopenharmony_ci	struct qm_debug *debug = &qm->debug;
87662306a36Sopenharmony_ci	int i;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	if (qm->fun_type == QM_HW_VF)
87962306a36Sopenharmony_ci		return 0;
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci	debug->qm_last_words = kcalloc(dfx_regs_num, sizeof(unsigned int), GFP_KERNEL);
88262306a36Sopenharmony_ci	if (!debug->qm_last_words)
88362306a36Sopenharmony_ci		return -ENOMEM;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	for (i = 0; i < dfx_regs_num; i++) {
88662306a36Sopenharmony_ci		debug->qm_last_words[i] = readl_relaxed(qm->io_base +
88762306a36Sopenharmony_ci			qm_dfx_regs[i].offset);
88862306a36Sopenharmony_ci	}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	return 0;
89162306a36Sopenharmony_ci}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_cistatic void qm_diff_regs_uninit(struct hisi_qm *qm, u32 reg_len)
89462306a36Sopenharmony_ci{
89562306a36Sopenharmony_ci	dfx_regs_uninit(qm, qm->debug.acc_diff_regs, reg_len);
89662306a36Sopenharmony_ci	dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci/**
90062306a36Sopenharmony_ci * hisi_qm_regs_debugfs_init() - Allocate memory for registers.
90162306a36Sopenharmony_ci * @qm: device qm handle.
90262306a36Sopenharmony_ci * @dregs: diff registers handle.
90362306a36Sopenharmony_ci * @reg_len: diff registers region length.
90462306a36Sopenharmony_ci */
90562306a36Sopenharmony_ciint hisi_qm_regs_debugfs_init(struct hisi_qm *qm,
90662306a36Sopenharmony_ci		struct dfx_diff_registers *dregs, u32 reg_len)
90762306a36Sopenharmony_ci{
90862306a36Sopenharmony_ci	int ret;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	if (!qm || !dregs)
91162306a36Sopenharmony_ci		return -EINVAL;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	if (qm->fun_type != QM_HW_PF)
91462306a36Sopenharmony_ci		return 0;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	ret = qm_last_regs_init(qm);
91762306a36Sopenharmony_ci	if (ret) {
91862306a36Sopenharmony_ci		dev_info(&qm->pdev->dev, "failed to init qm words memory!\n");
91962306a36Sopenharmony_ci		return ret;
92062306a36Sopenharmony_ci	}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	ret = qm_diff_regs_init(qm, dregs, reg_len);
92362306a36Sopenharmony_ci	if (ret) {
92462306a36Sopenharmony_ci		qm_last_regs_uninit(qm);
92562306a36Sopenharmony_ci		return ret;
92662306a36Sopenharmony_ci	}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	return 0;
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_qm_regs_debugfs_init);
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci/**
93362306a36Sopenharmony_ci * hisi_qm_regs_debugfs_uninit() - Free memory for registers.
93462306a36Sopenharmony_ci * @qm: device qm handle.
93562306a36Sopenharmony_ci * @reg_len: diff registers region length.
93662306a36Sopenharmony_ci */
93762306a36Sopenharmony_civoid hisi_qm_regs_debugfs_uninit(struct hisi_qm *qm, u32 reg_len)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	if (!qm || qm->fun_type != QM_HW_PF)
94062306a36Sopenharmony_ci		return;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	qm_diff_regs_uninit(qm, reg_len);
94362306a36Sopenharmony_ci	qm_last_regs_uninit(qm);
94462306a36Sopenharmony_ci}
94562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_qm_regs_debugfs_uninit);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci/**
94862306a36Sopenharmony_ci * hisi_qm_acc_diff_regs_dump() - Dump registers's value.
94962306a36Sopenharmony_ci * @qm: device qm handle.
95062306a36Sopenharmony_ci * @s: Debugfs file handle.
95162306a36Sopenharmony_ci * @dregs: diff registers handle.
95262306a36Sopenharmony_ci * @regs_len: diff registers region length.
95362306a36Sopenharmony_ci */
95462306a36Sopenharmony_civoid hisi_qm_acc_diff_regs_dump(struct hisi_qm *qm, struct seq_file *s,
95562306a36Sopenharmony_ci	struct dfx_diff_registers *dregs, u32 regs_len)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	u32 j, val, base_offset;
95862306a36Sopenharmony_ci	int i, ret;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	if (!qm || !s || !dregs)
96162306a36Sopenharmony_ci		return;
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	ret = hisi_qm_get_dfx_access(qm);
96462306a36Sopenharmony_ci	if (ret)
96562306a36Sopenharmony_ci		return;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	down_read(&qm->qps_lock);
96862306a36Sopenharmony_ci	for (i = 0; i < regs_len; i++) {
96962306a36Sopenharmony_ci		if (!dregs[i].reg_len)
97062306a36Sopenharmony_ci			continue;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci		for (j = 0; j < dregs[i].reg_len; j++) {
97362306a36Sopenharmony_ci			base_offset = dregs[i].reg_offset + j * QM_DFX_REGS_LEN;
97462306a36Sopenharmony_ci			val = readl(qm->io_base + base_offset);
97562306a36Sopenharmony_ci			if (val != dregs[i].regs[j])
97662306a36Sopenharmony_ci				seq_printf(s, "0x%08x = 0x%08x ---> 0x%08x\n",
97762306a36Sopenharmony_ci					   base_offset, dregs[i].regs[j], val);
97862306a36Sopenharmony_ci		}
97962306a36Sopenharmony_ci	}
98062306a36Sopenharmony_ci	up_read(&qm->qps_lock);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	hisi_qm_put_dfx_access(qm);
98362306a36Sopenharmony_ci}
98462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_qm_acc_diff_regs_dump);
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_civoid hisi_qm_show_last_dfx_regs(struct hisi_qm *qm)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	struct qm_debug *debug = &qm->debug;
98962306a36Sopenharmony_ci	struct pci_dev *pdev = qm->pdev;
99062306a36Sopenharmony_ci	u32 val;
99162306a36Sopenharmony_ci	int i;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	if (qm->fun_type == QM_HW_VF || !debug->qm_last_words)
99462306a36Sopenharmony_ci		return;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(qm_dfx_regs); i++) {
99762306a36Sopenharmony_ci		val = readl_relaxed(qm->io_base + qm_dfx_regs[i].offset);
99862306a36Sopenharmony_ci		if (debug->qm_last_words[i] != val)
99962306a36Sopenharmony_ci			pci_info(pdev, "%s \t= 0x%08x => 0x%08x\n",
100062306a36Sopenharmony_ci			qm_dfx_regs[i].name, debug->qm_last_words[i], val);
100162306a36Sopenharmony_ci	}
100262306a36Sopenharmony_ci}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_cistatic int qm_diff_regs_show(struct seq_file *s, void *unused)
100562306a36Sopenharmony_ci{
100662306a36Sopenharmony_ci	struct hisi_qm *qm = s->private;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.qm_diff_regs,
100962306a36Sopenharmony_ci					ARRAY_SIZE(qm_diff_regs));
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	return 0;
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(qm_diff_regs);
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_cistatic ssize_t qm_status_read(struct file *filp, char __user *buffer,
101662306a36Sopenharmony_ci			      size_t count, loff_t *pos)
101762306a36Sopenharmony_ci{
101862306a36Sopenharmony_ci	struct hisi_qm *qm = filp->private_data;
101962306a36Sopenharmony_ci	char buf[QM_DBG_READ_LEN];
102062306a36Sopenharmony_ci	int val, len;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	val = atomic_read(&qm->status.flags);
102362306a36Sopenharmony_ci	len = scnprintf(buf, QM_DBG_READ_LEN, "%s\n", qm_s[val]);
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	return simple_read_from_buffer(buffer, count, pos, buf, len);
102662306a36Sopenharmony_ci}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_cistatic const struct file_operations qm_status_fops = {
102962306a36Sopenharmony_ci	.owner = THIS_MODULE,
103062306a36Sopenharmony_ci	.open = simple_open,
103162306a36Sopenharmony_ci	.read = qm_status_read,
103262306a36Sopenharmony_ci};
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_cistatic void qm_create_debugfs_file(struct hisi_qm *qm, struct dentry *dir,
103562306a36Sopenharmony_ci				   enum qm_debug_file index)
103662306a36Sopenharmony_ci{
103762306a36Sopenharmony_ci	struct debugfs_file *file = qm->debug.files + index;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	debugfs_create_file(qm_debug_file_name[index], 0600, dir, file,
104062306a36Sopenharmony_ci			    &qm_debug_fops);
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	file->index = index;
104362306a36Sopenharmony_ci	mutex_init(&file->lock);
104462306a36Sopenharmony_ci	file->debug = &qm->debug;
104562306a36Sopenharmony_ci}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_cistatic int qm_debugfs_atomic64_set(void *data, u64 val)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	if (val)
105062306a36Sopenharmony_ci		return -EINVAL;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	atomic64_set((atomic64_t *)data, 0);
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	return 0;
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_cistatic int qm_debugfs_atomic64_get(void *data, u64 *val)
105862306a36Sopenharmony_ci{
105962306a36Sopenharmony_ci	*val = atomic64_read((atomic64_t *)data);
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	return 0;
106262306a36Sopenharmony_ci}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(qm_atomic64_ops, qm_debugfs_atomic64_get,
106562306a36Sopenharmony_ci			 qm_debugfs_atomic64_set, "%llu\n");
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci/**
106862306a36Sopenharmony_ci * hisi_qm_debug_init() - Initialize qm related debugfs files.
106962306a36Sopenharmony_ci * @qm: The qm for which we want to add debugfs files.
107062306a36Sopenharmony_ci *
107162306a36Sopenharmony_ci * Create qm related debugfs files.
107262306a36Sopenharmony_ci */
107362306a36Sopenharmony_civoid hisi_qm_debug_init(struct hisi_qm *qm)
107462306a36Sopenharmony_ci{
107562306a36Sopenharmony_ci	struct dfx_diff_registers *qm_regs = qm->debug.qm_diff_regs;
107662306a36Sopenharmony_ci	struct qm_dfx *dfx = &qm->debug.dfx;
107762306a36Sopenharmony_ci	struct dentry *qm_d;
107862306a36Sopenharmony_ci	void *data;
107962306a36Sopenharmony_ci	int i;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	qm_d = debugfs_create_dir("qm", qm->debug.debug_root);
108262306a36Sopenharmony_ci	qm->debug.qm_d = qm_d;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	/* only show this in PF */
108562306a36Sopenharmony_ci	if (qm->fun_type == QM_HW_PF) {
108662306a36Sopenharmony_ci		qm_create_debugfs_file(qm, qm->debug.debug_root, CURRENT_QM);
108762306a36Sopenharmony_ci		for (i = CURRENT_Q; i < DEBUG_FILE_NUM; i++)
108862306a36Sopenharmony_ci			qm_create_debugfs_file(qm, qm->debug.qm_d, i);
108962306a36Sopenharmony_ci	}
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	if (qm_regs)
109262306a36Sopenharmony_ci		debugfs_create_file("diff_regs", 0444, qm->debug.qm_d,
109362306a36Sopenharmony_ci					qm, &qm_diff_regs_fops);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	debugfs_create_file("regs", 0444, qm->debug.qm_d, qm, &qm_regs_fops);
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	debugfs_create_file("cmd", 0600, qm->debug.qm_d, qm, &qm_cmd_fops);
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	debugfs_create_file("status", 0444, qm->debug.qm_d, qm,
110062306a36Sopenharmony_ci			&qm_status_fops);
110162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(qm_dfx_files); i++) {
110262306a36Sopenharmony_ci		data = (atomic64_t *)((uintptr_t)dfx + qm_dfx_files[i].offset);
110362306a36Sopenharmony_ci		debugfs_create_file(qm_dfx_files[i].name,
110462306a36Sopenharmony_ci			0644,
110562306a36Sopenharmony_ci			qm_d,
110662306a36Sopenharmony_ci			data,
110762306a36Sopenharmony_ci			&qm_atomic64_ops);
110862306a36Sopenharmony_ci	}
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	if (test_bit(QM_SUPPORT_FUNC_QOS, &qm->caps))
111162306a36Sopenharmony_ci		hisi_qm_set_algqos_init(qm);
111262306a36Sopenharmony_ci}
111362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_qm_debug_init);
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci/**
111662306a36Sopenharmony_ci * hisi_qm_debug_regs_clear() - clear qm debug related registers.
111762306a36Sopenharmony_ci * @qm: The qm for which we want to clear its debug registers.
111862306a36Sopenharmony_ci */
111962306a36Sopenharmony_civoid hisi_qm_debug_regs_clear(struct hisi_qm *qm)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	const struct debugfs_reg32 *regs;
112262306a36Sopenharmony_ci	int i;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	/* clear current_qm */
112562306a36Sopenharmony_ci	writel(0x0, qm->io_base + QM_DFX_MB_CNT_VF);
112662306a36Sopenharmony_ci	writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF);
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	/* clear current_q */
112962306a36Sopenharmony_ci	writel(0x0, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
113062306a36Sopenharmony_ci	writel(0x0, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/*
113362306a36Sopenharmony_ci	 * these registers are reading and clearing, so clear them after
113462306a36Sopenharmony_ci	 * reading them.
113562306a36Sopenharmony_ci	 */
113662306a36Sopenharmony_ci	writel(0x1, qm->io_base + QM_DFX_CNT_CLR_CE);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	regs = qm_dfx_regs;
113962306a36Sopenharmony_ci	for (i = 0; i < CNT_CYC_REGS_NUM; i++) {
114062306a36Sopenharmony_ci		readl(qm->io_base + regs->offset);
114162306a36Sopenharmony_ci		regs++;
114262306a36Sopenharmony_ci	}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	/* clear clear_enable */
114562306a36Sopenharmony_ci	writel(0x0, qm->io_base + QM_DFX_CNT_CLR_CE);
114662306a36Sopenharmony_ci}
114762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_qm_debug_regs_clear);
1148