]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/perf/arm_pmu_platform.c
Merge tag 'char-misc-4.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[karo-tx-linux.git] / drivers / perf / arm_pmu_platform.c
1 /*
2  * platform_device probing code for ARM performance counters.
3  *
4  * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
5  * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
6  */
7 #define pr_fmt(fmt) "hw perfevents: " fmt
8
9 #include <linux/bug.h>
10 #include <linux/cpumask.h>
11 #include <linux/device.h>
12 #include <linux/errno.h>
13 #include <linux/irq.h>
14 #include <linux/irqdesc.h>
15 #include <linux/kconfig.h>
16 #include <linux/of.h>
17 #include <linux/of_device.h>
18 #include <linux/percpu.h>
19 #include <linux/perf/arm_pmu.h>
20 #include <linux/platform_device.h>
21 #include <linux/printk.h>
22 #include <linux/smp.h>
23
24 static int probe_current_pmu(struct arm_pmu *pmu,
25                              const struct pmu_probe_info *info)
26 {
27         int cpu = get_cpu();
28         unsigned int cpuid = read_cpuid_id();
29         int ret = -ENODEV;
30
31         pr_info("probing PMU on CPU %d\n", cpu);
32
33         for (; info->init != NULL; info++) {
34                 if ((cpuid & info->mask) != info->cpuid)
35                         continue;
36                 ret = info->init(pmu);
37                 break;
38         }
39
40         put_cpu();
41         return ret;
42 }
43
44 static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq)
45 {
46         int cpu, ret;
47         struct pmu_hw_events __percpu *hw_events = pmu->hw_events;
48
49         ret = irq_get_percpu_devid_partition(irq, &pmu->supported_cpus);
50         if (ret)
51                 return ret;
52
53         for_each_cpu(cpu, &pmu->supported_cpus)
54                 per_cpu(hw_events->irq, cpu) = irq;
55
56         return 0;
57 }
58
59 static bool pmu_has_irq_affinity(struct device_node *node)
60 {
61         return !!of_find_property(node, "interrupt-affinity", NULL);
62 }
63
64 static int pmu_parse_irq_affinity(struct device_node *node, int i)
65 {
66         struct device_node *dn;
67         int cpu;
68
69         /*
70          * If we don't have an interrupt-affinity property, we guess irq
71          * affinity matches our logical CPU order, as we used to assume.
72          * This is fragile, so we'll warn in pmu_parse_irqs().
73          */
74         if (!pmu_has_irq_affinity(node))
75                 return i;
76
77         dn = of_parse_phandle(node, "interrupt-affinity", i);
78         if (!dn) {
79                 pr_warn("failed to parse interrupt-affinity[%d] for %s\n",
80                         i, node->name);
81                 return -EINVAL;
82         }
83
84         /* Now look up the logical CPU number */
85         for_each_possible_cpu(cpu) {
86                 struct device_node *cpu_dn;
87
88                 cpu_dn = of_cpu_device_node_get(cpu);
89                 of_node_put(cpu_dn);
90
91                 if (dn == cpu_dn)
92                         break;
93         }
94
95         if (cpu >= nr_cpu_ids) {
96                 pr_warn("failed to find logical CPU for %s\n", dn->name);
97         }
98
99         of_node_put(dn);
100
101         return cpu;
102 }
103
104 static int pmu_parse_irqs(struct arm_pmu *pmu)
105 {
106         int i = 0, num_irqs;
107         struct platform_device *pdev = pmu->plat_device;
108         struct pmu_hw_events __percpu *hw_events = pmu->hw_events;
109
110         num_irqs = platform_irq_count(pdev);
111         if (num_irqs < 0) {
112                 pr_err("unable to count PMU IRQs\n");
113                 return num_irqs;
114         }
115
116         /*
117          * In this case we have no idea which CPUs are covered by the PMU.
118          * To match our prior behaviour, we assume all CPUs in this case.
119          */
120         if (num_irqs == 0) {
121                 pr_warn("no irqs for PMU, sampling events not supported\n");
122                 pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
123                 cpumask_setall(&pmu->supported_cpus);
124                 return 0;
125         }
126
127         if (num_irqs == 1) {
128                 int irq = platform_get_irq(pdev, 0);
129                 if (irq && irq_is_percpu(irq))
130                         return pmu_parse_percpu_irq(pmu, irq);
131         }
132
133         if (!pmu_has_irq_affinity(pdev->dev.of_node)) {
134                 pr_warn("no interrupt-affinity property for %pOF, guessing.\n",
135                         pdev->dev.of_node);
136         }
137
138         /*
139          * Some platforms have all PMU IRQs OR'd into a single IRQ, with a
140          * special platdata function that attempts to demux them.
141          */
142         if (dev_get_platdata(&pdev->dev))
143                 cpumask_setall(&pmu->supported_cpus);
144
145         for (i = 0; i < num_irqs; i++) {
146                 int cpu, irq;
147
148                 irq = platform_get_irq(pdev, i);
149                 if (WARN_ON(irq <= 0))
150                         continue;
151
152                 if (irq_is_percpu(irq)) {
153                         pr_warn("multiple PPIs or mismatched SPI/PPI detected\n");
154                         return -EINVAL;
155                 }
156
157                 cpu = pmu_parse_irq_affinity(pdev->dev.of_node, i);
158                 if (cpu < 0)
159                         return cpu;
160                 if (cpu >= nr_cpu_ids)
161                         continue;
162
163                 if (per_cpu(hw_events->irq, cpu)) {
164                         pr_warn("multiple PMU IRQs for the same CPU detected\n");
165                         return -EINVAL;
166                 }
167
168                 per_cpu(hw_events->irq, cpu) = irq;
169                 cpumask_set_cpu(cpu, &pmu->supported_cpus);
170         }
171
172         return 0;
173 }
174
175 int arm_pmu_device_probe(struct platform_device *pdev,
176                          const struct of_device_id *of_table,
177                          const struct pmu_probe_info *probe_table)
178 {
179         const struct of_device_id *of_id;
180         armpmu_init_fn init_fn;
181         struct device_node *node = pdev->dev.of_node;
182         struct arm_pmu *pmu;
183         int ret = -ENODEV;
184
185         pmu = armpmu_alloc();
186         if (!pmu)
187                 return -ENOMEM;
188
189         pmu->plat_device = pdev;
190
191         ret = pmu_parse_irqs(pmu);
192         if (ret)
193                 goto out_free;
194
195         if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
196                 init_fn = of_id->data;
197
198                 pmu->secure_access = of_property_read_bool(pdev->dev.of_node,
199                                                            "secure-reg-access");
200
201                 /* arm64 systems boot only as non-secure */
202                 if (IS_ENABLED(CONFIG_ARM64) && pmu->secure_access) {
203                         pr_warn("ignoring \"secure-reg-access\" property for arm64\n");
204                         pmu->secure_access = false;
205                 }
206
207                 ret = init_fn(pmu);
208         } else if (probe_table) {
209                 cpumask_setall(&pmu->supported_cpus);
210                 ret = probe_current_pmu(pmu, probe_table);
211         }
212
213         if (ret) {
214                 pr_info("%pOF: failed to probe PMU!\n", node);
215                 goto out_free;
216         }
217
218         ret = armpmu_request_irqs(pmu);
219         if (ret)
220                 goto out_free_irqs;
221
222         ret = armpmu_register(pmu);
223         if (ret)
224                 goto out_free;
225
226         return 0;
227
228 out_free_irqs:
229         armpmu_free_irqs(pmu);
230 out_free:
231         pr_info("%pOF: failed to register PMU devices!\n", node);
232         armpmu_free(pmu);
233         return ret;
234 }