| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Intel SOC Telemetry debugfs Driver: Currently supports APL |
|---|
| 3 | 4 | * Copyright (c) 2015, Intel Corporation. |
|---|
| 4 | 5 | * 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 | 6 | * |
|---|
| 15 | 7 | * This file provides the debugfs interfaces for telemetry. |
|---|
| 16 | 8 | * /sys/kernel/debug/telemetry/pss_info: Shows Primary Control Sub-Sys Counters |
|---|
| .. | .. |
|---|
| 23 | 15 | */ |
|---|
| 24 | 16 | #include <linux/debugfs.h> |
|---|
| 25 | 17 | #include <linux/device.h> |
|---|
| 18 | +#include <linux/mfd/intel_pmc_bxt.h> |
|---|
| 26 | 19 | #include <linux/module.h> |
|---|
| 27 | 20 | #include <linux/pci.h> |
|---|
| 28 | 21 | #include <linux/seq_file.h> |
|---|
| .. | .. |
|---|
| 30 | 23 | |
|---|
| 31 | 24 | #include <asm/cpu_device_id.h> |
|---|
| 32 | 25 | #include <asm/intel-family.h> |
|---|
| 33 | | -#include <asm/intel_pmc_ipc.h> |
|---|
| 34 | 26 | #include <asm/intel_telemetry.h> |
|---|
| 35 | 27 | |
|---|
| 36 | 28 | #define DRIVER_NAME "telemetry_soc_debugfs" |
|---|
| .. | .. |
|---|
| 71 | 63 | #define TELEM_PSS_LTR_BLOCKING_EVTS 20 |
|---|
| 72 | 64 | #define TELEM_IOSS_DX_D0IX_EVTS 25 |
|---|
| 73 | 65 | #define TELEM_IOSS_PG_EVTS 30 |
|---|
| 74 | | - |
|---|
| 75 | | -#define TELEM_DEBUGFS_CPU(model, data) \ |
|---|
| 76 | | - { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&data} |
|---|
| 77 | 66 | |
|---|
| 78 | 67 | #define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \ |
|---|
| 79 | 68 | if (evtlog[index].telem_evtid == (EVTID)) { \ |
|---|
| .. | .. |
|---|
| 319 | 308 | }; |
|---|
| 320 | 309 | |
|---|
| 321 | 310 | static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = { |
|---|
| 322 | | - TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_debugfs_conf), |
|---|
| 323 | | - TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf), |
|---|
| 311 | + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &telem_apl_debugfs_conf), |
|---|
| 312 | + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &telem_apl_debugfs_conf), |
|---|
| 324 | 313 | {} |
|---|
| 325 | 314 | }; |
|---|
| 326 | | - |
|---|
| 327 | 315 | MODULE_DEVICE_TABLE(x86cpu, telemetry_debugfs_cpu_ids); |
|---|
| 328 | 316 | |
|---|
| 329 | 317 | static int telemetry_debugfs_check_evts(void) |
|---|
| .. | .. |
|---|
| 477 | 465 | return 0; |
|---|
| 478 | 466 | } |
|---|
| 479 | 467 | |
|---|
| 480 | | -static int telem_pss_state_open(struct inode *inode, struct file *file) |
|---|
| 481 | | -{ |
|---|
| 482 | | - return single_open(file, telem_pss_states_show, inode->i_private); |
|---|
| 483 | | -} |
|---|
| 484 | | - |
|---|
| 485 | | -static const struct file_operations telem_pss_ops = { |
|---|
| 486 | | - .open = telem_pss_state_open, |
|---|
| 487 | | - .read = seq_read, |
|---|
| 488 | | - .llseek = seq_lseek, |
|---|
| 489 | | - .release = single_release, |
|---|
| 490 | | -}; |
|---|
| 468 | +DEFINE_SHOW_ATTRIBUTE(telem_pss_states); |
|---|
| 491 | 469 | |
|---|
| 492 | 470 | static int telem_ioss_states_show(struct seq_file *s, void *unused) |
|---|
| 493 | 471 | { |
|---|
| .. | .. |
|---|
| 516 | 494 | return 0; |
|---|
| 517 | 495 | } |
|---|
| 518 | 496 | |
|---|
| 519 | | -static int telem_ioss_state_open(struct inode *inode, struct file *file) |
|---|
| 520 | | -{ |
|---|
| 521 | | - return single_open(file, telem_ioss_states_show, inode->i_private); |
|---|
| 522 | | -} |
|---|
| 523 | | - |
|---|
| 524 | | -static const struct file_operations telem_ioss_ops = { |
|---|
| 525 | | - .open = telem_ioss_state_open, |
|---|
| 526 | | - .read = seq_read, |
|---|
| 527 | | - .llseek = seq_lseek, |
|---|
| 528 | | - .release = single_release, |
|---|
| 529 | | -}; |
|---|
| 497 | +DEFINE_SHOW_ATTRIBUTE(telem_ioss_states); |
|---|
| 530 | 498 | |
|---|
| 531 | 499 | static int telem_soc_states_show(struct seq_file *s, void *unused) |
|---|
| 532 | 500 | { |
|---|
| .. | .. |
|---|
| 675 | 643 | return 0; |
|---|
| 676 | 644 | } |
|---|
| 677 | 645 | |
|---|
| 678 | | -static int telem_soc_state_open(struct inode *inode, struct file *file) |
|---|
| 679 | | -{ |
|---|
| 680 | | - return single_open(file, telem_soc_states_show, inode->i_private); |
|---|
| 681 | | -} |
|---|
| 682 | | - |
|---|
| 683 | | -static const struct file_operations telem_socstate_ops = { |
|---|
| 684 | | - .open = telem_soc_state_open, |
|---|
| 685 | | - .read = seq_read, |
|---|
| 686 | | - .llseek = seq_lseek, |
|---|
| 687 | | - .release = single_release, |
|---|
| 688 | | -}; |
|---|
| 646 | +DEFINE_SHOW_ATTRIBUTE(telem_soc_states); |
|---|
| 689 | 647 | |
|---|
| 690 | 648 | static int telem_s0ix_res_get(void *data, u64 *val) |
|---|
| 691 | 649 | { |
|---|
| 650 | + struct telemetry_plt_config *plt_config = telemetry_get_pltdata(); |
|---|
| 692 | 651 | u64 s0ix_total_res; |
|---|
| 693 | 652 | int ret; |
|---|
| 694 | 653 | |
|---|
| 695 | | - ret = intel_pmc_s0ix_counter_read(&s0ix_total_res); |
|---|
| 654 | + ret = intel_pmc_s0ix_counter_read(plt_config->pmc, &s0ix_total_res); |
|---|
| 696 | 655 | if (ret) { |
|---|
| 697 | 656 | pr_err("Failed to read S0ix residency"); |
|---|
| 698 | 657 | return ret; |
|---|
| .. | .. |
|---|
| 727 | 686 | u32 verbosity; |
|---|
| 728 | 687 | int err; |
|---|
| 729 | 688 | |
|---|
| 730 | | - if (kstrtou32_from_user(userbuf, count, 0, &verbosity)) |
|---|
| 731 | | - return -EFAULT; |
|---|
| 689 | + err = kstrtou32_from_user(userbuf, count, 0, &verbosity); |
|---|
| 690 | + if (err) |
|---|
| 691 | + return err; |
|---|
| 732 | 692 | |
|---|
| 733 | 693 | err = telemetry_set_trace_verbosity(TELEM_PSS, verbosity); |
|---|
| 734 | 694 | if (err) { |
|---|
| 735 | 695 | pr_err("Changing PSS Trace Verbosity Failed. Error %d\n", err); |
|---|
| 736 | | - count = err; |
|---|
| 696 | + return err; |
|---|
| 737 | 697 | } |
|---|
| 738 | 698 | |
|---|
| 739 | 699 | return count; |
|---|
| .. | .. |
|---|
| 774 | 734 | u32 verbosity; |
|---|
| 775 | 735 | int err; |
|---|
| 776 | 736 | |
|---|
| 777 | | - if (kstrtou32_from_user(userbuf, count, 0, &verbosity)) |
|---|
| 778 | | - return -EFAULT; |
|---|
| 737 | + err = kstrtou32_from_user(userbuf, count, 0, &verbosity); |
|---|
| 738 | + if (err) |
|---|
| 739 | + return err; |
|---|
| 779 | 740 | |
|---|
| 780 | 741 | err = telemetry_set_trace_verbosity(TELEM_IOSS, verbosity); |
|---|
| 781 | 742 | if (err) { |
|---|
| 782 | 743 | pr_err("Changing IOSS Trace Verbosity Failed. Error %d\n", err); |
|---|
| 783 | | - count = err; |
|---|
| 744 | + return err; |
|---|
| 784 | 745 | } |
|---|
| 785 | 746 | |
|---|
| 786 | 747 | return count; |
|---|
| .. | .. |
|---|
| 877 | 838 | */ |
|---|
| 878 | 839 | if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp && |
|---|
| 879 | 840 | suspend_deep_ctr_exit == suspend_deep_ctr_temp) { |
|---|
| 880 | | - ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_SHLW_S0IX_REG, |
|---|
| 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, |
|---|
| 881 | 845 | &suspend_shlw_res_exit); |
|---|
| 882 | 846 | if (ret < 0) |
|---|
| 883 | 847 | goto out; |
|---|
| 884 | 848 | |
|---|
| 885 | | - ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_DEEP_S0IX_REG, |
|---|
| 849 | + ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_DEEP_S0IX_REG, |
|---|
| 886 | 850 | &suspend_deep_res_exit); |
|---|
| 887 | 851 | if (ret < 0) |
|---|
| 888 | 852 | goto out; |
|---|
| .. | .. |
|---|
| 941 | 905 | { |
|---|
| 942 | 906 | const struct x86_cpu_id *id; |
|---|
| 943 | 907 | int err; |
|---|
| 944 | | - struct dentry *f; |
|---|
| 908 | + struct dentry *dir; |
|---|
| 945 | 909 | |
|---|
| 946 | 910 | /* Only APL supported for now */ |
|---|
| 947 | 911 | id = x86_match_cpu(telemetry_debugfs_cpu_ids); |
|---|
| .. | .. |
|---|
| 950 | 914 | |
|---|
| 951 | 915 | debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data; |
|---|
| 952 | 916 | |
|---|
| 953 | | - err = telemetry_pltconfig_valid(); |
|---|
| 954 | | - if (err < 0) { |
|---|
| 917 | + if (!telemetry_get_pltdata()) { |
|---|
| 955 | 918 | pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n"); |
|---|
| 956 | 919 | return -ENODEV; |
|---|
| 957 | 920 | } |
|---|
| .. | .. |
|---|
| 964 | 927 | |
|---|
| 965 | 928 | register_pm_notifier(&pm_notifier); |
|---|
| 966 | 929 | |
|---|
| 967 | | - err = -ENOMEM; |
|---|
| 968 | | - debugfs_conf->telemetry_dbg_dir = debugfs_create_dir("telemetry", NULL); |
|---|
| 969 | | - if (!debugfs_conf->telemetry_dbg_dir) |
|---|
| 970 | | - goto out_pm; |
|---|
| 930 | + dir = debugfs_create_dir("telemetry", NULL); |
|---|
| 931 | + debugfs_conf->telemetry_dbg_dir = dir; |
|---|
| 971 | 932 | |
|---|
| 972 | | - f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO, |
|---|
| 973 | | - debugfs_conf->telemetry_dbg_dir, NULL, |
|---|
| 974 | | - &telem_pss_ops); |
|---|
| 975 | | - if (!f) { |
|---|
| 976 | | - pr_err("pss_sample_info debugfs register failed\n"); |
|---|
| 977 | | - goto out; |
|---|
| 978 | | - } |
|---|
| 979 | | - |
|---|
| 980 | | - f = debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, |
|---|
| 981 | | - debugfs_conf->telemetry_dbg_dir, NULL, |
|---|
| 982 | | - &telem_ioss_ops); |
|---|
| 983 | | - if (!f) { |
|---|
| 984 | | - pr_err("ioss_sample_info debugfs register failed\n"); |
|---|
| 985 | | - goto out; |
|---|
| 986 | | - } |
|---|
| 987 | | - |
|---|
| 988 | | - f = debugfs_create_file("soc_states", S_IFREG | S_IRUGO, |
|---|
| 989 | | - debugfs_conf->telemetry_dbg_dir, |
|---|
| 990 | | - NULL, &telem_socstate_ops); |
|---|
| 991 | | - if (!f) { |
|---|
| 992 | | - pr_err("ioss_sample_info debugfs register failed\n"); |
|---|
| 993 | | - goto out; |
|---|
| 994 | | - } |
|---|
| 995 | | - |
|---|
| 996 | | - f = debugfs_create_file("s0ix_residency_usec", S_IFREG | S_IRUGO, |
|---|
| 997 | | - debugfs_conf->telemetry_dbg_dir, |
|---|
| 998 | | - NULL, &telem_s0ix_fops); |
|---|
| 999 | | - if (!f) { |
|---|
| 1000 | | - pr_err("s0ix_residency_usec debugfs register failed\n"); |
|---|
| 1001 | | - goto out; |
|---|
| 1002 | | - } |
|---|
| 1003 | | - |
|---|
| 1004 | | - f = debugfs_create_file("pss_trace_verbosity", S_IFREG | S_IRUGO, |
|---|
| 1005 | | - debugfs_conf->telemetry_dbg_dir, NULL, |
|---|
| 1006 | | - &telem_pss_trc_verb_ops); |
|---|
| 1007 | | - if (!f) { |
|---|
| 1008 | | - pr_err("pss_trace_verbosity debugfs register failed\n"); |
|---|
| 1009 | | - goto out; |
|---|
| 1010 | | - } |
|---|
| 1011 | | - |
|---|
| 1012 | | - f = debugfs_create_file("ioss_trace_verbosity", S_IFREG | S_IRUGO, |
|---|
| 1013 | | - debugfs_conf->telemetry_dbg_dir, NULL, |
|---|
| 1014 | | - &telem_ioss_trc_verb_ops); |
|---|
| 1015 | | - if (!f) { |
|---|
| 1016 | | - pr_err("ioss_trace_verbosity debugfs register failed\n"); |
|---|
| 1017 | | - goto out; |
|---|
| 1018 | | - } |
|---|
| 1019 | | - |
|---|
| 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); |
|---|
| 1020 | 945 | return 0; |
|---|
| 1021 | | - |
|---|
| 1022 | | -out: |
|---|
| 1023 | | - debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir); |
|---|
| 1024 | | - debugfs_conf->telemetry_dbg_dir = NULL; |
|---|
| 1025 | | -out_pm: |
|---|
| 1026 | | - unregister_pm_notifier(&pm_notifier); |
|---|
| 1027 | | - |
|---|
| 1028 | | - return err; |
|---|
| 1029 | 946 | } |
|---|
| 1030 | 947 | |
|---|
| 1031 | 948 | static void __exit telemetry_debugfs_exit(void) |
|---|
| .. | .. |
|---|
| 1041 | 958 | MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>"); |
|---|
| 1042 | 959 | MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface"); |
|---|
| 1043 | 960 | MODULE_VERSION(DRIVER_VERSION); |
|---|
| 1044 | | -MODULE_LICENSE("GPL"); |
|---|
| 961 | +MODULE_LICENSE("GPL v2"); |
|---|