]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: qat - enable power management debugfs for GEN6 devices
authorGeorge Abraham P <george.abraham.p@intel.com>
Mon, 7 Jul 2025 12:28:46 +0000 (13:28 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 18 Jul 2025 10:51:59 +0000 (20:51 +1000)
The QAT driver includes infrastructure to report power management (PM)
information via debugfs. Extend this support to QAT GEN6 devices
by exposing PM debug data through the `pm_status` file.

This implementation reports the current PM state, power management
hardware control and status registers (CSR), and per-domain power
status specific to the QAT GEN6 architecture.

The debug functionality is implemented in adf_gen6_pm_dbgfs.c
and initialized as part of the enable_pm() function.

Co-developed-by: Vijay Sundar Selvamani <vijay.sundar.selvamani@intel.com>
Signed-off-by: Vijay Sundar Selvamani <vijay.sundar.selvamani@intel.com>
Signed-off-by: George Abraham P <george.abraham.p@intel.com>
Signed-off-by: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Documentation/ABI/testing/debugfs-driver-qat
drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c
drivers/crypto/intel/qat/qat_common/Makefile
drivers/crypto/intel/qat/qat_common/adf_gen6_pm.h
drivers/crypto/intel/qat/qat_common/adf_gen6_pm_dbgfs.c [new file with mode: 0644]

index bd6793760f29842b841217d4226f6d5538403a62..3f1efbbad6ca988786b5627d5ccfbdbcda98315c 100644 (file)
@@ -67,7 +67,7 @@ Contact:      qat-linux@intel.com
 Description:   (RO) Read returns power management information specific to the
                QAT device.
 
-               This attribute is only available for qat_4xxx devices.
+               This attribute is only available for qat_4xxx and qat_6xxx devices.
 
 What:          /sys/kernel/debug/qat_<device>_<BDF>/cnv_errors
 Date:          January 2024
index a21a10a8338f2fe7990148d7d7216c88eb3772b9..ecef3dc28a91e4d95a23d321d5f2812aad2c2e5f 100644 (file)
@@ -763,7 +763,16 @@ static int adf_init_device(struct adf_accel_dev *accel_dev)
 
 static int enable_pm(struct adf_accel_dev *accel_dev)
 {
-       return adf_init_admin_pm(accel_dev, ADF_GEN6_PM_DEFAULT_IDLE_FILTER);
+       int ret;
+
+       ret = adf_init_admin_pm(accel_dev, ADF_GEN6_PM_DEFAULT_IDLE_FILTER);
+       if (ret)
+               return ret;
+
+       /* Initialize PM internal data */
+       adf_gen6_init_dev_pm_data(accel_dev);
+
+       return 0;
 }
 
 static int dev_config(struct adf_accel_dev *accel_dev)
index 5826180c2051524bbaf4497036e7949dec9eaa10..34019d8637a50d11e5829b241e7a5e6b395bd832 100644 (file)
@@ -49,6 +49,7 @@ intel_qat-$(CONFIG_DEBUG_FS) += adf_cnv_dbgfs.o \
                                adf_fw_counters.o \
                                adf_gen4_pm_debugfs.o \
                                adf_gen4_tl.o \
+                               adf_gen6_pm_dbgfs.o \
                                adf_heartbeat_dbgfs.o \
                                adf_heartbeat.o \
                                adf_pm_dbgfs.o \
index 9a5b995f7ada2f1c5ae390beefbc37f0b40c195d..4c0d576e8c21883e4a87f9000d8d867f5b81c466 100644 (file)
@@ -24,5 +24,29 @@ struct adf_accel_dev;
 
 /* cpm_pm_status bitfields */
 #define ADF_GEN6_PM_INIT_STATE                 BIT(21)
+#define ADF_GEN6_PM_CPM_PM_STATE_MASK          GENMASK(22, 20)
+
+/* fusectl0 bitfields */
+#define ADF_GEN6_PM_ENABLE_PM_MASK             BIT(21)
+#define ADF_GEN6_PM_ENABLE_PM_IDLE_MASK                BIT(22)
+#define ADF_GEN6_PM_ENABLE_DEEP_PM_IDLE_MASK   BIT(23)
+
+/* cpm_pm_fw_init bitfields */
+#define ADF_GEN6_PM_IDLE_FILTER_MASK           GENMASK(5, 3)
+#define ADF_GEN6_PM_IDLE_ENABLE_MASK           BIT(2)
+
+/* ssm_pm_enable bitfield */
+#define ADF_GEN6_PM_SSM_PM_ENABLE_MASK         BIT(0)
+
+/* ssm_pm_domain_status bitfield */
+#define ADF_GEN6_PM_DOMAIN_POWERED_UP_MASK     BIT(0)
+
+#ifdef CONFIG_DEBUG_FS
+void adf_gen6_init_dev_pm_data(struct adf_accel_dev *accel_dev);
+#else
+static inline void adf_gen6_init_dev_pm_data(struct adf_accel_dev *accel_dev)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
 
 #endif /* ADF_GEN6_PM_H */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen6_pm_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_gen6_pm_dbgfs.c
new file mode 100644 (file)
index 0000000..603aefb
--- /dev/null
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2025 Intel Corporation */
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/string_helpers.h>
+
+#include "adf_admin.h"
+#include "adf_common_drv.h"
+#include "adf_gen6_pm.h"
+#include "adf_pm_dbgfs_utils.h"
+#include "icp_qat_fw_init_admin.h"
+
+#define PM_INFO_REGSET_ENTRY(_reg_, _field_) \
+       PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, ADF_GEN6_PM_##_field_##_MASK)
+
+static struct pm_status_row pm_fuse_rows[] = {
+       PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM),
+       PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM_IDLE),
+       PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_DEEP_PM_IDLE),
+};
+
+static struct pm_status_row pm_info_rows[] = {
+       PM_INFO_REGSET_ENTRY(pm.status, CPM_PM_STATE),
+       PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_ENABLE),
+       PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_FILTER),
+};
+
+static struct pm_status_row pm_ssm_rows[] = {
+       PM_INFO_REGSET_ENTRY(ssm.pm_enable, SSM_PM_ENABLE),
+       PM_INFO_REGSET_ENTRY(ssm.pm_domain_status, DOMAIN_POWERED_UP),
+};
+
+static struct pm_status_row pm_csrs_rows[] = {
+       PM_INFO_REGSET_ENTRY32(pm.fw_init, CPM_PM_FW_INIT),
+       PM_INFO_REGSET_ENTRY32(pm.status, CPM_PM_STATUS),
+};
+
+static_assert(sizeof(struct icp_qat_fw_init_admin_pm_info) < PAGE_SIZE);
+
+static ssize_t adf_gen6_print_pm_status(struct adf_accel_dev *accel_dev,
+                                       char __user *buf, size_t count,
+                                       loff_t *pos)
+{
+       void __iomem *pmisc = adf_get_pmisc_base(accel_dev);
+       struct icp_qat_fw_init_admin_pm_info *pm_info;
+       dma_addr_t p_state_addr;
+       u32 *pm_info_regs;
+       size_t len = 0;
+       char *pm_kv;
+       u32 val;
+       int ret;
+
+       pm_info = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!pm_info)
+               return -ENOMEM;
+
+       pm_kv = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!pm_kv) {
+               kfree(pm_info);
+               return -ENOMEM;
+       }
+
+       p_state_addr = dma_map_single(&GET_DEV(accel_dev), pm_info, PAGE_SIZE,
+                                     DMA_FROM_DEVICE);
+       ret = dma_mapping_error(&GET_DEV(accel_dev), p_state_addr);
+       if (ret)
+               goto out_free;
+
+       /* Query power management information from QAT FW */
+       ret = adf_get_pm_info(accel_dev, p_state_addr, PAGE_SIZE);
+       dma_unmap_single(&GET_DEV(accel_dev), p_state_addr, PAGE_SIZE,
+                        DMA_FROM_DEVICE);
+       if (ret)
+               goto out_free;
+
+       pm_info_regs = (u32 *)pm_info;
+
+       /* Fuse control register */
+       len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+                        "----------- PM Fuse info ---------\n");
+       len += adf_pm_scnprint_table_lower_keys(&pm_kv[len], pm_fuse_rows,
+                                               pm_info_regs, PAGE_SIZE - len,
+                                               ARRAY_SIZE(pm_fuse_rows));
+
+       /* Power management */
+       len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+                        "----------- PM Info --------------\n");
+
+       len += adf_pm_scnprint_table_lower_keys(&pm_kv[len], pm_info_rows,
+                                               pm_info_regs, PAGE_SIZE - len,
+                                               ARRAY_SIZE(pm_info_rows));
+       len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "pm_mode: ACTIVE\n");
+
+       /* Shared Slice Module */
+       len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+                        "----------- SSM_PM Info ----------\n");
+       len += adf_pm_scnprint_table_lower_keys(&pm_kv[len], pm_ssm_rows,
+                                               pm_info_regs, PAGE_SIZE - len,
+                                               ARRAY_SIZE(pm_ssm_rows));
+
+       /* Control status register content */
+       len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+                        "----------- HW PM CSRs -----------\n");
+       len += adf_pm_scnprint_table_upper_keys(&pm_kv[len], pm_csrs_rows,
+                                               pm_info_regs, PAGE_SIZE - len,
+                                               ARRAY_SIZE(pm_csrs_rows));
+
+       val = ADF_CSR_RD(pmisc, ADF_GEN6_PM_INTERRUPT);
+       len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "CPM_PM_INTERRUPT: %#x\n", val);
+       ret = simple_read_from_buffer(buf, count, pos, pm_kv, len);
+
+out_free:
+       kfree(pm_info);
+       kfree(pm_kv);
+
+       return ret;
+}
+
+void adf_gen6_init_dev_pm_data(struct adf_accel_dev *accel_dev)
+{
+       accel_dev->power_management.print_pm_status = adf_gen6_print_pm_status;
+       accel_dev->power_management.present = true;
+}
+EXPORT_SYMBOL_GPL(adf_gen6_init_dev_pm_data);