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