From patchwork Mon Sep 6 21:26:06 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Levitsky X-Patchwork-Id: 4260 Return-path: Envelope-to: mchehab@gaivota Delivery-date: Mon, 06 Sep 2010 19:28:34 -0300 Received: from mchehab by gaivota with local (Exim 4.72) (envelope-from ) id 1OskB0-0000sb-1c for mchehab@gaivota; Mon, 06 Sep 2010 19:28:34 -0300 Received: from bombadil.infradead.org [18.85.46.34] by gaivota with IMAP (fetchmail-6.3.17) for (single-drop); Mon, 06 Sep 2010 19:28:34 -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 1OsjCs-0005lL-TO; Mon, 06 Sep 2010 21:26:27 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753137Ab0IFV0Y (ORCPT + 1 other); Mon, 6 Sep 2010 17:26:24 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:57693 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755420Ab0IFV0X (ORCPT ); Mon, 6 Sep 2010 17:26:23 -0400 Received: by mail-fx0-f46.google.com with SMTP id 13so2662937fxm.19 for ; Mon, 06 Sep 2010 14:26:22 -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=W8thLfuzKaJkxzMIc8OaLp4v1qbea2VtN2KENJOoMGFPNhknCayHYnF4jVgvVEVkXb JKuIswBPvjkMMYTZVI5b/HEWmshrAYM8AF66ef9rjMc007ViJGvxnboMD/05fhfzAxdA PFPicnUX2pY3wimXpciO7+kV7LHhYkY7TvSnE= 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=FbGlkbXD+NrgZc++SkjR2S/vGKD8GDtUW1zO42jXlpKDYcOGzQ/apjuOJsZFqjxwi0 7D+Q10e8Svfi667L1Cj00Dg9XsBiiwYGKM9Nnbj8mb3Or/flIBeOV7YbCf2282x718g0 nLt/STijZZvf3B6TZN5xGLLdSp9eo/LYT2I+4= Received: by 10.223.103.84 with SMTP id j20mr3239712fao.35.1283808382471; Mon, 06 Sep 2010 14:26:22 -0700 (PDT) Received: from localhost.localdomain (IGLD-84-228-233-189.inter.net.il [84.228.233.189]) by mx.google.com with ESMTPS id k15sm2504881fai.16.2010.09.06.14.26.20 (version=SSLv3 cipher=RC4-MD5); Mon, 06 Sep 2010 14:26:21 -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/8] IR: plug races in IR raw thread. Date: Tue, 7 Sep 2010 00:26:06 +0300 Message-Id: <1283808373-27876-2-git-send-email-maximlevitsky@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1283808373-27876-1-git-send-email-maximlevitsky@gmail.com> References: <1283808373-27876-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 Acked-by: Jarod Wilson 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 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);