]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
crypto: hisilicon - add device load query functionality to debugfs
authorZongyu Wu <wuzongyu1@huawei.com>
Fri, 13 Mar 2026 09:40:39 +0000 (17:40 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sun, 22 Mar 2026 02:17:59 +0000 (11:17 +0900)
The accelerator device supports usage statistics. This patch enables
obtaining the accelerator's usage through the "dev_usage" file.
The returned number expressed as a percentage as a percentage.

Signed-off-by: Zongyu Wu <wuzongyu1@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Documentation/ABI/testing/debugfs-hisi-hpre
Documentation/ABI/testing/debugfs-hisi-sec
Documentation/ABI/testing/debugfs-hisi-zip
drivers/crypto/hisilicon/debugfs.c
drivers/crypto/hisilicon/hpre/hpre_main.c
drivers/crypto/hisilicon/sec2/sec_main.c
drivers/crypto/hisilicon/zip/zip_main.c
include/linux/hisi_acc_qm.h

index 29fb7d5ffc691f20c68ccf9bac7e26902b9982cf..5a137f701eead9b3174b2020786e74bba30eced7 100644 (file)
@@ -50,6 +50,13 @@ Description: Dump debug registers from the QM.
                Available for PF and VF in host. VF in guest currently only
                has one debug register.
 
+What:          /sys/kernel/debug/hisi_hpre/<bdf>/dev_usage
+Date:          Mar 2026
+Contact:       linux-crypto@vger.kernel.org
+Description:   Query the real-time bandwidth usage of device.
+               Returns the bandwidth usage of each channel on the device.
+               The returned number is in percentage.
+
 What:          /sys/kernel/debug/hisi_hpre/<bdf>/qm/current_q
 Date:          Sep 2019
 Contact:       linux-crypto@vger.kernel.org
index 82bf4a0dc7f78a0839875b0a828641990e6e8a20..676e2dc2de8d3e474011b8fe417f76311c6171b6 100644 (file)
@@ -24,6 +24,13 @@ Description: The <bdf> is related the function for PF and VF.
                1/1000~1000/1000 of total QoS. The driver reading alg_qos to
                get related QoS in the host and VM, Such as "cat alg_qos".
 
+What:          /sys/kernel/debug/hisi_sec2/<bdf>/dev_usage
+Date:          Mar 2026
+Contact:       linux-crypto@vger.kernel.org
+Description:   Query the real-time bandwidth usage of device.
+               Returns the bandwidth usage of each channel on the device.
+               The returned number is in percentage.
+
 What:          /sys/kernel/debug/hisi_sec2/<bdf>/qm/qm_regs
 Date:          Oct 2019
 Contact:       linux-crypto@vger.kernel.org
index 0abd65d27e9bb3b40dd8ee9dde6ef4b7a2067674..46bf47bf6b426fb905ae6dc5287bcacf6e5c1bc7 100644 (file)
@@ -36,6 +36,13 @@ Description: The <bdf> is related the function for PF and VF.
                1/1000~1000/1000 of total QoS. The driver reading alg_qos to
                get related QoS in the host and VM, Such as "cat alg_qos".
 
+What:          /sys/kernel/debug/hisi_zip/<bdf>/dev_usage
+Date:          Mar 2026
+Contact:       linux-crypto@vger.kernel.org
+Description:   Query the real-time bandwidth usage of device.
+               Returns the bandwidth usage of each channel on the device.
+               The returned number is in percentage.
+
 What:          /sys/kernel/debug/hisi_zip/<bdf>/qm/regs
 Date:          Nov 2018
 Contact:       linux-crypto@vger.kernel.org
index 32e9f83502894d980e8225636be1f567f8840359..5d8b4112c54346420a5d26aeee0b8c822f0b8db8 100644 (file)
@@ -1040,6 +1040,57 @@ void hisi_qm_show_last_dfx_regs(struct hisi_qm *qm)
        }
 }
 
+static int qm_usage_percent(struct hisi_qm *qm, int chan_num)
+{
+       u32 val, used_bw, total_bw;
+
+       val = readl(qm->io_base + QM_CHANNEL_USAGE_OFFSET +
+                               chan_num * QM_CHANNEL_ADDR_INTRVL);
+       used_bw = lower_16_bits(val);
+       total_bw = upper_16_bits(val);
+       if (!total_bw)
+               return -EIO;
+
+       if (total_bw <= used_bw)
+               return QM_MAX_DEV_USAGE;
+
+       return (used_bw * QM_DEV_USAGE_RATE) / total_bw;
+}
+
+static int qm_usage_show(struct seq_file *s, void *unused)
+{
+       struct hisi_qm *qm = s->private;
+       bool dev_is_active = true;
+       int i, ret;
+
+       /* If device is in suspended, usage is 0. */
+       ret = hisi_qm_get_dfx_access(qm);
+       if (ret == -EAGAIN) {
+               dev_is_active = false;
+       } else if (ret) {
+               dev_err(&qm->pdev->dev, "failed to get dfx access for usage_show!\n");
+               return ret;
+       }
+
+       ret = 0;
+       for (i = 0; i < qm->channel_data.channel_num; i++) {
+               if (dev_is_active) {
+                       ret = qm_usage_percent(qm, i);
+                       if (ret < 0) {
+                               hisi_qm_put_dfx_access(qm);
+                               return ret;
+                       }
+               }
+               seq_printf(s, "%s: %d\n", qm->channel_data.channel_name[i], ret);
+       }
+
+       if (dev_is_active)
+               hisi_qm_put_dfx_access(qm);
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(qm_usage);
+
 static int qm_diff_regs_show(struct seq_file *s, void *unused)
 {
        struct hisi_qm *qm = s->private;
@@ -1159,6 +1210,9 @@ void hisi_qm_debug_init(struct hisi_qm *qm)
                debugfs_create_file("diff_regs", 0444, qm->debug.qm_d,
                                        qm, &qm_diff_regs_fops);
 
+       if (qm->ver >= QM_HW_V5)
+               debugfs_create_file("dev_usage", 0444, qm->debug.debug_root, qm, &qm_usage_fops);
+
        debugfs_create_file("regs", 0444, qm->debug.qm_d, qm, &qm_regs_fops);
 
        debugfs_create_file("cmd", 0600, qm->debug.qm_d, qm, &qm_cmd_fops);
index 884d5d0afaf41f326e8fcd2868efffda49d164cb..357ab5e5887e47e60c971016e2fd32d082ed80c7 100644 (file)
 #define HPRE_DFX_COMMON2_LEN           0xE
 #define HPRE_DFX_CORE_LEN              0x43
 
+#define HPRE_MAX_CHANNEL_NUM           2
+
 static const char hpre_name[] = "hisi_hpre";
 static struct dentry *hpre_debugfs_root;
 static const struct pci_device_id hpre_dev_ids[] = {
@@ -370,6 +372,11 @@ static struct dfx_diff_registers hpre_diff_regs[] = {
        },
 };
 
+static const char *hpre_channel_name[HPRE_MAX_CHANNEL_NUM] = {
+       "RSA",
+       "ECC",
+};
+
 static const struct hisi_qm_err_ini hpre_err_ini;
 
 bool hpre_check_alg_support(struct hisi_qm *qm, u32 alg)
@@ -1234,6 +1241,16 @@ static int hpre_pre_store_cap_reg(struct hisi_qm *qm)
        return 0;
 }
 
+static void hpre_set_channels(struct hisi_qm *qm)
+{
+       struct qm_channel *channel_data = &qm->channel_data;
+       int i;
+
+       channel_data->channel_num = HPRE_MAX_CHANNEL_NUM;
+       for (i = 0; i < HPRE_MAX_CHANNEL_NUM; i++)
+               channel_data->channel_name[i] = hpre_channel_name[i];
+}
+
 static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
 {
        u64 alg_msk;
@@ -1267,6 +1284,7 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
                return ret;
        }
 
+       hpre_set_channels(qm);
        /* Fetch and save the value of capability registers */
        ret = hpre_pre_store_cap_reg(qm);
        if (ret) {
index efda8646fc60d57aad2553a1f214e0c695bc1ea5..6647b7340827ef253d7d0998976452e4e3421149 100644 (file)
 #define SEC_AEAD_BITMAP                        (GENMASK_ULL(7, 6) | GENMASK_ULL(18, 17) | \
                                        GENMASK_ULL(45, 43))
 
+#define SEC_MAX_CHANNEL_NUM            1
+
 struct sec_hw_error {
        u32 int_msk;
        const char *msg;
@@ -1288,6 +1290,14 @@ static int sec_pre_store_cap_reg(struct hisi_qm *qm)
        return 0;
 }
 
+static void sec_set_channels(struct hisi_qm *qm)
+{
+       struct qm_channel *channel_data = &qm->channel_data;
+
+       channel_data->channel_num = SEC_MAX_CHANNEL_NUM;
+       channel_data->channel_name[0] = "SEC";
+}
+
 static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
 {
        u64 alg_msk;
@@ -1325,6 +1335,7 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
                return ret;
        }
 
+       sec_set_channels(qm);
        /* Fetch and save the value of capability registers */
        ret = sec_pre_store_cap_reg(qm);
        if (ret) {
index 85b26ef1754855c2f5f3561d7b54c8f552e90d90..44df9c859bd8e5c94fe95f8ac9d61cb783affc95 100644 (file)
 #define HZIP_LIT_LEN_EN_OFFSET         0x301204
 #define HZIP_LIT_LEN_EN_EN             BIT(4)
 
+#define HZIP_MAX_CHANNEL_NUM           3
+
 enum {
        HZIP_HIGH_COMP_RATE,
        HZIP_HIGH_COMP_PERF,
@@ -359,6 +361,12 @@ static struct dfx_diff_registers hzip_diff_regs[] = {
        },
 };
 
+static const char *zip_channel_name[HZIP_MAX_CHANNEL_NUM] = {
+       "COMPRESS",
+       "DECOMPRESS",
+       "DAE"
+};
+
 static int hzip_diff_regs_show(struct seq_file *s, void *unused)
 {
        struct hisi_qm *qm = s->private;
@@ -1400,6 +1408,16 @@ static int zip_pre_store_cap_reg(struct hisi_qm *qm)
        return 0;
 }
 
+static void zip_set_channels(struct hisi_qm *qm)
+{
+       struct qm_channel *channel_data = &qm->channel_data;
+       int i;
+
+       channel_data->channel_num = HZIP_MAX_CHANNEL_NUM;
+       for (i = 0; i < HZIP_MAX_CHANNEL_NUM; i++)
+               channel_data->channel_name[i] = zip_channel_name[i];
+}
+
 static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
 {
        u64 alg_msk;
@@ -1438,6 +1456,7 @@ static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
                return ret;
        }
 
+       zip_set_channels(qm);
        /* Fetch and save the value of capability registers */
        ret = zip_pre_store_cap_reg(qm);
        if (ret) {
index 51a6dc2b97e96c13029f35c6c07de081379048d2..8a581b5bbbcd7b533de507943a41387697dda510 100644 (file)
 #define QM_MIG_REGION_SEL              0x100198
 #define QM_MIG_REGION_EN               BIT(0)
 
+#define QM_MAX_CHANNEL_NUM             8
+#define QM_CHANNEL_USAGE_OFFSET                0x1100
+#define QM_MAX_DEV_USAGE               100
+#define QM_DEV_USAGE_RATE              100
+#define QM_CHANNEL_ADDR_INTRVL         0x4
+
 /* uacce mode of the driver */
 #define UACCE_MODE_NOUACCE             0 /* don't use uacce */
 #define UACCE_MODE_SVA                 1 /* use uacce sva mode */
@@ -359,6 +365,11 @@ struct qm_rsv_buf {
        struct qm_dma qcdma;
 };
 
+struct qm_channel {
+       int channel_num;
+       const char *channel_name[QM_MAX_CHANNEL_NUM];
+};
+
 struct hisi_qm {
        enum qm_hw_ver ver;
        enum qm_fun_type fun_type;
@@ -433,6 +444,7 @@ struct hisi_qm {
        struct qm_err_isolate isolate_data;
 
        struct hisi_qm_cap_tables cap_tables;
+       struct qm_channel channel_data;
 };
 
 struct hisi_qp_status {