From mboxrd@z Thu Jan 1 00:00:00 1970 From: Greg KH Subject: [072/123] sched: Make wakeup side and atomic variants of completion API irq safe Date: Sat, 18 Sep 2010 11:58:36 -0700 Message-ID: <20100918185958.963057726@clark.site> References: <20100918185724.290702750@clark.site> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Content-Disposition: inline; filename=sched-make-wakeup-side-and-atomic-variants-of-completion-api-irq-safe.patch In-Reply-To: <20100918190024.GA14388@kroah.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-pm-bounces@lists.linux-foundation.org Errors-To: linux-pm-bounces@lists.linux-foundation.org To: linux-kernel@vger.kernel.org, stable@kernel.org Cc: Peter Zijlstra , Mike Galbraith , David Chinner , stable-review@kernel.org, Lachlan McIlroy , pm list , akpm@linux-foundation.org, torvalds@linux-foundation.org, Ingo Molnar , alan@lxorguk.ukuu.org.uk List-Id: linux-pm@vger.kernel.org From: Rafael J.Wysocki commit 7539a3b3d1f892dd97eaf094134d7de55c13befe upstream Alan Stern noticed that all the wakeup side (and atomic) variants of the completion APIs should be irq safe, but the newly introduced completion_done() and try_wait_for_completion() aren't. The use of the irq unsafe variants in IRQ contexts can cause crashes/hangs. Fix the problem by making them use spin_lock_irqsave() and spin_lock_irqrestore(). Reported-by: Alan Stern Signed-off-by: Rafael J. Wysocki Cc: Linus Torvalds Cc: Zhang Rui Cc: pm list Cc: Peter Zijlstra Cc: David Chinner Cc: Lachlan McIlroy LKML-Reference: <200912130007.30541.rjw@sisk.pl> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5947,14 +5947,15 @@ EXPORT_SYMBOL(wait_for_completion_killab */ bool try_wait_for_completion(struct completion *x) { + unsigned long flags; int ret = 1; - spin_lock_irq(&x->wait.lock); + spin_lock_irqsave(&x->wait.lock, flags); if (!x->done) ret = 0; else x->done--; - spin_unlock_irq(&x->wait.lock); + spin_unlock_irqrestore(&x->wait.lock, flags); return ret; } EXPORT_SYMBOL(try_wait_for_completion); @@ -5969,12 +5970,13 @@ EXPORT_SYMBOL(try_wait_for_completion); */ bool completion_done(struct completion *x) { + unsigned long flags; int ret = 1; - spin_lock_irq(&x->wait.lock); + spin_lock_irqsave(&x->wait.lock, flags); if (!x->done) ret = 0; - spin_unlock_irq(&x->wait.lock); + spin_unlock_irqrestore(&x->wait.lock, flags); return ret; } EXPORT_SYMBOL(completion_done);