.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2017 NXP |
---|
3 | 4 | * Copyright 2011,2016 Freescale Semiconductor, Inc. |
---|
4 | 5 | * Copyright 2011 Linaro Ltd. |
---|
5 | | - * |
---|
6 | | - * The code contained herein is licensed under the GNU General Public |
---|
7 | | - * License. You may obtain a copy of the GNU General Public License |
---|
8 | | - * Version 2 or later at the following locations: |
---|
9 | | - * |
---|
10 | | - * http://www.opensource.org/licenses/gpl-license.html |
---|
11 | | - * http://www.gnu.org/copyleft/gpl.html |
---|
12 | 6 | */ |
---|
13 | 7 | |
---|
14 | 8 | #include <linux/clk.h> |
---|
.. | .. |
---|
105 | 99 | cpumask_t cpu; |
---|
106 | 100 | struct hrtimer hrtimer; |
---|
107 | 101 | unsigned int active_events; |
---|
| 102 | + int id; |
---|
108 | 103 | struct device *dev; |
---|
109 | 104 | struct perf_event *mmdc_events[MMDC_NUM_COUNTERS]; |
---|
110 | 105 | struct hlist_node node; |
---|
.. | .. |
---|
295 | 290 | return -EOPNOTSUPP; |
---|
296 | 291 | } |
---|
297 | 292 | |
---|
298 | | - if (event->attr.exclude_user || |
---|
299 | | - event->attr.exclude_kernel || |
---|
300 | | - event->attr.exclude_hv || |
---|
301 | | - event->attr.exclude_idle || |
---|
302 | | - event->attr.exclude_host || |
---|
303 | | - event->attr.exclude_guest || |
---|
304 | | - event->attr.sample_period) |
---|
| 293 | + if (event->attr.sample_period) |
---|
305 | 294 | return -EINVAL; |
---|
306 | 295 | |
---|
307 | 296 | if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS) |
---|
.. | .. |
---|
445 | 434 | static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc, |
---|
446 | 435 | void __iomem *mmdc_base, struct device *dev) |
---|
447 | 436 | { |
---|
448 | | - int mmdc_num; |
---|
449 | | - |
---|
450 | 437 | *pmu_mmdc = (struct mmdc_pmu) { |
---|
451 | 438 | .pmu = (struct pmu) { |
---|
452 | 439 | .task_ctx_nr = perf_invalid_context, |
---|
.. | .. |
---|
457 | 444 | .start = mmdc_pmu_event_start, |
---|
458 | 445 | .stop = mmdc_pmu_event_stop, |
---|
459 | 446 | .read = mmdc_pmu_event_update, |
---|
| 447 | + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, |
---|
460 | 448 | }, |
---|
461 | 449 | .mmdc_base = mmdc_base, |
---|
462 | 450 | .dev = dev, |
---|
463 | 451 | .active_events = 0, |
---|
464 | 452 | }; |
---|
465 | 453 | |
---|
466 | | - mmdc_num = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL); |
---|
| 454 | + pmu_mmdc->id = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL); |
---|
467 | 455 | |
---|
468 | | - return mmdc_num; |
---|
| 456 | + return pmu_mmdc->id; |
---|
469 | 457 | } |
---|
470 | 458 | |
---|
471 | 459 | static int imx_mmdc_remove(struct platform_device *pdev) |
---|
472 | 460 | { |
---|
473 | 461 | struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev); |
---|
474 | 462 | |
---|
| 463 | + ida_simple_remove(&mmdc_ida, pmu_mmdc->id); |
---|
475 | 464 | cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node); |
---|
476 | 465 | perf_pmu_unregister(&pmu_mmdc->pmu); |
---|
477 | 466 | iounmap(pmu_mmdc->mmdc_base); |
---|
.. | .. |
---|
485 | 474 | { |
---|
486 | 475 | struct mmdc_pmu *pmu_mmdc; |
---|
487 | 476 | char *name; |
---|
488 | | - int mmdc_num; |
---|
489 | 477 | int ret; |
---|
490 | 478 | const struct of_device_id *of_id = |
---|
491 | 479 | of_match_device(imx_mmdc_dt_ids, &pdev->dev); |
---|
.. | .. |
---|
508 | 496 | cpuhp_mmdc_state = ret; |
---|
509 | 497 | } |
---|
510 | 498 | |
---|
511 | | - mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev); |
---|
512 | | - pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk; |
---|
513 | | - if (mmdc_num == 0) |
---|
514 | | - name = "mmdc"; |
---|
515 | | - else |
---|
516 | | - name = devm_kasprintf(&pdev->dev, |
---|
517 | | - GFP_KERNEL, "mmdc%d", mmdc_num); |
---|
| 499 | + ret = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev); |
---|
| 500 | + if (ret < 0) |
---|
| 501 | + goto pmu_free; |
---|
518 | 502 | |
---|
| 503 | + name = devm_kasprintf(&pdev->dev, |
---|
| 504 | + GFP_KERNEL, "mmdc%d", ret); |
---|
| 505 | + |
---|
| 506 | + pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk; |
---|
519 | 507 | pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data; |
---|
520 | 508 | |
---|
521 | 509 | hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC, |
---|
.. | .. |
---|
536 | 524 | |
---|
537 | 525 | pmu_register_err: |
---|
538 | 526 | pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret); |
---|
| 527 | + ida_simple_remove(&mmdc_ida, pmu_mmdc->id); |
---|
539 | 528 | cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node); |
---|
540 | 529 | hrtimer_cancel(&pmu_mmdc->hrtimer); |
---|
541 | 530 | pmu_free: |
---|