Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: qat - enable power management debugfs for GEN6 devices

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>

authored by

George Abraham P and committed by
Herbert Xu
c963ff0e 7c68005a

+160 -2
+1 -1
Documentation/ABI/testing/debugfs-driver-qat
··· 67 67 Description: (RO) Read returns power management information specific to the 68 68 QAT device. 69 69 70 - This attribute is only available for qat_4xxx devices. 70 + This attribute is only available for qat_4xxx and qat_6xxx devices. 71 71 72 72 What: /sys/kernel/debug/qat_<device>_<BDF>/cnv_errors 73 73 Date: January 2024
+10 -1
drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c
··· 763 763 764 764 static int enable_pm(struct adf_accel_dev *accel_dev) 765 765 { 766 - return adf_init_admin_pm(accel_dev, ADF_GEN6_PM_DEFAULT_IDLE_FILTER); 766 + int ret; 767 + 768 + ret = adf_init_admin_pm(accel_dev, ADF_GEN6_PM_DEFAULT_IDLE_FILTER); 769 + if (ret) 770 + return ret; 771 + 772 + /* Initialize PM internal data */ 773 + adf_gen6_init_dev_pm_data(accel_dev); 774 + 775 + return 0; 767 776 } 768 777 769 778 static int dev_config(struct adf_accel_dev *accel_dev)
+1
drivers/crypto/intel/qat/qat_common/Makefile
··· 49 49 adf_fw_counters.o \ 50 50 adf_gen4_pm_debugfs.o \ 51 51 adf_gen4_tl.o \ 52 + adf_gen6_pm_dbgfs.o \ 52 53 adf_heartbeat_dbgfs.o \ 53 54 adf_heartbeat.o \ 54 55 adf_pm_dbgfs.o \
+24
drivers/crypto/intel/qat/qat_common/adf_gen6_pm.h
··· 24 24 25 25 /* cpm_pm_status bitfields */ 26 26 #define ADF_GEN6_PM_INIT_STATE BIT(21) 27 + #define ADF_GEN6_PM_CPM_PM_STATE_MASK GENMASK(22, 20) 28 + 29 + /* fusectl0 bitfields */ 30 + #define ADF_GEN6_PM_ENABLE_PM_MASK BIT(21) 31 + #define ADF_GEN6_PM_ENABLE_PM_IDLE_MASK BIT(22) 32 + #define ADF_GEN6_PM_ENABLE_DEEP_PM_IDLE_MASK BIT(23) 33 + 34 + /* cpm_pm_fw_init bitfields */ 35 + #define ADF_GEN6_PM_IDLE_FILTER_MASK GENMASK(5, 3) 36 + #define ADF_GEN6_PM_IDLE_ENABLE_MASK BIT(2) 37 + 38 + /* ssm_pm_enable bitfield */ 39 + #define ADF_GEN6_PM_SSM_PM_ENABLE_MASK BIT(0) 40 + 41 + /* ssm_pm_domain_status bitfield */ 42 + #define ADF_GEN6_PM_DOMAIN_POWERED_UP_MASK BIT(0) 43 + 44 + #ifdef CONFIG_DEBUG_FS 45 + void adf_gen6_init_dev_pm_data(struct adf_accel_dev *accel_dev); 46 + #else 47 + static inline void adf_gen6_init_dev_pm_data(struct adf_accel_dev *accel_dev) 48 + { 49 + } 50 + #endif /* CONFIG_DEBUG_FS */ 27 51 28 52 #endif /* ADF_GEN6_PM_H */
+124
drivers/crypto/intel/qat/qat_common/adf_gen6_pm_dbgfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright(c) 2025 Intel Corporation */ 3 + #include <linux/dma-mapping.h> 4 + #include <linux/export.h> 5 + #include <linux/string_helpers.h> 6 + 7 + #include "adf_admin.h" 8 + #include "adf_common_drv.h" 9 + #include "adf_gen6_pm.h" 10 + #include "adf_pm_dbgfs_utils.h" 11 + #include "icp_qat_fw_init_admin.h" 12 + 13 + #define PM_INFO_REGSET_ENTRY(_reg_, _field_) \ 14 + PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, ADF_GEN6_PM_##_field_##_MASK) 15 + 16 + static struct pm_status_row pm_fuse_rows[] = { 17 + PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM), 18 + PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM_IDLE), 19 + PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_DEEP_PM_IDLE), 20 + }; 21 + 22 + static struct pm_status_row pm_info_rows[] = { 23 + PM_INFO_REGSET_ENTRY(pm.status, CPM_PM_STATE), 24 + PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_ENABLE), 25 + PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_FILTER), 26 + }; 27 + 28 + static struct pm_status_row pm_ssm_rows[] = { 29 + PM_INFO_REGSET_ENTRY(ssm.pm_enable, SSM_PM_ENABLE), 30 + PM_INFO_REGSET_ENTRY(ssm.pm_domain_status, DOMAIN_POWERED_UP), 31 + }; 32 + 33 + static struct pm_status_row pm_csrs_rows[] = { 34 + PM_INFO_REGSET_ENTRY32(pm.fw_init, CPM_PM_FW_INIT), 35 + PM_INFO_REGSET_ENTRY32(pm.status, CPM_PM_STATUS), 36 + }; 37 + 38 + static_assert(sizeof(struct icp_qat_fw_init_admin_pm_info) < PAGE_SIZE); 39 + 40 + static ssize_t adf_gen6_print_pm_status(struct adf_accel_dev *accel_dev, 41 + char __user *buf, size_t count, 42 + loff_t *pos) 43 + { 44 + void __iomem *pmisc = adf_get_pmisc_base(accel_dev); 45 + struct icp_qat_fw_init_admin_pm_info *pm_info; 46 + dma_addr_t p_state_addr; 47 + u32 *pm_info_regs; 48 + size_t len = 0; 49 + char *pm_kv; 50 + u32 val; 51 + int ret; 52 + 53 + pm_info = kzalloc(PAGE_SIZE, GFP_KERNEL); 54 + if (!pm_info) 55 + return -ENOMEM; 56 + 57 + pm_kv = kzalloc(PAGE_SIZE, GFP_KERNEL); 58 + if (!pm_kv) { 59 + kfree(pm_info); 60 + return -ENOMEM; 61 + } 62 + 63 + p_state_addr = dma_map_single(&GET_DEV(accel_dev), pm_info, PAGE_SIZE, 64 + DMA_FROM_DEVICE); 65 + ret = dma_mapping_error(&GET_DEV(accel_dev), p_state_addr); 66 + if (ret) 67 + goto out_free; 68 + 69 + /* Query power management information from QAT FW */ 70 + ret = adf_get_pm_info(accel_dev, p_state_addr, PAGE_SIZE); 71 + dma_unmap_single(&GET_DEV(accel_dev), p_state_addr, PAGE_SIZE, 72 + DMA_FROM_DEVICE); 73 + if (ret) 74 + goto out_free; 75 + 76 + pm_info_regs = (u32 *)pm_info; 77 + 78 + /* Fuse control register */ 79 + len += scnprintf(&pm_kv[len], PAGE_SIZE - len, 80 + "----------- PM Fuse info ---------\n"); 81 + len += adf_pm_scnprint_table_lower_keys(&pm_kv[len], pm_fuse_rows, 82 + pm_info_regs, PAGE_SIZE - len, 83 + ARRAY_SIZE(pm_fuse_rows)); 84 + 85 + /* Power management */ 86 + len += scnprintf(&pm_kv[len], PAGE_SIZE - len, 87 + "----------- PM Info --------------\n"); 88 + 89 + len += adf_pm_scnprint_table_lower_keys(&pm_kv[len], pm_info_rows, 90 + pm_info_regs, PAGE_SIZE - len, 91 + ARRAY_SIZE(pm_info_rows)); 92 + len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "pm_mode: ACTIVE\n"); 93 + 94 + /* Shared Slice Module */ 95 + len += scnprintf(&pm_kv[len], PAGE_SIZE - len, 96 + "----------- SSM_PM Info ----------\n"); 97 + len += adf_pm_scnprint_table_lower_keys(&pm_kv[len], pm_ssm_rows, 98 + pm_info_regs, PAGE_SIZE - len, 99 + ARRAY_SIZE(pm_ssm_rows)); 100 + 101 + /* Control status register content */ 102 + len += scnprintf(&pm_kv[len], PAGE_SIZE - len, 103 + "----------- HW PM CSRs -----------\n"); 104 + len += adf_pm_scnprint_table_upper_keys(&pm_kv[len], pm_csrs_rows, 105 + pm_info_regs, PAGE_SIZE - len, 106 + ARRAY_SIZE(pm_csrs_rows)); 107 + 108 + val = ADF_CSR_RD(pmisc, ADF_GEN6_PM_INTERRUPT); 109 + len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "CPM_PM_INTERRUPT: %#x\n", val); 110 + ret = simple_read_from_buffer(buf, count, pos, pm_kv, len); 111 + 112 + out_free: 113 + kfree(pm_info); 114 + kfree(pm_kv); 115 + 116 + return ret; 117 + } 118 + 119 + void adf_gen6_init_dev_pm_data(struct adf_accel_dev *accel_dev) 120 + { 121 + accel_dev->power_management.print_pm_status = adf_gen6_print_pm_status; 122 + accel_dev->power_management.present = true; 123 + } 124 + EXPORT_SYMBOL_GPL(adf_gen6_init_dev_pm_data);