From patchwork Fri Jul 30 11:38:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Levitsky X-Patchwork-Id: 3986 Return-path: Envelope-to: mchehab@infradead.org Delivery-date: Fri, 30 Jul 2010 11:39:15 +0000 Received: from bombadil.infradead.org [18.85.46.34] by pedra with IMAP (fetchmail-6.3.17) for (single-drop); Fri, 30 Jul 2010 09:07:16 -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 1Oenvm-0005GN-S4; Fri, 30 Jul 2010 11:39:15 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758495Ab0G3LjM (ORCPT + 1 other); Fri, 30 Jul 2010 07:39:12 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:45485 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758455Ab0G3LjK (ORCPT ); Fri, 30 Jul 2010 07:39:10 -0400 Received: by mail-fx0-f46.google.com with SMTP id 14so798188fxm.19 for ; Fri, 30 Jul 2010 04:39:09 -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=ht572++/cij4/bV/VYg6X9bt/b732wA1uSqVC+WT9+c=; b=NkWItv5RI4OsMUaaGYgx8n01neHOViju9jjCWTkWaKENhFVYa6kSYCgu6KDvd4nZNp 2p+H9LZ0z7sJAKaTrrVP6w5ds/G7XokO2Bs6yi9RFgJh0NVHu0IOIdjLP93z5Z7O8GQm 9qK8DWZ9EOkJ/iNd4rdyuI7WxGP17yFspHIHY= 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=pbM4WYGbbL6mOZ0DFmbGi+CdV9Ko2MmEYS36/N81U7hWDuo8kwYb8+mPtJ49wFfFaH taM99WgiiDQ/BZMAcl07dHuHSWHc3NNv9GC687n0GJ1f0LuJcZy3GHVi6nejnLuiWJQ3 HHWgA262OOyRgGLDjZWMhJn0rMrt3AikazMg8= Received: by 10.223.113.144 with SMTP id a16mr1896206faq.41.1280489949739; Fri, 30 Jul 2010 04:39:09 -0700 (PDT) Received: from localhost.localdomain (IGLD-84-228-19-51.inter.net.il [84.228.19.51]) by mx.google.com with ESMTPS id q17sm767482faa.21.2010.07.30.04.39.05 (version=SSLv3 cipher=RC4-MD5); Fri, 30 Jul 2010 04:39:09 -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 04/13] IR: fix locking in ir_raw_event_work Date: Fri, 30 Jul 2010 14:38:44 +0300 Message-Id: <1280489933-20865-5-git-send-email-maximlevitsky@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1280489933-20865-1-git-send-email-maximlevitsky@gmail.com> References: <1280489933-20865-1-git-send-email-maximlevitsky@gmail.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org It is prefectly possible to have ir_raw_event_work running concurently on two cpus, thus we must protect it from that situation. Just switch to a thread that we wake up as soon as we have data. This also ensures that this thread doesn't run unnessesarly. Signed-off-by: Maxim Levitsky --- drivers/media/IR/ir-core-priv.h | 2 +- drivers/media/IR/ir-raw-event.c | 42 ++++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index dc26e2b..84c7a9a 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -32,7 +32,7 @@ struct ir_raw_handler { struct ir_raw_event_ctrl { struct list_head list; /* to keep track of raw clients */ - struct work_struct rx_work; /* for the rx decoding workqueue */ + struct task_struct *thread; 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 9d5c029..d0c18db 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -12,9 +12,10 @@ * GNU General Public License for more details. */ -#include +#include #include #include +#include #include "ir-core-priv.h" /* Define the max number of pulse/space transitions to buffer */ @@ -33,20 +34,30 @@ static u64 available_protocols; static struct work_struct wq_load; #endif -static void ir_raw_event_work(struct work_struct *work) +static int ir_raw_event_thread(void *data) { struct ir_raw_event ev; struct ir_raw_handler *handler; - struct ir_raw_event_ctrl *raw = - container_of(work, struct ir_raw_event_ctrl, rx_work); + struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; + + while (!kthread_should_stop()) { + try_to_freeze(); - while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { mutex_lock(&ir_raw_handler_lock); - list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->input_dev, ev); + + 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; + } + mutex_unlock(&ir_raw_handler_lock); - raw->prev_ev = ev; + + set_current_state(TASK_INTERRUPTIBLE); + schedule(); } + + return 0; } /** @@ -141,7 +152,7 @@ void ir_raw_event_handle(struct input_dev *input_dev) if (!ir->raw) return; - schedule_work(&ir->raw->rx_work); + wake_up_process(ir->raw->thread); } EXPORT_SYMBOL_GPL(ir_raw_event_handle); @@ -170,7 +181,7 @@ int ir_raw_event_register(struct input_dev *input_dev) return -ENOMEM; ir->raw->input_dev = input_dev; - INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); + ir->raw->enabled_protocols = ~0; rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, GFP_KERNEL); @@ -180,6 +191,15 @@ int ir_raw_event_register(struct input_dev *input_dev) return rc; } + ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, + "rc%u", (unsigned int)ir->devno); + + if (IS_ERR(ir->raw->thread)) { + kfree(ir->raw); + ir->raw = NULL; + return PTR_ERR(ir->raw->thread); + } + mutex_lock(&ir_raw_handler_lock); list_add_tail(&ir->raw->list, &ir_raw_client_list); list_for_each_entry(handler, &ir_raw_handler_list, list) @@ -198,7 +218,7 @@ void ir_raw_event_unregister(struct input_dev *input_dev) if (!ir->raw) return; - cancel_work_sync(&ir->raw->rx_work); + kthread_stop(ir->raw->thread); mutex_lock(&ir_raw_handler_lock); list_del(&ir->raw->list);