All of lore.kernel.org
 help / color / mirror / Atom feed
From: will.deacon@arm.com (Will Deacon)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 9/9] ARM: perf: move irq registration into pmu implementation
Date: Fri, 10 Aug 2012 18:36:35 +0100	[thread overview]
Message-ID: <1344620195-22372-10-git-send-email-will.deacon@arm.com> (raw)
In-Reply-To: <1344620195-22372-1-git-send-email-will.deacon@arm.com>

From: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>

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>
---
 arch/arm/include/asm/pmu.h       |    2 +
 arch/arm/kernel/perf_event.c     |   72 ++++++-------------------------------
 arch/arm/kernel/perf_event_cpu.c |   66 ++++++++++++++++++++++++++++++++++-
 3 files changed, 79 insertions(+), 61 deletions(-)

diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index a993ad6..a26170d 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -78,6 +78,8 @@ struct arm_pmu {
 	void		(*start)(void);
 	void		(*stop)(void);
 	void		(*reset)(void *);
+	int		(*request_irq)(irq_handler_t handler);
+	void		(*free_irq)(void);
 	int		(*map_event)(struct perf_event *event);
 	int		num_events;
 	atomic_t	active_events;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 86fd399..93971b1 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;
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 56ddc98..8d7d8d4 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -70,6 +70,67 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 	return &__get_cpu_var(cpu_hw_events);
 }
 
+static void cpu_pmu_free_irq(void)
+{
+	int i, irq, irqs;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+	for (i = 0; i < irqs; ++i) {
+		if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
+			continue;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq >= 0)
+			free_irq(irq, cpu_pmu);
+	}
+}
+
+static int cpu_pmu_request_irq(irq_handler_t handler)
+{
+	int i, err, irq, irqs;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+
+	if (!pmu_device)
+		return -ENODEV;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+	if (irqs < 1) {
+		pr_err("no irqs for PMUs defined\n");
+		return -ENODEV;
+	}
+
+	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, handler, IRQF_NOBALANCING, "arm-pmu",
+				  cpu_pmu);
+		if (err) {
+			pr_err("unable to request IRQ%d for ARM PMU counters\n",
+				irq);
+			return err;
+		}
+
+		cpumask_set_cpu(i, &cpu_pmu->active_irqs);
+	}
+
+	return 0;
+}
+
 static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	int cpu;
@@ -79,7 +140,10 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 		events->used_mask = per_cpu(used_mask, cpu);
 		raw_spin_lock_init(&events->pmu_lock);
 	}
-	cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events;
+
+	cpu_pmu->get_hw_events	= cpu_pmu_get_cpu_events;
+	cpu_pmu->request_irq	= cpu_pmu_request_irq;
+	cpu_pmu->free_irq	= cpu_pmu_free_irq;
 
 	/* Ensure the PMU has sane values out of reset. */
 	if (cpu_pmu && cpu_pmu->reset)
-- 
1.7.4.1

  parent reply	other threads:[~2012-08-10 17:36 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-10 17:36 [PATCH 0/9] ARM perf updates for 3.7 Will Deacon
2012-08-10 17:36 ` [PATCH 1/9] ARM: PMU: Add runtime PM Support Will Deacon
2012-08-11 15:09   ` Ming Lei
2012-08-13 10:40     ` Will Deacon
2012-08-16 13:56       ` Jon Hunter
2012-08-10 17:36 ` [PATCH 2/9] ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs Will Deacon
2012-08-10 18:42   ` Rob Herring
2012-08-10 17:36 ` [PATCH 3/9] ARM: pmu: remove unused reservation mechanism Will Deacon
2012-08-10 17:36 ` [PATCH 4/9] ARM: pmu: remove arm_pmu_type enumeration Will Deacon
2012-08-13 14:17   ` Linus Walleij
2012-08-13 21:57   ` Jiandong Zheng
2012-08-14  8:43     ` Sudeep KarkadaNagesha
2012-08-14 16:53       ` Jiandong Zheng
2012-08-16 13:59   ` Jon Hunter
2012-08-17 14:08   ` Jon Hunter
2012-08-20  9:01     ` Will Deacon
2012-08-20 13:05       ` Jon Hunter
2012-08-23  5:45   ` Kukjin Kim
2012-08-10 17:36 ` [PATCH 5/9] ARM: perf: remove mysterious compiler barrier Will Deacon
2012-08-10 17:36 ` [PATCH 6/9] ARM: perf: probe devicetree in preference to current CPU Will Deacon
2012-08-10 17:36 ` [PATCH 7/9] ARM: perf: prepare for moving CPU PMU code into separate file Will Deacon
2012-08-10 17:36 ` [PATCH 8/9] ARM: perf: move CPU-specific PMU handling " Will Deacon
2012-08-10 17:36 ` Will Deacon [this message]
2012-08-13  9:11 ` [PATCH 0/9] ARM perf updates for 3.7 Hui Wang
2012-08-13  9:32   ` Will Deacon
2012-08-14  1:46     ` Hui Wang
2013-02-28  6:54       ` i.MX6Quad PMU irq handling (was: Re: [PATCH 0/9] ARM perf updates for 3.7) Dirk Behme
2013-02-28  7:27         ` Shawn Guo
2013-02-28  7:38         ` i.MX6Quad PMU irq handling Hui Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1344620195-22372-10-git-send-email-will.deacon@arm.com \
    --to=will.deacon@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.