mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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;
 



  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