All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] rt/threadirqs: put the irq thread handler in a callback
Date: Fri, 13 Feb 2009 04:38:57 +0100	[thread overview]
Message-ID: <4994f034.02e2660a.3130.23df@mx.google.com> (raw)

Currently, when a hardirq is threaded, it is processed by do_hardirq()
which guess the best low-level handler for this irq.

This makes several branch conditions to check for each irq triggered,
adding some (very small) latencies since we are in a fastpath (irq disabled)
of the irq processing.

So it's better to put these checks only once when the handler of the irq is set
and then only dereference one pointer to find the appropriate callback.

This patch makes the irq thread handler a field in struct irq_desc.

[Note, I'm not sure the check if (!desc->handle_irq_thread) is really
useful. I've put it to ensure that even an irq_desc which never gone to
__set_irq_handler() can be handled. But I'm not sure it is possible.]

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
 include/linux/irq.h |   11 ++++++++++-
 kernel/irq/chip.c   |    2 ++
 kernel/irq/manage.c |   27 ++++++++++++++++++---------
 3 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index aa9d62e..ff83182 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -30,6 +30,7 @@
 struct irq_desc;
 typedef	void (*irq_flow_handler_t)(unsigned int irq,
 					    struct irq_desc *desc);
+typedef void (*irq_thread_handler_t)(struct irq_desc *desc);
 
 
 /*
@@ -136,6 +137,7 @@ struct irq_chip {
  * struct irq_desc - interrupt descriptor
  * @irq:		interrupt number for this descriptor
  * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()]
+ * @handle_irq_thread:	highlevel threaded irq-events handler
  * @chip:		low level interrupt hardware access
  * @msi_desc:		MSI descriptor
  * @handler_data:	per-IRQ data for the irq_chip methods
@@ -161,6 +163,9 @@ struct irq_chip {
 struct irq_desc {
 	unsigned int		irq;
 	irq_flow_handler_t	handle_irq;
+#ifdef CONFIG_PREEMPT_HARDIRQS
+	irq_thread_handler_t	handle_irq_thread;
+#endif
 	struct irq_chip		*chip;
 	struct msi_desc		*msi_desc;
 	void			*handler_data;
@@ -393,10 +398,14 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
 extern void early_init_hardirqs(void);
 extern cycles_t irq_timestamp(unsigned int irq);
 
-#if defined(CONFIG_PREEMPT_HARDIRQS)
+#ifdef CONFIG_PREEMPT_HARDIRQS
 extern void init_hardirqs(void);
+extern void
+__set_irq_thread_handler(struct irq_desc *desc, irq_flow_handler_t handle);
 #else
 static inline void init_hardirqs(void) { }
+static inline void
+__set_irq_thread_handler(struct irq_desc *desc, irq_flow_handler_t handle) { }
 #endif
 
 #else	/* end GENERIC HARDIRQS */
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index f25b747..e8aa31c 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -605,6 +605,8 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 	desc->handle_irq = handle;
 	desc->name = name;
 
+	__set_irq_thread_handler(desc, handle);
+
 	if (handle != handle_bad_irq && is_chained) {
 		desc->status &= ~IRQ_DISABLED;
 		desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8e963a9..776c715 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -901,6 +901,21 @@ static void thread_do_irq(irq_desc_t *desc)
 	desc->chip->end(irq);
 }
 
+void
+__set_irq_thread_handler(struct irq_desc *desc, irq_flow_handler_t handle)
+{
+	if (handle == handle_simple_irq)
+		desc->handle_irq_thread = thread_simple_irq;
+	else if (handle == handle_level_irq)
+		desc->handle_irq_thread = thread_level_irq;
+	else if (handle == handle_fasteoi_irq)
+		desc->handle_irq_thread = thread_fasteoi_irq;
+	else if (handle == handle_edge_irq)
+		desc->handle_irq_thread = thread_edge_irq;
+	else
+		desc->handle_irq_thread = thread_do_irq;
+}
+
 static void do_hardirq(struct irq_desc *desc)
 {
 	spin_lock(&desc->lock);
@@ -908,16 +923,10 @@ static void do_hardirq(struct irq_desc *desc)
 	if (!(desc->status & IRQ_INPROGRESS))
 		goto out;
 
-	if (desc->handle_irq == handle_simple_irq)
-		thread_simple_irq(desc);
-	else if (desc->handle_irq == handle_level_irq)
-		thread_level_irq(desc);
-	else if (desc->handle_irq == handle_fasteoi_irq)
-		thread_fasteoi_irq(desc);
-	else if (desc->handle_irq == handle_edge_irq)
-		thread_edge_irq(desc);
-	else
+	if (unlikely(!desc->handle_irq_thread))
 		thread_do_irq(desc);
+	else
+		desc->handle_irq_thread(desc);
  out:
 	spin_unlock(&desc->lock);
 
-- 
1.6.1



             reply	other threads:[~2009-02-13  4:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-13  3:38 Frederic Weisbecker [this message]
2009-02-13  5:46 ` [PATCH] rt/threadirqs: put the irq thread handler in a callback Steven Rostedt

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=4994f034.02e2660a.3130.23df@mx.google.com \
    --to=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rostedt@goodmis.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.