linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paul Burton <paul.burton@imgtec.com>
To: Thomas Gleixner <tglx@linutronix.de>, Ralf Baechle <ralf@linux-mips.org>
Cc: <dianders@chromium.org>, James Hogan <james.hogan@imgtec.com>,
	Brian Norris <briannorris@chromium.org>,
	Jason Cooper <jason@lakedaemon.net>, <jeffy.chen@rock-chips.com>,
	Marc Zyngier <marc.zyngier@arm.com>,
	<linux-kernel@vger.kernel.org>, <linux-mips@linux-mips.org>,
	<tfiga@chromium.org>, Paul Burton <paul.burton@imgtec.com>
Subject: [RFC PATCH v1 2/9] genirq: Support shared per_cpu_devid interrupts
Date: Thu, 7 Sep 2017 16:25:35 -0700	[thread overview]
Message-ID: <20170907232542.20589-3-paul.burton@imgtec.com> (raw)
In-Reply-To: <20170907232542.20589-1-paul.burton@imgtec.com>

Up until now per_cpu_devid interrupts have not supported sharing. On
MIPS we have some percpu interrupts which are shared in many systems -
a single CPU interrupt line may be used to indicate a timer interrupt,
performance counter interrupt or fast debug channel interrupt. We have
up until now supported this with a series of hacks, wherein drivers call
each other's interrupt handlers & our MIPS GIC irqchip driver includes a
hack which configures the interrupt(s) for all CPUs. In order to allow
this mess to be cleaned up, this patch introduces support for shared
per_cpu_devid interrupts.

The major portion of this is supporting per_cpu_devid interrupts in
__handle_irq_event_percpu() and then making use of this, via
handle_irq_event_percpu(), from handler_percpu_devif_irq() to invoke the
handler for all actions associated with the shared interrupt. This does
have a few side effects worth noting:

 - per_cpu_devid interrupts will now add to the entropy pool via
   add_interrupt_randomness(), where they previously did not.

 - per_cpu_devid interrupts will record timings when IRQS_TIMINGS is
   set, via record_irq_time(), where they previously did not.

 - per_cpu_devid interrupts will handle an IRQ_WAKE_THREAD return from
   their handlers to wake a thread, where they previously did not.

I'm not aware of any reason the above should be bad side effects, so
sharing __handle_irq_event_percpu() for per_cpu_devid interrupts seems
like a positive.

The other area that requires work for shared per_cpu_devid interrupts is
__free_percpu_irq() which is adjusted to support removing the correct
struct irqaction from the list pointed to by the action field of struct
irqdesc, where it previously presumed only one action is present. The
new behaviour mirrors that of __free_irq().

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
---

 kernel/irq/chip.c   |  8 ++------
 kernel/irq/handle.c |  8 +++++++-
 kernel/irq/manage.c | 28 +++++++++++++++++++++-------
 3 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index f51b7b6d2451..063a125059b5 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -859,7 +859,6 @@ void handle_percpu_irq(struct irq_desc *desc)
 void handle_percpu_devid_irq(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct irqaction *action = desc->action;
 	unsigned int irq = irq_desc_get_irq(desc);
 	irqreturn_t res;
 
@@ -868,11 +867,8 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
 	if (chip->irq_ack)
 		chip->irq_ack(&desc->irq_data);
 
-	if (likely(action)) {
-		trace_irq_handler_entry(irq, action);
-		res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
-		trace_irq_handler_exit(irq, action, res);
-	} else {
+	res = handle_irq_event_percpu(desc);
+	if (unlikely(res == IRQ_NONE)) {
 		unsigned int cpu = smp_processor_id();
 		bool enabled = cpumask_test_cpu(cpu, desc->percpu_enabled);
 
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 79f987b942b8..f0309679f2c8 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -142,9 +142,15 @@ irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags
 
 	for_each_action_of_desc(desc, action) {
 		irqreturn_t res;
+		void *dev_id;
+
+		if (irq_settings_is_per_cpu_devid(desc))
+			dev_id = raw_cpu_ptr(action->percpu_dev_id);
+		else
+			dev_id = action->dev_id;
 
 		trace_irq_handler_entry(irq, action);
-		res = action->handler(irq, action->dev_id);
+		res = action->handler(irq, dev_id);
 		trace_irq_handler_exit(irq, action, res);
 
 		if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pF enabled interrupts\n",
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index fb5445a4a359..6b8a34971a0f 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1929,7 +1929,7 @@ EXPORT_SYMBOL_GPL(disable_percpu_irq);
 static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
-	struct irqaction *action;
+	struct irqaction *action, **action_ptr;
 	unsigned long flags;
 
 	WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
@@ -1939,20 +1939,34 @@ static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
 
-	action = desc->action;
-	if (!action || action->percpu_dev_id != dev_id) {
-		WARN(1, "Trying to free already-free IRQ %d\n", irq);
-		goto bad;
+	/*
+	 * There can be multiple actions per IRQ descriptor, find the right
+	 * one based on the dev_id:
+	 */
+	action_ptr = &desc->action;
+	for (;;) {
+		action = *action_ptr;
+
+		if (!action) {
+			WARN(1, "Trying to free already-free IRQ %d\n", irq);
+			goto bad;
+		}
+
+		if (action->percpu_dev_id == dev_id)
+			break;
+		action_ptr = &action->next;
 	}
 
-	if (!cpumask_empty(desc->percpu_enabled)) {
+	if ((action_ptr == &desc->action) &&
+	    !action->next &&
+	    !cpumask_empty(desc->percpu_enabled)) {
 		WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",
 		     irq, cpumask_first(desc->percpu_enabled));
 		goto bad;
 	}
 
 	/* Found it - now remove it from the list of entries: */
-	desc->action = NULL;
+	*action_ptr = action->next;
 
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 
-- 
2.14.1

  parent reply	other threads:[~2017-09-07 23:26 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-31  9:58 [patch 0/2] genirq: Handle NOAUTOEN interrupts correctly Thomas Gleixner
2017-05-31  9:58 ` [patch 1/2] genirq: Handle NOAUTOEN interrupt setup proper Thomas Gleixner
2017-05-31 13:54   ` Marc Zyngier
2017-05-31 15:18     ` Thomas Gleixner
2017-06-04 12:47   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-05-31  9:58 ` [patch 2/2] genirq: Warn when IRQ_NOAUTOEN is used with shared interrupts Thomas Gleixner
2017-06-04 12:48   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-09-06  6:00   ` [2/2] " Paul Burton
2017-09-06  8:16     ` Thomas Gleixner
2017-09-06 14:01       ` Paul Burton
2017-09-06 14:14         ` Thomas Gleixner
2017-09-07  1:18           ` Paul Burton
2017-09-07 23:25             ` [RFC PATCH v1 0/9] Support shared percpu interrupts; clean up MIPS hacks Paul Burton
2017-09-07 23:25               ` [RFC PATCH v1 1/9] genirq: Allow shared interrupt users to opt into IRQ_NOAUTOEN Paul Burton
2017-09-07 23:25               ` Paul Burton [this message]
2017-09-25 21:06                 ` [RFC PATCH v1 2/9] genirq: Support shared per_cpu_devid interrupts Thomas Gleixner
2017-09-26 12:00                   ` Thomas Gleixner
2017-10-19 14:08                     ` Thomas Gleixner
2017-09-07 23:25               ` [RFC PATCH v1 3/9] genirq: Introduce irq_is_percpu_devid() Paul Burton
2017-09-07 23:25               ` [RFC PATCH v1 4/9] MIPS: Remove perf_irq interrupt sharing fallback Paul Burton
2017-09-07 23:25               ` [RFC PATCH v1 5/9] MIPS: Remove perf_irq Paul Burton
2017-09-07 23:25               ` [RFC PATCH v1 6/9] MIPS: perf: percpu_devid interrupt support Paul Burton
2017-10-19 14:12                 ` Thomas Gleixner
2017-09-07 23:25               ` [RFC PATCH v1 7/9] MIPS: cevt-r4k: " Paul Burton
2017-09-07 23:25               ` [RFC PATCH v1 8/9] irqchip: mips-cpu: Set timer, FDC & perf interrupts percpu_devid Paul Burton
2017-09-07 23:25               ` [RFC PATCH v1 9/9] irqchip: mips-gic: Remove gic_all_vpes_local_irq_controller Paul Burton

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=20170907232542.20589-3-paul.burton@imgtec.com \
    --to=paul.burton@imgtec.com \
    --cc=briannorris@chromium.org \
    --cc=dianders@chromium.org \
    --cc=james.hogan@imgtec.com \
    --cc=jason@lakedaemon.net \
    --cc=jeffy.chen@rock-chips.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    --cc=marc.zyngier@arm.com \
    --cc=ralf@linux-mips.org \
    --cc=tfiga@chromium.org \
    --cc=tglx@linutronix.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).