Skip to contentSkip to conversation

perf/arm_cspmu: Miscellaneous improvements

PATCH Superseded Robin Murphy 3 participants 13 messages Jul 9 – Jul 13

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover perf/arm_cspmu: Miscellaneous improvements

Hi all,

These are a few quality-of-life improvements for CoreSight PMU that I've accumulated based on things which have come up in practical usage. There's no real dependency between any of the individual patches, it just felt right to send them as a series.

Thanks,
Robin.

Robin Murphy (4):
ACPI/APMT: Use stable device ID perf/arm_cspmu: Improve APMT-based PMU naming perf/arm_cspmu: Improve sub-module error reporting perf/arm_cspmu: Make IRQ more optional

 drivers/acpi/arm64/apmt.c          |  2 +-
 drivers/perf/arm_cspmu/arm_cspmu.c | 49 ++++++++++++++++++------------
 2 files changed, 31 insertions(+), 20 deletions(-)
Signature · 1 line
2.54.0.dirty
#1 lore raw

PATCH 1/4 ACPI/APMT: Use stable device ID

The APMT node format includes a unique identifier, so we can use this as the platform device ID to give userspace stable and identifiable device names, rather than auto numbering dependent on how the table is parsed.

Cc Lorenzo Pieralisi <[email protected]>
Cc Hanjun Guo <[email protected]>
Cc Sudeep Holla <[email protected]>
---
 drivers/acpi/arm64/apmt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/arm64/apmt.c +1 -1
index bb010f6164e5..ba48fcb26d52 100644
@@ -79,7 +79,7 @@ static int __init apmt_add_platform_device(struct acpi_apmt_node *node,
 	int ret, count;
 	struct resource res[DEV_MAX_RESOURCE_COUNT];
 
-	pdev = platform_device_alloc(DEV_NAME, PLATFORM_DEVID_AUTO);
+	pdev = platform_device_alloc(DEV_NAME, node->id);
 	if (!pdev)
 		return -ENOMEM;
 
Signature · 1 line
2.54.0.dirty
#2 lore raw

Re: [PATCH 1/4] ACPI/APMT: Use stable device ID

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Unvalidated u32 ACPI node ID is passed to a signed int parameter, causing unintended collisions with platform bus sentinel values and negative sysfs device names.
- [Medium] Lack of collision handling for firmware-supplied IDs causes complete APMT initialization failure on duplicate IDs.

Pre-existing issues:
- [High] Failure to cleanly unregister resources and platform devices on error paths leaks IRQ mappings and creates dangling pointers to unmapped ACPI tables (Use-After-Free).
- [High] Missing structural bounds checking on APMT node length allows infinite loops or out-of-bounds reads.
--

--- Patch [1]: [PATCH 1/4] ACPI/APMT: Use stable device ID --- commit 5ad772664b7900cfeb996b91d7d0c6ff27d931d6
Author: Robin Murphy <[email protected]>

ACPI/APMT: Use stable device ID

The APMT node format includes a unique identifier, so we can use this as the platform device ID to give userspace stable and identifiable device names, rather than auto numbering dependent on how the table is parsed.

drivers/acpi/arm64/apmt.c static int __init apmt_add_platform_device(struct acpi_apmt_node *node, · line 82

Quoted 8 lines
drivers/acpi/arm64/apmt.c +1 -1
@@ -79,7 +79,7 @@ static int __init apmt_add_platform_device(struct acpi_apmt_node *node,
 	int ret, count;
 	struct resource res[DEV_MAX_RESOURCE_COUNT];
 
-	pdev = platform_device_alloc(DEV_NAME, PLATFORM_DEVID_AUTO);
+	pdev = platform_device_alloc(DEV_NAME, node->id);

[Severity: High]
Because node->id is a u32 and platform_device_alloc() takes a signed int for the id parameter, could this cause unintended collisions?

If the firmware provides a large ID like 0xFFFFFFFE, this would be cast to -2 (PLATFORM_DEVID_AUTO), which seems to defeat the goal of using stable identifiers by falling back to auto-numbering.

Similarly, a value of 0xFFFFFFFF would become -1 (PLATFORM_DEVID_NONE), causing the ID to be omitted from the device name entirely, and other large values would result in negative sysfs device names.

[Severity: Medium]
By relying on the firmware for the ID rather than auto-numbering, is it possible for duplicate IDs to cause initialization failures?

If firmware provides two APMT nodes with the same id, platform_device_add() will return -EEXIST. When this propagates up to apmt_init_platform_devices():

apmt_init_platform_devices() {
    ...
    ret = apmt_add_platform_device(apmt_node, fwnode);
    if (ret) {
        acpi_free_fwnode_static(fwnode);
        return ret;
    }
    ...
}

Will this abort the entire APMT initialization and prevent all subsequent PMUs from being registered?

[Severity: High]
This is a pre-existing issue, but this patch might make it more reachable if duplicate firmware IDs trigger the error path.

If apmt_add_platform_device() fails, the loop in apmt_init_platform_devices() returns an error without unregistering the platform devices that were already successfully added during previous iterations.

When this error propagates to acpi_apmt_init(), it unmaps the table:

acpi_apmt_init() {
    ...
    ret = apmt_init_platform_devices();
    if (ret) {
        pr_err("Failed to initialize APMT platform devices...\n");
        acpi_put_table(apmt_table);
    }
}

Since the registered platform devices hold a pointer to the ACPI node in their platform_data, will unmapping the table leave them with dangling pointers that could cause a use-after-free when the arm_cspmu driver probes?

Additionally, the error path inside apmt_add_platform_device() does not appear to call acpi_unregister_gsi() to clean up the IRQ mapped by apmt_init_resources(), which might leak the GSI mapping.

[Severity: High]
This is another pre-existing issue, but looking at the table parsing loop in apmt_init_platform_devices():

apmt_init_platform_devices() {
    ...
    offset += apmt_node->length;
    ...
}

Does the loop inherently trust apmt_node->length without validating it against the structural bounds? If firmware provides a node with a length of 0, could this result in an infinite loop during early boot?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
#3 lore raw

Re: [PATCH 1/4] ACPI/APMT: Use stable device ID

In reply to Robin Murphy
Quoted 17 lines · Robin Murphy

The APMT node format includes a unique identifier, so we can use this as the platform device ID to give userspace stable and identifiable device names, rather than auto numbering dependent on how the table is parsed.

Cc Lorenzo Pieralisi <[email protected]>
Cc Hanjun Guo <[email protected]>
Cc Sudeep Holla <[email protected]>
---
  drivers/acpi/arm64/apmt.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/arm64/apmt.c +0 -0
index bb010f6164e5..ba48fcb26d52 100644

drivers/acpi/arm64/apmt.c static int __init apmt_add_platform_device(struct acpi_apmt_node *node, · line 82

Quoted 5 lines
drivers/acpi/arm64/apmt.c +1 -1
@@ -79,7 +79,7 @@ static int __init apmt_add_platform_device(struct acpi_apmt_node *node,
  	int ret, count;
  	struct resource res[DEV_MAX_RESOURCE_COUNT];
 
-	pdev = platform_device_alloc(DEV_NAME, PLATFORM_DEVID_AUTO);
+	pdev = platform_device_alloc(DEV_NAME, node->id);

Per the Sashiko comment, while I really wouldn't expect it to be an issue in practice, I guess we could explicitly check and truncate node->id to INT_MAX (probably with some degree of warning) here just in case.

Cheers,
Robin.

Quoted 3 lines
drivers/acpi/arm64/apmt.c +0 -0
  	if (!pdev)
  		return -ENOMEM;
 
Reviewed-by
#4 lore raw

Re: [PATCH 1/4] ACPI/APMT: Use stable device ID

Quoted 4 lines · Robin Murphy
Quoted 3 lines · Robin Murphy

The APMT node format includes a unique identifier, so we can use this as the platform device ID to give userspace stable and identifiable device names, rather than auto numbering dependent on how the table is parsed.

That's a good idea.

Quoted 9 lines
Quoted 9 lines
Cc Lorenzo Pieralisi <[email protected]>
Cc Hanjun Guo <[email protected]>
Cc Sudeep Holla <[email protected]>
---
  drivers/acpi/arm64/apmt.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
Quoted 12 lines

drivers/acpi/arm64/apmt.c static int __init apmt_add_platform_device(struct · line 83

Quoted 10 lines
drivers/acpi/arm64/apmt.c +1 -0
index bb010f6164e5..ba48fcb26d52 100644
@@ -79,7 +79,7 @@ static int __init apmt_add_platform_device(struct 
 acpi_apmt_node *node,
  	int ret, count;
  	struct resource res[DEV_MAX_RESOURCE_COUNT];
  -	pdev = platform_device_alloc(DEV_NAME, PLATFORM_DEVID_AUTO);
+	pdev = platform_device_alloc(DEV_NAME, node->id);

Per the Sashiko comment, while I really wouldn't expect it to be an issue in practice, I guess we could explicitly check and truncate node->id to INT_MAX (probably with some degree of warning) here just in case.

Yeah, it probably and hopefully won't happen but it makes sense to have a warning message regardless. With it

Cheers, Ilkka

Quoted 9 lines

Cheers,
Robin.

Quoted 3 lines
drivers/acpi/arm64/apmt.c +0 -0
  	if (!pdev)
  		return -ENOMEM;
#5 lore raw

PATCH 2/4 perf/arm_cspmu: Improve APMT-based PMU naming

In reply to Robin Murphy

On ACPI systems, it has not actually been possible for userspace to reliably tell which PMU corresponds to which APMT entry for types other than "ACPI device" - the evidence trail only leads from the arbitrarily-numbered PMU device to its arbitrarily-numbered parent platform device that has no distinguishing features either.

While we've now improved the platform device creation to associate the actual APMT unique ID, we may as well also tweak the PMU devices to substitute the arbitrary number with a different arbitrary number that might be more directly meaningful based on the APMT definitions.

We don't have an equivalent for Devicetree, but in that case the platform devices are at least identifiable via their sysfs-visible of_node.

---
 drivers/perf/arm_cspmu/arm_cspmu.c | 36 +++++++++++++++++-------------
 1 file changed, 21 insertions(+), 15 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +21 -15
index 80fb314d5135..0570be74d11f 100644
@@ -250,38 +250,44 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu)
 	struct device *dev;
 	struct acpi_apmt_node *apmt_node;
 	u8 pmu_type;
-	char *name;
 	char acpi_hid_string[ACPI_ID_LEN] = { 0 };
-	static atomic_t pmu_idx[ACPI_APMT_NODE_TYPE_COUNT] = { 0 };
+	static atomic_t pmu_idx;
+	u32 id;
 
 	dev = cspmu->dev;
 	apmt_node = arm_cspmu_apmt_node(dev);
 	if (!apmt_node)
 		return devm_kasprintf(dev, GFP_KERNEL, PMUNAME "_%u",
-				      atomic_fetch_inc(&pmu_idx[0]));
+				      atomic_fetch_inc(&pmu_idx));
 
 	pmu_type = apmt_node->type;
-
-	if (pmu_type >= ACPI_APMT_NODE_TYPE_COUNT) {
+	switch (pmu_type) {
+	default:
 		dev_err(dev, "unsupported PMU type-%u\n", pmu_type);
 		return NULL;
-	}
-
-	if (pmu_type == ACPI_APMT_NODE_TYPE_ACPI) {
+	case ACPI_APMT_NODE_TYPE_ACPI:
 		memcpy(acpi_hid_string,
 			&apmt_node->inst_primary,
 			sizeof(apmt_node->inst_primary));
-		name = devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%s_%u", PMUNAME,
+		return devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%s_%u", PMUNAME,
 				      arm_cspmu_type_str[pmu_type],
 				      acpi_hid_string,
 				      apmt_node->inst_secondary);
-	} else {
-		name = devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%d", PMUNAME,
-				      arm_cspmu_type_str[pmu_type],
-				      atomic_fetch_inc(&pmu_idx[pmu_type]));
-	}
+	case ACPI_APMT_NODE_TYPE_MC:
+		id = apmt_node->id;
+		break;
+	case ACPI_APMT_NODE_TYPE_SMMU:
+	case ACPI_APMT_NODE_TYPE_PCIE_ROOT:
+		id = apmt_node->inst_primary;
+		break;
+	case ACPI_APMT_NODE_TYPE_CACHE:
+		id = apmt_node->inst_secondary;
+		break;
+	};
 
-	return name;
+	return devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%u", PMUNAME,
+			      arm_cspmu_type_str[pmu_type],
+			      apmt_node->id);
 }
 
 static ssize_t arm_cspmu_cpumask_show(struct device *dev,
Signature · 1 line
2.54.0.dirty
#6 lore raw

Re: [PATCH 2/4] perf/arm_cspmu: Improve APMT-based PMU naming

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] The computed PMU identifier `id` is ignored during string formatting, resulting in incorrect PMU…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The computed PMU identifier id is ignored during string formatting, resulting in incorrect PMU names. Furthermore, apmt_node->inst_primary (u64) is truncated when assigned to id (u32). --

--- Patch [2]: [PATCH 2/4] perf/arm_cspmu: Improve APMT-based PMU naming --- commit a5bff38f664770528aefdc9e26aafbe6dc541317
Author: Robin Murphy <[email protected]>

perf/arm_cspmu: Improve APMT-based PMU naming

This commit attempts to improve APMT-based PMU naming on ACPI systems. It modifies arm_cspmu_get_name() to substitute arbitrary numbers with more meaningful identifiers based on APMT definitions by using a switch statement over the PMU type.

Quoted 5 lines
drivers/perf/arm_cspmu/arm_cspmu.c +0 -0
index e6292021f653e..b6565eda8e521 100644
@@ -250,38 +250,44 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu)

[ ... ]

drivers/perf/arm_cspmu/arm_cspmu.c static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu) · line 281

Quoted 6 lines
drivers/perf/arm_cspmu/arm_cspmu.c +6 -0
+	case ACPI_APMT_NODE_TYPE_MC:
+		id = apmt_node->id;
+		break;
+	case ACPI_APMT_NODE_TYPE_SMMU:
+	case ACPI_APMT_NODE_TYPE_PCIE_ROOT:
+		id = apmt_node->inst_primary;

[Severity: High]
Does this assignment truncate the 64-bit inst_primary value?

Looking at struct acpi_apmt_node, inst_primary is a u64, but the id variable is defined as a u32. This might cause sysfs name collisions if the upper 32 bits are non-zero.

drivers/perf/arm_cspmu/arm_cspmu.c static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu) · line 290

Quoted 10 lines
drivers/perf/arm_cspmu/arm_cspmu.c +8 -1
+		break;
+	case ACPI_APMT_NODE_TYPE_CACHE:
+		id = apmt_node->inst_secondary;
+		break;
+	};
 
-	return name;
+	return devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%u", PMUNAME,
+			      arm_cspmu_type_str[pmu_type],
+			      apmt_node->id);

[Severity: High]
Is it intentional to use apmt_node->id here instead of the local variable id we just computed in the switch statement above?

Since the computed id is ignored, multiple PMUs of the same type sharing the same apmt_node->id might result in identical names being generated. Will this cause sysfs name collisions and driver registration failures?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#7 lore raw

Re: [PATCH 2/4] perf/arm_cspmu: Improve APMT-based PMU naming

In reply to Robin Murphy
Quoted 71 lines · Robin Murphy

On ACPI systems, it has not actually been possible for userspace to reliably tell which PMU corresponds to which APMT entry for types other than "ACPI device" - the evidence trail only leads from the arbitrarily-numbered PMU device to its arbitrarily-numbered parent platform device that has no distinguishing features either.

While we've now improved the platform device creation to associate the actual APMT unique ID, we may as well also tweak the PMU devices to substitute the arbitrary number with a different arbitrary number that might be more directly meaningful based on the APMT definitions.

We don't have an equivalent for Devicetree, but in that case the platform devices are at least identifiable via their sysfs-visible of_node.

---
  drivers/perf/arm_cspmu/arm_cspmu.c | 36 +++++++++++++++++-------------
  1 file changed, 21 insertions(+), 15 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +13 -14
index 80fb314d5135..0570be74d11f 100644
@@ -250,38 +250,44 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu)
  	struct device *dev;
  	struct acpi_apmt_node *apmt_node;
  	u8 pmu_type;
-	char *name;
  	char acpi_hid_string[ACPI_ID_LEN] = { 0 };
-	static atomic_t pmu_idx[ACPI_APMT_NODE_TYPE_COUNT] = { 0 };
+	static atomic_t pmu_idx;
+	u32 id;
 
  	dev = cspmu->dev;
  	apmt_node = arm_cspmu_apmt_node(dev);
  	if (!apmt_node)
  		return devm_kasprintf(dev, GFP_KERNEL, PMUNAME "_%u",
-				      atomic_fetch_inc(&pmu_idx[0]));
+				      atomic_fetch_inc(&pmu_idx));
 
  	pmu_type = apmt_node->type;
-
-	if (pmu_type >= ACPI_APMT_NODE_TYPE_COUNT) {
+	switch (pmu_type) {
+	default:
  		dev_err(dev, "unsupported PMU type-%u\n", pmu_type);
  		return NULL;
-	}
-
-	if (pmu_type == ACPI_APMT_NODE_TYPE_ACPI) {
+	case ACPI_APMT_NODE_TYPE_ACPI:
  		memcpy(acpi_hid_string,
  			&apmt_node->inst_primary,
  			sizeof(apmt_node->inst_primary));
-		name = devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%s_%u", PMUNAME,
+		return devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%s_%u", PMUNAME,
  				      arm_cspmu_type_str[pmu_type],
  				      acpi_hid_string,
  				      apmt_node->inst_secondary);
-	} else {
-		name = devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%d", PMUNAME,
-				      arm_cspmu_type_str[pmu_type],
-				      atomic_fetch_inc(&pmu_idx[pmu_type]));
-	}
+	case ACPI_APMT_NODE_TYPE_MC:
+		id = apmt_node->id;
+		break;
+	case ACPI_APMT_NODE_TYPE_SMMU:
+	case ACPI_APMT_NODE_TYPE_PCIE_ROOT:
+		id = apmt_node->inst_primary;

drivers/perf/arm_cspmu/arm_cspmu.c static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu) · line 290

Quoted 10 lines
drivers/perf/arm_cspmu/arm_cspmu.c +8 -1
+		break;
+	case ACPI_APMT_NODE_TYPE_CACHE:
+		id = apmt_node->inst_secondary;
+		break;
+	};
 
-	return name;
+	return devm_kasprintf(dev, GFP_KERNEL, "%s_%s_%u", PMUNAME,
+			      arm_cspmu_type_str[pmu_type],
+			      apmt_node->id);

Seems I did forget this when I realised the instance fields could be useful and added the local "id" variable. The rest of the Sashiko noise is mostly nonsense.

Cheers,
Robin.

Quoted 3 lines
drivers/perf/arm_cspmu/arm_cspmu.c +0 -0
  }
 
  static ssize_t arm_cspmu_cpumask_show(struct device *dev,
#8 lore raw

PATCH 3/4 perf/arm_cspmu: Improve sub-module error reporting

In reply to Robin Murphy

When waiting for a sub-module to register, we return a bare -EPROBE_DEFER that ends up showing the end user:

platform arm-cs-arch-pmu.1: deferred probe pending (no reason)

wherein it's not necessarily clear that they might need to take some action to ensure the appropriate module is available to load. Let's use dev_err_probe() here so we can show exactly what we're waiting for.

Similarly, in the case where something's gone horribly wrong with an already-registered module, we can use dev_WARN() to standardise the device/driver attribution rather than just open-coding "arm_cspmu".

---
 drivers/perf/arm_cspmu/arm_cspmu.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +4 -2
index 0570be74d11f..0b26a1588eba 100644
@@ -438,13 +438,15 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
 				if (ret)
 					module_put(match->module);
 			} else {
-				WARN(1, "arm_cspmu failed to get module: %s\n",
+				dev_WARN(cspmu->dev, "Failed to get module: %s\n",
 					match->module_name);
 				ret = -EINVAL;
 			}
 		} else {
 			request_module_nowait(match->module_name);
-			ret = -EPROBE_DEFER;
+			ret = dev_err_probe(cspmu->dev, -EPROBE_DEFER,
+					    "Waiting for module %s to load\n",
+					    match->module_name);
 		}
 
 		mutex_unlock(&arm_cspmu_lock);
Signature · 1 line
2.54.0.dirty
Reviewed-by on v1 3/4
#9 lore raw

Re: [PATCH 3/4] perf/arm_cspmu: Improve sub-module error reporting

Quoted 9 lines · Robin Murphy

When waiting for a sub-module to register, we return a bare -EPROBE_DEFER that ends up showing the end user:

platform arm-cs-arch-pmu.1: deferred probe pending (no reason)

wherein it's not necessarily clear that they might need to take some action to ensure the appropriate module is available to load. Let's use dev_err_probe() here so we can show exactly what we're waiting for.

Quoted 5 lines

Similarly, in the case where something's gone horribly wrong with an already-registered module, we can use dev_WARN() to standardise the device/driver attribution rather than just open-coding "arm_cspmu".

Looks good to me,

Cheers, Ilkka

Quoted 30 lines

---
drivers/perf/arm_cspmu/arm_cspmu.c | 6 ++++--

1 file changed, 4 insertions(+), 2 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +4 -2
index 0570be74d11f..0b26a1588eba 100644
@@ -438,13 +438,15 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
 				if (ret)
 					module_put(match->module);
 			} else {
-				WARN(1, "arm_cspmu failed to get module: %s\n",
+				dev_WARN(cspmu->dev, "Failed to get module: %s\n",
 					match->module_name);
 				ret = -EINVAL;
 			}
 		} else {
 			request_module_nowait(match->module_name);
-			ret = -EPROBE_DEFER;
+			ret = dev_err_probe(cspmu->dev, -EPROBE_DEFER,
+					    "Waiting for module %s to load\n",
+					    match->module_name);
 		}
 
 		mutex_unlock(&arm_cspmu_lock);
Signature · 1 line
2.54.0.dirty
#10 lore raw

PATCH 4/4 perf/arm_cspmu: Make IRQ more optional

In reply to Robin Murphy

If we have 64-bit counters, we can reasonably assume we'll never have to handle an overflow before the end of the universe (since we're a system PMU with no sampling). Thus even if firmware does specify an IRQ, we can still continue in the event of being unable to request it. This can help systems where IRQs cannot be claimed exclusively, or are broken in other ways.

---
 drivers/perf/arm_cspmu/arm_cspmu.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +5 -2
index 0b26a1588eba..4ba47bccc99c 100644
@@ -1257,8 +1257,11 @@ static int arm_cspmu_device_probe(struct platform_device *pdev)
 		return ret;
 
 	ret = arm_cspmu_request_irq(cspmu);
-	if (ret)
-		return ret;
+	if (ret) {
+		if (counter_size(cspmu) < 64)
+			return ret;
+		dev_info(cspmu->dev, "Continuing without IRQ\n");
+	}
 
 	ret = arm_cspmu_get_cpus(cspmu);
 	if (ret)
Signature · 1 line
2.54.0.dirty
#11 lore raw

Re: [PATCH 4/4] perf/arm_cspmu: Make IRQ more optional

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] The driver improperly ignores `-EPROBE_DEFER` errors when requesting the IRQ for devices with…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The driver improperly ignores -EPROBE_DEFER errors when requesting the IRQ for devices with 64-bit counters, breaking the deferred probe mechanism and leading to non-deterministic boot behavior. --

--- Patch [4]: [PATCH 4/4] perf/arm_cspmu: Make IRQ more optional --- commit 9b3f415215659b0aa95020707b757a52d3157692
Author: Robin Murphy <[email protected]>

perf/arm_cspmu: Make IRQ more optional

If we have 64-bit counters, we can reasonably assume we'll never have to handle an overflow before the end of the universe (since we're a system PMU with no sampling). Thus even if firmware does specify an IRQ, we can still continue in the event of being unable to request it. This can help systems where IRQs cannot be claimed exclusively, or are broken in other ways.

Quoted 5 lines
drivers/perf/arm_cspmu/arm_cspmu.c +0 -0
index 1015d86957724..3e32342a609e4 100644

drivers/perf/arm_cspmu/arm_cspmu.c static int arm_cspmu_device_probe(struct platform_device *pdev) · line 1264

Quoted 10 lines
drivers/perf/arm_cspmu/arm_cspmu.c +5 -2
@@ -1257,8 +1257,11 @@ static int arm_cspmu_device_probe(struct platform_device *pdev)
 		return ret;
 
 	ret = arm_cspmu_request_irq(cspmu);
-	if (ret)
-		return ret;
+	if (ret) {
+		if (counter_size(cspmu) < 64)
+			return ret;
+		dev_info(cspmu->dev, "Continuing without IRQ\n");
+	}

[Severity: Medium]
Will this improperly ignore -EPROBE_DEFER if the interrupt controller is not yet probed?

If arm_cspmu_request_irq() returns -EPROBE_DEFER from platform_get_irq_optional():

drivers/perf/arm_cspmu/arm_cspmu.c:arm_cspmu_request_irq() {
    ...
	irq = platform_get_irq_optional(pdev, 0);
	if (irq < 0)
		return irq == -ENXIO ? 0 : irq;
    ...
}

and counter_size(cspmu) >= 64, it looks like this code will mask the error and continue without an IRQ, rather than deferring the probe. This could lead to non-deterministic boot behavior depending on probe timing.

Could we explicitly check for and propagate -EPROBE_DEFER here?

Quoted 3 lines
drivers/perf/arm_cspmu/arm_cspmu.c +0 -0
 	ret = arm_cspmu_get_cpus(cspmu);
 	if (ret)
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Reviewed-by on v1 4/4
#12 lore raw

Re: [PATCH 4/4] perf/arm_cspmu: Make IRQ more optional

In reply to Robin Murphy
Quoted 8 lines · Robin Murphy

If we have 64-bit counters, we can reasonably assume we'll never have to handle an overflow before the end of the universe (since we're a system PMU with no sampling). Thus even if firmware does specify an IRQ, we can still continue in the event of being unable to request it. This can help systems where IRQs cannot be claimed exclusively, or are broken in other ways.

Looks good to me,

Cheers, Ilkka

Quoted 26 lines

---
drivers/perf/arm_cspmu/arm_cspmu.c | 7 +++++--

1 file changed, 5 insertions(+), 2 deletions(-)
drivers/perf/arm_cspmu/arm_cspmu.c +5 -2
index 0b26a1588eba..4ba47bccc99c 100644
@@ -1257,8 +1257,11 @@ static int arm_cspmu_device_probe(struct platform_device *pdev)
 		return ret;
 
 	ret = arm_cspmu_request_irq(cspmu);
-	if (ret)
-		return ret;
+	if (ret) {
+		if (counter_size(cspmu) < 64)
+			return ret;
+		dev_info(cspmu->dev, "Continuing without IRQ\n");
+	}
 
 	ret = arm_cspmu_get_cpus(cspmu);
 	if (ret)
Signature · 1 line
2.54.0.dirty