194476b2bSKai Ye // SPDX-License-Identifier: GPL-2.0
294476b2bSKai Ye /* Copyright (c) 2022 HiSilicon Limited. */
394476b2bSKai Ye #include <linux/hisi_acc_qm.h>
494476b2bSKai Ye #include "qm_common.h"
594476b2bSKai Ye
694476b2bSKai Ye #define QM_DFX_BASE 0x0100000
794476b2bSKai Ye #define QM_DFX_STATE1 0x0104000
894476b2bSKai Ye #define QM_DFX_STATE2 0x01040C8
994476b2bSKai Ye #define QM_DFX_COMMON 0x0000
1094476b2bSKai Ye #define QM_DFX_BASE_LEN 0x5A
1194476b2bSKai Ye #define QM_DFX_STATE1_LEN 0x2E
1294476b2bSKai Ye #define QM_DFX_STATE2_LEN 0x11
1394476b2bSKai Ye #define QM_DFX_COMMON_LEN 0xC3
1494476b2bSKai Ye #define QM_DFX_REGS_LEN 4UL
1594476b2bSKai Ye #define QM_DBG_TMP_BUF_LEN 22
16*15f112f9SChenghai Huang #define QM_XQC_ADDR_MASK GENMASK(31, 0)
1794476b2bSKai Ye #define CURRENT_FUN_MASK GENMASK(5, 0)
1894476b2bSKai Ye #define CURRENT_Q_MASK GENMASK(31, 16)
1994476b2bSKai Ye #define QM_SQE_ADDR_MASK GENMASK(7, 0)
2094476b2bSKai Ye
2194476b2bSKai Ye #define QM_DFX_MB_CNT_VF 0x104010
2294476b2bSKai Ye #define QM_DFX_DB_CNT_VF 0x104020
2394476b2bSKai Ye #define QM_DFX_SQE_CNT_VF_SQN 0x104030
2494476b2bSKai Ye #define QM_DFX_CQE_CNT_VF_CQN 0x104040
2594476b2bSKai Ye #define QM_DFX_QN_SHIFT 16
2694476b2bSKai Ye #define QM_DFX_CNT_CLR_CE 0x100118
2794476b2bSKai Ye #define QM_DBG_WRITE_LEN 1024
288413fe3eSWeili Qian #define QM_IN_IDLE_ST_REG 0x1040e4
298413fe3eSWeili Qian #define QM_IN_IDLE_STATE 0x1
3094476b2bSKai Ye
3194476b2bSKai Ye static const char * const qm_debug_file_name[] = {
3294476b2bSKai Ye [CURRENT_QM] = "current_qm",
3394476b2bSKai Ye [CURRENT_Q] = "current_q",
3494476b2bSKai Ye [CLEAR_ENABLE] = "clear_enable",
3594476b2bSKai Ye };
3694476b2bSKai Ye
37c66272a4SWeili Qian static const char * const qm_s[] = {
38c66272a4SWeili Qian "work", "stop",
39c66272a4SWeili Qian };
40c66272a4SWeili Qian
4194476b2bSKai Ye struct qm_dfx_item {
4294476b2bSKai Ye const char *name;
4394476b2bSKai Ye u32 offset;
4494476b2bSKai Ye };
4594476b2bSKai Ye
469c756098SKai Ye struct qm_cmd_dump_item {
479c756098SKai Ye const char *cmd;
489c756098SKai Ye char *info_name;
499c756098SKai Ye int (*dump_fn)(struct hisi_qm *qm, char *cmd, char *info_name);
509c756098SKai Ye };
519c756098SKai Ye
5294476b2bSKai Ye static struct qm_dfx_item qm_dfx_files[] = {
5394476b2bSKai Ye {"err_irq", offsetof(struct qm_dfx, err_irq_cnt)},
5494476b2bSKai Ye {"aeq_irq", offsetof(struct qm_dfx, aeq_irq_cnt)},
5594476b2bSKai Ye {"abnormal_irq", offsetof(struct qm_dfx, abnormal_irq_cnt)},
5694476b2bSKai Ye {"create_qp_err", offsetof(struct qm_dfx, create_qp_err_cnt)},
5794476b2bSKai Ye {"mb_err", offsetof(struct qm_dfx, mb_err_cnt)},
5894476b2bSKai Ye };
5994476b2bSKai Ye
6094476b2bSKai Ye #define CNT_CYC_REGS_NUM 10
6194476b2bSKai Ye static const struct debugfs_reg32 qm_dfx_regs[] = {
6294476b2bSKai Ye /* XXX_CNT are reading clear register */
63a61fb707SWeili Qian {"QM_ECC_1BIT_CNT ", 0x104000},
64a61fb707SWeili Qian {"QM_ECC_MBIT_CNT ", 0x104008},
65a61fb707SWeili Qian {"QM_DFX_MB_CNT ", 0x104018},
66a61fb707SWeili Qian {"QM_DFX_DB_CNT ", 0x104028},
67a61fb707SWeili Qian {"QM_DFX_SQE_CNT ", 0x104038},
68a61fb707SWeili Qian {"QM_DFX_CQE_CNT ", 0x104048},
69a61fb707SWeili Qian {"QM_DFX_SEND_SQE_TO_ACC_CNT ", 0x104050},
70a61fb707SWeili Qian {"QM_DFX_WB_SQE_FROM_ACC_CNT ", 0x104058},
71a61fb707SWeili Qian {"QM_DFX_ACC_FINISH_CNT ", 0x104060},
72a61fb707SWeili Qian {"QM_DFX_CQE_ERR_CNT ", 0x1040b4},
73a61fb707SWeili Qian {"QM_DFX_FUNS_ACTIVE_ST ", 0x200},
74a61fb707SWeili Qian {"QM_ECC_1BIT_INF ", 0x104004},
75a61fb707SWeili Qian {"QM_ECC_MBIT_INF ", 0x10400c},
76a61fb707SWeili Qian {"QM_DFX_ACC_RDY_VLD0 ", 0x1040a0},
77a61fb707SWeili Qian {"QM_DFX_ACC_RDY_VLD1 ", 0x1040a4},
78a61fb707SWeili Qian {"QM_DFX_AXI_RDY_VLD ", 0x1040a8},
79a61fb707SWeili Qian {"QM_DFX_FF_ST0 ", 0x1040c8},
80a61fb707SWeili Qian {"QM_DFX_FF_ST1 ", 0x1040cc},
81a61fb707SWeili Qian {"QM_DFX_FF_ST2 ", 0x1040d0},
82a61fb707SWeili Qian {"QM_DFX_FF_ST3 ", 0x1040d4},
83a61fb707SWeili Qian {"QM_DFX_FF_ST4 ", 0x1040d8},
84a61fb707SWeili Qian {"QM_DFX_FF_ST5 ", 0x1040dc},
85a61fb707SWeili Qian {"QM_DFX_FF_ST6 ", 0x1040e0},
86a61fb707SWeili Qian {"QM_IN_IDLE_ST ", 0x1040e4},
878db78dd6SWeili Qian {"QM_CACHE_CTL ", 0x100050},
888db78dd6SWeili Qian {"QM_TIMEOUT_CFG ", 0x100070},
898db78dd6SWeili Qian {"QM_DB_TIMEOUT_CFG ", 0x100074},
908db78dd6SWeili Qian {"QM_FLR_PENDING_TIME_CFG ", 0x100078},
918db78dd6SWeili Qian {"QM_ARUSR_MCFG1 ", 0x100088},
928db78dd6SWeili Qian {"QM_AWUSR_MCFG1 ", 0x100098},
938db78dd6SWeili Qian {"QM_AXI_M_CFG_ENABLE ", 0x1000B0},
948db78dd6SWeili Qian {"QM_RAS_CE_THRESHOLD ", 0x1000F8},
958db78dd6SWeili Qian {"QM_AXI_TIMEOUT_CTRL ", 0x100120},
968db78dd6SWeili Qian {"QM_AXI_TIMEOUT_STATUS ", 0x100124},
978db78dd6SWeili Qian {"QM_CQE_AGGR_TIMEOUT_CTRL ", 0x100144},
988db78dd6SWeili Qian {"ACC_RAS_MSI_INT_SEL ", 0x1040fc},
998db78dd6SWeili Qian {"QM_CQE_OUT ", 0x104100},
1008db78dd6SWeili Qian {"QM_EQE_OUT ", 0x104104},
1018db78dd6SWeili Qian {"QM_AEQE_OUT ", 0x104108},
1028db78dd6SWeili Qian {"QM_DB_INFO0 ", 0x104180},
1038db78dd6SWeili Qian {"QM_DB_INFO1 ", 0x104184},
1048db78dd6SWeili Qian {"QM_AM_CTRL_GLOBAL ", 0x300000},
1058db78dd6SWeili Qian {"QM_AM_CURR_PORT_STS ", 0x300100},
1068db78dd6SWeili Qian {"QM_AM_CURR_TRANS_RETURN ", 0x300150},
1078db78dd6SWeili Qian {"QM_AM_CURR_RD_MAX_TXID ", 0x300154},
1088db78dd6SWeili Qian {"QM_AM_CURR_WR_MAX_TXID ", 0x300158},
1098db78dd6SWeili Qian {"QM_AM_ALARM_RRESP ", 0x300180},
1108db78dd6SWeili Qian {"QM_AM_ALARM_BRESP ", 0x300184},
11194476b2bSKai Ye };
11294476b2bSKai Ye
11394476b2bSKai Ye static const struct debugfs_reg32 qm_vf_dfx_regs[] = {
114a61fb707SWeili Qian {"QM_DFX_FUNS_ACTIVE_ST ", 0x200},
11594476b2bSKai Ye };
11694476b2bSKai Ye
11794476b2bSKai Ye /* define the QM's dfx regs region and region length */
11894476b2bSKai Ye static struct dfx_diff_registers qm_diff_regs[] = {
11994476b2bSKai Ye {
12094476b2bSKai Ye .reg_offset = QM_DFX_BASE,
12194476b2bSKai Ye .reg_len = QM_DFX_BASE_LEN,
12294476b2bSKai Ye }, {
12394476b2bSKai Ye .reg_offset = QM_DFX_STATE1,
12494476b2bSKai Ye .reg_len = QM_DFX_STATE1_LEN,
12594476b2bSKai Ye }, {
12694476b2bSKai Ye .reg_offset = QM_DFX_STATE2,
12794476b2bSKai Ye .reg_len = QM_DFX_STATE2_LEN,
12894476b2bSKai Ye }, {
12994476b2bSKai Ye .reg_offset = QM_DFX_COMMON,
13094476b2bSKai Ye .reg_len = QM_DFX_COMMON_LEN,
13194476b2bSKai Ye },
13294476b2bSKai Ye };
13394476b2bSKai Ye
file_to_qm(struct debugfs_file * file)13494476b2bSKai Ye static struct hisi_qm *file_to_qm(struct debugfs_file *file)
13594476b2bSKai Ye {
13694476b2bSKai Ye struct qm_debug *debug = file->debug;
13794476b2bSKai Ye
13894476b2bSKai Ye return container_of(debug, struct hisi_qm, debug);
13994476b2bSKai Ye }
14094476b2bSKai Ye
qm_cmd_read(struct file * filp,char __user * buffer,size_t count,loff_t * pos)14194476b2bSKai Ye static ssize_t qm_cmd_read(struct file *filp, char __user *buffer,
14294476b2bSKai Ye size_t count, loff_t *pos)
14394476b2bSKai Ye {
14494476b2bSKai Ye char buf[QM_DBG_READ_LEN];
14594476b2bSKai Ye int len;
14694476b2bSKai Ye
14794476b2bSKai Ye len = scnprintf(buf, QM_DBG_READ_LEN, "%s\n",
14894476b2bSKai Ye "Please echo help to cmd to get help information");
14994476b2bSKai Ye
15094476b2bSKai Ye return simple_read_from_buffer(buffer, count, pos, buf, len);
15194476b2bSKai Ye }
15294476b2bSKai Ye
dump_show(struct hisi_qm * qm,void * info,unsigned int info_size,char * info_name)15394476b2bSKai Ye static void dump_show(struct hisi_qm *qm, void *info,
15494476b2bSKai Ye unsigned int info_size, char *info_name)
15594476b2bSKai Ye {
15694476b2bSKai Ye struct device *dev = &qm->pdev->dev;
15794476b2bSKai Ye u8 *info_curr = info;
15894476b2bSKai Ye u32 i;
15994476b2bSKai Ye #define BYTE_PER_DW 4
16094476b2bSKai Ye
16194476b2bSKai Ye dev_info(dev, "%s DUMP\n", info_name);
16294476b2bSKai Ye for (i = 0; i < info_size; i += BYTE_PER_DW, info_curr += BYTE_PER_DW) {
16394476b2bSKai Ye pr_info("DW%u: %02X%02X %02X%02X\n", i / BYTE_PER_DW,
16494476b2bSKai Ye *(info_curr + 3), *(info_curr + 2), *(info_curr + 1), *(info_curr));
16594476b2bSKai Ye }
16694476b2bSKai Ye }
16794476b2bSKai Ye
qm_sqc_dump(struct hisi_qm * qm,char * s,char * name)1689c756098SKai Ye static int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
16994476b2bSKai Ye {
17094476b2bSKai Ye struct device *dev = &qm->pdev->dev;
1715b90073dSWeili Qian struct qm_sqc sqc;
17294476b2bSKai Ye u32 qp_id;
17394476b2bSKai Ye int ret;
17494476b2bSKai Ye
17594476b2bSKai Ye if (!s)
17694476b2bSKai Ye return -EINVAL;
17794476b2bSKai Ye
17894476b2bSKai Ye ret = kstrtou32(s, 0, &qp_id);
17994476b2bSKai Ye if (ret || qp_id >= qm->qp_num) {
18094476b2bSKai Ye dev_err(dev, "Please input qp num (0-%u)", qm->qp_num - 1);
18194476b2bSKai Ye return -EINVAL;
18294476b2bSKai Ye }
18394476b2bSKai Ye
1845b90073dSWeili Qian ret = qm_set_and_get_xqc(qm, QM_MB_CMD_SQC, &sqc, qp_id, 1);
1855b90073dSWeili Qian if (!ret) {
186*15f112f9SChenghai Huang sqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
187*15f112f9SChenghai Huang sqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
1885b90073dSWeili Qian dump_show(qm, &sqc, sizeof(struct qm_sqc), name);
18994476b2bSKai Ye
1905b90073dSWeili Qian return 0;
1915b90073dSWeili Qian }
1925b90073dSWeili Qian
19394476b2bSKai Ye down_read(&qm->qps_lock);
19494476b2bSKai Ye if (qm->sqc) {
195*15f112f9SChenghai Huang memcpy(&sqc, qm->sqc + qp_id * sizeof(struct qm_sqc), sizeof(struct qm_sqc));
196*15f112f9SChenghai Huang sqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
197*15f112f9SChenghai Huang sqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
198*15f112f9SChenghai Huang dump_show(qm, &sqc, sizeof(struct qm_sqc), "SOFT SQC");
19994476b2bSKai Ye }
20094476b2bSKai Ye up_read(&qm->qps_lock);
20194476b2bSKai Ye
20294476b2bSKai Ye return 0;
20394476b2bSKai Ye }
20494476b2bSKai Ye
qm_cqc_dump(struct hisi_qm * qm,char * s,char * name)2059c756098SKai Ye static int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
20694476b2bSKai Ye {
20794476b2bSKai Ye struct device *dev = &qm->pdev->dev;
2085b90073dSWeili Qian struct qm_cqc cqc;
20994476b2bSKai Ye u32 qp_id;
21094476b2bSKai Ye int ret;
21194476b2bSKai Ye
21294476b2bSKai Ye if (!s)
21394476b2bSKai Ye return -EINVAL;
21494476b2bSKai Ye
21594476b2bSKai Ye ret = kstrtou32(s, 0, &qp_id);
21694476b2bSKai Ye if (ret || qp_id >= qm->qp_num) {
21794476b2bSKai Ye dev_err(dev, "Please input qp num (0-%u)", qm->qp_num - 1);
21894476b2bSKai Ye return -EINVAL;
21994476b2bSKai Ye }
22094476b2bSKai Ye
2215b90073dSWeili Qian ret = qm_set_and_get_xqc(qm, QM_MB_CMD_CQC, &cqc, qp_id, 1);
2225b90073dSWeili Qian if (!ret) {
223*15f112f9SChenghai Huang cqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
224*15f112f9SChenghai Huang cqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
2255b90073dSWeili Qian dump_show(qm, &cqc, sizeof(struct qm_cqc), name);
22694476b2bSKai Ye
2275b90073dSWeili Qian return 0;
2285b90073dSWeili Qian }
2295b90073dSWeili Qian
23094476b2bSKai Ye down_read(&qm->qps_lock);
23194476b2bSKai Ye if (qm->cqc) {
232*15f112f9SChenghai Huang memcpy(&cqc, qm->cqc + qp_id * sizeof(struct qm_cqc), sizeof(struct qm_cqc));
233*15f112f9SChenghai Huang cqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
234*15f112f9SChenghai Huang cqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
235*15f112f9SChenghai Huang dump_show(qm, &cqc, sizeof(struct qm_cqc), "SOFT CQC");
23694476b2bSKai Ye }
23794476b2bSKai Ye up_read(&qm->qps_lock);
23894476b2bSKai Ye
23994476b2bSKai Ye return 0;
24094476b2bSKai Ye }
24194476b2bSKai Ye
qm_eqc_aeqc_dump(struct hisi_qm * qm,char * s,char * name)2429c756098SKai Ye static int qm_eqc_aeqc_dump(struct hisi_qm *qm, char *s, char *name)
24394476b2bSKai Ye {
24494476b2bSKai Ye struct device *dev = &qm->pdev->dev;
2455b90073dSWeili Qian struct qm_aeqc aeqc;
2465b90073dSWeili Qian struct qm_eqc eqc;
2479c756098SKai Ye size_t size;
24894476b2bSKai Ye void *xeqc;
24994476b2bSKai Ye int ret;
2509c756098SKai Ye u8 cmd;
25194476b2bSKai Ye
25294476b2bSKai Ye if (strsep(&s, " ")) {
25394476b2bSKai Ye dev_err(dev, "Please do not input extra characters!\n");
25494476b2bSKai Ye return -EINVAL;
25594476b2bSKai Ye }
25694476b2bSKai Ye
2579c756098SKai Ye if (!strcmp(name, "EQC")) {
2589c756098SKai Ye cmd = QM_MB_CMD_EQC;
2599c756098SKai Ye size = sizeof(struct qm_eqc);
2605b90073dSWeili Qian xeqc = &eqc;
2619c756098SKai Ye } else {
2629c756098SKai Ye cmd = QM_MB_CMD_AEQC;
2639c756098SKai Ye size = sizeof(struct qm_aeqc);
2645b90073dSWeili Qian xeqc = &aeqc;
2659c756098SKai Ye }
2669c756098SKai Ye
2675b90073dSWeili Qian ret = qm_set_and_get_xqc(qm, cmd, xeqc, 0, 1);
26894476b2bSKai Ye if (ret)
2695b90073dSWeili Qian return ret;
27094476b2bSKai Ye
271*15f112f9SChenghai Huang aeqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
272*15f112f9SChenghai Huang aeqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
273*15f112f9SChenghai Huang eqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
274*15f112f9SChenghai Huang eqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
27594476b2bSKai Ye dump_show(qm, xeqc, size, name);
27694476b2bSKai Ye
27794476b2bSKai Ye return ret;
27894476b2bSKai Ye }
27994476b2bSKai Ye
q_dump_param_parse(struct hisi_qm * qm,char * s,u32 * e_id,u32 * q_id,u16 q_depth)28094476b2bSKai Ye static int q_dump_param_parse(struct hisi_qm *qm, char *s,
28194476b2bSKai Ye u32 *e_id, u32 *q_id, u16 q_depth)
28294476b2bSKai Ye {
28394476b2bSKai Ye struct device *dev = &qm->pdev->dev;
28494476b2bSKai Ye unsigned int qp_num = qm->qp_num;
28594476b2bSKai Ye char *presult;
28694476b2bSKai Ye int ret;
28794476b2bSKai Ye
28894476b2bSKai Ye presult = strsep(&s, " ");
28994476b2bSKai Ye if (!presult) {
29094476b2bSKai Ye dev_err(dev, "Please input qp number!\n");
29194476b2bSKai Ye return -EINVAL;
29294476b2bSKai Ye }
29394476b2bSKai Ye
29494476b2bSKai Ye ret = kstrtou32(presult, 0, q_id);
29594476b2bSKai Ye if (ret || *q_id >= qp_num) {
29694476b2bSKai Ye dev_err(dev, "Please input qp num (0-%u)", qp_num - 1);
29794476b2bSKai Ye return -EINVAL;
29894476b2bSKai Ye }
29994476b2bSKai Ye
30094476b2bSKai Ye presult = strsep(&s, " ");
30194476b2bSKai Ye if (!presult) {
30294476b2bSKai Ye dev_err(dev, "Please input sqe number!\n");
30394476b2bSKai Ye return -EINVAL;
30494476b2bSKai Ye }
30594476b2bSKai Ye
30694476b2bSKai Ye ret = kstrtou32(presult, 0, e_id);
30794476b2bSKai Ye if (ret || *e_id >= q_depth) {
30894476b2bSKai Ye dev_err(dev, "Please input sqe num (0-%u)", q_depth - 1);
30994476b2bSKai Ye return -EINVAL;
31094476b2bSKai Ye }
31194476b2bSKai Ye
31294476b2bSKai Ye if (strsep(&s, " ")) {
31394476b2bSKai Ye dev_err(dev, "Please do not input extra characters!\n");
31494476b2bSKai Ye return -EINVAL;
31594476b2bSKai Ye }
31694476b2bSKai Ye
31794476b2bSKai Ye return 0;
31894476b2bSKai Ye }
31994476b2bSKai Ye
qm_sq_dump(struct hisi_qm * qm,char * s,char * name)3209c756098SKai Ye static int qm_sq_dump(struct hisi_qm *qm, char *s, char *name)
32194476b2bSKai Ye {
322*15f112f9SChenghai Huang u16 sq_depth = qm->qp_array->sq_depth;
32394476b2bSKai Ye struct hisi_qp *qp;
32494476b2bSKai Ye u32 qp_id, sqe_id;
325*15f112f9SChenghai Huang void *sqe;
32694476b2bSKai Ye int ret;
32794476b2bSKai Ye
32894476b2bSKai Ye ret = q_dump_param_parse(qm, s, &sqe_id, &qp_id, sq_depth);
32994476b2bSKai Ye if (ret)
33094476b2bSKai Ye return ret;
33194476b2bSKai Ye
332745a1189SChenghai Huang sqe = kzalloc(qm->sqe_size, GFP_KERNEL);
33394476b2bSKai Ye if (!sqe)
33494476b2bSKai Ye return -ENOMEM;
33594476b2bSKai Ye
33694476b2bSKai Ye qp = &qm->qp_array[qp_id];
337745a1189SChenghai Huang memcpy(sqe, qp->sqe + sqe_id * qm->sqe_size, qm->sqe_size);
338745a1189SChenghai Huang memset(sqe + qm->debug.sqe_mask_offset, QM_SQE_ADDR_MASK,
33994476b2bSKai Ye qm->debug.sqe_mask_len);
34094476b2bSKai Ye
341745a1189SChenghai Huang dump_show(qm, sqe, qm->sqe_size, name);
34294476b2bSKai Ye
34394476b2bSKai Ye kfree(sqe);
34494476b2bSKai Ye
34594476b2bSKai Ye return 0;
34694476b2bSKai Ye }
34794476b2bSKai Ye
qm_cq_dump(struct hisi_qm * qm,char * s,char * name)3489c756098SKai Ye static int qm_cq_dump(struct hisi_qm *qm, char *s, char *name)
34994476b2bSKai Ye {
35094476b2bSKai Ye struct qm_cqe *cqe_curr;
35194476b2bSKai Ye struct hisi_qp *qp;
35294476b2bSKai Ye u32 qp_id, cqe_id;
35394476b2bSKai Ye int ret;
35494476b2bSKai Ye
35594476b2bSKai Ye ret = q_dump_param_parse(qm, s, &cqe_id, &qp_id, qm->qp_array->cq_depth);
35694476b2bSKai Ye if (ret)
35794476b2bSKai Ye return ret;
35894476b2bSKai Ye
35994476b2bSKai Ye qp = &qm->qp_array[qp_id];
36094476b2bSKai Ye cqe_curr = qp->cqe + cqe_id;
3619c756098SKai Ye dump_show(qm, cqe_curr, sizeof(struct qm_cqe), name);
36294476b2bSKai Ye
36394476b2bSKai Ye return 0;
36494476b2bSKai Ye }
36594476b2bSKai Ye
qm_eq_aeq_dump(struct hisi_qm * qm,char * s,char * name)3669c756098SKai Ye static int qm_eq_aeq_dump(struct hisi_qm *qm, char *s, char *name)
36794476b2bSKai Ye {
36894476b2bSKai Ye struct device *dev = &qm->pdev->dev;
3699c756098SKai Ye u16 xeq_depth;
3709c756098SKai Ye size_t size;
37194476b2bSKai Ye void *xeqe;
37294476b2bSKai Ye u32 xeqe_id;
37394476b2bSKai Ye int ret;
37494476b2bSKai Ye
37594476b2bSKai Ye if (!s)
37694476b2bSKai Ye return -EINVAL;
37794476b2bSKai Ye
37894476b2bSKai Ye ret = kstrtou32(s, 0, &xeqe_id);
37994476b2bSKai Ye if (ret)
38094476b2bSKai Ye return -EINVAL;
38194476b2bSKai Ye
3829c756098SKai Ye if (!strcmp(name, "EQE")) {
3839c756098SKai Ye xeq_depth = qm->eq_depth;
3849c756098SKai Ye size = sizeof(struct qm_eqe);
3859c756098SKai Ye } else {
3869c756098SKai Ye xeq_depth = qm->aeq_depth;
3879c756098SKai Ye size = sizeof(struct qm_aeqe);
3889c756098SKai Ye }
3899c756098SKai Ye
3909c756098SKai Ye if (xeqe_id >= xeq_depth) {
3919c756098SKai Ye dev_err(dev, "Please input eqe or aeqe num (0-%u)", xeq_depth - 1);
39294476b2bSKai Ye return -EINVAL;
39394476b2bSKai Ye }
39494476b2bSKai Ye
39594476b2bSKai Ye down_read(&qm->qps_lock);
39694476b2bSKai Ye
39794476b2bSKai Ye if (qm->eqe && !strcmp(name, "EQE")) {
39894476b2bSKai Ye xeqe = qm->eqe + xeqe_id;
39994476b2bSKai Ye } else if (qm->aeqe && !strcmp(name, "AEQE")) {
40094476b2bSKai Ye xeqe = qm->aeqe + xeqe_id;
40194476b2bSKai Ye } else {
40294476b2bSKai Ye ret = -EINVAL;
40394476b2bSKai Ye goto err_unlock;
40494476b2bSKai Ye }
40594476b2bSKai Ye
40694476b2bSKai Ye dump_show(qm, xeqe, size, name);
40794476b2bSKai Ye
40894476b2bSKai Ye err_unlock:
40994476b2bSKai Ye up_read(&qm->qps_lock);
41094476b2bSKai Ye return ret;
41194476b2bSKai Ye }
41294476b2bSKai Ye
qm_dbg_help(struct hisi_qm * qm,char * s)41394476b2bSKai Ye static int qm_dbg_help(struct hisi_qm *qm, char *s)
41494476b2bSKai Ye {
41594476b2bSKai Ye struct device *dev = &qm->pdev->dev;
41694476b2bSKai Ye
41794476b2bSKai Ye if (strsep(&s, " ")) {
41894476b2bSKai Ye dev_err(dev, "Please do not input extra characters!\n");
41994476b2bSKai Ye return -EINVAL;
42094476b2bSKai Ye }
42194476b2bSKai Ye
42294476b2bSKai Ye dev_info(dev, "available commands:\n");
42394476b2bSKai Ye dev_info(dev, "sqc <num>\n");
42494476b2bSKai Ye dev_info(dev, "cqc <num>\n");
42594476b2bSKai Ye dev_info(dev, "eqc\n");
42694476b2bSKai Ye dev_info(dev, "aeqc\n");
42794476b2bSKai Ye dev_info(dev, "sq <num> <e>\n");
42894476b2bSKai Ye dev_info(dev, "cq <num> <e>\n");
42994476b2bSKai Ye dev_info(dev, "eq <e>\n");
43094476b2bSKai Ye dev_info(dev, "aeq <e>\n");
43194476b2bSKai Ye
43294476b2bSKai Ye return 0;
43394476b2bSKai Ye }
43494476b2bSKai Ye
4359c756098SKai Ye static const struct qm_cmd_dump_item qm_cmd_dump_table[] = {
4369c756098SKai Ye {
4379c756098SKai Ye .cmd = "sqc",
4389c756098SKai Ye .info_name = "SQC",
4399c756098SKai Ye .dump_fn = qm_sqc_dump,
4409c756098SKai Ye }, {
4419c756098SKai Ye .cmd = "cqc",
4429c756098SKai Ye .info_name = "CQC",
4439c756098SKai Ye .dump_fn = qm_cqc_dump,
4449c756098SKai Ye }, {
4459c756098SKai Ye .cmd = "eqc",
4469c756098SKai Ye .info_name = "EQC",
4479c756098SKai Ye .dump_fn = qm_eqc_aeqc_dump,
4489c756098SKai Ye }, {
4499c756098SKai Ye .cmd = "aeqc",
4509c756098SKai Ye .info_name = "AEQC",
4519c756098SKai Ye .dump_fn = qm_eqc_aeqc_dump,
4529c756098SKai Ye }, {
4539c756098SKai Ye .cmd = "sq",
4549c756098SKai Ye .info_name = "SQE",
4559c756098SKai Ye .dump_fn = qm_sq_dump,
4569c756098SKai Ye }, {
4579c756098SKai Ye .cmd = "cq",
4589c756098SKai Ye .info_name = "CQE",
4599c756098SKai Ye .dump_fn = qm_cq_dump,
4609c756098SKai Ye }, {
4619c756098SKai Ye .cmd = "eq",
4629c756098SKai Ye .info_name = "EQE",
4639c756098SKai Ye .dump_fn = qm_eq_aeq_dump,
4649c756098SKai Ye }, {
4659c756098SKai Ye .cmd = "aeq",
4669c756098SKai Ye .info_name = "AEQE",
4679c756098SKai Ye .dump_fn = qm_eq_aeq_dump,
4689c756098SKai Ye },
4699c756098SKai Ye };
4709c756098SKai Ye
qm_cmd_write_dump(struct hisi_qm * qm,const char * cmd_buf)47194476b2bSKai Ye static int qm_cmd_write_dump(struct hisi_qm *qm, const char *cmd_buf)
47294476b2bSKai Ye {
47394476b2bSKai Ye struct device *dev = &qm->pdev->dev;
47494476b2bSKai Ye char *presult, *s, *s_tmp;
4759c756098SKai Ye int table_size, i, ret;
47694476b2bSKai Ye
47794476b2bSKai Ye s = kstrdup(cmd_buf, GFP_KERNEL);
47894476b2bSKai Ye if (!s)
47994476b2bSKai Ye return -ENOMEM;
48094476b2bSKai Ye
48194476b2bSKai Ye s_tmp = s;
48294476b2bSKai Ye presult = strsep(&s, " ");
48394476b2bSKai Ye if (!presult) {
48494476b2bSKai Ye ret = -EINVAL;
48594476b2bSKai Ye goto err_buffer_free;
48694476b2bSKai Ye }
48794476b2bSKai Ye
4889c756098SKai Ye if (!strcmp(presult, "help")) {
48994476b2bSKai Ye ret = qm_dbg_help(qm, s);
4909c756098SKai Ye goto err_buffer_free;
4919c756098SKai Ye }
49294476b2bSKai Ye
4939c756098SKai Ye table_size = ARRAY_SIZE(qm_cmd_dump_table);
4949c756098SKai Ye for (i = 0; i < table_size; i++) {
4959c756098SKai Ye if (!strcmp(presult, qm_cmd_dump_table[i].cmd)) {
4969c756098SKai Ye ret = qm_cmd_dump_table[i].dump_fn(qm, s,
4979c756098SKai Ye qm_cmd_dump_table[i].info_name);
4989c756098SKai Ye break;
4999c756098SKai Ye }
5009c756098SKai Ye }
5019c756098SKai Ye
5029c756098SKai Ye if (i == table_size) {
50394476b2bSKai Ye dev_info(dev, "Please echo help\n");
5049c756098SKai Ye ret = -EINVAL;
5059c756098SKai Ye }
50694476b2bSKai Ye
50794476b2bSKai Ye err_buffer_free:
50894476b2bSKai Ye kfree(s_tmp);
50994476b2bSKai Ye
51094476b2bSKai Ye return ret;
51194476b2bSKai Ye }
51294476b2bSKai Ye
qm_cmd_write(struct file * filp,const char __user * buffer,size_t count,loff_t * pos)51394476b2bSKai Ye static ssize_t qm_cmd_write(struct file *filp, const char __user *buffer,
51494476b2bSKai Ye size_t count, loff_t *pos)
51594476b2bSKai Ye {
51694476b2bSKai Ye struct hisi_qm *qm = filp->private_data;
51794476b2bSKai Ye char *cmd_buf, *cmd_buf_tmp;
51894476b2bSKai Ye int ret;
51994476b2bSKai Ye
52094476b2bSKai Ye if (*pos)
52194476b2bSKai Ye return 0;
52294476b2bSKai Ye
52394476b2bSKai Ye ret = hisi_qm_get_dfx_access(qm);
52494476b2bSKai Ye if (ret)
52594476b2bSKai Ye return ret;
52694476b2bSKai Ye
52794476b2bSKai Ye /* Judge if the instance is being reset. */
52894476b2bSKai Ye if (unlikely(atomic_read(&qm->status.flags) == QM_STOP)) {
52994476b2bSKai Ye ret = 0;
53094476b2bSKai Ye goto put_dfx_access;
53194476b2bSKai Ye }
53294476b2bSKai Ye
53394476b2bSKai Ye if (count > QM_DBG_WRITE_LEN) {
53494476b2bSKai Ye ret = -ENOSPC;
53594476b2bSKai Ye goto put_dfx_access;
53694476b2bSKai Ye }
53794476b2bSKai Ye
53894476b2bSKai Ye cmd_buf = memdup_user_nul(buffer, count);
53994476b2bSKai Ye if (IS_ERR(cmd_buf)) {
54094476b2bSKai Ye ret = PTR_ERR(cmd_buf);
54194476b2bSKai Ye goto put_dfx_access;
54294476b2bSKai Ye }
54394476b2bSKai Ye
54494476b2bSKai Ye cmd_buf_tmp = strchr(cmd_buf, '\n');
54594476b2bSKai Ye if (cmd_buf_tmp) {
54694476b2bSKai Ye *cmd_buf_tmp = '\0';
54794476b2bSKai Ye count = cmd_buf_tmp - cmd_buf + 1;
54894476b2bSKai Ye }
54994476b2bSKai Ye
55094476b2bSKai Ye ret = qm_cmd_write_dump(qm, cmd_buf);
55194476b2bSKai Ye if (ret) {
55294476b2bSKai Ye kfree(cmd_buf);
55394476b2bSKai Ye goto put_dfx_access;
55494476b2bSKai Ye }
55594476b2bSKai Ye
55694476b2bSKai Ye kfree(cmd_buf);
55794476b2bSKai Ye
55894476b2bSKai Ye ret = count;
55994476b2bSKai Ye
56094476b2bSKai Ye put_dfx_access:
56194476b2bSKai Ye hisi_qm_put_dfx_access(qm);
56294476b2bSKai Ye return ret;
56394476b2bSKai Ye }
56494476b2bSKai Ye
56594476b2bSKai Ye static const struct file_operations qm_cmd_fops = {
56694476b2bSKai Ye .owner = THIS_MODULE,
56794476b2bSKai Ye .open = simple_open,
56894476b2bSKai Ye .read = qm_cmd_read,
56994476b2bSKai Ye .write = qm_cmd_write,
57094476b2bSKai Ye };
57194476b2bSKai Ye
57294476b2bSKai Ye /**
57394476b2bSKai Ye * hisi_qm_regs_dump() - Dump registers's value.
57494476b2bSKai Ye * @s: debugfs file handle.
57594476b2bSKai Ye * @regset: accelerator registers information.
57694476b2bSKai Ye *
57794476b2bSKai Ye * Dump accelerator registers.
57894476b2bSKai Ye */
hisi_qm_regs_dump(struct seq_file * s,struct debugfs_regset32 * regset)57994476b2bSKai Ye void hisi_qm_regs_dump(struct seq_file *s, struct debugfs_regset32 *regset)
58094476b2bSKai Ye {
58194476b2bSKai Ye struct pci_dev *pdev = to_pci_dev(regset->dev);
58294476b2bSKai Ye struct hisi_qm *qm = pci_get_drvdata(pdev);
58394476b2bSKai Ye const struct debugfs_reg32 *regs = regset->regs;
58494476b2bSKai Ye int regs_len = regset->nregs;
58594476b2bSKai Ye int i, ret;
58694476b2bSKai Ye u32 val;
58794476b2bSKai Ye
58894476b2bSKai Ye ret = hisi_qm_get_dfx_access(qm);
58994476b2bSKai Ye if (ret)
59094476b2bSKai Ye return;
59194476b2bSKai Ye
59294476b2bSKai Ye for (i = 0; i < regs_len; i++) {
59394476b2bSKai Ye val = readl(regset->base + regs[i].offset);
59494476b2bSKai Ye seq_printf(s, "%s= 0x%08x\n", regs[i].name, val);
59594476b2bSKai Ye }
59694476b2bSKai Ye
59794476b2bSKai Ye hisi_qm_put_dfx_access(qm);
59894476b2bSKai Ye }
59994476b2bSKai Ye EXPORT_SYMBOL_GPL(hisi_qm_regs_dump);
60094476b2bSKai Ye
qm_regs_show(struct seq_file * s,void * unused)60194476b2bSKai Ye static int qm_regs_show(struct seq_file *s, void *unused)
60294476b2bSKai Ye {
60394476b2bSKai Ye struct hisi_qm *qm = s->private;
60494476b2bSKai Ye struct debugfs_regset32 regset;
60594476b2bSKai Ye
60694476b2bSKai Ye if (qm->fun_type == QM_HW_PF) {
60794476b2bSKai Ye regset.regs = qm_dfx_regs;
60894476b2bSKai Ye regset.nregs = ARRAY_SIZE(qm_dfx_regs);
60994476b2bSKai Ye } else {
61094476b2bSKai Ye regset.regs = qm_vf_dfx_regs;
61194476b2bSKai Ye regset.nregs = ARRAY_SIZE(qm_vf_dfx_regs);
61294476b2bSKai Ye }
61394476b2bSKai Ye
61494476b2bSKai Ye regset.base = qm->io_base;
61594476b2bSKai Ye regset.dev = &qm->pdev->dev;
61694476b2bSKai Ye
61794476b2bSKai Ye hisi_qm_regs_dump(s, ®set);
61894476b2bSKai Ye
61994476b2bSKai Ye return 0;
62094476b2bSKai Ye }
62194476b2bSKai Ye
62294476b2bSKai Ye DEFINE_SHOW_ATTRIBUTE(qm_regs);
62394476b2bSKai Ye
current_q_read(struct hisi_qm * qm)62494476b2bSKai Ye static u32 current_q_read(struct hisi_qm *qm)
62594476b2bSKai Ye {
62694476b2bSKai Ye return readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) >> QM_DFX_QN_SHIFT;
62794476b2bSKai Ye }
62894476b2bSKai Ye
current_q_write(struct hisi_qm * qm,u32 val)62994476b2bSKai Ye static int current_q_write(struct hisi_qm *qm, u32 val)
63094476b2bSKai Ye {
63194476b2bSKai Ye u32 tmp;
63294476b2bSKai Ye
63394476b2bSKai Ye if (val >= qm->debug.curr_qm_qp_num)
63494476b2bSKai Ye return -EINVAL;
63594476b2bSKai Ye
63694476b2bSKai Ye tmp = val << QM_DFX_QN_SHIFT |
63794476b2bSKai Ye (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_FUN_MASK);
63894476b2bSKai Ye writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
63994476b2bSKai Ye
64094476b2bSKai Ye tmp = val << QM_DFX_QN_SHIFT |
64194476b2bSKai Ye (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_FUN_MASK);
64294476b2bSKai Ye writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
64394476b2bSKai Ye
64494476b2bSKai Ye return 0;
64594476b2bSKai Ye }
64694476b2bSKai Ye
clear_enable_read(struct hisi_qm * qm)64794476b2bSKai Ye static u32 clear_enable_read(struct hisi_qm *qm)
64894476b2bSKai Ye {
64994476b2bSKai Ye return readl(qm->io_base + QM_DFX_CNT_CLR_CE);
65094476b2bSKai Ye }
65194476b2bSKai Ye
65294476b2bSKai Ye /* rd_clr_ctrl 1 enable read clear, otherwise 0 disable it */
clear_enable_write(struct hisi_qm * qm,u32 rd_clr_ctrl)65394476b2bSKai Ye static int clear_enable_write(struct hisi_qm *qm, u32 rd_clr_ctrl)
65494476b2bSKai Ye {
65594476b2bSKai Ye if (rd_clr_ctrl > 1)
65694476b2bSKai Ye return -EINVAL;
65794476b2bSKai Ye
65894476b2bSKai Ye writel(rd_clr_ctrl, qm->io_base + QM_DFX_CNT_CLR_CE);
65994476b2bSKai Ye
66094476b2bSKai Ye return 0;
66194476b2bSKai Ye }
66294476b2bSKai Ye
current_qm_read(struct hisi_qm * qm)66394476b2bSKai Ye static u32 current_qm_read(struct hisi_qm *qm)
66494476b2bSKai Ye {
66594476b2bSKai Ye return readl(qm->io_base + QM_DFX_MB_CNT_VF);
66694476b2bSKai Ye }
66794476b2bSKai Ye
qm_get_vf_qp_num(struct hisi_qm * qm,u32 fun_num)66894476b2bSKai Ye static int qm_get_vf_qp_num(struct hisi_qm *qm, u32 fun_num)
66994476b2bSKai Ye {
67094476b2bSKai Ye u32 remain_q_num, vfq_num;
67194476b2bSKai Ye u32 num_vfs = qm->vfs_num;
67294476b2bSKai Ye
67394476b2bSKai Ye vfq_num = (qm->ctrl_qp_num - qm->qp_num) / num_vfs;
67494476b2bSKai Ye if (vfq_num >= qm->max_qp_num)
67594476b2bSKai Ye return qm->max_qp_num;
67694476b2bSKai Ye
67794476b2bSKai Ye remain_q_num = (qm->ctrl_qp_num - qm->qp_num) % num_vfs;
67894476b2bSKai Ye if (vfq_num + remain_q_num <= qm->max_qp_num)
67994476b2bSKai Ye return fun_num == num_vfs ? vfq_num + remain_q_num : vfq_num;
68094476b2bSKai Ye
68194476b2bSKai Ye /*
68294476b2bSKai Ye * if vfq_num + remain_q_num > max_qp_num, the last VFs,
68394476b2bSKai Ye * each with one more queue.
68494476b2bSKai Ye */
68594476b2bSKai Ye return fun_num + remain_q_num > num_vfs ? vfq_num + 1 : vfq_num;
68694476b2bSKai Ye }
68794476b2bSKai Ye
current_qm_write(struct hisi_qm * qm,u32 val)68894476b2bSKai Ye static int current_qm_write(struct hisi_qm *qm, u32 val)
68994476b2bSKai Ye {
69094476b2bSKai Ye u32 tmp;
69194476b2bSKai Ye
69294476b2bSKai Ye if (val > qm->vfs_num)
69394476b2bSKai Ye return -EINVAL;
69494476b2bSKai Ye
69594476b2bSKai Ye /* According PF or VF Dev ID to calculation curr_qm_qp_num and store */
69694476b2bSKai Ye if (!val)
69794476b2bSKai Ye qm->debug.curr_qm_qp_num = qm->qp_num;
69894476b2bSKai Ye else
69994476b2bSKai Ye qm->debug.curr_qm_qp_num = qm_get_vf_qp_num(qm, val);
70094476b2bSKai Ye
70194476b2bSKai Ye writel(val, qm->io_base + QM_DFX_MB_CNT_VF);
70294476b2bSKai Ye writel(val, qm->io_base + QM_DFX_DB_CNT_VF);
70394476b2bSKai Ye
70494476b2bSKai Ye tmp = val |
70594476b2bSKai Ye (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_Q_MASK);
70694476b2bSKai Ye writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
70794476b2bSKai Ye
70894476b2bSKai Ye tmp = val |
70994476b2bSKai Ye (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_Q_MASK);
71094476b2bSKai Ye writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
71194476b2bSKai Ye
71294476b2bSKai Ye return 0;
71394476b2bSKai Ye }
71494476b2bSKai Ye
qm_debug_read(struct file * filp,char __user * buf,size_t count,loff_t * pos)71594476b2bSKai Ye static ssize_t qm_debug_read(struct file *filp, char __user *buf,
71694476b2bSKai Ye size_t count, loff_t *pos)
71794476b2bSKai Ye {
71894476b2bSKai Ye struct debugfs_file *file = filp->private_data;
71994476b2bSKai Ye enum qm_debug_file index = file->index;
72094476b2bSKai Ye struct hisi_qm *qm = file_to_qm(file);
72194476b2bSKai Ye char tbuf[QM_DBG_TMP_BUF_LEN];
72294476b2bSKai Ye u32 val;
72394476b2bSKai Ye int ret;
72494476b2bSKai Ye
72594476b2bSKai Ye ret = hisi_qm_get_dfx_access(qm);
72694476b2bSKai Ye if (ret)
72794476b2bSKai Ye return ret;
72894476b2bSKai Ye
72994476b2bSKai Ye mutex_lock(&file->lock);
73094476b2bSKai Ye switch (index) {
73194476b2bSKai Ye case CURRENT_QM:
73294476b2bSKai Ye val = current_qm_read(qm);
73394476b2bSKai Ye break;
73494476b2bSKai Ye case CURRENT_Q:
73594476b2bSKai Ye val = current_q_read(qm);
73694476b2bSKai Ye break;
73794476b2bSKai Ye case CLEAR_ENABLE:
73894476b2bSKai Ye val = clear_enable_read(qm);
73994476b2bSKai Ye break;
74094476b2bSKai Ye default:
74194476b2bSKai Ye goto err_input;
74294476b2bSKai Ye }
74394476b2bSKai Ye mutex_unlock(&file->lock);
74494476b2bSKai Ye
74594476b2bSKai Ye hisi_qm_put_dfx_access(qm);
74694476b2bSKai Ye ret = scnprintf(tbuf, QM_DBG_TMP_BUF_LEN, "%u\n", val);
74794476b2bSKai Ye return simple_read_from_buffer(buf, count, pos, tbuf, ret);
74894476b2bSKai Ye
74994476b2bSKai Ye err_input:
75094476b2bSKai Ye mutex_unlock(&file->lock);
75194476b2bSKai Ye hisi_qm_put_dfx_access(qm);
75294476b2bSKai Ye return -EINVAL;
75394476b2bSKai Ye }
75494476b2bSKai Ye
qm_debug_write(struct file * filp,const char __user * buf,size_t count,loff_t * pos)75594476b2bSKai Ye static ssize_t qm_debug_write(struct file *filp, const char __user *buf,
75694476b2bSKai Ye size_t count, loff_t *pos)
75794476b2bSKai Ye {
75894476b2bSKai Ye struct debugfs_file *file = filp->private_data;
75994476b2bSKai Ye enum qm_debug_file index = file->index;
76094476b2bSKai Ye struct hisi_qm *qm = file_to_qm(file);
76194476b2bSKai Ye unsigned long val;
76294476b2bSKai Ye char tbuf[QM_DBG_TMP_BUF_LEN];
76394476b2bSKai Ye int len, ret;
76494476b2bSKai Ye
76594476b2bSKai Ye if (*pos != 0)
76694476b2bSKai Ye return 0;
76794476b2bSKai Ye
76894476b2bSKai Ye if (count >= QM_DBG_TMP_BUF_LEN)
76994476b2bSKai Ye return -ENOSPC;
77094476b2bSKai Ye
77194476b2bSKai Ye len = simple_write_to_buffer(tbuf, QM_DBG_TMP_BUF_LEN - 1, pos, buf,
77294476b2bSKai Ye count);
77394476b2bSKai Ye if (len < 0)
77494476b2bSKai Ye return len;
77594476b2bSKai Ye
77694476b2bSKai Ye tbuf[len] = '\0';
77794476b2bSKai Ye if (kstrtoul(tbuf, 0, &val))
77894476b2bSKai Ye return -EFAULT;
77994476b2bSKai Ye
78094476b2bSKai Ye ret = hisi_qm_get_dfx_access(qm);
78194476b2bSKai Ye if (ret)
78294476b2bSKai Ye return ret;
78394476b2bSKai Ye
78494476b2bSKai Ye mutex_lock(&file->lock);
78594476b2bSKai Ye switch (index) {
78694476b2bSKai Ye case CURRENT_QM:
78794476b2bSKai Ye ret = current_qm_write(qm, val);
78894476b2bSKai Ye break;
78994476b2bSKai Ye case CURRENT_Q:
79094476b2bSKai Ye ret = current_q_write(qm, val);
79194476b2bSKai Ye break;
79294476b2bSKai Ye case CLEAR_ENABLE:
79394476b2bSKai Ye ret = clear_enable_write(qm, val);
79494476b2bSKai Ye break;
79594476b2bSKai Ye default:
79694476b2bSKai Ye ret = -EINVAL;
79794476b2bSKai Ye }
79894476b2bSKai Ye mutex_unlock(&file->lock);
79994476b2bSKai Ye
80094476b2bSKai Ye hisi_qm_put_dfx_access(qm);
80194476b2bSKai Ye
80294476b2bSKai Ye if (ret)
80394476b2bSKai Ye return ret;
80494476b2bSKai Ye
80594476b2bSKai Ye return count;
80694476b2bSKai Ye }
80794476b2bSKai Ye
80894476b2bSKai Ye static const struct file_operations qm_debug_fops = {
80994476b2bSKai Ye .owner = THIS_MODULE,
81094476b2bSKai Ye .open = simple_open,
81194476b2bSKai Ye .read = qm_debug_read,
81294476b2bSKai Ye .write = qm_debug_write,
81394476b2bSKai Ye };
81494476b2bSKai Ye
dfx_regs_uninit(struct hisi_qm * qm,struct dfx_diff_registers * dregs,int reg_len)81594476b2bSKai Ye static void dfx_regs_uninit(struct hisi_qm *qm,
81694476b2bSKai Ye struct dfx_diff_registers *dregs, int reg_len)
81794476b2bSKai Ye {
81894476b2bSKai Ye int i;
81994476b2bSKai Ye
8208be09133SChenghai Huang if (!dregs)
8218be09133SChenghai Huang return;
8228be09133SChenghai Huang
82394476b2bSKai Ye /* Setting the pointer is NULL to prevent double free */
82494476b2bSKai Ye for (i = 0; i < reg_len; i++) {
8258be09133SChenghai Huang if (!dregs[i].regs)
8268be09133SChenghai Huang continue;
8278be09133SChenghai Huang
82894476b2bSKai Ye kfree(dregs[i].regs);
82994476b2bSKai Ye dregs[i].regs = NULL;
83094476b2bSKai Ye }
83194476b2bSKai Ye kfree(dregs);
83294476b2bSKai Ye }
83394476b2bSKai Ye
dfx_regs_init(struct hisi_qm * qm,const struct dfx_diff_registers * cregs,u32 reg_len)83494476b2bSKai Ye static struct dfx_diff_registers *dfx_regs_init(struct hisi_qm *qm,
83594476b2bSKai Ye const struct dfx_diff_registers *cregs, u32 reg_len)
83694476b2bSKai Ye {
83794476b2bSKai Ye struct dfx_diff_registers *diff_regs;
83894476b2bSKai Ye u32 j, base_offset;
83994476b2bSKai Ye int i;
84094476b2bSKai Ye
84194476b2bSKai Ye diff_regs = kcalloc(reg_len, sizeof(*diff_regs), GFP_KERNEL);
84294476b2bSKai Ye if (!diff_regs)
84394476b2bSKai Ye return ERR_PTR(-ENOMEM);
84494476b2bSKai Ye
84594476b2bSKai Ye for (i = 0; i < reg_len; i++) {
84694476b2bSKai Ye if (!cregs[i].reg_len)
84794476b2bSKai Ye continue;
84894476b2bSKai Ye
84994476b2bSKai Ye diff_regs[i].reg_offset = cregs[i].reg_offset;
85094476b2bSKai Ye diff_regs[i].reg_len = cregs[i].reg_len;
85194476b2bSKai Ye diff_regs[i].regs = kcalloc(QM_DFX_REGS_LEN, cregs[i].reg_len,
85294476b2bSKai Ye GFP_KERNEL);
85394476b2bSKai Ye if (!diff_regs[i].regs)
85494476b2bSKai Ye goto alloc_error;
85594476b2bSKai Ye
85694476b2bSKai Ye for (j = 0; j < diff_regs[i].reg_len; j++) {
85794476b2bSKai Ye base_offset = diff_regs[i].reg_offset +
85894476b2bSKai Ye j * QM_DFX_REGS_LEN;
85994476b2bSKai Ye diff_regs[i].regs[j] = readl(qm->io_base + base_offset);
86094476b2bSKai Ye }
86194476b2bSKai Ye }
86294476b2bSKai Ye
86394476b2bSKai Ye return diff_regs;
86494476b2bSKai Ye
86594476b2bSKai Ye alloc_error:
86694476b2bSKai Ye while (i > 0) {
86794476b2bSKai Ye i--;
86894476b2bSKai Ye kfree(diff_regs[i].regs);
86994476b2bSKai Ye }
87094476b2bSKai Ye kfree(diff_regs);
87194476b2bSKai Ye return ERR_PTR(-ENOMEM);
87294476b2bSKai Ye }
87394476b2bSKai Ye
qm_diff_regs_init(struct hisi_qm * qm,struct dfx_diff_registers * dregs,u32 reg_len)87494476b2bSKai Ye static int qm_diff_regs_init(struct hisi_qm *qm,
87594476b2bSKai Ye struct dfx_diff_registers *dregs, u32 reg_len)
87694476b2bSKai Ye {
8778be09133SChenghai Huang int ret;
8788be09133SChenghai Huang
87994476b2bSKai Ye qm->debug.qm_diff_regs = dfx_regs_init(qm, qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
8808be09133SChenghai Huang if (IS_ERR(qm->debug.qm_diff_regs)) {
8818be09133SChenghai Huang ret = PTR_ERR(qm->debug.qm_diff_regs);
8828be09133SChenghai Huang qm->debug.qm_diff_regs = NULL;
8838be09133SChenghai Huang return ret;
8848be09133SChenghai Huang }
88594476b2bSKai Ye
88694476b2bSKai Ye qm->debug.acc_diff_regs = dfx_regs_init(qm, dregs, reg_len);
88794476b2bSKai Ye if (IS_ERR(qm->debug.acc_diff_regs)) {
88894476b2bSKai Ye dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
8898be09133SChenghai Huang ret = PTR_ERR(qm->debug.acc_diff_regs);
8908be09133SChenghai Huang qm->debug.acc_diff_regs = NULL;
8918be09133SChenghai Huang return ret;
89294476b2bSKai Ye }
89394476b2bSKai Ye
89494476b2bSKai Ye return 0;
89594476b2bSKai Ye }
89694476b2bSKai Ye
qm_last_regs_uninit(struct hisi_qm * qm)89794476b2bSKai Ye static void qm_last_regs_uninit(struct hisi_qm *qm)
89894476b2bSKai Ye {
89994476b2bSKai Ye struct qm_debug *debug = &qm->debug;
90094476b2bSKai Ye
90194476b2bSKai Ye if (qm->fun_type == QM_HW_VF || !debug->qm_last_words)
90294476b2bSKai Ye return;
90394476b2bSKai Ye
90494476b2bSKai Ye kfree(debug->qm_last_words);
90594476b2bSKai Ye debug->qm_last_words = NULL;
90694476b2bSKai Ye }
90794476b2bSKai Ye
qm_last_regs_init(struct hisi_qm * qm)90894476b2bSKai Ye static int qm_last_regs_init(struct hisi_qm *qm)
90994476b2bSKai Ye {
91094476b2bSKai Ye int dfx_regs_num = ARRAY_SIZE(qm_dfx_regs);
91194476b2bSKai Ye struct qm_debug *debug = &qm->debug;
91294476b2bSKai Ye int i;
91394476b2bSKai Ye
91494476b2bSKai Ye if (qm->fun_type == QM_HW_VF)
91594476b2bSKai Ye return 0;
91694476b2bSKai Ye
91794476b2bSKai Ye debug->qm_last_words = kcalloc(dfx_regs_num, sizeof(unsigned int), GFP_KERNEL);
91894476b2bSKai Ye if (!debug->qm_last_words)
91994476b2bSKai Ye return -ENOMEM;
92094476b2bSKai Ye
92194476b2bSKai Ye for (i = 0; i < dfx_regs_num; i++) {
92294476b2bSKai Ye debug->qm_last_words[i] = readl_relaxed(qm->io_base +
92394476b2bSKai Ye qm_dfx_regs[i].offset);
92494476b2bSKai Ye }
92594476b2bSKai Ye
92694476b2bSKai Ye return 0;
92794476b2bSKai Ye }
92894476b2bSKai Ye
qm_diff_regs_uninit(struct hisi_qm * qm,u32 reg_len)92994476b2bSKai Ye static void qm_diff_regs_uninit(struct hisi_qm *qm, u32 reg_len)
93094476b2bSKai Ye {
93194476b2bSKai Ye dfx_regs_uninit(qm, qm->debug.acc_diff_regs, reg_len);
9328be09133SChenghai Huang qm->debug.acc_diff_regs = NULL;
93394476b2bSKai Ye dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs));
9348be09133SChenghai Huang qm->debug.qm_diff_regs = NULL;
93594476b2bSKai Ye }
93694476b2bSKai Ye
93794476b2bSKai Ye /**
93894476b2bSKai Ye * hisi_qm_regs_debugfs_init() - Allocate memory for registers.
93994476b2bSKai Ye * @qm: device qm handle.
94094476b2bSKai Ye * @dregs: diff registers handle.
94194476b2bSKai Ye * @reg_len: diff registers region length.
94294476b2bSKai Ye */
hisi_qm_regs_debugfs_init(struct hisi_qm * qm,struct dfx_diff_registers * dregs,u32 reg_len)94394476b2bSKai Ye int hisi_qm_regs_debugfs_init(struct hisi_qm *qm,
94494476b2bSKai Ye struct dfx_diff_registers *dregs, u32 reg_len)
94594476b2bSKai Ye {
94694476b2bSKai Ye int ret;
94794476b2bSKai Ye
94894476b2bSKai Ye if (!qm || !dregs)
94994476b2bSKai Ye return -EINVAL;
95094476b2bSKai Ye
95194476b2bSKai Ye if (qm->fun_type != QM_HW_PF)
95294476b2bSKai Ye return 0;
95394476b2bSKai Ye
95494476b2bSKai Ye ret = qm_last_regs_init(qm);
95594476b2bSKai Ye if (ret) {
95694476b2bSKai Ye dev_info(&qm->pdev->dev, "failed to init qm words memory!\n");
95794476b2bSKai Ye return ret;
95894476b2bSKai Ye }
95994476b2bSKai Ye
96094476b2bSKai Ye ret = qm_diff_regs_init(qm, dregs, reg_len);
96194476b2bSKai Ye if (ret) {
96294476b2bSKai Ye qm_last_regs_uninit(qm);
96394476b2bSKai Ye return ret;
96494476b2bSKai Ye }
96594476b2bSKai Ye
96694476b2bSKai Ye return 0;
96794476b2bSKai Ye }
96894476b2bSKai Ye EXPORT_SYMBOL_GPL(hisi_qm_regs_debugfs_init);
96994476b2bSKai Ye
97094476b2bSKai Ye /**
97194476b2bSKai Ye * hisi_qm_regs_debugfs_uninit() - Free memory for registers.
97294476b2bSKai Ye * @qm: device qm handle.
97394476b2bSKai Ye * @reg_len: diff registers region length.
97494476b2bSKai Ye */
hisi_qm_regs_debugfs_uninit(struct hisi_qm * qm,u32 reg_len)97594476b2bSKai Ye void hisi_qm_regs_debugfs_uninit(struct hisi_qm *qm, u32 reg_len)
97694476b2bSKai Ye {
97794476b2bSKai Ye if (!qm || qm->fun_type != QM_HW_PF)
97894476b2bSKai Ye return;
97994476b2bSKai Ye
98094476b2bSKai Ye qm_diff_regs_uninit(qm, reg_len);
98194476b2bSKai Ye qm_last_regs_uninit(qm);
98294476b2bSKai Ye }
98394476b2bSKai Ye EXPORT_SYMBOL_GPL(hisi_qm_regs_debugfs_uninit);
98494476b2bSKai Ye
98594476b2bSKai Ye /**
98694476b2bSKai Ye * hisi_qm_acc_diff_regs_dump() - Dump registers's value.
98794476b2bSKai Ye * @qm: device qm handle.
98894476b2bSKai Ye * @s: Debugfs file handle.
98994476b2bSKai Ye * @dregs: diff registers handle.
99094476b2bSKai Ye * @regs_len: diff registers region length.
99194476b2bSKai Ye */
hisi_qm_acc_diff_regs_dump(struct hisi_qm * qm,struct seq_file * s,struct dfx_diff_registers * dregs,u32 regs_len)99294476b2bSKai Ye void hisi_qm_acc_diff_regs_dump(struct hisi_qm *qm, struct seq_file *s,
99394476b2bSKai Ye struct dfx_diff_registers *dregs, u32 regs_len)
99494476b2bSKai Ye {
99594476b2bSKai Ye u32 j, val, base_offset;
99694476b2bSKai Ye int i, ret;
99794476b2bSKai Ye
99894476b2bSKai Ye if (!qm || !s || !dregs)
99994476b2bSKai Ye return;
100094476b2bSKai Ye
100194476b2bSKai Ye ret = hisi_qm_get_dfx_access(qm);
100294476b2bSKai Ye if (ret)
100394476b2bSKai Ye return;
100494476b2bSKai Ye
100594476b2bSKai Ye down_read(&qm->qps_lock);
100694476b2bSKai Ye for (i = 0; i < regs_len; i++) {
100794476b2bSKai Ye if (!dregs[i].reg_len)
100894476b2bSKai Ye continue;
100994476b2bSKai Ye
101094476b2bSKai Ye for (j = 0; j < dregs[i].reg_len; j++) {
101194476b2bSKai Ye base_offset = dregs[i].reg_offset + j * QM_DFX_REGS_LEN;
101294476b2bSKai Ye val = readl(qm->io_base + base_offset);
101394476b2bSKai Ye if (val != dregs[i].regs[j])
101494476b2bSKai Ye seq_printf(s, "0x%08x = 0x%08x ---> 0x%08x\n",
101594476b2bSKai Ye base_offset, dregs[i].regs[j], val);
101694476b2bSKai Ye }
101794476b2bSKai Ye }
101894476b2bSKai Ye up_read(&qm->qps_lock);
101994476b2bSKai Ye
102094476b2bSKai Ye hisi_qm_put_dfx_access(qm);
102194476b2bSKai Ye }
102294476b2bSKai Ye EXPORT_SYMBOL_GPL(hisi_qm_acc_diff_regs_dump);
102394476b2bSKai Ye
hisi_qm_show_last_dfx_regs(struct hisi_qm * qm)102494476b2bSKai Ye void hisi_qm_show_last_dfx_regs(struct hisi_qm *qm)
102594476b2bSKai Ye {
102694476b2bSKai Ye struct qm_debug *debug = &qm->debug;
102794476b2bSKai Ye struct pci_dev *pdev = qm->pdev;
102894476b2bSKai Ye u32 val;
102994476b2bSKai Ye int i;
103094476b2bSKai Ye
103194476b2bSKai Ye if (qm->fun_type == QM_HW_VF || !debug->qm_last_words)
103294476b2bSKai Ye return;
103394476b2bSKai Ye
103494476b2bSKai Ye for (i = 0; i < ARRAY_SIZE(qm_dfx_regs); i++) {
103594476b2bSKai Ye val = readl_relaxed(qm->io_base + qm_dfx_regs[i].offset);
103694476b2bSKai Ye if (debug->qm_last_words[i] != val)
103794476b2bSKai Ye pci_info(pdev, "%s \t= 0x%08x => 0x%08x\n",
103894476b2bSKai Ye qm_dfx_regs[i].name, debug->qm_last_words[i], val);
103994476b2bSKai Ye }
104094476b2bSKai Ye }
104194476b2bSKai Ye
qm_diff_regs_show(struct seq_file * s,void * unused)104294476b2bSKai Ye static int qm_diff_regs_show(struct seq_file *s, void *unused)
104394476b2bSKai Ye {
104494476b2bSKai Ye struct hisi_qm *qm = s->private;
104594476b2bSKai Ye
104694476b2bSKai Ye hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.qm_diff_regs,
104794476b2bSKai Ye ARRAY_SIZE(qm_diff_regs));
104894476b2bSKai Ye
104994476b2bSKai Ye return 0;
105094476b2bSKai Ye }
105194476b2bSKai Ye DEFINE_SHOW_ATTRIBUTE(qm_diff_regs);
105294476b2bSKai Ye
qm_state_show(struct seq_file * s,void * unused)10538413fe3eSWeili Qian static int qm_state_show(struct seq_file *s, void *unused)
10548413fe3eSWeili Qian {
10558413fe3eSWeili Qian struct hisi_qm *qm = s->private;
10568413fe3eSWeili Qian u32 val;
10578413fe3eSWeili Qian int ret;
10588413fe3eSWeili Qian
10598413fe3eSWeili Qian /* If device is in suspended, directly return the idle state. */
10608413fe3eSWeili Qian ret = hisi_qm_get_dfx_access(qm);
10618413fe3eSWeili Qian if (!ret) {
10628413fe3eSWeili Qian val = readl(qm->io_base + QM_IN_IDLE_ST_REG);
10638413fe3eSWeili Qian hisi_qm_put_dfx_access(qm);
10648413fe3eSWeili Qian } else if (ret == -EAGAIN) {
10658413fe3eSWeili Qian val = QM_IN_IDLE_STATE;
10668413fe3eSWeili Qian } else {
10678413fe3eSWeili Qian return ret;
10688413fe3eSWeili Qian }
10698413fe3eSWeili Qian
10708413fe3eSWeili Qian seq_printf(s, "%u\n", val);
10718413fe3eSWeili Qian
10728413fe3eSWeili Qian return 0;
10738413fe3eSWeili Qian }
10748413fe3eSWeili Qian
10758413fe3eSWeili Qian DEFINE_SHOW_ATTRIBUTE(qm_state);
10768413fe3eSWeili Qian
qm_status_read(struct file * filp,char __user * buffer,size_t count,loff_t * pos)107794476b2bSKai Ye static ssize_t qm_status_read(struct file *filp, char __user *buffer,
107894476b2bSKai Ye size_t count, loff_t *pos)
107994476b2bSKai Ye {
108094476b2bSKai Ye struct hisi_qm *qm = filp->private_data;
108194476b2bSKai Ye char buf[QM_DBG_READ_LEN];
108294476b2bSKai Ye int val, len;
108394476b2bSKai Ye
108494476b2bSKai Ye val = atomic_read(&qm->status.flags);
108594476b2bSKai Ye len = scnprintf(buf, QM_DBG_READ_LEN, "%s\n", qm_s[val]);
108694476b2bSKai Ye
108794476b2bSKai Ye return simple_read_from_buffer(buffer, count, pos, buf, len);
108894476b2bSKai Ye }
108994476b2bSKai Ye
109094476b2bSKai Ye static const struct file_operations qm_status_fops = {
109194476b2bSKai Ye .owner = THIS_MODULE,
109294476b2bSKai Ye .open = simple_open,
109394476b2bSKai Ye .read = qm_status_read,
109494476b2bSKai Ye };
109594476b2bSKai Ye
qm_create_debugfs_file(struct hisi_qm * qm,struct dentry * dir,enum qm_debug_file index)109694476b2bSKai Ye static void qm_create_debugfs_file(struct hisi_qm *qm, struct dentry *dir,
109794476b2bSKai Ye enum qm_debug_file index)
109894476b2bSKai Ye {
109994476b2bSKai Ye struct debugfs_file *file = qm->debug.files + index;
110094476b2bSKai Ye
110194476b2bSKai Ye file->index = index;
110294476b2bSKai Ye mutex_init(&file->lock);
110394476b2bSKai Ye file->debug = &qm->debug;
11043b7db97eSChenghai Huang
11053b7db97eSChenghai Huang debugfs_create_file(qm_debug_file_name[index], 0600, dir, file,
11063b7db97eSChenghai Huang &qm_debug_fops);
110794476b2bSKai Ye }
110894476b2bSKai Ye
qm_debugfs_atomic64_set(void * data,u64 val)110994476b2bSKai Ye static int qm_debugfs_atomic64_set(void *data, u64 val)
111094476b2bSKai Ye {
111194476b2bSKai Ye if (val)
111294476b2bSKai Ye return -EINVAL;
111394476b2bSKai Ye
111494476b2bSKai Ye atomic64_set((atomic64_t *)data, 0);
111594476b2bSKai Ye
111694476b2bSKai Ye return 0;
111794476b2bSKai Ye }
111894476b2bSKai Ye
qm_debugfs_atomic64_get(void * data,u64 * val)111994476b2bSKai Ye static int qm_debugfs_atomic64_get(void *data, u64 *val)
112094476b2bSKai Ye {
112194476b2bSKai Ye *val = atomic64_read((atomic64_t *)data);
112294476b2bSKai Ye
112394476b2bSKai Ye return 0;
112494476b2bSKai Ye }
112594476b2bSKai Ye
112694476b2bSKai Ye DEFINE_DEBUGFS_ATTRIBUTE(qm_atomic64_ops, qm_debugfs_atomic64_get,
112794476b2bSKai Ye qm_debugfs_atomic64_set, "%llu\n");
112894476b2bSKai Ye
112994476b2bSKai Ye /**
113094476b2bSKai Ye * hisi_qm_debug_init() - Initialize qm related debugfs files.
113194476b2bSKai Ye * @qm: The qm for which we want to add debugfs files.
113294476b2bSKai Ye *
113394476b2bSKai Ye * Create qm related debugfs files.
113494476b2bSKai Ye */
hisi_qm_debug_init(struct hisi_qm * qm)113594476b2bSKai Ye void hisi_qm_debug_init(struct hisi_qm *qm)
113694476b2bSKai Ye {
113794476b2bSKai Ye struct dfx_diff_registers *qm_regs = qm->debug.qm_diff_regs;
1138ce133a22SWeili Qian struct qm_dev_dfx *dev_dfx = &qm->debug.dev_dfx;
113994476b2bSKai Ye struct qm_dfx *dfx = &qm->debug.dfx;
114094476b2bSKai Ye struct dentry *qm_d;
114194476b2bSKai Ye void *data;
114294476b2bSKai Ye int i;
114394476b2bSKai Ye
114494476b2bSKai Ye qm_d = debugfs_create_dir("qm", qm->debug.debug_root);
114594476b2bSKai Ye qm->debug.qm_d = qm_d;
114694476b2bSKai Ye
114794476b2bSKai Ye /* only show this in PF */
114894476b2bSKai Ye if (qm->fun_type == QM_HW_PF) {
11498413fe3eSWeili Qian debugfs_create_file("qm_state", 0444, qm->debug.qm_d,
11508413fe3eSWeili Qian qm, &qm_state_fops);
11518413fe3eSWeili Qian
115294476b2bSKai Ye qm_create_debugfs_file(qm, qm->debug.debug_root, CURRENT_QM);
115394476b2bSKai Ye for (i = CURRENT_Q; i < DEBUG_FILE_NUM; i++)
115494476b2bSKai Ye qm_create_debugfs_file(qm, qm->debug.qm_d, i);
115594476b2bSKai Ye }
115694476b2bSKai Ye
115794476b2bSKai Ye if (qm_regs)
115894476b2bSKai Ye debugfs_create_file("diff_regs", 0444, qm->debug.qm_d,
115994476b2bSKai Ye qm, &qm_diff_regs_fops);
116094476b2bSKai Ye
116194476b2bSKai Ye debugfs_create_file("regs", 0444, qm->debug.qm_d, qm, &qm_regs_fops);
116294476b2bSKai Ye
116394476b2bSKai Ye debugfs_create_file("cmd", 0600, qm->debug.qm_d, qm, &qm_cmd_fops);
116494476b2bSKai Ye
116594476b2bSKai Ye debugfs_create_file("status", 0444, qm->debug.qm_d, qm,
116694476b2bSKai Ye &qm_status_fops);
1167ce133a22SWeili Qian
1168ce133a22SWeili Qian debugfs_create_u32("dev_state", 0444, qm->debug.qm_d, &dev_dfx->dev_state);
1169ce133a22SWeili Qian debugfs_create_u32("dev_timeout", 0644, qm->debug.qm_d, &dev_dfx->dev_timeout);
1170ce133a22SWeili Qian
117194476b2bSKai Ye for (i = 0; i < ARRAY_SIZE(qm_dfx_files); i++) {
117294476b2bSKai Ye data = (atomic64_t *)((uintptr_t)dfx + qm_dfx_files[i].offset);
117394476b2bSKai Ye debugfs_create_file(qm_dfx_files[i].name,
117494476b2bSKai Ye 0644,
117594476b2bSKai Ye qm_d,
117694476b2bSKai Ye data,
117794476b2bSKai Ye &qm_atomic64_ops);
117894476b2bSKai Ye }
117994476b2bSKai Ye
118094476b2bSKai Ye if (test_bit(QM_SUPPORT_FUNC_QOS, &qm->caps))
118194476b2bSKai Ye hisi_qm_set_algqos_init(qm);
118294476b2bSKai Ye }
118394476b2bSKai Ye EXPORT_SYMBOL_GPL(hisi_qm_debug_init);
118494476b2bSKai Ye
118594476b2bSKai Ye /**
118694476b2bSKai Ye * hisi_qm_debug_regs_clear() - clear qm debug related registers.
118794476b2bSKai Ye * @qm: The qm for which we want to clear its debug registers.
118894476b2bSKai Ye */
hisi_qm_debug_regs_clear(struct hisi_qm * qm)118994476b2bSKai Ye void hisi_qm_debug_regs_clear(struct hisi_qm *qm)
119094476b2bSKai Ye {
119194476b2bSKai Ye const struct debugfs_reg32 *regs;
119294476b2bSKai Ye int i;
119394476b2bSKai Ye
119494476b2bSKai Ye /* clear current_qm */
119594476b2bSKai Ye writel(0x0, qm->io_base + QM_DFX_MB_CNT_VF);
119694476b2bSKai Ye writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF);
119794476b2bSKai Ye
119894476b2bSKai Ye /* clear current_q */
119994476b2bSKai Ye writel(0x0, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
120094476b2bSKai Ye writel(0x0, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
120194476b2bSKai Ye
120294476b2bSKai Ye /*
120394476b2bSKai Ye * these registers are reading and clearing, so clear them after
120494476b2bSKai Ye * reading them.
120594476b2bSKai Ye */
120694476b2bSKai Ye writel(0x1, qm->io_base + QM_DFX_CNT_CLR_CE);
120794476b2bSKai Ye
120894476b2bSKai Ye regs = qm_dfx_regs;
120994476b2bSKai Ye for (i = 0; i < CNT_CYC_REGS_NUM; i++) {
121094476b2bSKai Ye readl(qm->io_base + regs->offset);
121194476b2bSKai Ye regs++;
121294476b2bSKai Ye }
121394476b2bSKai Ye
121494476b2bSKai Ye /* clear clear_enable */
121594476b2bSKai Ye writel(0x0, qm->io_base + QM_DFX_CNT_CLR_CE);
121694476b2bSKai Ye }
121794476b2bSKai Ye EXPORT_SYMBOL_GPL(hisi_qm_debug_regs_clear);
1218