Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf pmu-events: Don't assume pmu_event is an array

The current code assumes that a struct pmu_event can be iterated over
forward until a NULL pmu_event is encountered.

This makes it difficult to refactor pmu_event.

Add a loop function taking a callback function that's passed the struct
pmu_event.

This way the pmu_event is only needed for one element and not an entire
array.

Switch existing code iterating over the pmu_event arrays to use the new
loop function pmu_events_table_for_each_event.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.garry@huawei.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Will Deacon <will@kernel.org>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20220812230949.683239-11-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
660842e4 7ae5c03a

+315 -184
+20 -14
tools/perf/pmu-events/empty-pmu-events.c
··· 247 247 }, 248 248 }; 249 249 250 + int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, 251 + void *data) 252 + { 253 + for (const struct pmu_event *pe = &table[0]; 254 + pe->name || pe->metric_group || pe->metric_name; 255 + pe++) { 256 + int ret = fn(pe, table, data); 257 + 258 + if (ret) 259 + return ret; 260 + } 261 + return 0; 262 + } 263 + 250 264 const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu) 251 265 { 252 266 const struct pmu_event *table = NULL; ··· 305 291 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 306 292 tables->table; 307 293 tables++) { 308 - for (const struct pmu_event *pe = &tables->table[0]; 309 - pe->name || pe->metric_group || pe->metric_name; 310 - pe++) { 311 - int ret = fn(pe, &tables->table[0], data); 294 + int ret = pmu_events_table_for_each_event(tables->table, fn, data); 312 295 313 - if (ret) 314 - return ret; 315 - } 296 + if (ret) 297 + return ret; 316 298 } 317 299 return 0; 318 300 } ··· 329 319 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 330 320 tables->name; 331 321 tables++) { 332 - for (const struct pmu_event *pe = &tables->table[0]; 333 - pe->name || pe->metric_group || pe->metric_name; 334 - pe++) { 335 - int ret = fn(pe, &tables->table[0], data); 322 + int ret = pmu_events_table_for_each_event(tables->table, fn, data); 336 323 337 - if (ret) 338 - return ret; 339 - } 324 + if (ret) 325 + return ret; 340 326 } 341 327 return 0; 342 328 }
+20 -14
tools/perf/pmu-events/jevents.py
··· 410 410 \t}, 411 411 }; 412 412 413 + int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, 414 + void *data) 415 + { 416 + for (const struct pmu_event *pe = &table[0]; 417 + pe->name || pe->metric_group || pe->metric_name; 418 + pe++) { 419 + int ret = fn(pe, table, data); 420 + 421 + if (ret) 422 + return ret; 423 + } 424 + return 0; 425 + } 426 + 413 427 const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu) 414 428 { 415 429 const struct pmu_event *table = NULL; ··· 467 453 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 468 454 tables->table; 469 455 tables++) { 470 - for (const struct pmu_event *pe = &tables->table[0]; 471 - pe->name || pe->metric_group || pe->metric_name; 472 - pe++) { 473 - int ret = fn(pe, &tables->table[0], data); 456 + int ret = pmu_events_table_for_each_event(tables->table, fn, data); 474 457 475 - if (ret) 476 - return ret; 477 - } 458 + if (ret) 459 + return ret; 478 460 } 479 461 return 0; 480 462 } ··· 491 481 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 492 482 tables->name; 493 483 tables++) { 494 - for (const struct pmu_event *pe = &tables->table[0]; 495 - pe->name || pe->metric_group || pe->metric_name; 496 - pe++) { 497 - int ret = fn(pe, &tables->table[0], data); 484 + int ret = pmu_events_table_for_each_event(tables->table, fn, data); 498 485 499 - if (ret) 500 - return ret; 501 - } 486 + if (ret) 487 + return ret; 502 488 } 503 489 return 0; 504 490 }
+3
tools/perf/pmu-events/pmu-events.h
··· 34 34 const struct pmu_event *table, 35 35 void *data); 36 36 37 + int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, 38 + void *data); 39 + 37 40 const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu); 38 41 const struct pmu_event *find_core_events_table(const char *arch, const char *cpuid); 39 42 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data);
+80 -60
tools/perf/tests/pmu-events.c
··· 423 423 return 0; 424 424 } 425 425 426 + static int test__pmu_event_table_core_callback(const struct pmu_event *pe, 427 + const struct pmu_event *table __maybe_unused, 428 + void *data) 429 + { 430 + int *map_events = data; 431 + struct perf_pmu_test_event const **test_event_table; 432 + bool found = false; 433 + 434 + if (!pe->name) 435 + return 0; 436 + 437 + if (pe->pmu) 438 + test_event_table = &uncore_events[0]; 439 + else 440 + test_event_table = &core_events[0]; 441 + 442 + for (; *test_event_table; test_event_table++) { 443 + struct perf_pmu_test_event const *test_event = *test_event_table; 444 + struct pmu_event const *event = &test_event->event; 445 + 446 + if (strcmp(pe->name, event->name)) 447 + continue; 448 + found = true; 449 + (*map_events)++; 450 + 451 + if (compare_pmu_events(pe, event)) 452 + return -1; 453 + 454 + pr_debug("testing event table %s: pass\n", pe->name); 455 + } 456 + if (!found) { 457 + pr_err("testing event table: could not find event %s\n", pe->name); 458 + return -1; 459 + } 460 + return 0; 461 + } 462 + 463 + static int test__pmu_event_table_sys_callback(const struct pmu_event *pe, 464 + const struct pmu_event *table __maybe_unused, 465 + void *data) 466 + { 467 + int *map_events = data; 468 + struct perf_pmu_test_event const **test_event_table; 469 + bool found = false; 470 + 471 + test_event_table = &sys_events[0]; 472 + 473 + for (; *test_event_table; test_event_table++) { 474 + struct perf_pmu_test_event const *test_event = *test_event_table; 475 + struct pmu_event const *event = &test_event->event; 476 + 477 + if (strcmp(pe->name, event->name)) 478 + continue; 479 + found = true; 480 + (*map_events)++; 481 + 482 + if (compare_pmu_events(pe, event)) 483 + return TEST_FAIL; 484 + 485 + pr_debug("testing sys event table %s: pass\n", pe->name); 486 + } 487 + if (!found) { 488 + pr_debug("testing sys event table: could not find event %s\n", pe->name); 489 + return TEST_FAIL; 490 + } 491 + return TEST_OK; 492 + } 493 + 426 494 /* Verify generated events from pmu-events.c are as expected */ 427 495 static int test__pmu_event_table(struct test_suite *test __maybe_unused, 428 496 int subtest __maybe_unused) 429 497 { 430 - const struct pmu_event *sys_event_tables = find_sys_events_table("pme_test_soc_sys"); 498 + const struct pmu_event *sys_event_table = find_sys_events_table("pme_test_soc_sys"); 431 499 const struct pmu_event *table = find_core_events_table("testarch", "testcpu"); 432 - int map_events = 0, expected_events; 500 + int map_events = 0, expected_events, err; 433 501 434 502 /* ignore 3x sentinels */ 435 503 expected_events = ARRAY_SIZE(core_events) + 436 504 ARRAY_SIZE(uncore_events) + 437 505 ARRAY_SIZE(sys_events) - 3; 438 506 439 - if (!table || !sys_event_tables) 507 + if (!table || !sys_event_table) 440 508 return -1; 441 509 442 - for (; table->name; table++) { 443 - struct perf_pmu_test_event const **test_event_table; 444 - bool found = false; 510 + err = pmu_events_table_for_each_event(table, test__pmu_event_table_core_callback, 511 + &map_events); 512 + if (err) 513 + return err; 445 514 446 - if (table->pmu) 447 - test_event_table = &uncore_events[0]; 448 - else 449 - test_event_table = &core_events[0]; 450 - 451 - for (; *test_event_table; test_event_table++) { 452 - struct perf_pmu_test_event const *test_event = *test_event_table; 453 - struct pmu_event const *event = &test_event->event; 454 - 455 - if (strcmp(table->name, event->name)) 456 - continue; 457 - found = true; 458 - map_events++; 459 - 460 - if (compare_pmu_events(table, event)) 461 - return -1; 462 - 463 - pr_debug("testing event table %s: pass\n", table->name); 464 - } 465 - 466 - if (!found) { 467 - pr_err("testing event table: could not find event %s\n", 468 - table->name); 469 - return -1; 470 - } 471 - } 472 - 473 - for (table = sys_event_tables; table->name; table++) { 474 - struct perf_pmu_test_event const **test_event_table; 475 - bool found = false; 476 - 477 - test_event_table = &sys_events[0]; 478 - 479 - for (; *test_event_table; test_event_table++) { 480 - struct perf_pmu_test_event const *test_event = *test_event_table; 481 - struct pmu_event const *event = &test_event->event; 482 - 483 - if (strcmp(table->name, event->name)) 484 - continue; 485 - found = true; 486 - map_events++; 487 - 488 - if (compare_pmu_events(table, event)) 489 - return -1; 490 - 491 - pr_debug("testing sys event table %s: pass\n", table->name); 492 - } 493 - if (!found) { 494 - pr_debug("testing event table: could not find event %s\n", 495 - table->name); 496 - return -1; 497 - } 498 - } 515 + err = pmu_events_table_for_each_event(sys_event_table, test__pmu_event_table_sys_callback, 516 + &map_events); 517 + if (err) 518 + return err; 499 519 500 520 if (map_events != expected_events) { 501 521 pr_err("testing event table: found %d, but expected %d\n", 502 522 map_events, expected_events); 503 - return -1; 523 + return TEST_FAIL; 504 524 } 505 525 506 526 return 0;
+125 -56
tools/perf/util/metricgroup.c
··· 538 538 d->details, d->groups, d->metriclist); 539 539 } 540 540 541 + struct metricgroup_print_data { 542 + const char *pmu_name; 543 + struct strlist *metriclist; 544 + char *filter; 545 + struct rblist *groups; 546 + bool metricgroups; 547 + bool raw; 548 + bool details; 549 + }; 550 + 551 + static int metricgroup__print_callback(const struct pmu_event *pe, 552 + const struct pmu_event *table __maybe_unused, 553 + void *vdata) 554 + { 555 + struct metricgroup_print_data *data = vdata; 556 + 557 + if (!pe->metric_expr) 558 + return 0; 559 + 560 + if (data->pmu_name && perf_pmu__is_hybrid(pe->pmu) && strcmp(data->pmu_name, pe->pmu)) 561 + return 0; 562 + 563 + return metricgroup__print_pmu_event(pe, data->metricgroups, data->filter, 564 + data->raw, data->details, data->groups, 565 + data->metriclist); 566 + } 567 + 541 568 void metricgroup__print(bool metrics, bool metricgroups, char *filter, 542 569 bool raw, bool details, const char *pmu_name) 543 570 { 544 571 struct rblist groups; 545 572 struct rb_node *node, *next; 546 573 struct strlist *metriclist = NULL; 574 + const struct pmu_event *table; 547 575 548 576 if (!metricgroups) { 549 577 metriclist = strlist__new(NULL, NULL); ··· 583 555 groups.node_new = mep_new; 584 556 groups.node_cmp = mep_cmp; 585 557 groups.node_delete = mep_delete; 586 - for (const struct pmu_event *pe = pmu_events_table__find(); pe; pe++) { 558 + table = pmu_events_table__find(); 559 + if (table) { 560 + struct metricgroup_print_data data = { 561 + .pmu_name = pmu_name, 562 + .metriclist = metriclist, 563 + .metricgroups = metricgroups, 564 + .filter = filter, 565 + .raw = raw, 566 + .details = details, 567 + .groups = &groups, 568 + }; 587 569 588 - if (!pe->name && !pe->metric_group && !pe->metric_name) 589 - break; 590 - if (!pe->metric_expr) 591 - continue; 592 - if (pmu_name && perf_pmu__is_hybrid(pe->pmu) && 593 - strcmp(pmu_name, pe->pmu)) { 594 - continue; 595 - } 596 - if (metricgroup__print_pmu_event(pe, metricgroups, filter, 597 - raw, details, &groups, 598 - metriclist) < 0) 599 - return; 570 + pmu_events_table_for_each_event(table, 571 + metricgroup__print_callback, 572 + &data); 600 573 } 601 - 602 574 { 603 575 struct metricgroup_iter_data data = { 604 576 .fn = metricgroup__print_sys_event_iter, ··· 1071 1043 return ret; 1072 1044 } 1073 1045 1074 - #define table_for_each_event(__pe, __idx, __table) \ 1075 - if (__table) \ 1076 - for (__idx = 0, __pe = &__table[__idx]; \ 1077 - __pe->name || __pe->metric_group || __pe->metric_name; \ 1078 - __pe = &__table[++__idx]) 1046 + struct metricgroup__find_metric_data { 1047 + const char *metric; 1048 + const struct pmu_event *pe; 1049 + }; 1079 1050 1080 - #define table_for_each_metric(__pe, __idx, __table, __metric) \ 1081 - table_for_each_event(__pe, __idx, __table) \ 1082 - if (__pe->metric_expr && \ 1083 - (match_metric(__pe->metric_group, __metric) || \ 1084 - match_metric(__pe->metric_name, __metric))) 1051 + static int metricgroup__find_metric_callback(const struct pmu_event *pe, 1052 + const struct pmu_event *table __maybe_unused, 1053 + void *vdata) 1054 + { 1055 + struct metricgroup__find_metric_data *data = vdata; 1056 + 1057 + if (!match_metric(pe->metric_name, data->metric)) 1058 + return 0; 1059 + 1060 + data->pe = pe; 1061 + return -1; 1062 + } 1085 1063 1086 1064 const struct pmu_event *metricgroup__find_metric(const char *metric, 1087 1065 const struct pmu_event *table) 1088 1066 { 1089 - const struct pmu_event *pe; 1090 - int i; 1067 + struct metricgroup__find_metric_data data = { 1068 + .metric = metric, 1069 + .pe = NULL, 1070 + }; 1091 1071 1092 - table_for_each_event(pe, i, table) { 1093 - if (match_metric(pe->metric_name, metric)) 1094 - return pe; 1095 - } 1072 + pmu_events_table_for_each_event(table, metricgroup__find_metric_callback, &data); 1096 1073 1097 - return NULL; 1074 + return data.pe; 1098 1075 } 1099 1076 1100 1077 static int add_metric(struct list_head *metric_list, ··· 1184 1151 return right_count - left_count; 1185 1152 } 1186 1153 1154 + struct metricgroup__add_metric_data { 1155 + struct list_head *list; 1156 + const char *metric_name; 1157 + const char *modifier; 1158 + bool metric_no_group; 1159 + bool has_match; 1160 + }; 1161 + 1162 + static int metricgroup__add_metric_callback(const struct pmu_event *pe, 1163 + const struct pmu_event *table, 1164 + void *vdata) 1165 + { 1166 + struct metricgroup__add_metric_data *data = vdata; 1167 + int ret = 0; 1168 + 1169 + if (pe->metric_expr && 1170 + (match_metric(pe->metric_group, data->metric_name) || 1171 + match_metric(pe->metric_name, data->metric_name))) { 1172 + 1173 + data->has_match = true; 1174 + ret = add_metric(data->list, pe, data->modifier, data->metric_no_group, 1175 + /*root_metric=*/NULL, 1176 + /*visited_metrics=*/NULL, table); 1177 + } 1178 + return ret; 1179 + } 1180 + 1187 1181 /** 1188 1182 * metricgroup__add_metric - Find and add a metric, or a metric group. 1189 1183 * @metric_name: The name of the metric or metric group. For example, "IPC" ··· 1229 1169 struct list_head *metric_list, 1230 1170 const struct pmu_event *table) 1231 1171 { 1232 - const struct pmu_event *pe; 1233 1172 LIST_HEAD(list); 1234 - int i, ret; 1173 + int ret; 1235 1174 bool has_match = false; 1236 1175 1237 - /* 1238 - * Iterate over all metrics seeing if metric matches either the name or 1239 - * group. When it does add the metric to the list. 1240 - */ 1241 - table_for_each_metric(pe, i, table, metric_name) { 1242 - has_match = true; 1243 - ret = add_metric(&list, pe, modifier, metric_no_group, 1244 - /*root_metric=*/NULL, 1245 - /*visited_metrics=*/NULL, table); 1176 + { 1177 + struct metricgroup__add_metric_data data = { 1178 + .list = &list, 1179 + .metric_name = metric_name, 1180 + .modifier = modifier, 1181 + .metric_no_group = metric_no_group, 1182 + .has_match = false, 1183 + }; 1184 + /* 1185 + * Iterate over all metrics seeing if metric matches either the 1186 + * name or group. When it does add the metric to the list. 1187 + */ 1188 + ret = pmu_events_table_for_each_event(table, metricgroup__add_metric_callback, 1189 + &data); 1246 1190 if (ret) 1247 1191 goto out; 1248 - } 1249 1192 1193 + has_match = data.has_match; 1194 + } 1250 1195 { 1251 1196 struct metricgroup_iter_data data = { 1252 1197 .fn = metricgroup__add_metric_sys_event_iter, ··· 1667 1602 metric_no_merge, &perf_pmu__fake, metric_events, table); 1668 1603 } 1669 1604 1605 + static int metricgroup__has_metric_callback(const struct pmu_event *pe, 1606 + const struct pmu_event *table __maybe_unused, 1607 + void *vdata) 1608 + { 1609 + const char *metric = vdata; 1610 + 1611 + if (!pe->metric_expr) 1612 + return 0; 1613 + 1614 + if (match_metric(pe->metric_name, metric)) 1615 + return 1; 1616 + 1617 + return 0; 1618 + } 1619 + 1670 1620 bool metricgroup__has_metric(const char *metric) 1671 1621 { 1672 1622 const struct pmu_event *table = pmu_events_table__find(); 1673 - const struct pmu_event *pe; 1674 - int i; 1675 1623 1676 1624 if (!table) 1677 1625 return false; 1678 1626 1679 - for (i = 0; ; i++) { 1680 - pe = &table[i]; 1681 - 1682 - if (!pe->name && !pe->metric_group && !pe->metric_name) 1683 - break; 1684 - if (!pe->metric_expr) 1685 - continue; 1686 - if (match_metric(pe->metric_name, metric)) 1687 - return true; 1688 - } 1689 - return false; 1627 + return pmu_events_table_for_each_event(table, metricgroup__has_metric_callback, 1628 + (void *)metric) ? true : false; 1690 1629 } 1691 1630 1692 1631 int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
+37 -28
tools/perf/util/pmu.c
··· 791 791 return res; 792 792 } 793 793 794 + struct pmu_add_cpu_aliases_map_data { 795 + struct list_head *head; 796 + const char *name; 797 + const char *cpu_name; 798 + struct perf_pmu *pmu; 799 + }; 800 + 801 + static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 802 + const struct pmu_event *table __maybe_unused, 803 + void *vdata) 804 + { 805 + struct pmu_add_cpu_aliases_map_data *data = vdata; 806 + const char *pname = pe->pmu ? pe->pmu : data->cpu_name; 807 + 808 + if (!pe->name) 809 + return 0; 810 + 811 + if (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->name)) 812 + goto new_alias; 813 + 814 + if (strcmp(pname, data->name)) 815 + return 0; 816 + 817 + new_alias: 818 + /* need type casts to override 'const' */ 819 + __perf_pmu__new_alias(data->head, NULL, (char *)pe->name, (char *)pe->desc, 820 + (char *)pe->event, pe); 821 + return 0; 822 + } 823 + 794 824 /* 795 825 * From the pmu_events_map, find the table of PMU events that corresponds 796 826 * to the current running CPU. Then, add all PMU events from that table ··· 829 799 void pmu_add_cpu_aliases_table(struct list_head *head, struct perf_pmu *pmu, 830 800 const struct pmu_event *table) 831 801 { 832 - int i; 833 - const char *name = pmu->name; 834 - /* 835 - * Found a matching PMU events table. Create aliases 836 - */ 837 - i = 0; 838 - while (1) { 839 - const char *cpu_name = is_arm_pmu_core(name) ? name : "cpu"; 840 - const struct pmu_event *pe = &table[i++]; 841 - const char *pname = pe->pmu ? pe->pmu : cpu_name; 802 + struct pmu_add_cpu_aliases_map_data data = { 803 + .head = head, 804 + .name = pmu->name, 805 + .cpu_name = is_arm_pmu_core(pmu->name) ? pmu->name : "cpu", 806 + .pmu = pmu, 807 + }; 842 808 843 - if (!pe->name) { 844 - if (pe->metric_group || pe->metric_name) 845 - continue; 846 - break; 847 - } 848 - 849 - if (pmu->is_uncore && pmu_uncore_alias_match(pname, name)) 850 - goto new_alias; 851 - 852 - if (strcmp(pname, name)) 853 - continue; 854 - 855 - new_alias: 856 - /* need type casts to override 'const' */ 857 - __perf_pmu__new_alias(head, NULL, (char *)pe->name, 858 - (char *)pe->desc, (char *)pe->event, 859 - pe); 860 - } 809 + pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); 861 810 } 862 811 863 812 static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
+30 -12
tools/perf/util/s390-sample-raw.c
··· 129 129 } 130 130 } 131 131 132 + struct get_counter_name_data { 133 + int wanted; 134 + const char *result; 135 + }; 136 + 137 + static int get_counter_name_callback(const struct pmu_event *evp, 138 + const struct pmu_event *table __maybe_unused, 139 + void *vdata) 140 + { 141 + struct get_counter_name_data *data = vdata; 142 + int rc, event_nr; 143 + 144 + if (evp->name == NULL || evp->event == NULL) 145 + return 0; 146 + rc = sscanf(evp->event, "event=%x", &event_nr); 147 + if (rc == 1 && event_nr == data->wanted) { 148 + data->result = evp->name; 149 + return 1; /* Terminate the search. */ 150 + } 151 + return 0; 152 + } 153 + 132 154 /* Scan the PMU table and extract the logical name of a counter from the 133 155 * PMU events table. Input is the counter set and counter number with in the 134 156 * set. Construct the event number and use this as key. If they match return ··· 159 137 */ 160 138 static const char *get_counter_name(int set, int nr, const struct pmu_event *table) 161 139 { 162 - int rc, event_nr, wanted = get_counterset_start(set) + nr; 140 + struct get_counter_name_data data = { 141 + .wanted = get_counterset_start(set) + nr, 142 + .result = NULL, 143 + }; 163 144 164 - if (table) { 165 - const struct pmu_event *evp = table; 145 + if (!table) 146 + return NULL; 166 147 167 - for (; evp->name || evp->event || evp->desc; ++evp) { 168 - if (evp->name == NULL || evp->event == NULL) 169 - continue; 170 - rc = sscanf(evp->event, "event=%x", &event_nr); 171 - if (rc == 1 && event_nr == wanted) 172 - return evp->name; 173 - } 174 - } 175 - return NULL; 148 + pmu_events_table_for_each_event(table, get_counter_name_callback, &data); 149 + return data.result; 176 150 } 177 151 178 152 static void s390_cpumcfdg_dump(struct perf_sample *sample)