diff options
| author | Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com> | 2012-07-31 10:34:25 +0100 | 
|---|---|---|
| committer | Will Deacon <will.deacon@arm.com> | 2012-08-23 11:35:52 +0100 | 
| commit | 051f1b13144dd8553d5a5104dde94c7263ae3ba7 (patch) | |
| tree | b9f10b81ace1d986a01c28afddec1f2cc8028e66 /arch/arm/kernel/perf_event.c | |
| parent | 5505b206ca006d0506d1d3b3c494aa86234f66e2 (diff) | |
| download | olio-linux-3.10-051f1b13144dd8553d5a5104dde94c7263ae3ba7.tar.xz olio-linux-3.10-051f1b13144dd8553d5a5104dde94c7263ae3ba7.zip  | |
ARM: perf: move irq registration into pmu implementation
This patch moves the CPU-specific IRQ registration and parsing code into
the CPU PMU backend. This is required because a PMU may have more than
one interrupt, which in turn can be either PPI (per-cpu) or SPI
(requiring strict affinity setting at the interrupt distributor).
Signed-off-by: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
[will: cosmetic edits and reworked interrupt dispatching]
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/perf_event.c')
| -rw-r--r-- | arch/arm/kernel/perf_event.c | 72 | 
1 files changed, 12 insertions, 60 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 86fd3993717..93971b1a4f0 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -297,87 +297,39 @@ validate_group(struct perf_event *event)  	return 0;  } -static irqreturn_t armpmu_platform_irq(int irq, void *dev) +static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)  {  	struct arm_pmu *armpmu = (struct arm_pmu *) dev;  	struct platform_device *plat_device = armpmu->plat_device;  	struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev); -	return plat->handle_irq(irq, dev, armpmu->handle_irq); +	if (plat && plat->handle_irq) +		return plat->handle_irq(irq, dev, armpmu->handle_irq); +	else +		return armpmu->handle_irq(irq, dev);  }  static void  armpmu_release_hardware(struct arm_pmu *armpmu)  { -	int i, irq, irqs; -	struct platform_device *pmu_device = armpmu->plat_device; - -	irqs = min(pmu_device->num_resources, num_possible_cpus()); - -	for (i = 0; i < irqs; ++i) { -		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) -			continue; -		irq = platform_get_irq(pmu_device, i); -		if (irq >= 0) -			free_irq(irq, armpmu); -	} - -	pm_runtime_put_sync(&pmu_device->dev); +	armpmu->free_irq(); +	pm_runtime_put_sync(&armpmu->plat_device->dev);  }  static int  armpmu_reserve_hardware(struct arm_pmu *armpmu)  { -	struct arm_pmu_platdata *plat; -	irq_handler_t handle_irq; -	int i, err, irq, irqs; +	int err;  	struct platform_device *pmu_device = armpmu->plat_device;  	if (!pmu_device)  		return -ENODEV; -	plat = dev_get_platdata(&pmu_device->dev); -	if (plat && plat->handle_irq) -		handle_irq = armpmu_platform_irq; -	else -		handle_irq = armpmu->handle_irq; - -	irqs = min(pmu_device->num_resources, num_possible_cpus()); -	if (irqs < 1) { -		pr_err("no irqs for PMUs defined\n"); -		return -ENODEV; -	} -  	pm_runtime_get_sync(&pmu_device->dev); - -	for (i = 0; i < irqs; ++i) { -		err = 0; -		irq = platform_get_irq(pmu_device, i); -		if (irq < 0) -			continue; - -		/* -		 * If we have a single PMU interrupt that we can't shift, -		 * assume that we're running on a uniprocessor machine and -		 * continue. Otherwise, continue without this interrupt. -		 */ -		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { -			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", -				    irq, i); -			continue; -		} - -		err = request_irq(irq, handle_irq, -				  IRQF_DISABLED | IRQF_NOBALANCING, -				  "arm-pmu", armpmu); -		if (err) { -			pr_err("unable to request IRQ%d for ARM PMU counters\n", -				irq); -			armpmu_release_hardware(armpmu); -			return err; -		} - -		cpumask_set_cpu(i, &armpmu->active_irqs); +	err = armpmu->request_irq(armpmu_dispatch_irq); +	if (err) { +		armpmu_release_hardware(armpmu); +		return err;  	}  	return 0;  |