From patchwork Mon Aug 30 08:52:21 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Levitsky X-Patchwork-Id: 4239 Return-path: Envelope-to: mchehab@pedra Delivery-date: Mon, 30 Aug 2010 08:45:13 -0300 Received: from mchehab by pedra with local (Exim 4.72) (envelope-from ) id 1Oq2nY-0004Xj-Nh for mchehab@pedra; Mon, 30 Aug 2010 08:45:12 -0300 Received: from bombadil.infradead.org [18.85.46.34] by pedra with IMAP (fetchmail-6.3.17) for (single-drop); Mon, 30 Aug 2010 08:45:12 -0300 (BRT) Received: from vger.kernel.org ([209.132.180.67]) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1Oq06f-0006Ko-Ou; Mon, 30 Aug 2010 08:52:45 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754785Ab0H3Iwn (ORCPT + 1 other); Mon, 30 Aug 2010 04:52:43 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:50033 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753959Ab0H3Iwl (ORCPT ); Mon, 30 Aug 2010 04:52:41 -0400 Received: by mail-bw0-f46.google.com with SMTP id 11so3528183bwz.19 for ; Mon, 30 Aug 2010 01:52:41 -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=SEOm1jwNrNUrUynSyDXTm5AV1Afnli7HKBId7Y+L3Ck=; b=U/0IwR2ahX6NRwAB2SRJD/u+qOpk8s9HZkH2fXnQkqkwwi4+kangyA38aUr5Hy5ts1 QUTFztnkJ76mW5sR9oHgPy7yRblhDQqOlkVsGBYzTTD8Rowzak6onGxcTyC2rKnnE7Zv Uu77EVc6mPsBxDjpILSDrbYXYGJq2sidFuu+o= 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=Tg+WtjApVf/SRG6MdiP6SbAMrSOT55HB3DWfILK9IJIQB72sTTJCNTBq9SPHcVNlCR vjvpdPvuKppHBI6mCnNC8OjIhN3siRk+otJaB1f2NpHE0bKxvouHQ3O0scdTgLSOzYO9 mX+8KdhYnZHo0cl5PJ0mstNeiQP1+CILcj7GI= Received: by 10.204.78.143 with SMTP id l15mr2999752bkk.22.1283158360981; Mon, 30 Aug 2010 01:52:40 -0700 (PDT) Received: from localhost.localdomain (IGLD-84-228-220-57.inter.net.il [84.228.220.57]) by mx.google.com with ESMTPS id d27sm5012102bku.22.2010.08.30.01.52.38 (version=SSLv3 cipher=RC4-MD5); Mon, 30 Aug 2010 01:52:40 -0700 (PDT) From: Maxim Levitsky To: lirc-list@lists.sourceforge.net Cc: Jarod Wilson , linux-input@vger.kernel.org, linux-media@vger.kernel.org, Mauro Carvalho Chehab , Christoph Bartelmus , Maxim Levitsky Subject: [PATCH 1/7] IR: plug races in handling threads. Date: Mon, 30 Aug 2010 11:52:21 +0300 Message-Id: <1283158348-7429-2-git-send-email-maximlevitsky@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1283158348-7429-1-git-send-email-maximlevitsky@gmail.com> References: <1283158348-7429-1-git-send-email-maximlevitsky@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Sender: Mauro Carvalho Chehab 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 --- 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 43094e7..56797be 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);