fix short copy handling in copy_mc_pipe_to_iter()
[sfrench/cifs-2.6.git] / drivers / perf / hisilicon / hisi_uncore_l3c_pmu.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * HiSilicon SoC L3C uncore Hardware event counters support
4  *
5  * Copyright (C) 2017 HiSilicon Limited
6  * Author: Anurup M <anurup.m@huawei.com>
7  *         Shaokun Zhang <zhangshaokun@hisilicon.com>
8  *
9  * This code is based on the uncore PMUs like arm-cci and arm-ccn.
10  */
11 #include <linux/acpi.h>
12 #include <linux/bug.h>
13 #include <linux/cpuhotplug.h>
14 #include <linux/interrupt.h>
15 #include <linux/irq.h>
16 #include <linux/list.h>
17 #include <linux/smp.h>
18
19 #include "hisi_uncore_pmu.h"
20
21 /* L3C register definition */
22 #define L3C_PERF_CTRL           0x0408
23 #define L3C_INT_MASK            0x0800
24 #define L3C_INT_STATUS          0x0808
25 #define L3C_INT_CLEAR           0x080c
26 #define L3C_CORE_CTRL           0x1b04
27 #define L3C_TRACETAG_CTRL       0x1b20
28 #define L3C_DATSRC_TYPE         0x1b48
29 #define L3C_DATSRC_CTRL         0x1bf0
30 #define L3C_EVENT_CTRL          0x1c00
31 #define L3C_VERSION             0x1cf0
32 #define L3C_EVENT_TYPE0         0x1d00
33 /*
34  * If the HW version only supports a 48-bit counter, then
35  * bits [63:48] are reserved, which are Read-As-Zero and
36  * Writes-Ignored.
37  */
38 #define L3C_CNTR0_LOWER         0x1e00
39
40 /* L3C has 8-counters */
41 #define L3C_NR_COUNTERS         0x8
42
43 #define L3C_PERF_CTRL_EN        0x10000
44 #define L3C_TRACETAG_EN         BIT(31)
45 #define L3C_TRACETAG_REQ_SHIFT  7
46 #define L3C_TRACETAG_MARK_EN    BIT(0)
47 #define L3C_TRACETAG_REQ_EN     (L3C_TRACETAG_MARK_EN | BIT(2))
48 #define L3C_TRACETAG_CORE_EN    (L3C_TRACETAG_MARK_EN | BIT(3))
49 #define L3C_CORE_EN             BIT(20)
50 #define L3C_COER_NONE           0x0
51 #define L3C_DATSRC_MASK         0xFF
52 #define L3C_DATSRC_SKT_EN       BIT(23)
53 #define L3C_DATSRC_NONE         0x0
54 #define L3C_EVTYPE_NONE         0xff
55 #define L3C_V1_NR_EVENTS        0x59
56 #define L3C_V2_NR_EVENTS        0xFF
57
58 HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_core, config1, 7, 0);
59 HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_req, config1, 10, 8);
60 HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_cfg, config1, 15, 11);
61 HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_skt, config1, 16, 16);
62
63 static void hisi_l3c_pmu_config_req_tracetag(struct perf_event *event)
64 {
65         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
66         u32 tt_req = hisi_get_tt_req(event);
67
68         if (tt_req) {
69                 u32 val;
70
71                 /* Set request-type for tracetag */
72                 val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
73                 val |= tt_req << L3C_TRACETAG_REQ_SHIFT;
74                 val |= L3C_TRACETAG_REQ_EN;
75                 writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
76
77                 /* Enable request-tracetag statistics */
78                 val = readl(l3c_pmu->base + L3C_PERF_CTRL);
79                 val |= L3C_TRACETAG_EN;
80                 writel(val, l3c_pmu->base + L3C_PERF_CTRL);
81         }
82 }
83
84 static void hisi_l3c_pmu_clear_req_tracetag(struct perf_event *event)
85 {
86         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
87         u32 tt_req = hisi_get_tt_req(event);
88
89         if (tt_req) {
90                 u32 val;
91
92                 /* Clear request-type */
93                 val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
94                 val &= ~(tt_req << L3C_TRACETAG_REQ_SHIFT);
95                 val &= ~L3C_TRACETAG_REQ_EN;
96                 writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
97
98                 /* Disable request-tracetag statistics */
99                 val = readl(l3c_pmu->base + L3C_PERF_CTRL);
100                 val &= ~L3C_TRACETAG_EN;
101                 writel(val, l3c_pmu->base + L3C_PERF_CTRL);
102         }
103 }
104
105 static void hisi_l3c_pmu_write_ds(struct perf_event *event, u32 ds_cfg)
106 {
107         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
108         struct hw_perf_event *hwc = &event->hw;
109         u32 reg, reg_idx, shift, val;
110         int idx = hwc->idx;
111
112         /*
113          * Select the appropriate datasource register(L3C_DATSRC_TYPE0/1).
114          * There are 2 datasource ctrl register for the 8 hardware counters.
115          * Datasrc is 8-bits and for the former 4 hardware counters,
116          * L3C_DATSRC_TYPE0 is chosen. For the latter 4 hardware counters,
117          * L3C_DATSRC_TYPE1 is chosen.
118          */
119         reg = L3C_DATSRC_TYPE + (idx / 4) * 4;
120         reg_idx = idx % 4;
121         shift = 8 * reg_idx;
122
123         val = readl(l3c_pmu->base + reg);
124         val &= ~(L3C_DATSRC_MASK << shift);
125         val |= ds_cfg << shift;
126         writel(val, l3c_pmu->base + reg);
127 }
128
129 static void hisi_l3c_pmu_config_ds(struct perf_event *event)
130 {
131         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
132         u32 ds_cfg = hisi_get_datasrc_cfg(event);
133         u32 ds_skt = hisi_get_datasrc_skt(event);
134
135         if (ds_cfg)
136                 hisi_l3c_pmu_write_ds(event, ds_cfg);
137
138         if (ds_skt) {
139                 u32 val;
140
141                 val = readl(l3c_pmu->base + L3C_DATSRC_CTRL);
142                 val |= L3C_DATSRC_SKT_EN;
143                 writel(val, l3c_pmu->base + L3C_DATSRC_CTRL);
144         }
145 }
146
147 static void hisi_l3c_pmu_clear_ds(struct perf_event *event)
148 {
149         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
150         u32 ds_cfg = hisi_get_datasrc_cfg(event);
151         u32 ds_skt = hisi_get_datasrc_skt(event);
152
153         if (ds_cfg)
154                 hisi_l3c_pmu_write_ds(event, L3C_DATSRC_NONE);
155
156         if (ds_skt) {
157                 u32 val;
158
159                 val = readl(l3c_pmu->base + L3C_DATSRC_CTRL);
160                 val &= ~L3C_DATSRC_SKT_EN;
161                 writel(val, l3c_pmu->base + L3C_DATSRC_CTRL);
162         }
163 }
164
165 static void hisi_l3c_pmu_config_core_tracetag(struct perf_event *event)
166 {
167         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
168         u32 core = hisi_get_tt_core(event);
169
170         if (core) {
171                 u32 val;
172
173                 /* Config and enable core information */
174                 writel(core, l3c_pmu->base + L3C_CORE_CTRL);
175                 val = readl(l3c_pmu->base + L3C_PERF_CTRL);
176                 val |= L3C_CORE_EN;
177                 writel(val, l3c_pmu->base + L3C_PERF_CTRL);
178
179                 /* Enable core-tracetag statistics */
180                 val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
181                 val |= L3C_TRACETAG_CORE_EN;
182                 writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
183         }
184 }
185
186 static void hisi_l3c_pmu_clear_core_tracetag(struct perf_event *event)
187 {
188         struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
189         u32 core = hisi_get_tt_core(event);
190
191         if (core) {
192                 u32 val;
193
194                 /* Clear core information */
195                 writel(L3C_COER_NONE, l3c_pmu->base + L3C_CORE_CTRL);
196                 val = readl(l3c_pmu->base + L3C_PERF_CTRL);
197                 val &= ~L3C_CORE_EN;
198                 writel(val, l3c_pmu->base + L3C_PERF_CTRL);
199
200                 /* Disable core-tracetag statistics */
201                 val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
202                 val &= ~L3C_TRACETAG_CORE_EN;
203                 writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
204         }
205 }
206
207 static void hisi_l3c_pmu_enable_filter(struct perf_event *event)
208 {
209         if (event->attr.config1 != 0x0) {
210                 hisi_l3c_pmu_config_req_tracetag(event);
211                 hisi_l3c_pmu_config_core_tracetag(event);
212                 hisi_l3c_pmu_config_ds(event);
213         }
214 }
215
216 static void hisi_l3c_pmu_disable_filter(struct perf_event *event)
217 {
218         if (event->attr.config1 != 0x0) {
219                 hisi_l3c_pmu_clear_ds(event);
220                 hisi_l3c_pmu_clear_core_tracetag(event);
221                 hisi_l3c_pmu_clear_req_tracetag(event);
222         }
223 }
224
225 /*
226  * Select the counter register offset using the counter index
227  */
228 static u32 hisi_l3c_pmu_get_counter_offset(int cntr_idx)
229 {
230         return (L3C_CNTR0_LOWER + (cntr_idx * 8));
231 }
232
233 static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu,
234                                      struct hw_perf_event *hwc)
235 {
236         return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
237 }
238
239 static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu,
240                                        struct hw_perf_event *hwc, u64 val)
241 {
242         writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
243 }
244
245 static void hisi_l3c_pmu_write_evtype(struct hisi_pmu *l3c_pmu, int idx,
246                                       u32 type)
247 {
248         u32 reg, reg_idx, shift, val;
249
250         /*
251          * Select the appropriate event select register(L3C_EVENT_TYPE0/1).
252          * There are 2 event select registers for the 8 hardware counters.
253          * Event code is 8-bits and for the former 4 hardware counters,
254          * L3C_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
255          * L3C_EVENT_TYPE1 is chosen.
256          */
257         reg = L3C_EVENT_TYPE0 + (idx / 4) * 4;
258         reg_idx = idx % 4;
259         shift = 8 * reg_idx;
260
261         /* Write event code to L3C_EVENT_TYPEx Register */
262         val = readl(l3c_pmu->base + reg);
263         val &= ~(L3C_EVTYPE_NONE << shift);
264         val |= (type << shift);
265         writel(val, l3c_pmu->base + reg);
266 }
267
268 static void hisi_l3c_pmu_start_counters(struct hisi_pmu *l3c_pmu)
269 {
270         u32 val;
271
272         /*
273          * Set perf_enable bit in L3C_PERF_CTRL register to start counting
274          * for all enabled counters.
275          */
276         val = readl(l3c_pmu->base + L3C_PERF_CTRL);
277         val |= L3C_PERF_CTRL_EN;
278         writel(val, l3c_pmu->base + L3C_PERF_CTRL);
279 }
280
281 static void hisi_l3c_pmu_stop_counters(struct hisi_pmu *l3c_pmu)
282 {
283         u32 val;
284
285         /*
286          * Clear perf_enable bit in L3C_PERF_CTRL register to stop counting
287          * for all enabled counters.
288          */
289         val = readl(l3c_pmu->base + L3C_PERF_CTRL);
290         val &= ~(L3C_PERF_CTRL_EN);
291         writel(val, l3c_pmu->base + L3C_PERF_CTRL);
292 }
293
294 static void hisi_l3c_pmu_enable_counter(struct hisi_pmu *l3c_pmu,
295                                         struct hw_perf_event *hwc)
296 {
297         u32 val;
298
299         /* Enable counter index in L3C_EVENT_CTRL register */
300         val = readl(l3c_pmu->base + L3C_EVENT_CTRL);
301         val |= (1 << hwc->idx);
302         writel(val, l3c_pmu->base + L3C_EVENT_CTRL);
303 }
304
305 static void hisi_l3c_pmu_disable_counter(struct hisi_pmu *l3c_pmu,
306                                          struct hw_perf_event *hwc)
307 {
308         u32 val;
309
310         /* Clear counter index in L3C_EVENT_CTRL register */
311         val = readl(l3c_pmu->base + L3C_EVENT_CTRL);
312         val &= ~(1 << hwc->idx);
313         writel(val, l3c_pmu->base + L3C_EVENT_CTRL);
314 }
315
316 static void hisi_l3c_pmu_enable_counter_int(struct hisi_pmu *l3c_pmu,
317                                             struct hw_perf_event *hwc)
318 {
319         u32 val;
320
321         val = readl(l3c_pmu->base + L3C_INT_MASK);
322         /* Write 0 to enable interrupt */
323         val &= ~(1 << hwc->idx);
324         writel(val, l3c_pmu->base + L3C_INT_MASK);
325 }
326
327 static void hisi_l3c_pmu_disable_counter_int(struct hisi_pmu *l3c_pmu,
328                                              struct hw_perf_event *hwc)
329 {
330         u32 val;
331
332         val = readl(l3c_pmu->base + L3C_INT_MASK);
333         /* Write 1 to mask interrupt */
334         val |= (1 << hwc->idx);
335         writel(val, l3c_pmu->base + L3C_INT_MASK);
336 }
337
338 static u32 hisi_l3c_pmu_get_int_status(struct hisi_pmu *l3c_pmu)
339 {
340         return readl(l3c_pmu->base + L3C_INT_STATUS);
341 }
342
343 static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx)
344 {
345         writel(1 << idx, l3c_pmu->base + L3C_INT_CLEAR);
346 }
347
348 static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = {
349         { "HISI0213", },
350         { "HISI0214", },
351         {}
352 };
353 MODULE_DEVICE_TABLE(acpi, hisi_l3c_pmu_acpi_match);
354
355 static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
356                                   struct hisi_pmu *l3c_pmu)
357 {
358         /*
359          * Use the SCCL_ID and CCL_ID to identify the L3C PMU, while
360          * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1].
361          */
362         if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
363                                      &l3c_pmu->sccl_id)) {
364                 dev_err(&pdev->dev, "Can not read l3c sccl-id!\n");
365                 return -EINVAL;
366         }
367
368         if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id",
369                                      &l3c_pmu->ccl_id)) {
370                 dev_err(&pdev->dev, "Can not read l3c ccl-id!\n");
371                 return -EINVAL;
372         }
373
374         l3c_pmu->base = devm_platform_ioremap_resource(pdev, 0);
375         if (IS_ERR(l3c_pmu->base)) {
376                 dev_err(&pdev->dev, "ioremap failed for l3c_pmu resource\n");
377                 return PTR_ERR(l3c_pmu->base);
378         }
379
380         l3c_pmu->identifier = readl(l3c_pmu->base + L3C_VERSION);
381
382         return 0;
383 }
384
385 static struct attribute *hisi_l3c_pmu_v1_format_attr[] = {
386         HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
387         NULL,
388 };
389
390 static const struct attribute_group hisi_l3c_pmu_v1_format_group = {
391         .name = "format",
392         .attrs = hisi_l3c_pmu_v1_format_attr,
393 };
394
395 static struct attribute *hisi_l3c_pmu_v2_format_attr[] = {
396         HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
397         HISI_PMU_FORMAT_ATTR(tt_core, "config1:0-7"),
398         HISI_PMU_FORMAT_ATTR(tt_req, "config1:8-10"),
399         HISI_PMU_FORMAT_ATTR(datasrc_cfg, "config1:11-15"),
400         HISI_PMU_FORMAT_ATTR(datasrc_skt, "config1:16"),
401         NULL
402 };
403
404 static const struct attribute_group hisi_l3c_pmu_v2_format_group = {
405         .name = "format",
406         .attrs = hisi_l3c_pmu_v2_format_attr,
407 };
408
409 static struct attribute *hisi_l3c_pmu_v1_events_attr[] = {
410         HISI_PMU_EVENT_ATTR(rd_cpipe,           0x00),
411         HISI_PMU_EVENT_ATTR(wr_cpipe,           0x01),
412         HISI_PMU_EVENT_ATTR(rd_hit_cpipe,       0x02),
413         HISI_PMU_EVENT_ATTR(wr_hit_cpipe,       0x03),
414         HISI_PMU_EVENT_ATTR(victim_num,         0x04),
415         HISI_PMU_EVENT_ATTR(rd_spipe,           0x20),
416         HISI_PMU_EVENT_ATTR(wr_spipe,           0x21),
417         HISI_PMU_EVENT_ATTR(rd_hit_spipe,       0x22),
418         HISI_PMU_EVENT_ATTR(wr_hit_spipe,       0x23),
419         HISI_PMU_EVENT_ATTR(back_invalid,       0x29),
420         HISI_PMU_EVENT_ATTR(retry_cpu,          0x40),
421         HISI_PMU_EVENT_ATTR(retry_ring,         0x41),
422         HISI_PMU_EVENT_ATTR(prefetch_drop,      0x42),
423         NULL,
424 };
425
426 static const struct attribute_group hisi_l3c_pmu_v1_events_group = {
427         .name = "events",
428         .attrs = hisi_l3c_pmu_v1_events_attr,
429 };
430
431 static struct attribute *hisi_l3c_pmu_v2_events_attr[] = {
432         HISI_PMU_EVENT_ATTR(l3c_hit,            0x48),
433         HISI_PMU_EVENT_ATTR(cycles,             0x7f),
434         HISI_PMU_EVENT_ATTR(l3c_ref,            0xb8),
435         HISI_PMU_EVENT_ATTR(dat_access,         0xb9),
436         NULL
437 };
438
439 static const struct attribute_group hisi_l3c_pmu_v2_events_group = {
440         .name = "events",
441         .attrs = hisi_l3c_pmu_v2_events_attr,
442 };
443
444 static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
445
446 static struct attribute *hisi_l3c_pmu_cpumask_attrs[] = {
447         &dev_attr_cpumask.attr,
448         NULL,
449 };
450
451 static const struct attribute_group hisi_l3c_pmu_cpumask_attr_group = {
452         .attrs = hisi_l3c_pmu_cpumask_attrs,
453 };
454
455 static struct device_attribute hisi_l3c_pmu_identifier_attr =
456         __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
457
458 static struct attribute *hisi_l3c_pmu_identifier_attrs[] = {
459         &hisi_l3c_pmu_identifier_attr.attr,
460         NULL
461 };
462
463 static const struct attribute_group hisi_l3c_pmu_identifier_group = {
464         .attrs = hisi_l3c_pmu_identifier_attrs,
465 };
466
467 static const struct attribute_group *hisi_l3c_pmu_v1_attr_groups[] = {
468         &hisi_l3c_pmu_v1_format_group,
469         &hisi_l3c_pmu_v1_events_group,
470         &hisi_l3c_pmu_cpumask_attr_group,
471         &hisi_l3c_pmu_identifier_group,
472         NULL,
473 };
474
475 static const struct attribute_group *hisi_l3c_pmu_v2_attr_groups[] = {
476         &hisi_l3c_pmu_v2_format_group,
477         &hisi_l3c_pmu_v2_events_group,
478         &hisi_l3c_pmu_cpumask_attr_group,
479         &hisi_l3c_pmu_identifier_group,
480         NULL
481 };
482
483 static const struct hisi_uncore_ops hisi_uncore_l3c_ops = {
484         .write_evtype           = hisi_l3c_pmu_write_evtype,
485         .get_event_idx          = hisi_uncore_pmu_get_event_idx,
486         .start_counters         = hisi_l3c_pmu_start_counters,
487         .stop_counters          = hisi_l3c_pmu_stop_counters,
488         .enable_counter         = hisi_l3c_pmu_enable_counter,
489         .disable_counter        = hisi_l3c_pmu_disable_counter,
490         .enable_counter_int     = hisi_l3c_pmu_enable_counter_int,
491         .disable_counter_int    = hisi_l3c_pmu_disable_counter_int,
492         .write_counter          = hisi_l3c_pmu_write_counter,
493         .read_counter           = hisi_l3c_pmu_read_counter,
494         .get_int_status         = hisi_l3c_pmu_get_int_status,
495         .clear_int_status       = hisi_l3c_pmu_clear_int_status,
496         .enable_filter          = hisi_l3c_pmu_enable_filter,
497         .disable_filter         = hisi_l3c_pmu_disable_filter,
498 };
499
500 static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
501                                   struct hisi_pmu *l3c_pmu)
502 {
503         int ret;
504
505         ret = hisi_l3c_pmu_init_data(pdev, l3c_pmu);
506         if (ret)
507                 return ret;
508
509         ret = hisi_uncore_pmu_init_irq(l3c_pmu, pdev);
510         if (ret)
511                 return ret;
512
513         if (l3c_pmu->identifier >= HISI_PMU_V2) {
514                 l3c_pmu->counter_bits = 64;
515                 l3c_pmu->check_event = L3C_V2_NR_EVENTS;
516                 l3c_pmu->pmu_events.attr_groups = hisi_l3c_pmu_v2_attr_groups;
517         } else {
518                 l3c_pmu->counter_bits = 48;
519                 l3c_pmu->check_event = L3C_V1_NR_EVENTS;
520                 l3c_pmu->pmu_events.attr_groups = hisi_l3c_pmu_v1_attr_groups;
521         }
522
523         l3c_pmu->num_counters = L3C_NR_COUNTERS;
524         l3c_pmu->ops = &hisi_uncore_l3c_ops;
525         l3c_pmu->dev = &pdev->dev;
526         l3c_pmu->on_cpu = -1;
527
528         return 0;
529 }
530
531 static int hisi_l3c_pmu_probe(struct platform_device *pdev)
532 {
533         struct hisi_pmu *l3c_pmu;
534         char *name;
535         int ret;
536
537         l3c_pmu = devm_kzalloc(&pdev->dev, sizeof(*l3c_pmu), GFP_KERNEL);
538         if (!l3c_pmu)
539                 return -ENOMEM;
540
541         platform_set_drvdata(pdev, l3c_pmu);
542
543         ret = hisi_l3c_pmu_dev_probe(pdev, l3c_pmu);
544         if (ret)
545                 return ret;
546
547         ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
548                                        &l3c_pmu->node);
549         if (ret) {
550                 dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
551                 return ret;
552         }
553
554         /*
555          * CCL_ID is used to identify the L3C in the same SCCL which was
556          * used _UID by mistake.
557          */
558         name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
559                               l3c_pmu->sccl_id, l3c_pmu->ccl_id);
560         l3c_pmu->pmu = (struct pmu) {
561                 .name           = name,
562                 .module         = THIS_MODULE,
563                 .task_ctx_nr    = perf_invalid_context,
564                 .event_init     = hisi_uncore_pmu_event_init,
565                 .pmu_enable     = hisi_uncore_pmu_enable,
566                 .pmu_disable    = hisi_uncore_pmu_disable,
567                 .add            = hisi_uncore_pmu_add,
568                 .del            = hisi_uncore_pmu_del,
569                 .start          = hisi_uncore_pmu_start,
570                 .stop           = hisi_uncore_pmu_stop,
571                 .read           = hisi_uncore_pmu_read,
572                 .attr_groups    = l3c_pmu->pmu_events.attr_groups,
573                 .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
574         };
575
576         ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
577         if (ret) {
578                 dev_err(l3c_pmu->dev, "L3C PMU register failed!\n");
579                 cpuhp_state_remove_instance_nocalls(
580                         CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, &l3c_pmu->node);
581         }
582
583         return ret;
584 }
585
586 static int hisi_l3c_pmu_remove(struct platform_device *pdev)
587 {
588         struct hisi_pmu *l3c_pmu = platform_get_drvdata(pdev);
589
590         perf_pmu_unregister(&l3c_pmu->pmu);
591         cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
592                                             &l3c_pmu->node);
593         return 0;
594 }
595
596 static struct platform_driver hisi_l3c_pmu_driver = {
597         .driver = {
598                 .name = "hisi_l3c_pmu",
599                 .acpi_match_table = ACPI_PTR(hisi_l3c_pmu_acpi_match),
600                 .suppress_bind_attrs = true,
601         },
602         .probe = hisi_l3c_pmu_probe,
603         .remove = hisi_l3c_pmu_remove,
604 };
605
606 static int __init hisi_l3c_pmu_module_init(void)
607 {
608         int ret;
609
610         ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
611                                       "AP_PERF_ARM_HISI_L3_ONLINE",
612                                       hisi_uncore_pmu_online_cpu,
613                                       hisi_uncore_pmu_offline_cpu);
614         if (ret) {
615                 pr_err("L3C PMU: Error setup hotplug, ret = %d\n", ret);
616                 return ret;
617         }
618
619         ret = platform_driver_register(&hisi_l3c_pmu_driver);
620         if (ret)
621                 cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE);
622
623         return ret;
624 }
625 module_init(hisi_l3c_pmu_module_init);
626
627 static void __exit hisi_l3c_pmu_module_exit(void)
628 {
629         platform_driver_unregister(&hisi_l3c_pmu_driver);
630         cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE);
631 }
632 module_exit(hisi_l3c_pmu_module_exit);
633
634 MODULE_DESCRIPTION("HiSilicon SoC L3C uncore PMU driver");
635 MODULE_LICENSE("GPL v2");
636 MODULE_AUTHOR("Anurup M <anurup.m@huawei.com>");
637 MODULE_AUTHOR("Shaokun Zhang <zhangshaokun@hisilicon.com>");