Skip to content

Commit 81e5ee4

Browse files
Anshuman Khandualwilldeacon
authored andcommitted
arm_pmu: acpi: Refactor arm_spe_acpi_register_device()
Sanity checking all the GICC tables for same interrupt number, and ensuring a homogeneous ACPI based machine, could be used for other platform devices as well. Hence this refactors arm_spe_acpi_register_device() into a common helper arm_acpi_register_pmu_device(). Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Co-developed-by: Will Deacon <will@kernel.org> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> Link: https://lore.kernel.org/r/20230817055405.249630-2-anshuman.khandual@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent d11a698 commit 81e5ee4

File tree

1 file changed

+64
-40
lines changed

1 file changed

+64
-40
lines changed

drivers/perf/arm_pmu_acpi.c

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,62 @@ static void arm_pmu_acpi_unregister_irq(int cpu)
6969
acpi_unregister_gsi(gsi);
7070
}
7171

72+
static int __maybe_unused
73+
arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len,
74+
u16 (*parse_gsi)(struct acpi_madt_generic_interrupt *))
75+
{
76+
int cpu, this_hetid, hetid, irq, ret;
77+
u16 this_gsi = 0, gsi = 0;
78+
79+
/*
80+
* Ensure that platform device must have IORESOURCE_IRQ
81+
* resource to hold gsi interrupt.
82+
*/
83+
if (pdev->num_resources != 1)
84+
return -ENXIO;
85+
86+
if (pdev->resource[0].flags != IORESOURCE_IRQ)
87+
return -ENXIO;
88+
89+
/*
90+
* Sanity check all the GICC tables for the same interrupt
91+
* number. For now, only support homogeneous ACPI machines.
92+
*/
93+
for_each_possible_cpu(cpu) {
94+
struct acpi_madt_generic_interrupt *gicc;
95+
96+
gicc = acpi_cpu_get_madt_gicc(cpu);
97+
if (gicc->header.length < len)
98+
return gsi ? -ENXIO : 0;
99+
100+
this_gsi = parse_gsi(gicc);
101+
this_hetid = find_acpi_cpu_topology_hetero_id(cpu);
102+
if (!gsi) {
103+
hetid = this_hetid;
104+
gsi = this_gsi;
105+
} else if (hetid != this_hetid || gsi != this_gsi) {
106+
pr_warn("ACPI: %s: must be homogeneous\n", pdev->name);
107+
return -ENXIO;
108+
}
109+
}
110+
111+
if (!this_gsi)
112+
return 0;
113+
114+
irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH);
115+
if (irq < 0) {
116+
pr_warn("ACPI: %s Unable to register interrupt: %d\n", pdev->name, gsi);
117+
return -ENXIO;
118+
}
119+
120+
pdev->resource[0].start = irq;
121+
ret = platform_device_register(pdev);
122+
if (ret)
123+
acpi_unregister_gsi(gsi);
124+
125+
return ret;
126+
}
127+
72128
#if IS_ENABLED(CONFIG_ARM_SPE_PMU)
73129
static struct resource spe_resources[] = {
74130
{
@@ -84,54 +140,22 @@ static struct platform_device spe_dev = {
84140
.num_resources = ARRAY_SIZE(spe_resources)
85141
};
86142

143+
static u16 arm_spe_parse_gsi(struct acpi_madt_generic_interrupt *gicc)
144+
{
145+
return gicc->spe_interrupt;
146+
}
147+
87148
/*
88149
* For lack of a better place, hook the normal PMU MADT walk
89150
* and create a SPE device if we detect a recent MADT with
90151
* a homogeneous PPI mapping.
91152
*/
92153
static void arm_spe_acpi_register_device(void)
93154
{
94-
int cpu, hetid, irq, ret;
95-
bool first = true;
96-
u16 gsi = 0;
97-
98-
/*
99-
* Sanity check all the GICC tables for the same interrupt number.
100-
* For now, we only support homogeneous ACPI/SPE machines.
101-
*/
102-
for_each_possible_cpu(cpu) {
103-
struct acpi_madt_generic_interrupt *gicc;
104-
105-
gicc = acpi_cpu_get_madt_gicc(cpu);
106-
if (gicc->header.length < ACPI_MADT_GICC_SPE)
107-
return;
108-
109-
if (first) {
110-
gsi = gicc->spe_interrupt;
111-
if (!gsi)
112-
return;
113-
hetid = find_acpi_cpu_topology_hetero_id(cpu);
114-
first = false;
115-
} else if ((gsi != gicc->spe_interrupt) ||
116-
(hetid != find_acpi_cpu_topology_hetero_id(cpu))) {
117-
pr_warn("ACPI: SPE must be homogeneous\n");
118-
return;
119-
}
120-
}
121-
122-
irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE,
123-
ACPI_ACTIVE_HIGH);
124-
if (irq < 0) {
125-
pr_warn("ACPI: SPE Unable to register interrupt: %d\n", gsi);
126-
return;
127-
}
128-
129-
spe_resources[0].start = irq;
130-
ret = platform_device_register(&spe_dev);
131-
if (ret < 0) {
155+
int ret = arm_acpi_register_pmu_device(&spe_dev, ACPI_MADT_GICC_SPE,
156+
arm_spe_parse_gsi);
157+
if (ret)
132158
pr_warn("ACPI: SPE: Unable to register device\n");
133-
acpi_unregister_gsi(gsi);
134-
}
135159
}
136160
#else
137161
static inline void arm_spe_acpi_register_device(void)

0 commit comments

Comments
 (0)