From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Ingo Molnar <mingo@elte.hu>,
Peter Zijlstra <peterz@infradead.org>, Tom Lyon <pugs@cisco.com>,
Alex Williamson <alex.williamson@redhat.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
Avi Kivity <avi@redhat.com>,
Marcelo Tosatti <mtosatti@redhat.com>,
Jan Kiszka <jan.kiszka@siemens.com>,
Jan Kiszka <jan.kiszka@web.de>
Subject: [RFC patch 2/4] genirq: Move action walk outside of desc->lock held region
Date: Wed, 15 Dec 2010 23:12:38 -0000 [thread overview]
Message-ID: <20101215230531.242147932@linutronix.de> (raw)
In-Reply-To: <20101215230352.411894017@linutronix.de>
[-- Attachment #1: genirq-move-action-walk-outside-desc-lock-region.patch --]
[-- Type: text/plain, Size: 4863 bytes --]
The global serialization of request/free_irq allows us to reduce the
spinlocked and interrupt disabled regions as the global lock protects
the action chain and basic setup functions.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Tom Lyon <pugs@cisco.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Jan Kiszka <jan.kiszka@web.de>
---
kernel/irq/manage.c | 73 +++++++++++++++++++++++++++-------------------------
1 file changed, 39 insertions(+), 34 deletions(-)
Index: linux-2.6-tip/kernel/irq/manage.c
===================================================================
--- linux-2.6-tip.orig/kernel/irq/manage.c
+++ linux-2.6-tip/kernel/irq/manage.c
@@ -658,8 +658,8 @@ __setup_irq(unsigned int irq, struct irq
{
struct irqaction *old, **old_ptr;
const char *old_name = NULL;
+ bool nested, shared = false;
unsigned long flags;
- int nested, shared = 0;
int ret;
if (!desc)
@@ -705,30 +705,10 @@ __setup_irq(unsigned int irq, struct irq
}
/*
- * Create a handler thread when a thread function is supplied
- * and the interrupt does not nest into another interrupt
- * thread.
+ * This is called with register_lock held, so we can walk the
+ * action chain w/o holding desc->lock. Nothing can add or
+ * remove an action.
*/
- if (new->thread_fn && !nested) {
- struct task_struct *t;
-
- t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
- new->name);
- if (IS_ERR(t))
- return PTR_ERR(t);
- /*
- * We keep the reference to the task struct even if
- * the thread dies to avoid that the interrupt code
- * references an already freed task_struct.
- */
- get_task_struct(t);
- new->thread = t;
- }
-
- /*
- * The following block of code has to be executed atomically
- */
- raw_spin_lock_irqsave(&desc->lock, flags);
old_ptr = &desc->action;
old = *old_ptr;
if (old) {
@@ -756,14 +736,36 @@ __setup_irq(unsigned int irq, struct irq
old_ptr = &old->next;
old = *old_ptr;
} while (old);
- shared = 1;
+ shared = true;
+ }
+
+ /*
+ * Create a handler thread when a thread function is supplied
+ * and the interrupt does not nest into another interrupt
+ * thread.
+ */
+ if (new->thread_fn && !nested) {
+ struct task_struct *t;
+
+ t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
+ new->name);
+ if (IS_ERR(t))
+ return PTR_ERR(t);
+ /*
+ * We keep the reference to the task struct even if
+ * the thread dies to avoid that the interrupt code
+ * references an already freed task_struct.
+ */
+ get_task_struct(t);
+ new->thread = t;
}
if (!shared) {
irq_chip_set_defaults(desc->irq_data.chip);
-
init_waitqueue_head(&desc->wait_for_threads);
+ raw_spin_lock_irqsave(&desc->lock, flags);
+
/* Setup the type (level, edge polarity) if configured: */
if (new->flags & IRQF_TRIGGER_MASK) {
ret = __irq_set_trigger(desc, irq,
@@ -773,6 +775,7 @@ __setup_irq(unsigned int irq, struct irq
goto out_thread;
} else
compat_irq_chip_set_default_handler(desc);
+
#if defined(CONFIG_IRQ_PER_CPU)
if (new->flags & IRQF_PERCPU)
desc->status |= IRQ_PER_CPU;
@@ -799,13 +802,17 @@ __setup_irq(unsigned int irq, struct irq
/* Set default affinity mask once everything is setup */
setup_affinity(irq, desc);
- } else if ((new->flags & IRQF_TRIGGER_MASK)
- && (new->flags & IRQF_TRIGGER_MASK)
- != (desc->status & IRQ_TYPE_SENSE_MASK)) {
+ } else {
+ raw_spin_lock_irqsave(&desc->lock, flags);
+
+ if ((new->flags & IRQF_TRIGGER_MASK)
+ && (new->flags & IRQF_TRIGGER_MASK)
+ != (desc->status & IRQ_TYPE_SENSE_MASK)) {
/* hope the handler works with the actual trigger mode... */
pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
(int)(new->flags & IRQF_TRIGGER_MASK));
+ }
}
new->irq = irq;
@@ -848,7 +855,7 @@ mismatch:
dump_stack();
}
#endif
- ret = -EBUSY;
+ return -EBUSY;
out_thread:
raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -897,8 +904,6 @@ static struct irqaction *__free_irq(unsi
if (!desc)
return NULL;
- raw_spin_lock_irqsave(&desc->lock, flags);
-
/*
* There can be multiple actions per IRQ descriptor, find the right
* one based on the dev_id:
@@ -909,8 +914,6 @@ static struct irqaction *__free_irq(unsi
if (!action) {
WARN(1, "Trying to free already-free IRQ %d\n", irq);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
return NULL;
}
@@ -919,6 +922,8 @@ static struct irqaction *__free_irq(unsi
action_ptr = &action->next;
}
+ raw_spin_lock_irqsave(&desc->lock, flags);
+
/* Found it - now remove it from the list of entries: */
*action_ptr = action->next;
next prev parent reply other threads:[~2010-12-15 23:13 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-15 23:12 [RFC patch 0/4] genirq: Provide adaptive irq oneshot functionality Thomas Gleixner
2010-12-15 23:12 ` [RFC patch 1/4] genirq: Globally serialize request/free_irq Thomas Gleixner
2010-12-15 23:12 ` Thomas Gleixner [this message]
2010-12-15 23:12 ` [RFC patch 3/4] genirq: Add notification mechanism for adaptive shared irqs Thomas Gleixner
2010-12-15 23:12 ` [RFC patch 4/4] genirq: Add support for IRQF_COND_ONESHOT Thomas Gleixner
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=20101215230531.242147932@linutronix.de \
--to=tglx@linutronix.de \
--cc=alex.williamson@redhat.com \
--cc=avi@redhat.com \
--cc=jan.kiszka@siemens.com \
--cc=jan.kiszka@web.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=mst@redhat.com \
--cc=mtosatti@redhat.com \
--cc=peterz@infradead.org \
--cc=pugs@cisco.com \
/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
Powered by JetHome