tools/power turbostat: Allow adding PMT counters directly by sysfs path

Allow user to add PMT counters by either identifying the source with:
guid=%u,seq=%u
or, since this patch, with direct sysfs path:
path=%s, for example path=/sys/class/intel_pmt/telem5

In the later case, the guid and sequence number will be infered
by turbostat.

Signed-off-by: Patryk Wlazlyn <patryk.wlazlyn@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by Patryk Wlazlyn and committed by Len Brown 83fbeb9f 16ce4678

+106 -1
+106 -1
tools/power/x86/turbostat/turbostat.c
··· 9788 9788 return strncmp(prefix, str, strlen(prefix)) == 0; 9789 9789 } 9790 9790 9791 + int pmt_parse_from_path(const char *target_path, unsigned int *out_guid, unsigned int *out_seq) 9792 + { 9793 + struct pmt_diriter_t pmt_iter; 9794 + const struct dirent *dirname; 9795 + struct stat stat, target_stat; 9796 + int fd_telem_dir = -1; 9797 + int fd_target_dir; 9798 + unsigned int seq = 0; 9799 + unsigned long guid, target_guid; 9800 + int ret = -1; 9801 + 9802 + fd_target_dir = open(target_path, O_RDONLY | O_DIRECTORY); 9803 + if (fd_target_dir == -1) { 9804 + return -1; 9805 + } 9806 + 9807 + if (fstat(fd_target_dir, &target_stat) == -1) { 9808 + fprintf(stderr, "%s: Failed to stat the target: %s", __func__, strerror(errno)); 9809 + exit(1); 9810 + } 9811 + 9812 + if (parse_telem_info_file(fd_target_dir, "guid", "%lx", &target_guid)) { 9813 + fprintf(stderr, "%s: Failed to parse the target guid file: %s", __func__, strerror(errno)); 9814 + exit(1); 9815 + } 9816 + 9817 + close(fd_target_dir); 9818 + 9819 + pmt_diriter_init(&pmt_iter); 9820 + 9821 + for (dirname = pmt_diriter_begin(&pmt_iter, SYSFS_TELEM_PATH); dirname != NULL; 9822 + dirname = pmt_diriter_next(&pmt_iter)) { 9823 + 9824 + fd_telem_dir = openat(dirfd(pmt_iter.dir), dirname->d_name, O_RDONLY | O_DIRECTORY); 9825 + if (fd_telem_dir == -1) { 9826 + continue; 9827 + } 9828 + 9829 + if (parse_telem_info_file(fd_telem_dir, "guid", "%lx", &guid)) { 9830 + fprintf(stderr, "%s: Failed to parse the guid file: %s", __func__, strerror(errno)); 9831 + continue; 9832 + } 9833 + 9834 + if (fstat(fd_telem_dir, &stat) == -1) { 9835 + fprintf(stderr, "%s: Failed to stat %s directory: %s", __func__, 9836 + dirname->d_name, strerror(errno)); 9837 + continue; 9838 + } 9839 + 9840 + /* 9841 + * If reached the same directory as target, exit the loop. 9842 + * Seq has the correct value now. 9843 + */ 9844 + if (stat.st_dev == target_stat.st_dev && stat.st_ino == target_stat.st_ino) { 9845 + ret = 0; 9846 + break; 9847 + } 9848 + 9849 + /* 9850 + * If reached directory with the same guid, 9851 + * but it's not the target directory yet, 9852 + * increment seq and continue the search. 9853 + */ 9854 + if (guid == target_guid) 9855 + ++seq; 9856 + 9857 + close(fd_telem_dir); 9858 + fd_telem_dir = -1; 9859 + } 9860 + 9861 + pmt_diriter_remove(&pmt_iter); 9862 + 9863 + if (fd_telem_dir != -1) 9864 + close(fd_telem_dir); 9865 + 9866 + if (!ret) { 9867 + *out_guid = target_guid; 9868 + *out_seq = seq; 9869 + } 9870 + 9871 + return ret; 9872 + } 9873 + 9791 9874 void parse_add_command_pmt(char *add_command) 9792 9875 { 9793 9876 char *name = NULL; 9794 9877 char *type_name = NULL; 9795 9878 char *format_name = NULL; 9879 + char *direct_path = NULL; 9880 + static const char direct_path_prefix[] = "path="; 9796 9881 unsigned int offset; 9797 9882 unsigned int lsb; 9798 9883 unsigned int msb; ··· 9966 9881 goto next; 9967 9882 } 9968 9883 9884 + if (strncmp(add_command, direct_path_prefix, strlen(direct_path_prefix)) == 0) { 9885 + direct_path = add_command + strlen(direct_path_prefix); 9886 + goto next; 9887 + } 9969 9888 next: 9970 9889 add_command = strchr(add_command, ','); 9971 9890 if (add_command) { ··· 10041 9952 exit(1); 10042 9953 } 10043 9954 9955 + if (direct_path && has_guid) { 9956 + printf("%s: path and guid+seq parameters are mutually exclusive\n" 9957 + "notice: passed guid=0x%x and path=%s\n", __func__, guid, direct_path); 9958 + exit(1); 9959 + } 9960 + 9961 + if (direct_path) { 9962 + if (pmt_parse_from_path(direct_path, &guid, &seq)) { 9963 + printf("%s: failed to parse PMT file from %s\n", __func__, direct_path); 9964 + exit(1); 9965 + } 9966 + 9967 + /* GUID was just infered from the direct path. */ 9968 + has_guid = true; 9969 + } 9970 + 10044 9971 if (!has_guid) { 10045 - printf("%s: missing %s\n", __func__, "guid"); 9972 + printf("%s: missing %s\n", __func__, "guid or path"); 10046 9973 exit(1); 10047 9974 } 10048 9975