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, ®set); 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