Skip to contentSkip to conversation

Arm interconnect PMU driver tidyup

PATCH Superseded Robin Murphy 2 participants 9 messages Feb 15, 2018 – Mar 6, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v2 cover Arm interconnect PMU driver tidyup

Hi arm-soc folks,

PLease consider this series tidying up the Arm interconnect code in drivers/bus to separate the PMU parts out into drivers/perf where Will and Mark can handle future maintenance more easily.

FWIW, the patches are also available on a branch here:

git://linux-arm.org/linux-rm.git perf

Thanks,
Robin.

---

Since v1:
- Add acks.
- Extra patch to break the direct cci_ctrl_base dependency.

Robin Murphy (6):
drivers/bus: Move Arm CCN PMU driver drivers/bus: Split Arm CCI driver perf/arm-cci: Simplify CPU hotplug bus/arm-cci: Streamline devicetree handling a bit perf/arm-cci: Clean up model discovery perf/arm-cci: Untangle global cci_ctrl_base

 .../bindings/{arm/ccn.txt => perf/arm-ccn.txt}     |    0
 Documentation/{arm/CCN.txt => perf/arm-ccn.txt}    |    0
 drivers/bus/Kconfig                                |   36 -
 drivers/bus/Makefile                               |    2 -
 drivers/bus/arm-cci.c                              | 1763 +-------------------
 drivers/perf/Kconfig                               |   33 +
 drivers/perf/Makefile                              |    2 +
 drivers/{bus => perf}/arm-cci.c                    |  738 +-------
 drivers/{bus => perf}/arm-ccn.c                    |    0
 9 files changed, 117 insertions(+), 2457 deletions(-)
 rename Documentation/devicetree/bindings/{arm/ccn.txt => perf/arm-ccn.txt} (100%)
 rename Documentation/{arm/CCN.txt => perf/arm-ccn.txt} (100%)
 copy drivers/{bus => perf}/arm-cci.c (71%)
 rename drivers/{bus => perf}/arm-ccn.c (100%)
Signature · 1 line
2.16.1.dirty
#1 lore raw

PATCH v2 1/6 drivers/bus: Move Arm CCN PMU driver

The arm-ccn driver is purely a perf driver for the CCN PMU, not a bus driver in the sense of the other residents of drivers/bus/, so let's move it to the appropriate place for SoC PMU drivers. Not to mention moving the documentation accordingly as well.

---
 .../devicetree/bindings/{arm/ccn.txt => perf/arm-ccn.txt}         | 0
 Documentation/{arm/CCN.txt => perf/arm-ccn.txt}                   | 0
 drivers/bus/Kconfig                                               | 8 --------
 drivers/bus/Makefile                                              | 2 --
 drivers/perf/Kconfig                                              | 7 +++++++
 drivers/perf/Makefile                                             | 1 +
 drivers/{bus => perf}/arm-ccn.c                                   | 0
 7 files changed, 8 insertions(+), 10 deletions(-)
 rename Documentation/devicetree/bindings/{arm/ccn.txt => perf/arm-ccn.txt} (100%)
 rename Documentation/{arm/CCN.txt => perf/arm-ccn.txt} (100%)
 rename drivers/{bus => perf}/arm-ccn.c (100%)
Documentation/devicetree/bindings/perf/arm-ccn.txt renamed from Documentation/devicetree/bindings/arm/ccn.txt +0 -0
similarity index 100%
rename from Documentation/devicetree/bindings/arm/ccn.txt
rename to Documentation/devicetree/bindings/perf/arm-ccn.txt
Documentation/perf/arm-ccn.txt renamed from Documentation/arm/CCN.txt +0 -0
similarity index 100%
rename from Documentation/arm/CCN.txt
rename to Documentation/perf/arm-ccn.txt
drivers/bus/Kconfig +0 -8
index 57e011d36a79..116446c42c6b 100644
@@ -48,14 +48,6 @@ config ARM_CCI5xx_PMU
 
 	  If unsure, say Y
 
-config ARM_CCN
-	tristate "ARM CCN driver support"
-	depends on ARM || ARM64
-	depends on PERF_EVENTS
-	help
-	  PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
-	  interconnect.
-
 config BRCMSTB_GISB_ARB
 	bool "Broadcom STB GISB bus arbiter"
 	depends on ARM || ARM64 || MIPS
drivers/bus/Makefile +0 -2
index 9bcd0bf3954b..19733afddd0a 100644
@@ -5,8 +5,6 @@
 
 # Interconnect bus drivers for ARM platforms
 obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
-obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
-
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
drivers/perf/Kconfig +7 -0
index da5724cd89cf..331b6d992b5a 100644
@@ -5,6 +5,13 @@
 menu "Performance monitor support"
 	depends on PERF_EVENTS
 
+config ARM_CCN
+	tristate "ARM CCN driver support"
+	depends on ARM || ARM64
+	help
+	  PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
+	  interconnect.
+
 config ARM_PMU
 	depends on ARM || ARM64
 	bool "ARM PMU framework"
drivers/perf/Makefile +1 -0
index c2f27419bdf0..5004abee0f3a 100644
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_ARM_CCN) += arm-ccn.o
 obj-$(CONFIG_ARM_DSU_PMU) += arm_dsu_pmu.o
 obj-$(CONFIG_ARM_PMU) += arm_pmu.o arm_pmu_platform.o
 obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o
drivers/perf/arm-ccn.c renamed from drivers/bus/arm-ccn.c +0 -0
similarity index 100%
rename from drivers/bus/arm-ccn.c
rename to drivers/perf/arm-ccn.c
Signature · 1 line
2.16.1.dirty
#2 lore raw

PATCH v2 2/6 drivers/bus: Split Arm CCI driver

In reply to Robin Murphy

The arm-cci driver is really two entirely separate drivers; one for MCPM port control and the other for the performance monitors. Since they are already relatively self-contained, let's take the plunge and move the PMU parts out to drivers/perf where they belong these days. For non-MCPM systems this leaves a small dependency on the remaining "bus" stub for initial probing and discovery, but we end up with something that still fits the general pattern of its fellow system PMU drivers to ease future maintenance.

Moving code to a new file also offers a perfect excuse to modernise the license/copyright headers and clean up some funky linewraps on the way.

---
 drivers/bus/Kconfig             |   28 -
 drivers/bus/arm-cci.c           | 1745 +--------------------------------------
 drivers/perf/Kconfig            |   26 +
 drivers/perf/Makefile           |    1 +
 drivers/{bus => perf}/arm-cci.c |  607 +-------------
 5 files changed, 44 insertions(+), 2363 deletions(-)
 copy drivers/{bus => perf}/arm-cci.c (75%)
drivers/bus/Kconfig +0 -28
index 116446c42c6b..39ddb63be993 100644
@@ -8,25 +8,10 @@ menu "Bus devices"
 config ARM_CCI
 	bool
 
-config ARM_CCI_PMU
-	bool
-	select ARM_CCI
-
 config ARM_CCI400_COMMON
 	bool
 	select ARM_CCI
 
-config ARM_CCI400_PMU
-	bool "ARM CCI400 PMU support"
-	depends on (ARM && CPU_V7) || ARM64
-	depends on PERF_EVENTS
-	select ARM_CCI400_COMMON
-	select ARM_CCI_PMU
-	help
-	  Support for PMU events monitoring on the ARM CCI-400 (cache coherent
-	  interconnect). CCI-400 supports counting events related to the
-	  connected slave/master interfaces.
-
 config ARM_CCI400_PORT_CTRL
 	bool
 	depends on ARM && OF && CPU_V7
@@ -35,19 +20,6 @@ config ARM_CCI400_PORT_CTRL
 	  Low level power management driver for CCI400 cache coherent
 	  interconnect for ARM platforms.
 
-config ARM_CCI5xx_PMU
-	bool "ARM CCI-500/CCI-550 PMU support"
-	depends on (ARM && CPU_V7) || ARM64
-	depends on PERF_EVENTS
-	select ARM_CCI_PMU
-	help
-	  Support for PMU events monitoring on the ARM CCI-500/CCI-550 cache
-	  coherent interconnects. Both of them provide 8 independent event counters,
-	  which can count events pertaining to the slave/master interfaces as well
-	  as the internal events to the CCI.
-
-	  If unsure, say Y
-
 config BRCMSTB_GISB_ARB
 	bool "Broadcom STB GISB bus arbiter"
 	depends on ARM || ARM64 || MIPS
drivers/bus/arm-cci.c +2 -1743

1,782 lines not on this page · raw message

drivers/perf/Kconfig +26 -0
index 331b6d992b5a..28bb5a029558 100644
@@ -5,6 +5,32 @@
 menu "Performance monitor support"
 	depends on PERF_EVENTS
 
+config ARM_CCI_PMU
+	bool
+	select ARM_CCI
+
+config ARM_CCI400_PMU
+	bool "ARM CCI400 PMU support"
+	depends on (ARM && CPU_V7) || ARM64
+	select ARM_CCI400_COMMON
+	select ARM_CCI_PMU
+	help
+	  Support for PMU events monitoring on the ARM CCI-400 (cache coherent
+	  interconnect). CCI-400 supports counting events related to the
+	  connected slave/master interfaces.
+
+config ARM_CCI5xx_PMU
+	bool "ARM CCI-500/CCI-550 PMU support"
+	depends on (ARM && CPU_V7) || ARM64
+	select ARM_CCI_PMU
+	help
+	  Support for PMU events monitoring on the ARM CCI-500/CCI-550 cache
+	  coherent interconnects. Both of them provide 8 independent event counters,
+	  which can count events pertaining to the slave/master interfaces as well
+	  as the internal events to the CCI.
+
+	  If unsure, say Y
+
 config ARM_CCN
 	tristate "ARM CCN driver support"
 	depends on ARM || ARM64
drivers/perf/Makefile +1 -0
index 5004abee0f3a..b3902bd37d53 100644
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_ARM_CCI_PMU) += arm-cci.o
 obj-$(CONFIG_ARM_CCN) += arm-ccn.o
 obj-$(CONFIG_ARM_DSU_PMU) += arm_dsu_pmu.o
 obj-$(CONFIG_ARM_PMU) += arm_pmu.o arm_pmu_platform.o
drivers/perf/arm-cci.c renamed from drivers/bus/arm-cci.c +15 -592

660 lines not on this page · raw message

Signature · 1 line
2.16.1.dirty
#3 lore raw

PATCH v2 3/6 perf/arm-cci: Simplify CPU hotplug

In reply to Robin Murphy

Realistically, systems with multiple CCIs are unlikely to ever exist, and since the driver only actually supports a single instance anyway there's really no need to do the multi-instance hotplug state dance.

Take the opportunity to simplify the hotplug-related code all over, addressing the context-migration TODO in the process for good measure.

---
 drivers/perf/arm-cci.c | 56 +++++++++++++++++---------------------------------
 1 file changed, 19 insertions(+), 37 deletions(-)
drivers/perf/arm-cci.c +19 -37
index d5f8c750fd41..242623fbce1f 100644
@@ -90,6 +90,7 @@ static struct cci_pmu_model cci_pmu_models[];
 struct cci_pmu {
 	void __iomem *base;
 	struct pmu pmu;
+	int cpu;
 	int nr_irqs;
 	int *irqs;
 	unsigned long active_irqs;
@@ -99,12 +100,12 @@ struct cci_pmu {
 	int num_cntrs;
 	atomic_t active_events;
 	struct mutex reserve_mutex;
-	struct hlist_node node;
-	cpumask_t cpus;
 };
 
 #define to_cci_pmu(c)	(container_of(c, struct cci_pmu, pmu))
 
+static struct cci_pmu *g_cci_pmu;
+
 enum cci_models {
 #ifdef CONFIG_ARM_CCI400_PMU
 	CCI400_R0,
@@ -1325,7 +1326,6 @@ static int cci_pmu_event_init(struct perf_event *event)
 	struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
 	atomic_t *active_events = &cci_pmu->active_events;
 	int err = 0;
-	int cpu;
 
 	if (event->attr.type != event->pmu->type)
 		return -ENOENT;
@@ -1352,10 +1352,9 @@ static int cci_pmu_event_init(struct perf_event *event)
 	 * the event being installed into its context, so the PMU's CPU can't
 	 * change under our feet.
 	 */
-	cpu = cpumask_first(&cci_pmu->cpus);
-	if (event->cpu < 0 || cpu < 0)
+	if (event->cpu < 0)
 		return -EINVAL;
-	event->cpu = cpu;
+	event->cpu = cci_pmu->cpu;
 
 	event->destroy = hw_perf_event_destroy;
 	if (!atomic_inc_not_zero(active_events)) {
@@ -1382,11 +1381,7 @@ static ssize_t pmu_cpumask_attr_show(struct device *dev,
 	struct pmu *pmu = dev_get_drvdata(dev);
 	struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
 
-	int n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
-			  cpumask_pr_args(&cci_pmu->cpus));
-	buf[n++] = '\n';
-	buf[n] = '\0';
-	return n;
+	return cpumap_print_to_pagebuf(true, buf, cpumask_of(cci_pmu->cpu));
 }
 
 static struct device_attribute pmu_cpumask_attr =
@@ -1455,21 +1450,19 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
 	return perf_pmu_register(&cci_pmu->pmu, name, -1);
 }
 
-static int cci_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+static int cci_pmu_offline_cpu(unsigned int cpu)
 {
-	struct cci_pmu *cci_pmu = hlist_entry_safe(node, struct cci_pmu, node);
-	unsigned int target;
+	int target;
 
-	if (!cpumask_test_and_clear_cpu(cpu, &cci_pmu->cpus))
+	if (!g_cci_pmu || cpu != g_cci_pmu->cpu)
 		return 0;
+
 	target = cpumask_any_but(cpu_online_mask, cpu);
 	if (target >= nr_cpu_ids)
 		return 0;
-	/*
-	 * TODO: migrate context once core races on event->ctx have
-	 * been fixed.
-	 */
-	cpumask_set_cpu(target, &cci_pmu->cpus);
+
+	perf_pmu_migrate_context(&g_cci_pmu->pmu, cpu, target);
+	g_cci_pmu->cpu = target;
 	return 0;
 }
 
@@ -1706,7 +1699,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
 	raw_spin_lock_init(&cci_pmu->hw_events.pmu_lock);
 	mutex_init(&cci_pmu->reserve_mutex);
 	atomic_set(&cci_pmu->active_events, 0);
-	cpumask_set_cpu(get_cpu(), &cci_pmu->cpus);
+	cci_pmu->cpu = get_cpu();
 
 	ret = cci_pmu_init(cci_pmu, pdev);
 	if (ret) {
@@ -1714,9 +1707,11 @@ static int cci_pmu_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE,
-					 &cci_pmu->node);
+	cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE,
+				  "perf/arm/cci:online", NULL,
+				  cci_pmu_offline_cpu);
 	put_cpu();
+	g_cci_pmu = cci_pmu;
 	pr_info("ARM %s PMU driver probed", cci_pmu->model->name);
 	return 0;
 }
@@ -1729,19 +1724,6 @@ static struct platform_driver cci_pmu_driver = {
 	.probe = cci_pmu_probe,
 };
 
-static int __init cci_platform_init(void)
-{
-	int ret;
-
-	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CCI_ONLINE,
-				      "perf/arm/cci:online", NULL,
-				      cci_pmu_offline_cpu);
-	if (ret)
-		return ret;
-
-	return platform_driver_register(&cci_pmu_driver);
-}
-
-device_initcall(cci_platform_init);
+builtin_platform_driver(cci_pmu_driver);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ARM CCI PMU support");
Signature · 1 line
2.16.1.dirty
#4 lore raw

PATCH v2 4/6 bus/arm-cci: Streamline devicetree handling a bit

In reply to Robin Murphy

Rather than iterating over child nodes explicitly testing for availability, we can just use the other helper which already subsumes that check. Also, the availability check is already NULL-safe, so get rid of a redundant check in cci_probe(), too.

---
 drivers/bus/arm-cci.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/bus/arm-cci.c +2 -5
index 503c1789dd02..23dc0b890d0c 100644
@@ -448,13 +448,10 @@ static int cci_probe_ports(struct device_node *np)
 	if (!ports)
 		return -ENOMEM;
 
-	for_each_child_of_node(np, cp) {
+	for_each_available_child_of_node(np, cp) {
 		if (!of_match_node(arm_cci_ctrl_if_matches, cp))
 			continue;
 
-		if (!of_device_is_available(cp))
-			continue;
-
 		i = nb_ace + nb_ace_lite;
 
 		if (i >= nb_cci_ports)
@@ -534,7 +531,7 @@ static int cci_probe(void)
 	struct resource res;
 
 	np = of_find_matching_node(NULL, arm_cci_matches);
-	if(!np || !of_device_is_available(np))
+	if (!of_device_is_available(np))
 		return -ENODEV;
 
 	ret = of_address_to_resource(np, 0, &res);
Signature · 1 line
2.16.1.dirty
#5 lore raw

PATCH v2 5/6 perf/arm-cci: Clean up model discovery

In reply to Robin Murphy

Since I am the self-appointed of_device_get_match_data() police, it's only right that I should clean up this driver while I'm otherwise touching it. This also reveals that we're passing around a struct platform_device in places where we only ever care about its regular device, so straighten that out in the process.

---
 drivers/perf/arm-cci.c | 40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)
drivers/perf/arm-cci.c +16 -24
index 242623fbce1f..336f1455cf96 100644
@@ -8,6 +8,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/perf_event.h>
@@ -371,14 +372,14 @@ static int probe_cci400_revision(void)
 		return CCI400_R1;
 }
 
-static const struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
+static const struct cci_pmu_model *probe_cci_model(void)
 {
 	if (platform_has_secure_cci_access())
 		return &cci_pmu_models[probe_cci400_revision()];
 	return NULL;
 }
 #else	/* !CONFIG_ARM_CCI400_PMU */
-static inline struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
+static inline struct cci_pmu_model *probe_cci_model(void)
 {
 	return NULL;
 }
@@ -1589,20 +1590,6 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
 	{},
 };
 
-static inline const struct cci_pmu_model *get_cci_model(struct platform_device *pdev)
-{
-	const struct of_device_id *match = of_match_node(arm_cci_pmu_matches,
-							pdev->dev.of_node);
-	if (!match)
-		return NULL;
-	if (match->data)
-		return match->data;
-
-	dev_warn(&pdev->dev, "DEPRECATED compatible property,"
-			 "requires secure access to CCI registers");
-	return probe_cci_model(pdev);
-}
-
 static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
 {
 	int i;
@@ -1614,7 +1601,7 @@ static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
 	return false;
 }
 
-static struct cci_pmu *cci_pmu_alloc(struct platform_device *pdev)
+static struct cci_pmu *cci_pmu_alloc(struct device *dev)
 {
 	struct cci_pmu *cci_pmu;
 	const struct cci_pmu_model *model;
@@ -1624,28 +1611,33 @@ static struct cci_pmu *cci_pmu_alloc(struct platform_device *pdev)
 	 * them explicitly on an error, as it would end up in driver
 	 * detach.
 	 */
-	model = get_cci_model(pdev);
+	model = of_device_get_match_data(dev);
 	if (!model) {
-		dev_warn(&pdev->dev, "CCI PMU version not supported\n");
+		dev_warn(dev,
+			 "DEPRECATED compatible property, requires secure access to CCI registers");
+		model = probe_cci_model();
+	}
+	if (!model) {
+		dev_warn(dev, "CCI PMU version not supported\n");
 		return ERR_PTR(-ENODEV);
 	}
 
-	cci_pmu = devm_kzalloc(&pdev->dev, sizeof(*cci_pmu), GFP_KERNEL);
+	cci_pmu = devm_kzalloc(dev, sizeof(*cci_pmu), GFP_KERNEL);
 	if (!cci_pmu)
 		return ERR_PTR(-ENOMEM);
 
 	cci_pmu->model = model;
-	cci_pmu->irqs = devm_kcalloc(&pdev->dev, CCI_PMU_MAX_HW_CNTRS(model),
+	cci_pmu->irqs = devm_kcalloc(dev, CCI_PMU_MAX_HW_CNTRS(model),
 					sizeof(*cci_pmu->irqs), GFP_KERNEL);
 	if (!cci_pmu->irqs)
 		return ERR_PTR(-ENOMEM);
-	cci_pmu->hw_events.events = devm_kcalloc(&pdev->dev,
+	cci_pmu->hw_events.events = devm_kcalloc(dev,
 					     CCI_PMU_MAX_HW_CNTRS(model),
 					     sizeof(*cci_pmu->hw_events.events),
 					     GFP_KERNEL);
 	if (!cci_pmu->hw_events.events)
 		return ERR_PTR(-ENOMEM);
-	cci_pmu->hw_events.used_mask = devm_kcalloc(&pdev->dev,
+	cci_pmu->hw_events.used_mask = devm_kcalloc(dev,
 						BITS_TO_LONGS(CCI_PMU_MAX_HW_CNTRS(model)),
 						sizeof(*cci_pmu->hw_events.used_mask),
 						GFP_KERNEL);
@@ -1661,7 +1653,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
 	struct cci_pmu *cci_pmu;
 	int i, ret, irq;
 
-	cci_pmu = cci_pmu_alloc(pdev);
+	cci_pmu = cci_pmu_alloc(&pdev->dev);
 	if (IS_ERR(cci_pmu))
 		return PTR_ERR(cci_pmu);
 
Signature · 1 line
2.16.1.dirty
#6 lore raw

PATCH v2 6/6 perf/arm-cci: Untangle global cci_ctrl_base

In reply to Robin Murphy

Depending directly on the bus driver's global cci_ctrl_base variable is a little unpleasant, and exporting it to allow the PMU driver to be modular would be even more so. Let's make things a little better abstracted by adding the control register block to the cci_pmu instance data alongside the PMU register block, and communicating the mapped address from the bus driver via platform data.

It's not practical to try the same thing for the bus driver itself, given that the globals are entangled with the hairy assembly code for port control, so we leave them be there. It would however be prudent to move them to the __ro_after_init section in passing, since the addresses really should never be changing once set.

---
 drivers/bus/arm-cci.c  | 17 +++++++++++++----
 drivers/perf/arm-cci.c | 47 ++++++++++++++++++++++++-----------------------
 2 files changed, 37 insertions(+), 27 deletions(-)
drivers/bus/arm-cci.c +13 -4
index 23dc0b890d0c..443e4c3fd357 100644
@@ -25,9 +25,8 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
-/* Referenced read-only by the PMU driver; see drivers/perf/arm-cci.c */
-void __iomem *cci_ctrl_base;
-static unsigned long cci_ctrl_phys;
+static void __iomem *cci_ctrl_base __ro_after_init;
+static unsigned long cci_ctrl_phys __ro_after_init;
 
 #ifdef CONFIG_ARM_CCI400_PORT_CTRL
 struct cci_nb_ports {
@@ -56,6 +55,15 @@ static const struct of_device_id arm_cci_matches[] = {
 	{},
 };
 
+static const struct of_dev_auxdata arm_cci_auxdata[] = {
+	OF_DEV_AUXDATA("arm,cci-400-pmu", 0, NULL, &cci_ctrl_base),
+	OF_DEV_AUXDATA("arm,cci-400-pmu,r0", 0, NULL, &cci_ctrl_base),
+	OF_DEV_AUXDATA("arm,cci-400-pmu,r1", 0, NULL, &cci_ctrl_base),
+	OF_DEV_AUXDATA("arm,cci-500-pmu,r0", 0, NULL, &cci_ctrl_base),
+	OF_DEV_AUXDATA("arm,cci-550-pmu,r0", 0, NULL, &cci_ctrl_base),
+	{}
+};
+
 #define DRIVER_NAME		"ARM-CCI"
 
 static int cci_platform_probe(struct platform_device *pdev)
@@ -63,7 +71,8 @@ static int cci_platform_probe(struct platform_device *pdev)
 	if (!cci_probed())
 		return -ENODEV;
 
-	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	return of_platform_populate(pdev->dev.of_node, NULL,
+				    arm_cci_auxdata, &pdev->dev);
 }
 
 static struct platform_driver cci_platform_driver = {
drivers/perf/arm-cci.c +24 -23

141 lines not on this page · raw message

Signature · 1 line
2.16.1.dirty
#7 lore raw

v2 cover Arm interconnect PMU driver tidyup

In reply to Robin Murphy
Quoted 9 lines · Robin Murphy

Hi arm-soc folks,

PLease consider this series tidying up the Arm interconnect code in drivers/bus to separate the PMU parts out into drivers/perf where Will and Mark can handle future maintenance more easily.

FWIW, the patches are also available on a branch here:

git://linux-arm.org/linux-rm.git perf

This is not a signed tag, so I applied the patches manually to the drivers branch. To add to the bike-shedding, I would have preferred a different approach over the auxdata array, either exporting a function based interface, or calling ioremap() on the physical address multiple times, but each of those has other downsides, so your version seems good enough.

Thanks,

Arnd

#8 lore raw

v2 cover Arm interconnect PMU driver tidyup

Hi Arnd,

Quoted 7 lines · Arnd Bergmann
Quoted 6 lines · Robin Murphy

Hi arm-soc folks,

PLease consider this series tidying up the Arm interconnect code in drivers/bus to separate the PMU parts out into drivers/perf where Will and Mark can handle future maintenance more easily.

Quoted 5 lines
Quoted 3 lines

FWIW, the patches are also available on a branch here:

git://linux-arm.org/linux-rm.git perf

This is not a signed tag, so I applied the patches manually to the drivers

Yes, that was merely a convenience branch for reviewers; I see actual pull requests as being for maintainers, whereas I'm just some oik ;)

Quoted 5 lines

branch. To add to the bike-shedding, I would have preferred a different approach over the auxdata array, either exporting a function based interface, or calling ioremap() on the physical address multiple times, but each of those has other downsides, so your version seems good enough.

Yeah, all of the options were pretty horrible, but this one was about the most concise and didn't need to introduce any new infrastructure. We have this "PMU as a child of some other device" issue coming up on various other IP blocks as well; the resource claiming conflicts seem to get in the way the most.

Thanks for applying!

Robin.