From: Robin Murphy Date: Thu, 19 Feb 2026 17:27:53 +0000 (+0000) Subject: perf/arm-cmn: Stop claiming entire iomem region X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5394396ff5488f007248727988b722c5d4f0638b;p=thirdparty%2Fkernel%2Flinux.git perf/arm-cmn: Stop claiming entire iomem region So far, the PMU has been the only thing of interest in the vast mass of CMN registers, so we've gotten away with simply claiming the entire iomem region. However, now that we can support other features like MPAM controllers for the system caches, the PMU driver needs to stop being selfish and learn to share. Similarly to arm-ni, requesting just the DTC node(s) should suffice for staking our exclusive claim to the PMU features, as requesting hundreds of tiny regions for all the individual pmu_event_sel registers is definitely not worth the considerable bother. As a consequence, we can also streamline the annoying CMN-600 special cases even more. The ACPI binding has in fact always specified a strict order for all resources, so we can reasonably drop the ancient pretence of swapping base and cfg, which IIRC was more just a moment of doubt on my part than anything else. Cc: James Morse Signed-off-by: Robin Murphy Tested-by: Ben Horgan Reviewed-by: Ilkka Koskinen Signed-off-by: Will Deacon --- diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 40c05c519a1d9..1ac91cda67801 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -2132,6 +2132,8 @@ static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp, i static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int idx) { struct arm_cmn_dtc *dtc = cmn->dtc + idx; + const struct resource *cfg; + resource_size_t base, size; dtc->pmu_base = dn->pmu_base; dtc->base = dtc->pmu_base - arm_cmn_pmu_offset(cmn, dn); @@ -2139,6 +2141,13 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id if (dtc->irq < 0) return dtc->irq; + cfg = platform_get_resource(to_platform_device(cmn->dev), IORESOURCE_MEM, 0); + base = dtc->base - cmn->base + cfg->start; + size = cmn->part == PART_CMN600 ? SZ_16K : SZ_64K; + if (!devm_request_mem_region(cmn->dev, base, size, dev_name(cmn->dev))) + return dev_err_probe(cmn->dev, -EBUSY, + "Failed to request DTC region 0x%llx\n", base); + writel_relaxed(CMN_DT_DTC_CTL_DT_EN, dtc->base + CMN_DT_DTC_CTL); writel_relaxed(CMN_DT_PMCR_PMU_EN | CMN_DT_PMCR_OVFL_INTR_EN, CMN_DT_PMCR(dtc)); writeq_relaxed(0, CMN_DT_PMCCNTR(dtc)); @@ -2525,43 +2534,26 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) return 0; } -static int arm_cmn600_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn) +static int arm_cmn_get_root(struct arm_cmn *cmn, const struct resource *cfg) { - struct resource *cfg, *root; - - cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!cfg) - return -EINVAL; - - root = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!root) - return -EINVAL; - - if (!resource_contains(cfg, root)) - swap(cfg, root); - /* - * Note that devm_ioremap_resource() is dumb and won't let the platform - * device claim cfg when the ACPI companion device has already claimed - * root within it. But since they *are* already both claimed in the - * appropriate name, we don't really need to do it again here anyway. - */ - cmn->base = devm_ioremap(cmn->dev, cfg->start, resource_size(cfg)); - if (!cmn->base) - return -ENOMEM; + const struct device_node *np = cmn->dev->of_node; + const struct resource *root; + u32 rootnode; - return root->start - cfg->start; -} + if (cmn->part != PART_CMN600) + return 0; -static int arm_cmn600_of_probe(struct device_node *np) -{ - u32 rootnode; + if (np) + return of_property_read_u32(np, "arm,root-node", &rootnode) ?: rootnode; - return of_property_read_u32(np, "arm,root-node", &rootnode) ?: rootnode; + root = platform_get_resource(to_platform_device(cmn->dev), IORESOURCE_MEM, 1); + return root ? root->start - cfg->start : -EINVAL; } static int arm_cmn_probe(struct platform_device *pdev) { struct arm_cmn *cmn; + const struct resource *cfg; const char *name; static atomic_t id; int err, rootnode, this_id; @@ -2575,16 +2567,16 @@ static int arm_cmn_probe(struct platform_device *pdev) cmn->cpu = cpumask_local_spread(0, dev_to_node(cmn->dev)); platform_set_drvdata(pdev, cmn); - if (cmn->part == PART_CMN600 && has_acpi_companion(cmn->dev)) { - rootnode = arm_cmn600_acpi_probe(pdev, cmn); - } else { - rootnode = 0; - cmn->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(cmn->base)) - return PTR_ERR(cmn->base); - if (cmn->part == PART_CMN600) - rootnode = arm_cmn600_of_probe(pdev->dev.of_node); - } + cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!cfg) + return -EINVAL; + + /* Map the whole region now, claim the DTCs once we've found them */ + cmn->base = devm_ioremap(cmn->dev, cfg->start, resource_size(cfg)); + if (IS_ERR(cmn->base)) + return PTR_ERR(cmn->base); + + rootnode = arm_cmn_get_root(cmn, cfg); if (rootnode < 0) return rootnode;