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

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>

authored by

Anshuman Khandual and committed by
Will Deacon
81e5ee47 d11a6987

+64 -40
+64 -40
drivers/perf/arm_pmu_acpi.c
··· 69 69 acpi_unregister_gsi(gsi); 70 70 } 71 71 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 + 72 128 #if IS_ENABLED(CONFIG_ARM_SPE_PMU) 73 129 static struct resource spe_resources[] = { 74 130 { ··· 140 84 .num_resources = ARRAY_SIZE(spe_resources) 141 85 }; 142 86 87 + static u16 arm_spe_parse_gsi(struct acpi_madt_generic_interrupt *gicc) 88 + { 89 + return gicc->spe_interrupt; 90 + } 91 + 143 92 /* 144 93 * For lack of a better place, hook the normal PMU MADT walk 145 94 * and create a SPE device if we detect a recent MADT with ··· 152 91 */ 153 92 static void arm_spe_acpi_register_device(void) 154 93 { 155 - int cpu, hetid, irq, ret; 156 - bool first = true; 157 - u16 gsi = 0; 158 - 159 - /* 160 - * Sanity check all the GICC tables for the same interrupt number. 161 - * For now, we only support homogeneous ACPI/SPE machines. 162 - */ 163 - for_each_possible_cpu(cpu) { 164 - struct acpi_madt_generic_interrupt *gicc; 165 - 166 - gicc = acpi_cpu_get_madt_gicc(cpu); 167 - if (gicc->header.length < ACPI_MADT_GICC_SPE) 168 - return; 169 - 170 - if (first) { 171 - gsi = gicc->spe_interrupt; 172 - if (!gsi) 173 - return; 174 - hetid = find_acpi_cpu_topology_hetero_id(cpu); 175 - first = false; 176 - } else if ((gsi != gicc->spe_interrupt) || 177 - (hetid != find_acpi_cpu_topology_hetero_id(cpu))) { 178 - pr_warn("ACPI: SPE must be homogeneous\n"); 179 - return; 180 - } 181 - } 182 - 183 - irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, 184 - ACPI_ACTIVE_HIGH); 185 - if (irq < 0) { 186 - pr_warn("ACPI: SPE Unable to register interrupt: %d\n", gsi); 187 - return; 188 - } 189 - 190 - spe_resources[0].start = irq; 191 - ret = platform_device_register(&spe_dev); 192 - if (ret < 0) { 94 + int ret = arm_acpi_register_pmu_device(&spe_dev, ACPI_MADT_GICC_SPE, 95 + arm_spe_parse_gsi); 96 + if (ret) 193 97 pr_warn("ACPI: SPE: Unable to register device\n"); 194 - acpi_unregister_gsi(gsi); 195 - } 196 98 } 197 99 #else 198 100 static inline void arm_spe_acpi_register_device(void)