Skip to content

Commit c963ff0

Browse files
georgeabpherbertx
authored andcommitted
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>
1 parent 7c68005 commit c963ff0

5 files changed

Lines changed: 160 additions & 2 deletions

File tree

Documentation/ABI/testing/debugfs-driver-qat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Contact: qat-linux@intel.com
6767
Description: (RO) Read returns power management information specific to the
6868
QAT device.
6969

70-
This attribute is only available for qat_4xxx devices.
70+
This attribute is only available for qat_4xxx and qat_6xxx devices.
7171

7272
What: /sys/kernel/debug/qat_<device>_<BDF>/cnv_errors
7373
Date: January 2024

drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,16 @@ static int adf_init_device(struct adf_accel_dev *accel_dev)
763763

764764
static int enable_pm(struct adf_accel_dev *accel_dev)
765765
{
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;
767776
}
768777

769778
static int dev_config(struct adf_accel_dev *accel_dev)

drivers/crypto/intel/qat/qat_common/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ intel_qat-$(CONFIG_DEBUG_FS) += adf_cnv_dbgfs.o \
4949
adf_fw_counters.o \
5050
adf_gen4_pm_debugfs.o \
5151
adf_gen4_tl.o \
52+
adf_gen6_pm_dbgfs.o \
5253
adf_heartbeat_dbgfs.o \
5354
adf_heartbeat.o \
5455
adf_pm_dbgfs.o \

drivers/crypto/intel/qat/qat_common/adf_gen6_pm.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,29 @@ struct adf_accel_dev;
2424

2525
/* cpm_pm_status bitfields */
2626
#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 */
2751

2852
#endif /* ADF_GEN6_PM_H */
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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);

0 commit comments

Comments
 (0)