[PATCH v7 8/9] arm64: pmu: Detect and enable multiple PMUs in an ACPI system

Jeremy Linton jeremy.linton at arm.com
Fri Aug 26 15:44:59 PDT 2016


Hi,

On 08/26/2016 10:04 AM, Punit Agrawal wrote:
(trimming)
>> +			pmu = kzalloc(sizeof(struct pmu_types), GFP_KERNEL);
>> +			if (!pmu) {
>> +				pr_warn("Unable to allocate pmu_types\n");
>> +				/*
>> +				 * continue to count cpus for any pmu_types
>> +				 * already allocated, but don't allocate any
>> +				 * more pmu_types. This avoids undercounting.
>> +				 */
>> +				alloc_failure = true;
>
> Why not just fail probe and return an error? What is the benefit of
> having some of the PMUs available?

AFAIC, there isn't a good reason for penalizing PMU's which we can get 
working if a subset of the system PMUs can't be created. But this is per 
PMU type, so with current systems the kzalloc will be called a max of 2 
times (there is the potential of a 3rd time, due to some other error 
handling, but that doesn't change the argument much). AKA, this doesn't 
result in "partial registration" of a PMU.

So, really the only question in my mind is does it work if one of the 
allocations fails and the other succeeds, and the answer is yes, the 
remaining interrupts/etc get associated with the correct PMU, and it 
gets created and should work as well as perf currently works in systems 
with heterogeneous PMUs (cue discussion about CPU process migration).

So, since this is early boot, and we are taking a tiny allocation, if 
this fails i suspect that the machine will probably die anyway, not due 
to the choice of whether the PMU is counted properly or not. I would 
guess the platform allocation or similar will die..

(trimming)

>> +/*
>> + * For the given cpu/pmu type, walk all known GSIs, register them, and add
>> + * them to the resource structure. Return the number of GSI's contained
>> + * in the res structure, and the id of the last CPU/PMU we added.
>> + */
>> +static int __init arm_pmu_acpi_gsi_res(struct pmu_types *pmus,
>> +				       struct resource *res, int *last_cpu_id)
>> +{
>> +	int i, count;
>> +	int irq;
>> +
>> +	/* lets group all the PMU's from similar CPU's together */
>> +	count = 0;
>> +	for_each_possible_cpu(i) {
>> +		struct cpuinfo_arm64 *cinfo = per_cpu_ptr(&cpu_data, i);
>> +
>> +		if (pmus->cpu_type == MIDR_PARTNUM(cinfo->reg_midr)) {
>> +			if (pmu_irqs[i].gsi == 0)
>> +				continue;
>
> Please don't silently continue if the irq is missing. It deserves a user
> visible message. We don't want users complaining about kernel issues
> when the firmware fails to provide the required information.

See below.

>
>> +
>> +			irq = acpi_register_gsi(NULL, pmu_irqs[i].gsi,
>> +						pmu_irqs[i].trigger,
>> +						ACPI_ACTIVE_HIGH);
>
> Check for the return value of acpi_register_gsi as it can return an
> error.

Ok, so this is probably a little subtle, but IIRC from a few months back 
when I was testing this/reworking it, duplicate GSI registrations for 
exclusive PPI's result in errors (see any random discussion about PPI's 
not being ACPI GSI's). As the code to handle SPI vs PPI exists in the 
platform code, I decided to ignore registration errors until such a 
determination can be made. AKA, i'm potentially tossing invalid irq's 
into the irq list for PPIs, but it doesn't matter because they are 
temporary ignored. The core ARM PMU code, has a much better handle on 
what is a correct interrupt binding, so the decision about whether these 
failures need to be worried about are delayed until then. This results 
in a large simplification because we handle the irq deregistration 
necessarily for any further errors together, AKA you will notice a 
complete lack of differing code paths for PPI vs SPI in this module.

As far as gsi=0, in cases where there are placeholder GICC entries in 
the MADT (think disabled CPU) then i've seen gsi=0. I'm not sure that is 
incorrect, so again it gets skipped, the pmu mask doesn't have it 
listed, and everything "works". So if i'm going to add a message here 
i'm, going to wrap it in a reg_midr!=0 check.

>
>> +
>> +			res[count].start = res[count].end = irq;
>> +			res[count].flags = IORESOURCE_IRQ;
>> +
>> +			if (pmu_irqs[i].trigger == ACPI_EDGE_SENSITIVE)
>> +				res[count].flags |= IORESOURCE_IRQ_HIGHEDGE;
>> +			else
>> +				res[count].flags |= IORESOURCE_IRQ_HIGHLEVEL;
>> +
>> +			pmu_irqs[i].registered = true;
>> +			count++;
>> +			(*last_cpu_id) = cinfo->reg_midr;
>
> What is the benefit of using the entire MIDR for cpu_id when the
> grouping is done on the basis of a subset, i.e., part number.

Because the platform code isn't partnum specific, unless the the 
ARMV8_PMU_PART_PROBE() macro is utilized. Delaying any decisions about 
what part of the MIDR happens to be used (if any) to the part probe 
table is probably a good idea. Especially if someone happens to think 
that they want a ARMV8_PMU_PART_REVISION_PROBE() or similar macro..


If anything It might be worth removing the partnum checks in this module 
as well. That way should someone ship a machine with the same CPU only 
differing by revision (or pick your favorite !partnum field) they get 
different PMUs definitions. Why anyone would do that I cannot guess, but 
I do see that apparently the xscale version was important at one point.





More information about the linux-arm-kernel mailing list