Skip to contentSkip to conversation

perf/arm_cspmu: Fixes and cleanups

PATCH Applied Robin Murphy 5 participants 10 messages Jun 5, 2023 – Jul 3, 2023

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

v2 cover perf/arm_cspmu: Fixes and cleanups

v1: https://lore.kernel.org/linux-arm-kernel/[email protected]/

Quick update fixing the issues in patch #4 pointed out by Ilkka.

Thanks,
Robin.

Robin Murphy (4):
perf/arm_cspmu: Fix event attribute type
ACPI/APMT: Don't register invalid resource
perf/arm_cspmu: Clean up ACPI dependency
perf/arm_cspmu: Decouple APMT dependency

 drivers/acpi/arm64/apmt.c          | 10 ++--
 drivers/perf/arm_cspmu/Kconfig     |  3 +-
 drivers/perf/arm_cspmu/arm_cspmu.c | 79 ++++++++++++++----------------
 drivers/perf/arm_cspmu/arm_cspmu.h |  5 +-
 4 files changed, 45 insertions(+), 52 deletions(-)
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
#1 lore raw

PATCH v2 1/4 perf/arm_cspmu: Fix event attribute type

ARM_CSPMU_EVENT_ATTR() defines a struct perf_pmu_events_attr, so arm_cspmu_sysfs_event_show() should not be interpreting it as struct dev_ext_attribute.

Fixes e37dfd65731d ("perf: arm_cspmu: Add support for ARM CoreSight PMU driver")

---

Decided to stick with this rather than change the definition, because I like avoiding casts :)

 drivers/perf/arm_cspmu/arm_cspmu.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +4 -4
index a3f1c410b417..72dc7a9e1ca8 100644
@@ -189,10 +189,10 @@ static inline bool use_64b_counter_reg(const struct arm_cspmu *cspmu)
 ssize_t arm_cspmu_sysfs_event_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct dev_ext_attribute *eattr =
-		container_of(attr, struct dev_ext_attribute, attr);
-	return sysfs_emit(buf, "event=0x%llx\n",
-			  (unsigned long long)eattr->var);
+	struct perf_pmu_events_attr *pmu_attr;
+
+	pmu_attr = container_of(attr, typeof(*pmu_attr), attr);
+	return sysfs_emit(buf, "event=0x%llx\n", pmu_attr->id);
 }
 EXPORT_SYMBOL_GPL(arm_cspmu_sysfs_event_show);
 
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
#2 lore raw

PATCH v2 2/4 ACPI/APMT: Don't register invalid resource

In reply to Robin Murphy

Don't register a resource for the second page unless the dual-page extension flag is actually present to say it's valid.

---
 drivers/acpi/arm64/apmt.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/acpi/arm64/apmt.c +6 -4
index 8cab69fa5d59..aa7d5c3c0dd8 100644
@@ -35,11 +35,13 @@ static int __init apmt_init_resources(struct resource *res,
 
 	num_res++;
 
-	res[num_res].start = node->base_address1;
-	res[num_res].end = node->base_address1 + SZ_4K - 1;
-	res[num_res].flags = IORESOURCE_MEM;
+	if (node->flags & ACPI_APMT_FLAGS_DUAL_PAGE) {
+		res[num_res].start = node->base_address1;
+		res[num_res].end = node->base_address1 + SZ_4K - 1;
+		res[num_res].flags = IORESOURCE_MEM;
 
-	num_res++;
+		num_res++;
+	}
 
 	if (node->ovflw_irq != 0) {
 		trigger = (node->ovflw_irq_flags & ACPI_APMT_OVFLW_IRQ_FLAGS_MODE);
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
maintainer Acked-by on v2 2/4
#3 lore raw

Re: [PATCH v2 2/4] ACPI/APMT: Don't register invalid resource

Quoted 9 lines · Robin Murphy

Don't register a resource for the second page unless the dual-page extension flag is actually present to say it's valid.

Quoted 3 lines
---
 drivers/acpi/arm64/apmt.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

As you mentioned in v1 I don't think we need to backport this since the kernel is working around it (in code you are cleaning up) even though that would not hurt.

Lorenzo

Quoted 25 lines
drivers/acpi/arm64/apmt.c +6 -4
index 8cab69fa5d59..aa7d5c3c0dd8 100644
@@ -35,11 +35,13 @@ static int __init apmt_init_resources(struct resource *res,
 
 	num_res++;
 
-	res[num_res].start = node->base_address1;
-	res[num_res].end = node->base_address1 + SZ_4K - 1;
-	res[num_res].flags = IORESOURCE_MEM;
+	if (node->flags & ACPI_APMT_FLAGS_DUAL_PAGE) {
+		res[num_res].start = node->base_address1;
+		res[num_res].end = node->base_address1 + SZ_4K - 1;
+		res[num_res].flags = IORESOURCE_MEM;
 
-	num_res++;
+		num_res++;
+	}
 
 	if (node->ovflw_irq != 0) {
 		trigger = (node->ovflw_irq_flags & ACPI_APMT_OVFLW_IRQ_FLAGS_MODE);
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
#4 lore raw

PATCH v2 3/4 perf/arm_cspmu: Clean up ACPI dependency

In reply to Robin Murphy

Build-wise, the ACPI dependency consists of only a couple of things which could probably stand being factored out into ACPI helpers anyway. However for the immediate concern of working towards Devicetree support here, it's easy enough to make a few tweaks to contain the affected code locally, such that we can relax the Kconfig dependency.

---
 drivers/perf/arm_cspmu/Kconfig     |  3 +--
 drivers/perf/arm_cspmu/arm_cspmu.c | 17 +++++++++++++++--
 2 files changed, 16 insertions(+), 4 deletions(-)
drivers/perf/arm_cspmu/Kconfig +1 -2
index 0b316fe69a45..25d25ded0983 100644
@@ -4,8 +4,7 @@
 
 config ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU
 	tristate "ARM Coresight Architecture PMU"
-	depends on ARM64 && ACPI
-	depends on ACPI_APMT || COMPILE_TEST
+	depends on ARM64 || COMPILE_TEST
 	help
 	  Provides support for performance monitoring unit (PMU) devices
 	  based on ARM CoreSight PMU architecture. Note that this PMU
drivers/perf/arm_cspmu/arm_cspmu.c +15 -2
index 72dc7a9e1ca8..3b91115c376d 100644
@@ -28,7 +28,6 @@
 #include <linux/module.h>
 #include <linux/perf_event.h>
 #include <linux/platform_device.h>
-#include <acpi/processor.h>
 
 #include "arm_cspmu.h"
 #include "nvidia_cspmu.h"
@@ -1075,6 +1074,9 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu)
 	return 0;
 }
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_ARM64)
+#include <acpi/processor.h>
+
 static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid)
 {
 	u32 acpi_uid;
@@ -1099,7 +1101,7 @@ static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid)
 	return -ENODEV;
 }
 
-static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu)
+static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
 {
 	struct device *dev;
 	struct acpi_apmt_node *apmt_node;
@@ -1135,6 +1137,17 @@ static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu)
 
 	return 0;
 }
+#else
+static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
+{
+	return -ENODEV;
+}
+#endif
+
+static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu)
+{
+	return arm_cspmu_acpi_get_cpus(cspmu);
+}
 
 static int arm_cspmu_register_pmu(struct arm_cspmu *cspmu)
 {
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
#5 lore raw

Re: [PATCH v2 3/4] perf/arm_cspmu: Clean up ACPI dependency

Hi Robin,

Quoted 9 lines · Robin Murphy

Build-wise, the ACPI dependency consists of only a couple of things which could probably stand being factored out into ACPI helpers anyway. However for the immediate concern of working towards Devicetree support here, it's easy enough to make a few tweaks to contain the affected code locally, such that we can relax the Kconfig dependency.

Thanks for your patch, which is now commit f9bd34e3753ea8f1 ("perf/arm_cspmu: Clean up ACPI dependency") upstream.

drivers/perf/arm_cspmu/Kconfig line 7

Quoted 9 lines
drivers/perf/arm_cspmu/Kconfig +1 -2
@@ -4,8 +4,7 @@
 
 config ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU
        tristate "ARM Coresight Architecture PMU"
-       depends on ARM64 && ACPI
-       depends on ACPI_APMT || COMPILE_TEST
+       depends on ARM64 || COMPILE_TEST

From looking at the code, the "arm-cs-arch-pmu" platform device can be instantiated only through ACPI. So I think it is a bit premature to relax the dependency, and expose this question to people configuring an ARM64 kernel without ACPI/APMT support.

Am I missing something?
Thanks!

drivers/perf/arm_cspmu/Kconfig line 10

Quoted 3 lines
drivers/perf/arm_cspmu/Kconfig +0 -0
        help
          Provides support for performance monitoring unit (PMU) devices
          based on ARM CoreSight PMU architecture. Note that this PMU

Gr{oetje,eeting}s,

Geert

Signature · 5 lines
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
#6 lore raw

Re: [PATCH v2 3/4] perf/arm_cspmu: Clean up ACPI dependency

Hi Geert,

Quoted 31 lines · Geert Uytterhoeven

Hi Robin,

Quoted 9 lines · Robin Murphy

Build-wise, the ACPI dependency consists of only a couple of things which could probably stand being factored out into ACPI helpers anyway. However for the immediate concern of working towards Devicetree support here, it's easy enough to make a few tweaks to contain the affected code locally, such that we can relax the Kconfig dependency.

Thanks for your patch, which is now commit f9bd34e3753ea8f1 ("perf/arm_cspmu: Clean up ACPI dependency") upstream.

drivers/perf/arm_cspmu/Kconfig line 7

Quoted 9 lines
drivers/perf/arm_cspmu/Kconfig +1 -2
@@ -4,8 +4,7 @@
 
  config ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU
         tristate "ARM Coresight Architecture PMU"
-       depends on ARM64 && ACPI
-       depends on ACPI_APMT || COMPILE_TEST
+       depends on ARM64 || COMPILE_TEST

From looking at the code, the "arm-cs-arch-pmu" platform device can
be instantiated only through ACPI. So I think it is a bit premature to relax the dependency, and expose this question to people configuring an ARM64 kernel without ACPI/APMT support.

Quoted 1 line

Am I missing something?

As was mentioned in the original cover letter on v1, these patches were actually the bottom half of a branch adding DT support - the DT parts are still untested and not quite complete (there's a property I don't need for the thing I'm looking at, but still deserves to be hooked up in general), but it seemed worth landing these prep patches since they impact what Besar and Ilkka are also working on in parallel.

At this point, the kconfig could indeed be "depends on (ARM64 && ACPI_APMT) || COMPILE_TEST". I can't recall why I didn't change that when splitting these patches out for posting - I may have decided the impact was negligible (i.e. even with DT support, it's still going to be a driver most people won't care about anyway), or the visibility vs. functional dependency aspect may have just slipped my mind entirely. You're welcome to make that change for now if you'd like to.

(I'm not sure how soon I'll be posting the follow-up DT patches, since I'm dependent on other people to provide testing and feedback, and haven't heard any news yet)

Thanks,
Robin.

Quoted 10 lines

Thanks!

drivers/perf/arm_cspmu/Kconfig line 10

Quoted 3 lines
drivers/perf/arm_cspmu/Kconfig +0 -0
         help
           Provides support for performance monitoring unit (PMU) devices
           based on ARM CoreSight PMU architecture. Note that this PMU

Gr{oetje,eeting}s,

Geert

#7 lore raw

PATCH v2 4/4 perf/arm_cspmu: Decouple APMT dependency

In reply to Robin Murphy

The functional paths of the driver need not care about ACPI, so abstract the property of atomic doubleword access as its own flag (repacking the structure for a better fit). We also do not need to go poking directly at the APMT for standard resources which the ACPI layer has already dealt with, so deal with the optional MMIO page and interrupt in the normal firmware-agnostic manner. The few remaining portions of probing that *are* APMT-specific can still easily retrieve the APMT pointer as needed without us having to carry a duplicate copy around everywhere.

---
v2: Fix platdata dereferences, clean up now-unused acpi.h include too.

---
 drivers/perf/arm_cspmu/arm_cspmu.c | 54 ++++++++++--------------------
 drivers/perf/arm_cspmu/arm_cspmu.h |  5 ++-
 2 files changed, 19 insertions(+), 40 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +17 -37
index 3b91115c376d..38e1170af347 100644
@@ -100,10 +100,6 @@
 #define ARM_CSPMU_ACTIVE_CPU_MASK		0x0
 #define ARM_CSPMU_ASSOCIATED_CPU_MASK		0x1
 
-/* Check if field f in flags is set with value v */
-#define CHECK_APMT_FLAG(flags, f, v) \
-	((flags & (ACPI_APMT_FLAGS_ ## f)) == (ACPI_APMT_FLAGS_ ## f ## _ ## v))
-
 /* Check and use default if implementer doesn't provide attribute callback */
 #define CHECK_DEFAULT_IMPL_OPS(ops, callback)			\
 	do {							\
@@ -121,6 +117,11 @@
 
 static unsigned long arm_cspmu_cpuhp_state;
 
+static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev)
+{
+	return *(struct acpi_apmt_node **)dev_get_platdata(dev);
+}
+
 /*
  * In CoreSight PMU architecture, all of the MMIO registers are 32-bit except
  * counter register. The counter register can be implemented as 32-bit or 64-bit
@@ -155,12 +156,6 @@ static u64 read_reg64_hilohi(const void __iomem *addr, u32 max_poll_count)
 	return val;
 }
 
-/* Check if PMU supports 64-bit single copy atomic. */
-static inline bool supports_64bit_atomics(const struct arm_cspmu *cspmu)
-{
-	return CHECK_APMT_FLAG(cspmu->apmt_node->flags, ATOMIC, SUPP);
-}
-
 /* Check if cycle counter is supported. */
 static inline bool supports_cycle_counter(const struct arm_cspmu *cspmu)
 {
@@ -319,7 +314,7 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu)
 	static atomic_t pmu_idx[ACPI_APMT_NODE_TYPE_COUNT] = { 0 };
 
 	dev = cspmu->dev;
-	apmt_node = cspmu->apmt_node;
+	apmt_node = arm_cspmu_apmt_node(dev);
 	pmu_type = apmt_node->type;
 
 	if (pmu_type >= ACPI_APMT_NODE_TYPE_COUNT) {
@@ -396,8 +391,8 @@ static const struct impl_match impl_match[] = {
 static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
 {
 	int ret;
-	struct acpi_apmt_node *apmt_node = cspmu->apmt_node;
 	struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops;
+	struct acpi_apmt_node *apmt_node = arm_cspmu_apmt_node(cspmu->dev);
 	const struct impl_match *match = impl_match;
 
 	/*
@@ -719,7 +714,7 @@ static u64 arm_cspmu_read_counter(struct perf_event *event)
 		offset = counter_offset(sizeof(u64), event->hw.idx);
 		counter_addr = cspmu->base1 + offset;
 
-		return supports_64bit_atomics(cspmu) ?
+		return cspmu->has_atomic_dword ?
 			       readq(counter_addr) :
 			       read_reg64_hilohi(counter_addr, HILOHI_MAX_POLL);
 	}
@@ -910,24 +905,18 @@ static struct arm_cspmu *arm_cspmu_alloc(struct platform_device *pdev)
 {
 	struct acpi_apmt_node *apmt_node;
 	struct arm_cspmu *cspmu;
-	struct device *dev;
-
-	dev = &pdev->dev;
-	apmt_node = *(struct acpi_apmt_node **)dev_get_platdata(dev);
-	if (!apmt_node) {
-		dev_err(dev, "failed to get APMT node\n");
-		return NULL;
-	}
+	struct device *dev = &pdev->dev;
 
 	cspmu = devm_kzalloc(dev, sizeof(*cspmu), GFP_KERNEL);
 	if (!cspmu)
 		return NULL;
 
 	cspmu->dev = dev;
-	cspmu->apmt_node = apmt_node;
-
 	platform_set_drvdata(pdev, cspmu);
 
+	apmt_node = arm_cspmu_apmt_node(dev);
+	cspmu->has_atomic_dword = apmt_node->flags & ACPI_APMT_FLAGS_ATOMIC;
+
 	return cspmu;
 }
 
@@ -935,11 +924,9 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu)
 {
 	struct device *dev;
 	struct platform_device *pdev;
-	struct acpi_apmt_node *apmt_node;
 
 	dev = cspmu->dev;
 	pdev = to_platform_device(dev);
-	apmt_node = cspmu->apmt_node;
 
 	/* Base address for page 0. */
 	cspmu->base0 = devm_platform_ioremap_resource(pdev, 0);
@@ -950,7 +937,7 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu)
 
 	/* Base address for page 1 if supported. Otherwise point to page 0. */
 	cspmu->base1 = cspmu->base0;
-	if (CHECK_APMT_FLAG(apmt_node->flags, DUAL_PAGE, SUPP)) {
+	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
 		cspmu->base1 = devm_platform_ioremap_resource(pdev, 1);
 		if (IS_ERR(cspmu->base1)) {
 			dev_err(dev, "ioremap failed for page-1 resource\n");
@@ -1047,19 +1034,14 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu)
 	int irq, ret;
 	struct device *dev;
 	struct platform_device *pdev;
-	struct acpi_apmt_node *apmt_node;
 
 	dev = cspmu->dev;
 	pdev = to_platform_device(dev);
-	apmt_node = cspmu->apmt_node;
 
 	/* Skip IRQ request if the PMU does not support overflow interrupt. */
-	if (apmt_node->ovflw_irq == 0)
-		return 0;
-
-	irq = platform_get_irq(pdev, 0);
+	irq = platform_get_irq_optional(pdev, 0);
 	if (irq < 0)
-		return irq;
+		return irq == -ENXIO ? 0 : irq;
 
 	ret = devm_request_irq(dev, irq, arm_cspmu_handle_irq,
 			       IRQF_NOBALANCING | IRQF_NO_THREAD, dev_name(dev),
@@ -1103,13 +1085,11 @@ static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid)
 
 static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
 {
-	struct device *dev;
 	struct acpi_apmt_node *apmt_node;
 	int affinity_flag;
 	int cpu;
 
-	dev = cspmu->pmu.dev;
-	apmt_node = cspmu->apmt_node;
+	apmt_node = arm_cspmu_apmt_node(cspmu->dev);
 	affinity_flag = apmt_node->flags & ACPI_APMT_FLAGS_AFFINITY;
 
 	if (affinity_flag == ACPI_APMT_FLAGS_AFFINITY_PROC) {
@@ -1131,7 +1111,7 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
 	}
 
 	if (cpumask_empty(&cspmu->associated_cpus)) {
-		dev_dbg(dev, "No cpu associated with the PMU\n");
+		dev_dbg(cspmu->dev, "No cpu associated with the PMU\n");
 		return -ENODEV;
 	}
 
drivers/perf/arm_cspmu/arm_cspmu.h +2 -3
index 51323b175a4a..83df53d1c132 100644
@@ -8,7 +8,6 @@
 #ifndef __ARM_CSPMU_H__
 #define __ARM_CSPMU_H__
 
-#include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/cpumask.h>
 #include <linux/device.h>
@@ -118,16 +117,16 @@ struct arm_cspmu_impl {
 struct arm_cspmu {
 	struct pmu pmu;
 	struct device *dev;
-	struct acpi_apmt_node *apmt_node;
 	const char *name;
 	const char *identifier;
 	void __iomem *base0;
 	void __iomem *base1;
-	int irq;
 	cpumask_t associated_cpus;
 	cpumask_t active_cpu;
 	struct hlist_node cpuhp_node;
+	int irq;
 
+	bool has_atomic_dword;
 	u32 pmcfgr;
 	u32 num_logical_ctrs;
 	u32 num_set_clr_reg;
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
#8 lore raw

Re: [PATCH v2 4/4] perf/arm_cspmu: Decouple APMT dependency

Quoted 11 lines · Robin Murphy

The functional paths of the driver need not care about ACPI, so abstract the property of atomic doubleword access as its own flag (repacking the structure for a better fit). We also do not need to go poking directly at the APMT for standard resources which the ACPI layer has already dealt with, so deal with the optional MMIO page and interrupt in the normal firmware-agnostic manner. The few remaining portions of probing that *are* APMT-specific can still easily retrieve the APMT pointer as needed without us having to carry a duplicate copy around everywhere.

Cheers, Ilkka

Quoted 207 lines

---
v2: Fix platdata dereferences, clean up now-unused acpi.h include too.
---
drivers/perf/arm_cspmu/arm_cspmu.c | 54 ++++++++++-------------------- drivers/perf/arm_cspmu/arm_cspmu.h | 5 ++-

2 files changed, 19 insertions(+), 40 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +17 -37
index 3b91115c376d..38e1170af347 100644
@@ -100,10 +100,6 @@
 #define ARM_CSPMU_ACTIVE_CPU_MASK		0x0
 #define ARM_CSPMU_ASSOCIATED_CPU_MASK		0x1
 
-/* Check if field f in flags is set with value v */
-#define CHECK_APMT_FLAG(flags, f, v) \
-	((flags & (ACPI_APMT_FLAGS_ ## f)) == (ACPI_APMT_FLAGS_ ## f ## _ ## v))
-
 /* Check and use default if implementer doesn't provide attribute callback */
 #define CHECK_DEFAULT_IMPL_OPS(ops, callback)			\
 	do {							\
@@ -121,6 +117,11 @@
 
 static unsigned long arm_cspmu_cpuhp_state;
 
+static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev)
+{
+	return *(struct acpi_apmt_node **)dev_get_platdata(dev);
+}
+
 /*
 * In CoreSight PMU architecture, all of the MMIO registers are 32-bit except
 * counter register. The counter register can be implemented as 32-bit or 64-bit
@@ -155,12 +156,6 @@ static u64 read_reg64_hilohi(const void __iomem *addr, u32 max_poll_count)
 	return val;
 }
 
-/* Check if PMU supports 64-bit single copy atomic. */
-static inline bool supports_64bit_atomics(const struct arm_cspmu *cspmu)
-{
-	return CHECK_APMT_FLAG(cspmu->apmt_node->flags, ATOMIC, SUPP);
-}
-
 /* Check if cycle counter is supported. */
 static inline bool supports_cycle_counter(const struct arm_cspmu *cspmu)
 {
@@ -319,7 +314,7 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu)
 	static atomic_t pmu_idx[ACPI_APMT_NODE_TYPE_COUNT] = { 0 };
 
 	dev = cspmu->dev;
-	apmt_node = cspmu->apmt_node;
+	apmt_node = arm_cspmu_apmt_node(dev);
 	pmu_type = apmt_node->type;
 
 	if (pmu_type >= ACPI_APMT_NODE_TYPE_COUNT) {
@@ -396,8 +391,8 @@ static const struct impl_match impl_match[] = {
 static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
 {
 	int ret;
-	struct acpi_apmt_node *apmt_node = cspmu->apmt_node;
 	struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops;
+	struct acpi_apmt_node *apmt_node = arm_cspmu_apmt_node(cspmu->dev);
 	const struct impl_match *match = impl_match;
 
 	/*
@@ -719,7 +714,7 @@ static u64 arm_cspmu_read_counter(struct perf_event *event)
 		offset = counter_offset(sizeof(u64), event->hw.idx);
 		counter_addr = cspmu->base1 + offset;
 
-		return supports_64bit_atomics(cspmu) ?
+		return cspmu->has_atomic_dword ?
 			       readq(counter_addr) :
 			       read_reg64_hilohi(counter_addr, HILOHI_MAX_POLL);
 	}
@@ -910,24 +905,18 @@ static struct arm_cspmu *arm_cspmu_alloc(struct platform_device *pdev)
 {
 	struct acpi_apmt_node *apmt_node;
 	struct arm_cspmu *cspmu;
-	struct device *dev;
-
-	dev = &pdev->dev;
-	apmt_node = *(struct acpi_apmt_node **)dev_get_platdata(dev);
-	if (!apmt_node) {
-		dev_err(dev, "failed to get APMT node\n");
-		return NULL;
-	}
+	struct device *dev = &pdev->dev;
 
 	cspmu = devm_kzalloc(dev, sizeof(*cspmu), GFP_KERNEL);
 	if (!cspmu)
 		return NULL;
 
 	cspmu->dev = dev;
-	cspmu->apmt_node = apmt_node;
-
 	platform_set_drvdata(pdev, cspmu);
 
+	apmt_node = arm_cspmu_apmt_node(dev);
+	cspmu->has_atomic_dword = apmt_node->flags & ACPI_APMT_FLAGS_ATOMIC;
+
 	return cspmu;
 }
 
@@ -935,11 +924,9 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu)
 {
 	struct device *dev;
 	struct platform_device *pdev;
-	struct acpi_apmt_node *apmt_node;
 
 	dev = cspmu->dev;
 	pdev = to_platform_device(dev);
-	apmt_node = cspmu->apmt_node;
 
 	/* Base address for page 0. */
 	cspmu->base0 = devm_platform_ioremap_resource(pdev, 0);
@@ -950,7 +937,7 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu)
 
 	/* Base address for page 1 if supported. Otherwise point to page 0. */
 	cspmu->base1 = cspmu->base0;
-	if (CHECK_APMT_FLAG(apmt_node->flags, DUAL_PAGE, SUPP)) {
+	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
 		cspmu->base1 = devm_platform_ioremap_resource(pdev, 1);
 		if (IS_ERR(cspmu->base1)) {
 			dev_err(dev, "ioremap failed for page-1 resource\n");
@@ -1047,19 +1034,14 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu)
 	int irq, ret;
 	struct device *dev;
 	struct platform_device *pdev;
-	struct acpi_apmt_node *apmt_node;
 
 	dev = cspmu->dev;
 	pdev = to_platform_device(dev);
-	apmt_node = cspmu->apmt_node;
 
 	/* Skip IRQ request if the PMU does not support overflow interrupt. */
-	if (apmt_node->ovflw_irq == 0)
-		return 0;
-
-	irq = platform_get_irq(pdev, 0);
+	irq = platform_get_irq_optional(pdev, 0);
 	if (irq < 0)
-		return irq;
+		return irq == -ENXIO ? 0 : irq;
 
 	ret = devm_request_irq(dev, irq, arm_cspmu_handle_irq,
 			       IRQF_NOBALANCING | IRQF_NO_THREAD, dev_name(dev),
@@ -1103,13 +1085,11 @@ static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid)
 
 static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
 {
-	struct device *dev;
 	struct acpi_apmt_node *apmt_node;
 	int affinity_flag;
 	int cpu;
 
-	dev = cspmu->pmu.dev;
-	apmt_node = cspmu->apmt_node;
+	apmt_node = arm_cspmu_apmt_node(cspmu->dev);
 	affinity_flag = apmt_node->flags & ACPI_APMT_FLAGS_AFFINITY;
 
 	if (affinity_flag == ACPI_APMT_FLAGS_AFFINITY_PROC) {
@@ -1131,7 +1111,7 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
 	}
 
 	if (cpumask_empty(&cspmu->associated_cpus)) {
-		dev_dbg(dev, "No cpu associated with the PMU\n");
+		dev_dbg(cspmu->dev, "No cpu associated with the PMU\n");
 		return -ENODEV;
 	}
 
drivers/perf/arm_cspmu/arm_cspmu.h +2 -3
index 51323b175a4a..83df53d1c132 100644
@@ -8,7 +8,6 @@
 #ifndef __ARM_CSPMU_H__
 #define __ARM_CSPMU_H__
 
-#include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/cpumask.h>
 #include <linux/device.h>
@@ -118,16 +117,16 @@ struct arm_cspmu_impl {
 struct arm_cspmu {
 	struct pmu pmu;
 	struct device *dev;
-	struct acpi_apmt_node *apmt_node;
 	const char *name;
 	const char *identifier;
 	void __iomem *base0;
 	void __iomem *base1;
-	int irq;
 	cpumask_t associated_cpus;
 	cpumask_t active_cpu;
 	struct hlist_node cpuhp_node;
+	int irq;
 
+	bool has_atomic_dword;
 	u32 pmcfgr;
 	u32 num_logical_ctrs;
 	u32 num_set_clr_reg;
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
maintainer Applied
#9 lore raw
In reply to Robin Murphy
Quoted 8 lines · Robin Murphy

v1: https://lore.kernel.org/linux-arm-kernel/[email protected]/

Quick update fixing the issues in patch #4 pointed out by Ilkka.

Thanks,
Robin.

[...]

Applied to will (for-next/perf), thanks!

[1/4] perf/arm_cspmu: Fix event attribute type

      https://git.kernel.org/will/c/71e0cb32d5fc
[2/4] ACPI/APMT: Don't register invalid resource
      https://git.kernel.org/will/c/87b3b6d53efc
[3/4] perf/arm_cspmu: Clean up ACPI dependency
      https://git.kernel.org/will/c/f9bd34e3753e
[4/4] perf/arm_cspmu: Decouple APMT dependency
      https://git.kernel.org/will/c/d2e3bb512818

Cheers,

Signature · 10 lines
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev

_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel