Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <james.morse@arm.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Tested-by: Ben Horgan <ben.horgan@arm.com>
Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Robin Murphy and committed by
Will Deacon
5394396f 15ed3fa2

+31 -39
+31 -39
drivers/perf/arm-cmn.c
··· 2132 2132 static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int idx) 2133 2133 { 2134 2134 struct arm_cmn_dtc *dtc = cmn->dtc + idx; 2135 + const struct resource *cfg; 2136 + resource_size_t base, size; 2135 2137 2136 2138 dtc->pmu_base = dn->pmu_base; 2137 2139 dtc->base = dtc->pmu_base - arm_cmn_pmu_offset(cmn, dn); 2138 2140 dtc->irq = platform_get_irq(to_platform_device(cmn->dev), idx); 2139 2141 if (dtc->irq < 0) 2140 2142 return dtc->irq; 2143 + 2144 + cfg = platform_get_resource(to_platform_device(cmn->dev), IORESOURCE_MEM, 0); 2145 + base = dtc->base - cmn->base + cfg->start; 2146 + size = cmn->part == PART_CMN600 ? SZ_16K : SZ_64K; 2147 + if (!devm_request_mem_region(cmn->dev, base, size, dev_name(cmn->dev))) 2148 + return dev_err_probe(cmn->dev, -EBUSY, 2149 + "Failed to request DTC region 0x%llx\n", base); 2141 2150 2142 2151 writel_relaxed(CMN_DT_DTC_CTL_DT_EN, dtc->base + CMN_DT_DTC_CTL); 2143 2152 writel_relaxed(CMN_DT_PMCR_PMU_EN | CMN_DT_PMCR_OVFL_INTR_EN, CMN_DT_PMCR(dtc)); ··· 2534 2525 return 0; 2535 2526 } 2536 2527 2537 - static int arm_cmn600_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn) 2528 + static int arm_cmn_get_root(struct arm_cmn *cmn, const struct resource *cfg) 2538 2529 { 2539 - struct resource *cfg, *root; 2540 - 2541 - cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2542 - if (!cfg) 2543 - return -EINVAL; 2544 - 2545 - root = platform_get_resource(pdev, IORESOURCE_MEM, 1); 2546 - if (!root) 2547 - return -EINVAL; 2548 - 2549 - if (!resource_contains(cfg, root)) 2550 - swap(cfg, root); 2551 - /* 2552 - * Note that devm_ioremap_resource() is dumb and won't let the platform 2553 - * device claim cfg when the ACPI companion device has already claimed 2554 - * root within it. But since they *are* already both claimed in the 2555 - * appropriate name, we don't really need to do it again here anyway. 2556 - */ 2557 - cmn->base = devm_ioremap(cmn->dev, cfg->start, resource_size(cfg)); 2558 - if (!cmn->base) 2559 - return -ENOMEM; 2560 - 2561 - return root->start - cfg->start; 2562 - } 2563 - 2564 - static int arm_cmn600_of_probe(struct device_node *np) 2565 - { 2530 + const struct device_node *np = cmn->dev->of_node; 2531 + const struct resource *root; 2566 2532 u32 rootnode; 2567 2533 2568 - return of_property_read_u32(np, "arm,root-node", &rootnode) ?: rootnode; 2534 + if (cmn->part != PART_CMN600) 2535 + return 0; 2536 + 2537 + if (np) 2538 + return of_property_read_u32(np, "arm,root-node", &rootnode) ?: rootnode; 2539 + 2540 + root = platform_get_resource(to_platform_device(cmn->dev), IORESOURCE_MEM, 1); 2541 + return root ? root->start - cfg->start : -EINVAL; 2569 2542 } 2570 2543 2571 2544 static int arm_cmn_probe(struct platform_device *pdev) 2572 2545 { 2573 2546 struct arm_cmn *cmn; 2547 + const struct resource *cfg; 2574 2548 const char *name; 2575 2549 static atomic_t id; 2576 2550 int err, rootnode, this_id; ··· 2567 2575 cmn->cpu = cpumask_local_spread(0, dev_to_node(cmn->dev)); 2568 2576 platform_set_drvdata(pdev, cmn); 2569 2577 2570 - if (cmn->part == PART_CMN600 && has_acpi_companion(cmn->dev)) { 2571 - rootnode = arm_cmn600_acpi_probe(pdev, cmn); 2572 - } else { 2573 - rootnode = 0; 2574 - cmn->base = devm_platform_ioremap_resource(pdev, 0); 2575 - if (IS_ERR(cmn->base)) 2576 - return PTR_ERR(cmn->base); 2577 - if (cmn->part == PART_CMN600) 2578 - rootnode = arm_cmn600_of_probe(pdev->dev.of_node); 2579 - } 2578 + cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2579 + if (!cfg) 2580 + return -EINVAL; 2581 + 2582 + /* Map the whole region now, claim the DTCs once we've found them */ 2583 + cmn->base = devm_ioremap(cmn->dev, cfg->start, resource_size(cfg)); 2584 + if (IS_ERR(cmn->base)) 2585 + return PTR_ERR(cmn->base); 2586 + 2587 + rootnode = arm_cmn_get_root(cmn, cfg); 2580 2588 if (rootnode < 0) 2581 2589 return rootnode; 2582 2590