From patchwork Fri Oct 15 15:07:47 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Levitsky X-Patchwork-Id: 4617 Return-path: Envelope-to: mchehab@pedra Delivery-date: Fri, 15 Oct 2010 12:18:39 -0300 Received: from mchehab by pedra with local (Exim 4.72) (envelope-from ) id 1P6m3K-00064U-Q5 for mchehab@pedra; Fri, 15 Oct 2010 12:18:39 -0300 Received: from casper.infradead.org [85.118.1.10] by pedra with IMAP (fetchmail-6.3.17) for (single-drop); Fri, 15 Oct 2010 12:18:38 -0300 (BRT) Received: from vger.kernel.org ([209.132.180.67]) by casper.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1P6m1D-0002bQ-Hb; Fri, 15 Oct 2010 15:16:27 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756169Ab0JOPQO (ORCPT + 1 other); Fri, 15 Oct 2010 11:16:14 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:64150 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756153Ab0JOPQN (ORCPT ); Fri, 15 Oct 2010 11:16:13 -0400 Received: by fxm4 with SMTP id 4so496650fxm.19 for ; Fri, 15 Oct 2010 08:16:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=IvV4QVAPOKcZjdYBXdI9n1nYBQ8o/XDMJ+BrwzgXQxA=; b=q1xHcPycskdEUf1CehandpNLYboioz7OT92lARHiG1mQgIZHJdeeHZaLrE/1S+X8vj 1QMsLhcVTTX8zB9TNwO0qDt8cpOl2Lf+8l+1TSs956/KF8d1m+MHG5qjWzsa3DILd92c ZJKDliVYaKW3JUnY38LVssNKgfOja8p+sJfZ0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=ZZ7Sc385kSTVa8bKpgytbIh/SyX/7918eHKMIKJgpxuIqoeBWqRkN5WtrJb9ex+3yA 8UuUH88W8rKK+92J93tCH7eKeBIdYDDC8Q/7o9+muB/dws2HRYZZ/lfRn2K7ES7kgksO R6ZrEnrloBkthWpB0ol5kgepI2t+4g7tOhw7Y= Received: by 10.204.53.9 with SMTP id k9mr853217bkg.102.1287155284474; Fri, 15 Oct 2010 08:08:04 -0700 (PDT) Received: from maxim-laptop ([77.125.7.102]) by mx.google.com with ESMTPS id t10sm6907156bkj.16.2010.10.15.08.08.01 (version=SSLv3 cipher=RC4-MD5); Fri, 15 Oct 2010 08:08:02 -0700 (PDT) From: Maxim Levitsky To: lirc-list@lists.sourceforge.net Cc: Jarod Wilson , =?UTF-8?q?David=20H=C3=A4rdeman?= , mchehab@infradead.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, Maxim Levitsky Subject: [PATCH 1/7] IR: plug races in IR raw thread. Date: Fri, 15 Oct 2010 17:07:47 +0200 Message-Id: <1287155273-16171-2-git-send-email-maximlevitsky@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1287155273-16171-1-git-send-email-maximlevitsky@gmail.com> References: <1287155273-16171-1-git-send-email-maximlevitsky@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Sender: Unfortunelly (my fault) the kernel thread that now handles IR processing has classical races in regard to wakeup and stop. This patch hopefully closes them all. Tested with module reload running in a loop, while receiver is blasted with IR data for 10 minutes. Signed-off-by: Maxim Levitsky Acked-by: Jarod Wilson --- drivers/media/IR/ir-core-priv.h | 2 ++ drivers/media/IR/ir-raw-event.c | 34 +++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index a85a8c7..761e7f4 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -17,6 +17,7 @@ #define _IR_RAW_EVENT #include +#include #include struct ir_raw_handler { @@ -33,6 +34,7 @@ struct ir_raw_handler { struct ir_raw_event_ctrl { struct list_head list; /* to keep track of raw clients */ struct task_struct *thread; + spinlock_t lock; struct kfifo kfifo; /* fifo for the pulse/space durations */ ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 8e0e1b1..119b567 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -39,22 +39,34 @@ static int ir_raw_event_thread(void *data) struct ir_raw_event ev; struct ir_raw_handler *handler; struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; + int retval; while (!kthread_should_stop()) { - try_to_freeze(); - mutex_lock(&ir_raw_handler_lock); + spin_lock_irq(&raw->lock); + retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + + if (!retval) { + set_current_state(TASK_INTERRUPTIBLE); - while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { - list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->input_dev, ev); - raw->prev_ev = ev; + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + + spin_unlock_irq(&raw->lock); + schedule(); + continue; } - mutex_unlock(&ir_raw_handler_lock); + spin_unlock_irq(&raw->lock); - set_current_state(TASK_INTERRUPTIBLE); - schedule(); + + BUG_ON(retval != sizeof(ev)); + + mutex_lock(&ir_raw_handler_lock); + list_for_each_entry(handler, &ir_raw_handler_list, list) + handler->decode(raw->input_dev, ev); + raw->prev_ev = ev; + mutex_unlock(&ir_raw_handler_lock); } return 0; @@ -232,11 +244,14 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); void ir_raw_event_handle(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); + unsigned long flags; if (!ir->raw) return; + spin_lock_irqsave(&ir->raw->lock, flags); wake_up_process(ir->raw->thread); + spin_unlock_irqrestore(&ir->raw->lock, flags); } EXPORT_SYMBOL_GPL(ir_raw_event_handle); @@ -275,6 +290,7 @@ int ir_raw_event_register(struct input_dev *input_dev) return rc; } + spin_lock_init(&ir->raw->lock); ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, "rc%u", (unsigned int)ir->devno);