brintos

brintos / linux-shallow public Read only

0
0
Text · 9.1 KiB · ee0b507 Raw
267 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright(c) 2023 Intel Corporation */3#include <linux/dma-mapping.h>4#include <linux/kernel.h>5#include <linux/string_helpers.h>6#include <linux/stringify.h>7 8#include "adf_accel_devices.h"9#include "adf_admin.h"10#include "adf_common_drv.h"11#include "adf_gen4_pm.h"12#include "icp_qat_fw_init_admin.h"13 14/*15 * This is needed because a variable is used to index the mask at16 * pm_scnprint_table(), making it not compile time constant, so the compile17 * asserts from FIELD_GET() or u32_get_bits() won't be fulfilled.18 */19#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))20 21#define PM_INFO_MEMBER_OFF(member)	\22	(offsetof(struct icp_qat_fw_init_admin_pm_info, member) / sizeof(u32))23 24#define PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, _mask_)	\25{								\26	.reg_offset = PM_INFO_MEMBER_OFF(_reg_),		\27	.key = __stringify(_field_),				\28	.field_mask = _mask_,					\29}30 31#define PM_INFO_REGSET_ENTRY32(_reg_, _field_)	\32	PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, GENMASK(31, 0))33 34#define PM_INFO_REGSET_ENTRY(_reg_, _field_)	\35	PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, ADF_GEN4_PM_##_field_##_MASK)36 37#define PM_INFO_MAX_KEY_LEN	2138 39struct pm_status_row {40	int reg_offset;41	u32 field_mask;42	const char *key;43};44 45static struct pm_status_row pm_fuse_rows[] = {46	PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM),47	PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM_IDLE),48	PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_DEEP_PM_IDLE),49};50 51static struct pm_status_row pm_info_rows[] = {52	PM_INFO_REGSET_ENTRY(pm.status, CPM_PM_STATE),53	PM_INFO_REGSET_ENTRY(pm.status, PENDING_WP),54	PM_INFO_REGSET_ENTRY(pm.status, CURRENT_WP),55	PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_ENABLE),56	PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_FILTER),57	PM_INFO_REGSET_ENTRY(pm.main, MIN_PWR_ACK),58	PM_INFO_REGSET_ENTRY(pm.thread, MIN_PWR_ACK_PENDING),59	PM_INFO_REGSET_ENTRY(pm.main, THR_VALUE),60};61 62static struct pm_status_row pm_ssm_rows[] = {63	PM_INFO_REGSET_ENTRY(ssm.pm_enable, SSM_PM_ENABLE),64	PM_INFO_REGSET_ENTRY32(ssm.active_constraint, ACTIVE_CONSTRAINT),65	PM_INFO_REGSET_ENTRY(ssm.pm_domain_status, DOMAIN_POWER_GATED),66	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, ATH_ACTIVE_COUNT),67	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, CPH_ACTIVE_COUNT),68	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, PKE_ACTIVE_COUNT),69	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, CPR_ACTIVE_COUNT),70	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, DCPR_ACTIVE_COUNT),71	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, UCS_ACTIVE_COUNT),72	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, XLT_ACTIVE_COUNT),73	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, WAT_ACTIVE_COUNT),74	PM_INFO_REGSET_ENTRY(ssm.pm_active_status, WCP_ACTIVE_COUNT),75	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, ATH_MANAGED_COUNT),76	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, CPH_MANAGED_COUNT),77	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, PKE_MANAGED_COUNT),78	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, CPR_MANAGED_COUNT),79	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, DCPR_MANAGED_COUNT),80	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, UCS_MANAGED_COUNT),81	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, XLT_MANAGED_COUNT),82	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, WAT_MANAGED_COUNT),83	PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, WCP_MANAGED_COUNT),84};85 86static struct pm_status_row pm_log_rows[] = {87	PM_INFO_REGSET_ENTRY32(event_counters.host_msg, HOST_MSG_EVENT_COUNT),88	PM_INFO_REGSET_ENTRY32(event_counters.sys_pm, SYS_PM_EVENT_COUNT),89	PM_INFO_REGSET_ENTRY32(event_counters.local_ssm, SSM_EVENT_COUNT),90	PM_INFO_REGSET_ENTRY32(event_counters.timer, TIMER_EVENT_COUNT),91	PM_INFO_REGSET_ENTRY32(event_counters.unknown, UNKNOWN_EVENT_COUNT),92};93 94static struct pm_status_row pm_event_rows[ICP_QAT_NUMBER_OF_PM_EVENTS] = {95	PM_INFO_REGSET_ENTRY32(event_log[0], EVENT0),96	PM_INFO_REGSET_ENTRY32(event_log[1], EVENT1),97	PM_INFO_REGSET_ENTRY32(event_log[2], EVENT2),98	PM_INFO_REGSET_ENTRY32(event_log[3], EVENT3),99	PM_INFO_REGSET_ENTRY32(event_log[4], EVENT4),100	PM_INFO_REGSET_ENTRY32(event_log[5], EVENT5),101	PM_INFO_REGSET_ENTRY32(event_log[6], EVENT6),102	PM_INFO_REGSET_ENTRY32(event_log[7], EVENT7),103};104 105static struct pm_status_row pm_csrs_rows[] = {106	PM_INFO_REGSET_ENTRY32(pm.fw_init, CPM_PM_FW_INIT),107	PM_INFO_REGSET_ENTRY32(pm.status, CPM_PM_STATUS),108	PM_INFO_REGSET_ENTRY32(pm.main, CPM_PM_MASTER_FW),109	PM_INFO_REGSET_ENTRY32(pm.pwrreq, CPM_PM_PWRREQ),110};111 112static int pm_scnprint_table(char *buff, struct pm_status_row *table,113			     u32 *pm_info_regs, size_t buff_size, int table_len,114			     bool lowercase)115{116	char key[PM_INFO_MAX_KEY_LEN];117	int wr = 0;118	int i;119 120	for (i = 0; i < table_len; i++) {121		if (lowercase)122			string_lower(key, table[i].key);123		else124			string_upper(key, table[i].key);125 126		wr += scnprintf(&buff[wr], buff_size - wr, "%s: %#x\n", key,127				field_get(table[i].field_mask,128					  pm_info_regs[table[i].reg_offset]));129	}130 131	return wr;132}133 134static int pm_scnprint_table_upper_keys(char *buff, struct pm_status_row *table,135					u32 *pm_info_regs, size_t buff_size,136					int table_len)137{138	return pm_scnprint_table(buff, table, pm_info_regs, buff_size,139				 table_len, false);140}141 142static int pm_scnprint_table_lower_keys(char *buff, struct pm_status_row *table,143					u32 *pm_info_regs, size_t buff_size,144					int table_len)145{146	return pm_scnprint_table(buff, table, pm_info_regs, buff_size,147				 table_len, true);148}149 150static_assert(sizeof(struct icp_qat_fw_init_admin_pm_info) < PAGE_SIZE);151 152static ssize_t adf_gen4_print_pm_status(struct adf_accel_dev *accel_dev,153					char __user *buf, size_t count,154					loff_t *pos)155{156	void __iomem *pmisc = adf_get_pmisc_base(accel_dev);157	struct adf_pm *pm = &accel_dev->power_management;158	struct icp_qat_fw_init_admin_pm_info *pm_info;159	dma_addr_t p_state_addr;160	u32 *pm_info_regs;161	char *pm_kv;162	int len = 0;163	u32 val;164	int ret;165 166	pm_info = kmalloc(PAGE_SIZE, GFP_KERNEL);167	if (!pm_info)168		return -ENOMEM;169 170	pm_kv = kmalloc(PAGE_SIZE, GFP_KERNEL);171	if (!pm_kv) {172		ret = -ENOMEM;173		goto out_free;174	}175 176	p_state_addr = dma_map_single(&GET_DEV(accel_dev), pm_info, PAGE_SIZE,177				      DMA_FROM_DEVICE);178	ret = dma_mapping_error(&GET_DEV(accel_dev), p_state_addr);179	if (ret)180		goto out_free;181 182	/* Query PM info from QAT FW */183	ret = adf_get_pm_info(accel_dev, p_state_addr, PAGE_SIZE);184	dma_unmap_single(&GET_DEV(accel_dev), p_state_addr, PAGE_SIZE,185			 DMA_FROM_DEVICE);186	if (ret)187		goto out_free;188 189	pm_info_regs = (u32 *)pm_info;190 191	/* Fusectl related */192	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,193			 "----------- PM Fuse info ---------\n");194	len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_fuse_rows,195					    pm_info_regs, PAGE_SIZE - len,196					    ARRAY_SIZE(pm_fuse_rows));197	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "max_pwrreq: %#x\n",198			 pm_info->max_pwrreq);199	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "min_pwrreq: %#x\n",200			 pm_info->min_pwrreq);201 202	/* PM related */203	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,204			 "------------  PM Info ------------\n");205	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "power_level: %s\n",206			 pm_info->pwr_state == PM_SET_MIN ? "min" : "max");207	len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_info_rows,208					    pm_info_regs, PAGE_SIZE - len,209					    ARRAY_SIZE(pm_info_rows));210	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "pm_mode: STATIC\n");211 212	/* SSM related */213	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,214			 "----------- SSM_PM Info ----------\n");215	len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_ssm_rows,216					    pm_info_regs, PAGE_SIZE - len,217					    ARRAY_SIZE(pm_ssm_rows));218 219	/* Log related */220	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,221			 "------------- PM Log -------------\n");222	len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_log_rows,223					    pm_info_regs, PAGE_SIZE - len,224					    ARRAY_SIZE(pm_log_rows));225 226	len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_event_rows,227					    pm_info_regs, PAGE_SIZE - len,228					    ARRAY_SIZE(pm_event_rows));229 230	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "idle_irq_count: %#x\n",231			 pm->idle_irq_counters);232	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "fw_irq_count: %#x\n",233			 pm->fw_irq_counters);234	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,235			 "throttle_irq_count: %#x\n", pm->throttle_irq_counters);236	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "host_ack_count: %#x\n",237			 pm->host_ack_counter);238	len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "host_nack_count: %#x\n",239			 pm->host_nack_counter);240 241	/* CSRs content */242	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,243			 "----------- HW PM CSRs -----------\n");244	len += pm_scnprint_table_upper_keys(&pm_kv[len], pm_csrs_rows,245					    pm_info_regs, PAGE_SIZE - len,246					    ARRAY_SIZE(pm_csrs_rows));247 248	val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG);249	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,250			 "CPM_PM_HOST_MSG: %#x\n", val);251	val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_INTERRUPT);252	len += scnprintf(&pm_kv[len], PAGE_SIZE - len,253			 "CPM_PM_INTERRUPT: %#x\n", val);254	ret = simple_read_from_buffer(buf, count, pos, pm_kv, len);255 256out_free:257	kfree(pm_info);258	kfree(pm_kv);259	return ret;260}261 262void adf_gen4_init_dev_pm_data(struct adf_accel_dev *accel_dev)263{264	accel_dev->power_management.print_pm_status = adf_gen4_print_pm_status;265	accel_dev->power_management.present = true;266}267