License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-2.6-block.git] / tools / perf / util / pmu.c
index ac16a9db1fb566ca14d272e33bc34e5166ea2b81..b10b35a6313819f1ff560e1c1b9e67b4111fb796 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/list.h>
 #include <linux/compiler.h>
 #include <sys/types.h>
@@ -470,17 +471,36 @@ static void pmu_read_sysfs(void)
        closedir(dir);
 }
 
+static struct cpu_map *__pmu_cpumask(const char *path)
+{
+       FILE *file;
+       struct cpu_map *cpus;
+
+       file = fopen(path, "r");
+       if (!file)
+               return NULL;
+
+       cpus = cpu_map__read(file);
+       fclose(file);
+       return cpus;
+}
+
+/*
+ * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
+ * may have a "cpus" file.
+ */
+#define CPUS_TEMPLATE_UNCORE   "%s/bus/event_source/devices/%s/cpumask"
+#define CPUS_TEMPLATE_CPU      "%s/bus/event_source/devices/%s/cpus"
+
 static struct cpu_map *pmu_cpumask(const char *name)
 {
-       struct stat st;
        char path[PATH_MAX];
-       FILE *file;
        struct cpu_map *cpus;
        const char *sysfs = sysfs__mountpoint();
        const char *templates[] = {
-                "%s/bus/event_source/devices/%s/cpumask",
-                "%s/bus/event_source/devices/%s/cpus",
-                NULL
+               CPUS_TEMPLATE_UNCORE,
+               CPUS_TEMPLATE_CPU,
+               NULL
        };
        const char **template;
 
@@ -489,20 +509,25 @@ static struct cpu_map *pmu_cpumask(const char *name)
 
        for (template = templates; *template; template++) {
                snprintf(path, PATH_MAX, *template, sysfs, name);
-               if (stat(path, &st) == 0)
-                       break;
+               cpus = __pmu_cpumask(path);
+               if (cpus)
+                       return cpus;
        }
 
-       if (!*template)
-               return NULL;
+       return NULL;
+}
 
-       file = fopen(path, "r");
-       if (!file)
-               return NULL;
+static bool pmu_is_uncore(const char *name)
+{
+       char path[PATH_MAX];
+       struct cpu_map *cpus;
+       const char *sysfs = sysfs__mountpoint();
 
-       cpus = cpu_map__read(file);
-       fclose(file);
-       return cpus;
+       snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
+       cpus = __pmu_cpumask(path);
+       cpu_map__put(cpus);
+
+       return !!cpus;
 }
 
 /*
@@ -617,6 +642,8 @@ static struct perf_pmu *pmu_lookup(const char *name)
 
        pmu->cpus = pmu_cpumask(name);
 
+       pmu->is_uncore = pmu_is_uncore(name);
+
        INIT_LIST_HEAD(&pmu->format);
        INIT_LIST_HEAD(&pmu->aliases);
        list_splice(&format, &pmu->format);