From f146c7bc85a51f95c05e0f8173d484eb301ece78 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Thu, 13 Aug 2026 18:52:04 +0200 Subject: PCI: Add pci_irq_type() to query the allocated interrupt type Add a helper that returns PCI_IRQ_MSIX, PCI_IRQ_MSI, or PCI_IRQ_INTX based on the interrupt type the PCI core selected after pci_alloc_irq_vectors(). Several drivers already open-code this check against pdev->msix_enabled and pdev->msi_enabled, or even open code this helper [1]. A common helper avoids the duplication and keeps drivers from accessing the bitfield directly (see also [2]). Acked-by: Bjorn Helgaas Tested-by: John Hubbard Link: https://elixir.bootlin.com/linux/v7.1/source/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c#L196 [1] Inspired-by: John Hubbard Link: https://lore.kernel.org/all/DKKG2QM3YJYB.Z2H2B2UXJ75N@kernel.org/ [2] Reviewed-by: Gary Guo Link: https://patch.msgid.link/20260813165234.620555-5-dakr@kernel.org [ Add missing pci_irq_type() stub for CONFIG_PCI=n. ] Signed-off-by: Danilo Krummrich --- tools/perf/util/help-unknown-cmd.c | 122 +++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tools/perf/util/help-unknown-cmd.c (limited to 'tools/perf/util/help-unknown-cmd.c') diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c new file mode 100644 index 000000000..a0a46e34f --- /dev/null +++ b/tools/perf/util/help-unknown-cmd.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "cache.h" +#include "config.h" +#include +#include +#include +#include +#include "../builtin.h" +#include "levenshtein.h" +#include + +static int autocorrect; + +static int perf_unknown_cmd_config(const char *var, const char *value, + void *cb __maybe_unused) +{ + if (!strcmp(var, "help.autocorrect")) + return perf_config_int(&autocorrect, var,value); + + return 0; +} + +static int levenshtein_compare(const void *p1, const void *p2) +{ + const struct cmdname *const *c1 = p1, *const *c2 = p2; + const char *s1 = (*c1)->name, *s2 = (*c2)->name; + int l1 = (*c1)->len; + int l2 = (*c2)->len; + return l1 != l2 ? l1 - l2 : strcmp(s1, s2); +} + +static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) +{ + unsigned int i, nr = cmds->cnt + old->cnt; + void *tmp; + + if (nr > cmds->alloc) { + /* Choose bigger one to alloc */ + if (alloc_nr(cmds->alloc) < nr) + cmds->alloc = nr; + else + cmds->alloc = alloc_nr(cmds->alloc); + tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names)); + if (!tmp) + return -1; + cmds->names = tmp; + } + for (i = 0; i < old->cnt; i++) + cmds->names[cmds->cnt++] = old->names[i]; + zfree(&old->names); + old->cnt = 0; + return 0; +} + +const char *help_unknown_cmd(const char *cmd, struct cmdnames *main_cmds) +{ + unsigned int i, n = 0, best_similarity = 0; + struct cmdnames other_cmds; + + memset(&other_cmds, 0, sizeof(other_cmds)); + + perf_config(perf_unknown_cmd_config, NULL); + + load_command_list("perf-", main_cmds, &other_cmds); + + if (add_cmd_list(main_cmds, &other_cmds) < 0) { + fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n"); + goto end; + } + qsort(main_cmds->names, main_cmds->cnt, + sizeof(main_cmds->names), cmdname_compare); + uniq(main_cmds); + + if (main_cmds->cnt) { + /* This reuses cmdname->len for similarity index */ + for (i = 0; i < main_cmds->cnt; ++i) { + main_cmds->names[i]->len = + levenshtein(cmd, main_cmds->names[i]->name, + /*swap_penalty=*/0, + /*substition_penality=*/2, + /*insertion_penality=*/1, + /*deletion_penalty=*/1); + } + qsort(main_cmds->names, main_cmds->cnt, + sizeof(*main_cmds->names), levenshtein_compare); + + best_similarity = main_cmds->names[0]->len; + n = 1; + while (n < main_cmds->cnt && best_similarity == main_cmds->names[n]->len) + ++n; + } + + if (autocorrect && n == 1) { + const char *assumed = main_cmds->names[0]->name; + + main_cmds->names[0] = NULL; + clean_cmdnames(&other_cmds); + fprintf(stderr, "WARNING: You called a perf program named '%s', " + "which does not exist.\n" + "Continuing under the assumption that you meant '%s'\n", + cmd, assumed); + if (autocorrect > 0) { + fprintf(stderr, "in %0.1f seconds automatically...\n", + (float)autocorrect/10.0); + poll(NULL, 0, autocorrect * 100); + } + return assumed; + } + + fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd); + + if (main_cmds->cnt && best_similarity < 6) { + fprintf(stderr, "\nDid you mean %s?\n", + n < 2 ? "this": "one of these"); + + for (i = 0; i < n; i++) + fprintf(stderr, "\t%s\n", main_cmds->names[i]->name); + } +end: + clean_cmdnames(&other_cmds); + return NULL; +} -- cgit v1.3.1