brintos

brintos / linux-shallow public Read only

0
0
Text · 26.8 KiB · 70e5736 Raw
962 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel SOC Telemetry debugfs Driver: Currently supports APL4 * Copyright (c) 2015, Intel Corporation.5 * All Rights Reserved.6 *7 * This file provides the debugfs interfaces for telemetry.8 * /sys/kernel/debug/telemetry/pss_info: Shows Primary Control Sub-Sys Counters9 * /sys/kernel/debug/telemetry/ioss_info: Shows IO Sub-System Counters10 * /sys/kernel/debug/telemetry/soc_states: Shows SoC State11 * /sys/kernel/debug/telemetry/pss_trace_verbosity: Read and Change Tracing12 *				Verbosity via firmware13 * /sys/kernel/debug/telemetry/ioss_race_verbosity: Write and Change Tracing14 *				Verbosity via firmware15 */16#include <linux/debugfs.h>17#include <linux/device.h>18#include <linux/mfd/intel_pmc_bxt.h>19#include <linux/module.h>20#include <linux/pci.h>21#include <linux/seq_file.h>22#include <linux/suspend.h>23 24#include <asm/cpu_device_id.h>25#include <asm/intel-family.h>26#include <asm/intel_telemetry.h>27 28#define DRIVER_NAME			"telemetry_soc_debugfs"29#define DRIVER_VERSION			"1.0.0"30 31/* ApolloLake SoC Event-IDs */32#define TELEM_APL_PSS_PSTATES_ID	0x280233#define TELEM_APL_PSS_IDLE_ID		0x280634#define TELEM_APL_PCS_IDLE_BLOCKED_ID	0x2C0035#define TELEM_APL_PCS_S0IX_BLOCKED_ID	0x2C0136#define TELEM_APL_PSS_WAKEUP_ID		0x2C0237#define TELEM_APL_PSS_LTR_BLOCKING_ID	0x2C0338 39#define TELEM_APL_S0IX_TOTAL_OCC_ID	0x400040#define TELEM_APL_S0IX_SHLW_OCC_ID	0x400141#define TELEM_APL_S0IX_DEEP_OCC_ID	0x400242#define TELEM_APL_S0IX_TOTAL_RES_ID	0x480043#define TELEM_APL_S0IX_SHLW_RES_ID	0x480144#define TELEM_APL_S0IX_DEEP_RES_ID	0x480245#define TELEM_APL_D0IX_ID		0x581A46#define TELEM_APL_D3_ID			0x581947#define TELEM_APL_PG_ID			0x581848 49#define TELEM_INFO_SRAMEVTS_MASK	0xFF0050#define TELEM_INFO_SRAMEVTS_SHIFT	0x851#define TELEM_SSRAM_READ_TIMEOUT	1052 53#define TELEM_MASK_BIT			154#define TELEM_MASK_BYTE			0xFF55#define BYTES_PER_LONG			856#define TELEM_APL_MASK_PCS_STATE	0xF57 58/* Max events in bitmap to check for */59#define TELEM_PSS_IDLE_EVTS		2560#define TELEM_PSS_IDLE_BLOCKED_EVTS	2061#define TELEM_PSS_S0IX_BLOCKED_EVTS	2062#define TELEM_PSS_S0IX_WAKEUP_EVTS	2063#define TELEM_PSS_LTR_BLOCKING_EVTS	2064#define TELEM_IOSS_DX_D0IX_EVTS		2565#define TELEM_IOSS_PG_EVTS		3066 67#define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \68	if (evtlog[index].telem_evtid == (EVTID)) { \69		for (idx = 0; idx < (EVTNUM); idx++) \70			(BUF)[idx] = ((EVTLOG) >> (EVTDAT)[idx].bit_pos) & \71				     (MASK); \72	continue; \73	} \74}75 76#define TELEM_CHECK_AND_PARSE_CTRS(EVTID, CTR) { \77	if (evtlog[index].telem_evtid == (EVTID)) { \78		(CTR) = evtlog[index].telem_evtlog; \79		continue; \80	} \81}82 83static u8 suspend_prep_ok;84static u32 suspend_shlw_ctr_temp, suspend_deep_ctr_temp;85static u64 suspend_shlw_res_temp, suspend_deep_res_temp;86 87struct telemetry_susp_stats {88	u32 shlw_ctr;89	u32 deep_ctr;90	u64 shlw_res;91	u64 deep_res;92};93 94/* Bitmap definitions for default counters in APL */95struct telem_pss_idle_stateinfo {96	const char *name;97	u32 bit_pos;98};99 100static struct telem_pss_idle_stateinfo telem_apl_pss_idle_data[] = {101	{"IA_CORE0_C1E",		0},102	{"IA_CORE1_C1E",		1},103	{"IA_CORE2_C1E",		2},104	{"IA_CORE3_C1E",		3},105	{"IA_CORE0_C6",			16},106	{"IA_CORE1_C6",			17},107	{"IA_CORE2_C6",			18},108	{"IA_CORE3_C6",			19},109	{"IA_MODULE0_C7",		32},110	{"IA_MODULE1_C7",		33},111	{"GT_RC6",			40},112	{"IUNIT_PROCESSING_IDLE",	41},113	{"FAR_MEM_IDLE",		43},114	{"DISPLAY_IDLE",		44},115	{"IUNIT_INPUT_SYSTEM_IDLE",	45},116	{"PCS_STATUS",			60},117};118 119struct telem_pcs_blkd_info {120	const char *name;121	u32 bit_pos;122};123 124static struct telem_pcs_blkd_info telem_apl_pcs_idle_blkd_data[] = {125	{"COMPUTE",			0},126	{"MISC",			8},127	{"MODULE_ACTIONS_PENDING",	16},128	{"LTR",				24},129	{"DISPLAY_WAKE",		32},130	{"ISP_WAKE",			40},131	{"PSF0_ACTIVE",			48},132};133 134static struct telem_pcs_blkd_info telem_apl_pcs_s0ix_blkd_data[] = {135	{"LTR",				0},136	{"IRTL",			8},137	{"WAKE_DEADLINE_PENDING",	16},138	{"DISPLAY",			24},139	{"ISP",				32},140	{"CORE",			40},141	{"PMC",				48},142	{"MISC",			56},143};144 145struct telem_pss_ltr_info {146	const char *name;147	u32 bit_pos;148};149 150static struct telem_pss_ltr_info telem_apl_pss_ltr_data[] = {151	{"CORE_ACTIVE",		0},152	{"MEM_UP",		8},153	{"DFX",			16},154	{"DFX_FORCE_LTR",	24},155	{"DISPLAY",		32},156	{"ISP",			40},157	{"SOUTH",		48},158};159 160struct telem_pss_wakeup_info {161	const char *name;162	u32 bit_pos;163};164 165static struct telem_pss_wakeup_info telem_apl_pss_wakeup[] = {166	{"IP_IDLE",			0},167	{"DISPLAY_WAKE",		8},168	{"VOLTAGE_REG_INT",		16},169	{"DROWSY_TIMER (HOTPLUG)",	24},170	{"CORE_WAKE",			32},171	{"MISC_S0IX",			40},172	{"MISC_ABORT",			56},173};174 175struct telem_ioss_d0ix_stateinfo {176	const char *name;177	u32 bit_pos;178};179 180static struct telem_ioss_d0ix_stateinfo telem_apl_ioss_d0ix_data[] = {181	{"CSE",		0},182	{"SCC2",	1},183	{"GMM",		2},184	{"XDCI",	3},185	{"XHCI",	4},186	{"ISH",		5},187	{"AVS",		6},188	{"PCIE0P1",	7},189	{"PECI0P0",	8},190	{"LPSS",	9},191	{"SCC",		10},192	{"PWM",		11},193	{"PCIE1_P3",    12},194	{"PCIE1_P2",    13},195	{"PCIE1_P1",    14},196	{"PCIE1_P0",    15},197	{"CNV",		16},198	{"SATA",	17},199	{"PRTC",	18},200};201 202struct telem_ioss_pg_info {203	const char *name;204	u32 bit_pos;205};206 207static struct telem_ioss_pg_info telem_apl_ioss_pg_data[] = {208	{"LPSS",	0},209	{"SCC",		1},210	{"P2SB",	2},211	{"SCC2",	3},212	{"GMM",		4},213	{"PCIE0",	5},214	{"XDCI",	6},215	{"xHCI",	7},216	{"CSE",		8},217	{"SPI",		9},218	{"AVSPGD4",	10},219	{"AVSPGD3",	11},220	{"AVSPGD2",	12},221	{"AVSPGD1",	13},222	{"ISH",		14},223	{"EXI",		15},224	{"NPKVRC",	16},225	{"NPKVNN",	17},226	{"CUNIT",	18},227	{"FUSE_CTRL",	19},228	{"PCIE1",	20},229	{"CNV",		21},230	{"LPC",		22},231	{"SATA",	23},232	{"SMB",		24},233	{"PRTC",	25},234};235 236struct telemetry_debugfs_conf {237	struct telemetry_susp_stats suspend_stats;238	struct dentry *telemetry_dbg_dir;239 240	/* Bitmap Data */241	struct telem_ioss_d0ix_stateinfo *ioss_d0ix_data;242	struct telem_pss_idle_stateinfo *pss_idle_data;243	struct telem_pcs_blkd_info *pcs_idle_blkd_data;244	struct telem_pcs_blkd_info *pcs_s0ix_blkd_data;245	struct telem_pss_wakeup_info *pss_wakeup;246	struct telem_pss_ltr_info *pss_ltr_data;247	struct telem_ioss_pg_info *ioss_pg_data;248	u8 pcs_idle_blkd_evts;249	u8 pcs_s0ix_blkd_evts;250	u8 pss_wakeup_evts;251	u8 pss_idle_evts;252	u8 pss_ltr_evts;253	u8 ioss_d0ix_evts;254	u8 ioss_pg_evts;255 256	/* IDs */257	u16  pss_ltr_blocking_id;258	u16  pcs_idle_blkd_id;259	u16  pcs_s0ix_blkd_id;260	u16  s0ix_total_occ_id;261	u16  s0ix_shlw_occ_id;262	u16  s0ix_deep_occ_id;263	u16  s0ix_total_res_id;264	u16  s0ix_shlw_res_id;265	u16  s0ix_deep_res_id;266	u16  pss_wakeup_id;267	u16  ioss_d0ix_id;268	u16  pstates_id;269	u16  pss_idle_id;270	u16  ioss_d3_id;271	u16  ioss_pg_id;272};273 274static struct telemetry_debugfs_conf *debugfs_conf;275 276static struct telemetry_debugfs_conf telem_apl_debugfs_conf = {277	.pss_idle_data = telem_apl_pss_idle_data,278	.pcs_idle_blkd_data = telem_apl_pcs_idle_blkd_data,279	.pcs_s0ix_blkd_data = telem_apl_pcs_s0ix_blkd_data,280	.pss_ltr_data = telem_apl_pss_ltr_data,281	.pss_wakeup = telem_apl_pss_wakeup,282	.ioss_d0ix_data = telem_apl_ioss_d0ix_data,283	.ioss_pg_data = telem_apl_ioss_pg_data,284 285	.pss_idle_evts = ARRAY_SIZE(telem_apl_pss_idle_data),286	.pcs_idle_blkd_evts = ARRAY_SIZE(telem_apl_pcs_idle_blkd_data),287	.pcs_s0ix_blkd_evts = ARRAY_SIZE(telem_apl_pcs_s0ix_blkd_data),288	.pss_ltr_evts = ARRAY_SIZE(telem_apl_pss_ltr_data),289	.pss_wakeup_evts = ARRAY_SIZE(telem_apl_pss_wakeup),290	.ioss_d0ix_evts = ARRAY_SIZE(telem_apl_ioss_d0ix_data),291	.ioss_pg_evts = ARRAY_SIZE(telem_apl_ioss_pg_data),292 293	.pstates_id = TELEM_APL_PSS_PSTATES_ID,294	.pss_idle_id = TELEM_APL_PSS_IDLE_ID,295	.pcs_idle_blkd_id = TELEM_APL_PCS_IDLE_BLOCKED_ID,296	.pcs_s0ix_blkd_id = TELEM_APL_PCS_S0IX_BLOCKED_ID,297	.pss_wakeup_id = TELEM_APL_PSS_WAKEUP_ID,298	.pss_ltr_blocking_id = TELEM_APL_PSS_LTR_BLOCKING_ID,299	.s0ix_total_occ_id = TELEM_APL_S0IX_TOTAL_OCC_ID,300	.s0ix_shlw_occ_id = TELEM_APL_S0IX_SHLW_OCC_ID,301	.s0ix_deep_occ_id = TELEM_APL_S0IX_DEEP_OCC_ID,302	.s0ix_total_res_id = TELEM_APL_S0IX_TOTAL_RES_ID,303	.s0ix_shlw_res_id = TELEM_APL_S0IX_SHLW_RES_ID,304	.s0ix_deep_res_id = TELEM_APL_S0IX_DEEP_RES_ID,305	.ioss_d0ix_id = TELEM_APL_D0IX_ID,306	.ioss_d3_id = TELEM_APL_D3_ID,307	.ioss_pg_id = TELEM_APL_PG_ID,308};309 310static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = {311	X86_MATCH_VFM(INTEL_ATOM_GOLDMONT,	&telem_apl_debugfs_conf),312	X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS,	&telem_apl_debugfs_conf),313	{}314};315MODULE_DEVICE_TABLE(x86cpu, telemetry_debugfs_cpu_ids);316 317static int telemetry_debugfs_check_evts(void)318{319	if ((debugfs_conf->pss_idle_evts > TELEM_PSS_IDLE_EVTS) ||320	    (debugfs_conf->pcs_idle_blkd_evts > TELEM_PSS_IDLE_BLOCKED_EVTS) ||321	    (debugfs_conf->pcs_s0ix_blkd_evts > TELEM_PSS_S0IX_BLOCKED_EVTS) ||322	    (debugfs_conf->pss_ltr_evts > TELEM_PSS_LTR_BLOCKING_EVTS) ||323	    (debugfs_conf->pss_wakeup_evts > TELEM_PSS_S0IX_WAKEUP_EVTS) ||324	    (debugfs_conf->ioss_d0ix_evts > TELEM_IOSS_DX_D0IX_EVTS) ||325	    (debugfs_conf->ioss_pg_evts > TELEM_IOSS_PG_EVTS))326		return -EINVAL;327 328	return 0;329}330 331static int telem_pss_states_show(struct seq_file *s, void *unused)332{333	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];334	struct telemetry_debugfs_conf *conf = debugfs_conf;335	const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];336	u32 pcs_idle_blkd[TELEM_PSS_IDLE_BLOCKED_EVTS],337	    pcs_s0ix_blkd[TELEM_PSS_S0IX_BLOCKED_EVTS],338	    pss_s0ix_wakeup[TELEM_PSS_S0IX_WAKEUP_EVTS],339	    pss_ltr_blkd[TELEM_PSS_LTR_BLOCKING_EVTS],340	    pss_idle[TELEM_PSS_IDLE_EVTS];341	int index, idx, ret, err = 0;342	u64 pstates = 0;343 344	ret = telemetry_read_eventlog(TELEM_PSS, evtlog,345				      TELEM_MAX_OS_ALLOCATED_EVENTS);346	if (ret < 0)347		return ret;348 349	err = telemetry_get_evtname(TELEM_PSS, name,350				    TELEM_MAX_OS_ALLOCATED_EVENTS);351	if (err < 0)352		return err;353 354	seq_puts(s, "\n----------------------------------------------------\n");355	seq_puts(s, "\tPSS TELEM EVENTLOG (Residency = field/19.2 us\n");356	seq_puts(s, "----------------------------------------------------\n");357	for (index = 0; index < ret; index++) {358		seq_printf(s, "%-32s %llu\n",359			   name[index], evtlog[index].telem_evtlog);360 361		/* Fetch PSS IDLE State */362		if (evtlog[index].telem_evtid == conf->pss_idle_id) {363			pss_idle[conf->pss_idle_evts - 1] =364			(evtlog[index].telem_evtlog >>365			conf->pss_idle_data[conf->pss_idle_evts - 1].bit_pos) &366			TELEM_APL_MASK_PCS_STATE;367		}368 369		TELEM_CHECK_AND_PARSE_EVTS(conf->pss_idle_id,370					   conf->pss_idle_evts - 1,371					   pss_idle, evtlog[index].telem_evtlog,372					   conf->pss_idle_data, TELEM_MASK_BIT);373 374		TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_idle_blkd_id,375					   conf->pcs_idle_blkd_evts,376					   pcs_idle_blkd,377					   evtlog[index].telem_evtlog,378					   conf->pcs_idle_blkd_data,379					   TELEM_MASK_BYTE);380 381		TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_s0ix_blkd_id,382					   conf->pcs_s0ix_blkd_evts,383					   pcs_s0ix_blkd,384					   evtlog[index].telem_evtlog,385					   conf->pcs_s0ix_blkd_data,386					   TELEM_MASK_BYTE);387 388		TELEM_CHECK_AND_PARSE_EVTS(conf->pss_wakeup_id,389					   conf->pss_wakeup_evts,390					   pss_s0ix_wakeup,391					   evtlog[index].telem_evtlog,392					   conf->pss_wakeup, TELEM_MASK_BYTE);393 394		TELEM_CHECK_AND_PARSE_EVTS(conf->pss_ltr_blocking_id,395					   conf->pss_ltr_evts, pss_ltr_blkd,396					   evtlog[index].telem_evtlog,397					   conf->pss_ltr_data, TELEM_MASK_BYTE);398 399		if (evtlog[index].telem_evtid == debugfs_conf->pstates_id)400			pstates = evtlog[index].telem_evtlog;401	}402 403	seq_puts(s, "\n--------------------------------------\n");404	seq_puts(s, "PStates\n");405	seq_puts(s, "--------------------------------------\n");406	seq_puts(s, "Domain\t\t\t\tFreq(Mhz)\n");407	seq_printf(s, " IA\t\t\t\t %llu\n GT\t\t\t\t %llu\n",408		   (pstates & TELEM_MASK_BYTE)*100,409		   ((pstates >> 8) & TELEM_MASK_BYTE)*50/3);410 411	seq_printf(s, " IUNIT\t\t\t\t %llu\n SA\t\t\t\t %llu\n",412		   ((pstates >> 16) & TELEM_MASK_BYTE)*25,413		   ((pstates >> 24) & TELEM_MASK_BYTE)*50/3);414 415	seq_puts(s, "\n--------------------------------------\n");416	seq_puts(s, "PSS IDLE Status\n");417	seq_puts(s, "--------------------------------------\n");418	seq_puts(s, "Device\t\t\t\t\tIDLE\n");419	for (index = 0; index < debugfs_conf->pss_idle_evts; index++) {420		seq_printf(s, "%-32s\t%u\n",421			   debugfs_conf->pss_idle_data[index].name,422			   pss_idle[index]);423	}424 425	seq_puts(s, "\n--------------------------------------\n");426	seq_puts(s, "PSS Idle blkd Status (~1ms saturating bucket)\n");427	seq_puts(s, "--------------------------------------\n");428	seq_puts(s, "Blocker\t\t\t\t\tCount\n");429	for (index = 0; index < debugfs_conf->pcs_idle_blkd_evts; index++) {430		seq_printf(s, "%-32s\t%u\n",431			   debugfs_conf->pcs_idle_blkd_data[index].name,432			   pcs_idle_blkd[index]);433	}434 435	seq_puts(s, "\n--------------------------------------\n");436	seq_puts(s, "PSS S0ix blkd Status (~1ms saturating bucket)\n");437	seq_puts(s, "--------------------------------------\n");438	seq_puts(s, "Blocker\t\t\t\t\tCount\n");439	for (index = 0; index < debugfs_conf->pcs_s0ix_blkd_evts; index++) {440		seq_printf(s, "%-32s\t%u\n",441			   debugfs_conf->pcs_s0ix_blkd_data[index].name,442			   pcs_s0ix_blkd[index]);443	}444 445	seq_puts(s, "\n--------------------------------------\n");446	seq_puts(s, "LTR Blocking Status (~1ms saturating bucket)\n");447	seq_puts(s, "--------------------------------------\n");448	seq_puts(s, "Blocker\t\t\t\t\tCount\n");449	for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) {450		seq_printf(s, "%-32s\t%u\n",451			   debugfs_conf->pss_ltr_data[index].name,452			   pss_s0ix_wakeup[index]);453	}454 455	seq_puts(s, "\n--------------------------------------\n");456	seq_puts(s, "Wakes Status (~1ms saturating bucket)\n");457	seq_puts(s, "--------------------------------------\n");458	seq_puts(s, "Wakes\t\t\t\t\tCount\n");459	for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) {460		seq_printf(s, "%-32s\t%u\n",461			   debugfs_conf->pss_wakeup[index].name,462			   pss_ltr_blkd[index]);463	}464 465	return 0;466}467 468DEFINE_SHOW_ATTRIBUTE(telem_pss_states);469 470static int telem_ioss_states_show(struct seq_file *s, void *unused)471{472	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];473	const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];474	int index, ret, err;475 476	ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,477				      TELEM_MAX_OS_ALLOCATED_EVENTS);478	if (ret < 0)479		return ret;480 481	err = telemetry_get_evtname(TELEM_IOSS, name,482				    TELEM_MAX_OS_ALLOCATED_EVENTS);483	if (err < 0)484		return err;485 486	seq_puts(s, "--------------------------------------\n");487	seq_puts(s, "\tI0SS TELEMETRY EVENTLOG\n");488	seq_puts(s, "--------------------------------------\n");489	for (index = 0; index < ret; index++) {490		seq_printf(s, "%-32s 0x%llx\n",491			   name[index], evtlog[index].telem_evtlog);492	}493 494	return 0;495}496 497DEFINE_SHOW_ATTRIBUTE(telem_ioss_states);498 499static int telem_soc_states_show(struct seq_file *s, void *unused)500{501	u32 d3_sts[TELEM_IOSS_DX_D0IX_EVTS], d0ix_sts[TELEM_IOSS_DX_D0IX_EVTS];502	u32 pg_sts[TELEM_IOSS_PG_EVTS], pss_idle[TELEM_PSS_IDLE_EVTS];503	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];504	u32 s0ix_total_ctr = 0, s0ix_shlw_ctr = 0, s0ix_deep_ctr = 0;505	u64 s0ix_total_res = 0, s0ix_shlw_res = 0, s0ix_deep_res = 0;506	struct telemetry_debugfs_conf *conf = debugfs_conf;507	struct pci_dev *dev = NULL;508	int index, idx, ret;509	u32 d3_state;510	u16 pmcsr;511 512	ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,513				      TELEM_MAX_OS_ALLOCATED_EVENTS);514	if (ret < 0)515		return ret;516 517	for (index = 0; index < ret; index++) {518		TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d3_id,519					   conf->ioss_d0ix_evts,520					   d3_sts, evtlog[index].telem_evtlog,521					   conf->ioss_d0ix_data,522					   TELEM_MASK_BIT);523 524		TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_pg_id, conf->ioss_pg_evts,525					   pg_sts, evtlog[index].telem_evtlog,526					   conf->ioss_pg_data, TELEM_MASK_BIT);527 528		TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d0ix_id,529					   conf->ioss_d0ix_evts,530					   d0ix_sts, evtlog[index].telem_evtlog,531					   conf->ioss_d0ix_data,532					   TELEM_MASK_BIT);533 534		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_occ_id,535					   s0ix_total_ctr);536 537		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,538					   s0ix_shlw_ctr);539 540		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,541					   s0ix_deep_ctr);542 543		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_res_id,544					   s0ix_total_res);545 546		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,547					   s0ix_shlw_res);548 549		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,550					   s0ix_deep_res);551	}552 553	seq_puts(s, "\n---------------------------------------------------\n");554	seq_puts(s, "S0IX Type\t\t\t Occurrence\t\t Residency(us)\n");555	seq_puts(s, "---------------------------------------------------\n");556 557	seq_printf(s, "S0IX Shallow\t\t\t %10u\t %10llu\n",558		   s0ix_shlw_ctr -559		   conf->suspend_stats.shlw_ctr,560		   (u64)((s0ix_shlw_res -561		   conf->suspend_stats.shlw_res)*10/192));562 563	seq_printf(s, "S0IX Deep\t\t\t %10u\t %10llu\n",564		   s0ix_deep_ctr -565		   conf->suspend_stats.deep_ctr,566		   (u64)((s0ix_deep_res -567		   conf->suspend_stats.deep_res)*10/192));568 569	seq_printf(s, "Suspend(With S0ixShallow)\t %10u\t %10llu\n",570		   conf->suspend_stats.shlw_ctr,571		   (u64)(conf->suspend_stats.shlw_res*10)/192);572 573	seq_printf(s, "Suspend(With S0ixDeep)\t\t %10u\t %10llu\n",574		   conf->suspend_stats.deep_ctr,575		   (u64)(conf->suspend_stats.deep_res*10)/192);576 577	seq_printf(s, "TOTAL S0IX\t\t\t %10u\t %10llu\n", s0ix_total_ctr,578		   (u64)(s0ix_total_res*10/192));579	seq_puts(s, "\n-------------------------------------------------\n");580	seq_puts(s, "\t\tDEVICE STATES\n");581	seq_puts(s, "-------------------------------------------------\n");582 583	for_each_pci_dev(dev) {584		pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);585		d3_state = ((pmcsr & PCI_PM_CTRL_STATE_MASK) ==586			    (__force int)PCI_D3hot) ? 1 : 0;587 588		seq_printf(s, "pci %04x %04X %s %20.20s: ",589			   dev->vendor, dev->device, dev_name(&dev->dev),590			   dev_driver_string(&dev->dev));591		seq_printf(s, " d3:%x\n", d3_state);592	}593 594	seq_puts(s, "\n--------------------------------------\n");595	seq_puts(s, "D3/D0i3 Status\n");596	seq_puts(s, "--------------------------------------\n");597	seq_puts(s, "Block\t\t D3\t D0i3\n");598	for (index = 0; index < conf->ioss_d0ix_evts; index++) {599		seq_printf(s, "%-10s\t %u\t %u\n",600			   conf->ioss_d0ix_data[index].name,601			   d3_sts[index], d0ix_sts[index]);602	}603 604	seq_puts(s, "\n--------------------------------------\n");605	seq_puts(s, "South Complex PowerGate Status\n");606	seq_puts(s, "--------------------------------------\n");607	seq_puts(s, "Device\t\t PG\n");608	for (index = 0; index < conf->ioss_pg_evts; index++) {609		seq_printf(s, "%-10s\t %u\n",610			   conf->ioss_pg_data[index].name,611			   pg_sts[index]);612	}613 614	evtlog->telem_evtid = conf->pss_idle_id;615	ret = telemetry_read_events(TELEM_PSS, evtlog, 1);616	if (ret < 0)617		return ret;618 619	seq_puts(s, "\n-----------------------------------------\n");620	seq_puts(s, "North Idle Status\n");621	seq_puts(s, "-----------------------------------------\n");622	for (idx = 0; idx < conf->pss_idle_evts - 1; idx++) {623		pss_idle[idx] =	(evtlog->telem_evtlog >>624				conf->pss_idle_data[idx].bit_pos) &625				TELEM_MASK_BIT;626	}627 628	pss_idle[idx] = (evtlog->telem_evtlog >>629			conf->pss_idle_data[idx].bit_pos) &630			TELEM_APL_MASK_PCS_STATE;631 632	for (index = 0; index < conf->pss_idle_evts; index++) {633		seq_printf(s, "%-30s %u\n",634			   conf->pss_idle_data[index].name,635			   pss_idle[index]);636	}637 638	seq_puts(s, "\nPCS_STATUS Code\n");639	seq_puts(s, "0:C0 1:C1 2:C1_DN_WT_DEV 3:C2 4:C2_WT_DE_MEM_UP\n");640	seq_puts(s, "5:C2_WT_DE_MEM_DOWN 6:C2_UP_WT_DEV 7:C2_DN 8:C2_VOA\n");641	seq_puts(s, "9:C2_VOA_UP 10:S0IX_PRE 11:S0IX\n");642 643	return 0;644}645 646DEFINE_SHOW_ATTRIBUTE(telem_soc_states);647 648static int telem_s0ix_res_get(void *data, u64 *val)649{650	struct telemetry_plt_config *plt_config = telemetry_get_pltdata();651	u64 s0ix_total_res;652	int ret;653 654	ret = intel_pmc_s0ix_counter_read(plt_config->pmc, &s0ix_total_res);655	if (ret) {656		pr_err("Failed to read S0ix residency");657		return ret;658	}659 660	*val = s0ix_total_res;661 662	return 0;663}664 665DEFINE_DEBUGFS_ATTRIBUTE(telem_s0ix_fops, telem_s0ix_res_get, NULL, "%llu\n");666 667static int telem_pss_trc_verb_show(struct seq_file *s, void *unused)668{669	u32 verbosity;670	int err;671 672	err = telemetry_get_trace_verbosity(TELEM_PSS, &verbosity);673	if (err) {674		pr_err("Get PSS Trace Verbosity Failed with Error %d\n", err);675		return -EFAULT;676	}677 678	seq_printf(s, "PSS Trace Verbosity %u\n", verbosity);679	return 0;680}681 682static ssize_t telem_pss_trc_verb_write(struct file *file,683					const char __user *userbuf,684					size_t count, loff_t *ppos)685{686	u32 verbosity;687	int err;688 689	err = kstrtou32_from_user(userbuf, count, 0, &verbosity);690	if (err)691		return err;692 693	err = telemetry_set_trace_verbosity(TELEM_PSS, verbosity);694	if (err) {695		pr_err("Changing PSS Trace Verbosity Failed. Error %d\n", err);696		return err;697	}698 699	return count;700}701 702static int telem_pss_trc_verb_open(struct inode *inode, struct file *file)703{704	return single_open(file, telem_pss_trc_verb_show, inode->i_private);705}706 707static const struct file_operations telem_pss_trc_verb_ops = {708	.open		= telem_pss_trc_verb_open,709	.read		= seq_read,710	.write		= telem_pss_trc_verb_write,711	.llseek		= seq_lseek,712	.release	= single_release,713};714 715static int telem_ioss_trc_verb_show(struct seq_file *s, void *unused)716{717	u32 verbosity;718	int err;719 720	err = telemetry_get_trace_verbosity(TELEM_IOSS, &verbosity);721	if (err) {722		pr_err("Get IOSS Trace Verbosity Failed with Error %d\n", err);723		return -EFAULT;724	}725 726	seq_printf(s, "IOSS Trace Verbosity %u\n", verbosity);727	return 0;728}729 730static ssize_t telem_ioss_trc_verb_write(struct file *file,731					 const char __user *userbuf,732					 size_t count, loff_t *ppos)733{734	u32 verbosity;735	int err;736 737	err = kstrtou32_from_user(userbuf, count, 0, &verbosity);738	if (err)739		return err;740 741	err = telemetry_set_trace_verbosity(TELEM_IOSS, verbosity);742	if (err) {743		pr_err("Changing IOSS Trace Verbosity Failed. Error %d\n", err);744		return err;745	}746 747	return count;748}749 750static int telem_ioss_trc_verb_open(struct inode *inode, struct file *file)751{752	return single_open(file, telem_ioss_trc_verb_show, inode->i_private);753}754 755static const struct file_operations telem_ioss_trc_verb_ops = {756	.open		= telem_ioss_trc_verb_open,757	.read		= seq_read,758	.write		= telem_ioss_trc_verb_write,759	.llseek		= seq_lseek,760	.release	= single_release,761};762 763static int pm_suspend_prep_cb(void)764{765	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];766	struct telemetry_debugfs_conf *conf = debugfs_conf;767	int ret, index;768 769	ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,770			TELEM_MAX_OS_ALLOCATED_EVENTS);771	if (ret < 0) {772		suspend_prep_ok = 0;773		goto out;774	}775 776	for (index = 0; index < ret; index++) {777 778		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,779					   suspend_shlw_ctr_temp);780 781		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,782					   suspend_deep_ctr_temp);783 784		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,785					   suspend_shlw_res_temp);786 787		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,788					   suspend_deep_res_temp);789	}790	suspend_prep_ok = 1;791out:792	return NOTIFY_OK;793}794 795static int pm_suspend_exit_cb(void)796{797	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];798	static u32 suspend_shlw_ctr_exit, suspend_deep_ctr_exit;799	static u64 suspend_shlw_res_exit, suspend_deep_res_exit;800	struct telemetry_debugfs_conf *conf = debugfs_conf;801	int ret, index;802 803	if (!suspend_prep_ok)804		goto out;805 806	ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,807					  TELEM_MAX_OS_ALLOCATED_EVENTS);808	if (ret < 0)809		goto out;810 811	for (index = 0; index < ret; index++) {812		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,813					   suspend_shlw_ctr_exit);814 815		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,816					   suspend_deep_ctr_exit);817 818		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,819					   suspend_shlw_res_exit);820 821		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,822					   suspend_deep_res_exit);823	}824 825	if ((suspend_shlw_ctr_exit < suspend_shlw_ctr_temp) ||826	    (suspend_deep_ctr_exit < suspend_deep_ctr_temp) ||827	    (suspend_shlw_res_exit < suspend_shlw_res_temp) ||828	    (suspend_deep_res_exit < suspend_deep_res_temp)) {829		pr_err("Wrong s0ix counters detected\n");830		goto out;831	}832 833	/*834	 * Due to some design limitations in the firmware, sometimes the835	 * counters do not get updated by the time we reach here. As a836	 * workaround, we try to see if this was a genuine case of sleep837	 * failure or not by cross-checking from PMC GCR registers directly.838	 */839	if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp &&840	    suspend_deep_ctr_exit == suspend_deep_ctr_temp) {841		struct telemetry_plt_config *plt_config = telemetry_get_pltdata();842		struct intel_pmc_dev *pmc = plt_config->pmc;843 844		ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_SHLW_S0IX_REG,845					  &suspend_shlw_res_exit);846		if (ret < 0)847			goto out;848 849		ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_DEEP_S0IX_REG,850					  &suspend_deep_res_exit);851		if (ret < 0)852			goto out;853 854		if (suspend_shlw_res_exit > suspend_shlw_res_temp)855			suspend_shlw_ctr_exit++;856 857		if (suspend_deep_res_exit > suspend_deep_res_temp)858			suspend_deep_ctr_exit++;859	}860 861	suspend_shlw_ctr_exit -= suspend_shlw_ctr_temp;862	suspend_deep_ctr_exit -= suspend_deep_ctr_temp;863	suspend_shlw_res_exit -= suspend_shlw_res_temp;864	suspend_deep_res_exit -= suspend_deep_res_temp;865 866	if (suspend_shlw_ctr_exit != 0) {867		conf->suspend_stats.shlw_ctr +=868		suspend_shlw_ctr_exit;869 870		conf->suspend_stats.shlw_res +=871		suspend_shlw_res_exit;872	}873 874	if (suspend_deep_ctr_exit != 0) {875		conf->suspend_stats.deep_ctr +=876		suspend_deep_ctr_exit;877 878		conf->suspend_stats.deep_res +=879		suspend_deep_res_exit;880	}881 882out:883	suspend_prep_ok = 0;884	return NOTIFY_OK;885}886 887static int pm_notification(struct notifier_block *this,888			   unsigned long event, void *ptr)889{890	switch (event) {891	case PM_SUSPEND_PREPARE:892		return pm_suspend_prep_cb();893	case PM_POST_SUSPEND:894		return pm_suspend_exit_cb();895	}896 897	return NOTIFY_DONE;898}899 900static struct notifier_block pm_notifier = {901	.notifier_call = pm_notification,902};903 904static int __init telemetry_debugfs_init(void)905{906	const struct x86_cpu_id *id;907	int err;908	struct dentry *dir;909 910	/* Only APL supported for now */911	id = x86_match_cpu(telemetry_debugfs_cpu_ids);912	if (!id)913		return -ENODEV;914 915	debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;916 917	if (!telemetry_get_pltdata()) {918		pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");919		return -ENODEV;920	}921 922	err = telemetry_debugfs_check_evts();923	if (err < 0) {924		pr_info("telemetry_debugfs_check_evts failed\n");925		return -EINVAL;926	}927 928	register_pm_notifier(&pm_notifier);929 930	dir = debugfs_create_dir("telemetry", NULL);931	debugfs_conf->telemetry_dbg_dir = dir;932 933	debugfs_create_file("pss_info", S_IFREG | S_IRUGO, dir, NULL,934			    &telem_pss_states_fops);935	debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, dir, NULL,936			    &telem_ioss_states_fops);937	debugfs_create_file("soc_states", S_IFREG | S_IRUGO, dir, NULL,938			    &telem_soc_states_fops);939	debugfs_create_file("s0ix_residency_usec", S_IFREG | S_IRUGO, dir, NULL,940			    &telem_s0ix_fops);941	debugfs_create_file("pss_trace_verbosity", S_IFREG | S_IRUGO, dir, NULL,942			    &telem_pss_trc_verb_ops);943	debugfs_create_file("ioss_trace_verbosity", S_IFREG | S_IRUGO, dir,944			    NULL, &telem_ioss_trc_verb_ops);945	return 0;946}947 948static void __exit telemetry_debugfs_exit(void)949{950	debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);951	debugfs_conf->telemetry_dbg_dir = NULL;952	unregister_pm_notifier(&pm_notifier);953}954 955late_initcall(telemetry_debugfs_init);956module_exit(telemetry_debugfs_exit);957 958MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");959MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface");960MODULE_VERSION(DRIVER_VERSION);961MODULE_LICENSE("GPL v2");962