Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * platform_device probing code for ARM performance counters.
0004  *
0005  * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
0006  * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
0007  */
0008 #define pr_fmt(fmt) "hw perfevents: " fmt
0009 #define dev_fmt pr_fmt
0010 
0011 #include <linux/bug.h>
0012 #include <linux/cpumask.h>
0013 #include <linux/device.h>
0014 #include <linux/errno.h>
0015 #include <linux/irq.h>
0016 #include <linux/irqdesc.h>
0017 #include <linux/kconfig.h>
0018 #include <linux/of.h>
0019 #include <linux/of_device.h>
0020 #include <linux/percpu.h>
0021 #include <linux/perf/arm_pmu.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/printk.h>
0024 #include <linux/smp.h>
0025 
0026 static int probe_current_pmu(struct arm_pmu *pmu,
0027                  const struct pmu_probe_info *info)
0028 {
0029     int cpu = get_cpu();
0030     unsigned int cpuid = read_cpuid_id();
0031     int ret = -ENODEV;
0032 
0033     pr_info("probing PMU on CPU %d\n", cpu);
0034 
0035     for (; info->init != NULL; info++) {
0036         if ((cpuid & info->mask) != info->cpuid)
0037             continue;
0038         ret = info->init(pmu);
0039         break;
0040     }
0041 
0042     put_cpu();
0043     return ret;
0044 }
0045 
0046 static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq)
0047 {
0048     int cpu, ret;
0049     struct pmu_hw_events __percpu *hw_events = pmu->hw_events;
0050 
0051     ret = irq_get_percpu_devid_partition(irq, &pmu->supported_cpus);
0052     if (ret)
0053         return ret;
0054 
0055     for_each_cpu(cpu, &pmu->supported_cpus)
0056         per_cpu(hw_events->irq, cpu) = irq;
0057 
0058     return 0;
0059 }
0060 
0061 static bool pmu_has_irq_affinity(struct device_node *node)
0062 {
0063     return !!of_find_property(node, "interrupt-affinity", NULL);
0064 }
0065 
0066 static int pmu_parse_irq_affinity(struct device *dev, int i)
0067 {
0068     struct device_node *dn;
0069     int cpu;
0070 
0071     /*
0072      * If we don't have an interrupt-affinity property, we guess irq
0073      * affinity matches our logical CPU order, as we used to assume.
0074      * This is fragile, so we'll warn in pmu_parse_irqs().
0075      */
0076     if (!pmu_has_irq_affinity(dev->of_node))
0077         return i;
0078 
0079     dn = of_parse_phandle(dev->of_node, "interrupt-affinity", i);
0080     if (!dn) {
0081         dev_warn(dev, "failed to parse interrupt-affinity[%d]\n", i);
0082         return -EINVAL;
0083     }
0084 
0085     cpu = of_cpu_node_to_id(dn);
0086     if (cpu < 0) {
0087         dev_warn(dev, "failed to find logical CPU for %pOFn\n", dn);
0088         cpu = nr_cpu_ids;
0089     }
0090 
0091     of_node_put(dn);
0092 
0093     return cpu;
0094 }
0095 
0096 static int pmu_parse_irqs(struct arm_pmu *pmu)
0097 {
0098     int i = 0, num_irqs;
0099     struct platform_device *pdev = pmu->plat_device;
0100     struct pmu_hw_events __percpu *hw_events = pmu->hw_events;
0101     struct device *dev = &pdev->dev;
0102 
0103     num_irqs = platform_irq_count(pdev);
0104     if (num_irqs < 0)
0105         return dev_err_probe(dev, num_irqs, "unable to count PMU IRQs\n");
0106 
0107     /*
0108      * In this case we have no idea which CPUs are covered by the PMU.
0109      * To match our prior behaviour, we assume all CPUs in this case.
0110      */
0111     if (num_irqs == 0) {
0112         dev_warn(dev, "no irqs for PMU, sampling events not supported\n");
0113         pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
0114         cpumask_setall(&pmu->supported_cpus);
0115         return 0;
0116     }
0117 
0118     if (num_irqs == 1) {
0119         int irq = platform_get_irq(pdev, 0);
0120         if ((irq > 0) && irq_is_percpu_devid(irq))
0121             return pmu_parse_percpu_irq(pmu, irq);
0122     }
0123 
0124     if (nr_cpu_ids != 1 && !pmu_has_irq_affinity(dev->of_node))
0125         dev_warn(dev, "no interrupt-affinity property, guessing.\n");
0126 
0127     for (i = 0; i < num_irqs; i++) {
0128         int cpu, irq;
0129 
0130         irq = platform_get_irq(pdev, i);
0131         if (WARN_ON(irq <= 0))
0132             continue;
0133 
0134         if (irq_is_percpu_devid(irq)) {
0135             dev_warn(dev, "multiple PPIs or mismatched SPI/PPI detected\n");
0136             return -EINVAL;
0137         }
0138 
0139         cpu = pmu_parse_irq_affinity(dev, i);
0140         if (cpu < 0)
0141             return cpu;
0142         if (cpu >= nr_cpu_ids)
0143             continue;
0144 
0145         if (per_cpu(hw_events->irq, cpu)) {
0146             dev_warn(dev, "multiple PMU IRQs for the same CPU detected\n");
0147             return -EINVAL;
0148         }
0149 
0150         per_cpu(hw_events->irq, cpu) = irq;
0151         cpumask_set_cpu(cpu, &pmu->supported_cpus);
0152     }
0153 
0154     return 0;
0155 }
0156 
0157 static int armpmu_request_irqs(struct arm_pmu *armpmu)
0158 {
0159     struct pmu_hw_events __percpu *hw_events = armpmu->hw_events;
0160     int cpu, err = 0;
0161 
0162     for_each_cpu(cpu, &armpmu->supported_cpus) {
0163         int irq = per_cpu(hw_events->irq, cpu);
0164         if (!irq)
0165             continue;
0166 
0167         err = armpmu_request_irq(irq, cpu);
0168         if (err)
0169             break;
0170     }
0171 
0172     return err;
0173 }
0174 
0175 static void armpmu_free_irqs(struct arm_pmu *armpmu)
0176 {
0177     int cpu;
0178     struct pmu_hw_events __percpu *hw_events = armpmu->hw_events;
0179 
0180     for_each_cpu(cpu, &armpmu->supported_cpus) {
0181         int irq = per_cpu(hw_events->irq, cpu);
0182 
0183         armpmu_free_irq(irq, cpu);
0184     }
0185 }
0186 
0187 int arm_pmu_device_probe(struct platform_device *pdev,
0188              const struct of_device_id *of_table,
0189              const struct pmu_probe_info *probe_table)
0190 {
0191     armpmu_init_fn init_fn;
0192     struct device *dev = &pdev->dev;
0193     struct arm_pmu *pmu;
0194     int ret = -ENODEV;
0195 
0196     pmu = armpmu_alloc();
0197     if (!pmu)
0198         return -ENOMEM;
0199 
0200     pmu->plat_device = pdev;
0201 
0202     ret = pmu_parse_irqs(pmu);
0203     if (ret)
0204         goto out_free;
0205 
0206     init_fn = of_device_get_match_data(dev);
0207     if (init_fn) {
0208         pmu->secure_access = of_property_read_bool(dev->of_node,
0209                                "secure-reg-access");
0210 
0211         /* arm64 systems boot only as non-secure */
0212         if (IS_ENABLED(CONFIG_ARM64) && pmu->secure_access) {
0213             dev_warn(dev, "ignoring \"secure-reg-access\" property for arm64\n");
0214             pmu->secure_access = false;
0215         }
0216 
0217         ret = init_fn(pmu);
0218     } else if (probe_table) {
0219         cpumask_setall(&pmu->supported_cpus);
0220         ret = probe_current_pmu(pmu, probe_table);
0221     }
0222 
0223     if (ret) {
0224         dev_err(dev, "failed to probe PMU!\n");
0225         goto out_free;
0226     }
0227 
0228     ret = armpmu_request_irqs(pmu);
0229     if (ret)
0230         goto out_free_irqs;
0231 
0232     ret = armpmu_register(pmu);
0233     if (ret) {
0234         dev_err(dev, "failed to register PMU devices!\n");
0235         goto out_free_irqs;
0236     }
0237 
0238     return 0;
0239 
0240 out_free_irqs:
0241     armpmu_free_irqs(pmu);
0242 out_free:
0243     armpmu_free(pmu);
0244     return ret;
0245 }