forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-02-20 e636c8d336489bf3eed5878299e6cc045bbad077
kernel/drivers/perf/arm_dsu_pmu.c
....@@ -1,19 +1,17 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * ARM DynamIQ Shared Unit (DSU) PMU driver
34 *
45 * Copyright (C) ARM Limited, 2017.
56 *
67 * Based on ARM CCI-PMU, ARMv8 PMU-v3 drivers.
7
- *
8
- * This program is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License
10
- * version 2 as published by the Free Software Foundation.
118 */
129
1310 #define PMUNAME "arm_dsu"
1411 #define DRVNAME PMUNAME "_pmu"
1512 #define pr_fmt(fmt) DRVNAME ": " fmt
1613
14
+#include <linux/acpi.h>
1715 #include <linux/bitmap.h>
1816 #include <linux/bitops.h>
1917 #include <linux/bug.h>
....@@ -562,13 +560,7 @@
562560 return -EINVAL;
563561 }
564562
565
- if (has_branch_stack(event) ||
566
- event->attr.exclude_user ||
567
- event->attr.exclude_kernel ||
568
- event->attr.exclude_hv ||
569
- event->attr.exclude_idle ||
570
- event->attr.exclude_host ||
571
- event->attr.exclude_guest) {
563
+ if (has_branch_stack(event)) {
572564 dev_dbg(dsu_pmu->pmu.dev, "Can't support filtering\n");
573565 return -EINVAL;
574566 }
....@@ -612,18 +604,19 @@
612604 }
613605
614606 /**
615
- * dsu_pmu_dt_get_cpus: Get the list of CPUs in the cluster.
607
+ * dsu_pmu_dt_get_cpus: Get the list of CPUs in the cluster
608
+ * from device tree.
616609 */
617
-static int dsu_pmu_dt_get_cpus(struct device_node *dev, cpumask_t *mask)
610
+static int dsu_pmu_dt_get_cpus(struct device *dev, cpumask_t *mask)
618611 {
619612 int i = 0, n, cpu;
620613 struct device_node *cpu_node;
621614
622
- n = of_count_phandle_with_args(dev, "cpus", NULL);
615
+ n = of_count_phandle_with_args(dev->of_node, "cpus", NULL);
623616 if (n <= 0)
624617 return -ENODEV;
625618 for (; i < n; i++) {
626
- cpu_node = of_parse_phandle(dev, "cpus", i);
619
+ cpu_node = of_parse_phandle(dev->of_node, "cpus", i);
627620 if (!cpu_node)
628621 break;
629622 cpu = of_cpu_node_to_id(cpu_node);
....@@ -637,6 +630,36 @@
637630 continue;
638631 cpumask_set_cpu(cpu, mask);
639632 }
633
+ return 0;
634
+}
635
+
636
+/**
637
+ * dsu_pmu_acpi_get_cpus: Get the list of CPUs in the cluster
638
+ * from ACPI.
639
+ */
640
+static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask)
641
+{
642
+#ifdef CONFIG_ACPI
643
+ int cpu;
644
+
645
+ /*
646
+ * A dsu pmu node is inside a cluster parent node along with cpu nodes.
647
+ * We need to find out all cpus that have the same parent with this pmu.
648
+ */
649
+ for_each_possible_cpu(cpu) {
650
+ struct acpi_device *acpi_dev;
651
+ struct device *cpu_dev = get_cpu_device(cpu);
652
+
653
+ if (!cpu_dev)
654
+ continue;
655
+
656
+ acpi_dev = ACPI_COMPANION(cpu_dev);
657
+ if (acpi_dev &&
658
+ acpi_dev->parent == ACPI_COMPANION(dev)->parent)
659
+ cpumask_set_cpu(cpu, mask);
660
+ }
661
+#endif
662
+
640663 return 0;
641664 }
642665
....@@ -685,6 +708,7 @@
685708 {
686709 int irq, rc;
687710 struct dsu_pmu *dsu_pmu;
711
+ struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
688712 char *name;
689713 static atomic_t pmu_idx = ATOMIC_INIT(-1);
690714
....@@ -692,17 +716,24 @@
692716 if (IS_ERR(dsu_pmu))
693717 return PTR_ERR(dsu_pmu);
694718
695
- rc = dsu_pmu_dt_get_cpus(pdev->dev.of_node, &dsu_pmu->associated_cpus);
719
+ if (IS_ERR_OR_NULL(fwnode))
720
+ return -ENOENT;
721
+
722
+ if (is_of_node(fwnode))
723
+ rc = dsu_pmu_dt_get_cpus(&pdev->dev, &dsu_pmu->associated_cpus);
724
+ else if (is_acpi_device_node(fwnode))
725
+ rc = dsu_pmu_acpi_get_cpus(&pdev->dev, &dsu_pmu->associated_cpus);
726
+ else
727
+ return -ENOENT;
728
+
696729 if (rc) {
697730 dev_warn(&pdev->dev, "Failed to parse the CPUs\n");
698731 return rc;
699732 }
700733
701734 irq = platform_get_irq(pdev, 0);
702
- if (irq < 0) {
703
- dev_warn(&pdev->dev, "Failed to find IRQ\n");
735
+ if (irq < 0)
704736 return -EINVAL;
705
- }
706737
707738 name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_%d",
708739 PMUNAME, atomic_inc_return(&pmu_idx));
....@@ -735,6 +766,7 @@
735766 .read = dsu_pmu_read,
736767
737768 .attr_groups = dsu_pmu_attr_groups,
769
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
738770 };
739771
740772 rc = perf_pmu_register(&dsu_pmu->pmu, name, -1);
....@@ -762,11 +794,22 @@
762794 { .compatible = "arm,dsu-pmu", },
763795 {},
764796 };
797
+MODULE_DEVICE_TABLE(of, dsu_pmu_of_match);
798
+
799
+#ifdef CONFIG_ACPI
800
+static const struct acpi_device_id dsu_pmu_acpi_match[] = {
801
+ { "ARMHD500", 0},
802
+ {},
803
+};
804
+MODULE_DEVICE_TABLE(acpi, dsu_pmu_acpi_match);
805
+#endif
765806
766807 static struct platform_driver dsu_pmu_driver = {
767808 .driver = {
768809 .name = DRVNAME,
769810 .of_match_table = of_match_ptr(dsu_pmu_of_match),
811
+ .acpi_match_table = ACPI_PTR(dsu_pmu_acpi_match),
812
+ .suppress_bind_attrs = true,
770813 },
771814 .probe = dsu_pmu_device_probe,
772815 .remove = dsu_pmu_device_remove,
....@@ -823,7 +866,11 @@
823866 if (ret < 0)
824867 return ret;
825868 dsu_pmu_cpuhp_state = ret;
826
- return platform_driver_register(&dsu_pmu_driver);
869
+ ret = platform_driver_register(&dsu_pmu_driver);
870
+ if (ret)
871
+ cpuhp_remove_multi_state(dsu_pmu_cpuhp_state);
872
+
873
+ return ret;
827874 }
828875
829876 static void __exit dsu_pmu_exit(void)
....@@ -835,7 +882,6 @@
835882 module_init(dsu_pmu_init);
836883 module_exit(dsu_pmu_exit);
837884
838
-MODULE_DEVICE_TABLE(of, dsu_pmu_of_match);
839885 MODULE_DESCRIPTION("Perf driver for ARM DynamIQ Shared Unit");
840886 MODULE_AUTHOR("Suzuki K Poulose <suzuki.poulose@arm.com>");
841887 MODULE_LICENSE("GPL v2");