All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maxim Levitsky <maximlevitsky@gmail.com>
To: lirc-list@lists.sourceforge.net
Cc: Jarod Wilson <jarod@wilsonet.com>,
	linux-input@vger.kernel.org, linux-media@vger.kernel.org,
	Mauro Carvalho Chehab <mchehab@redhat.com>,
	Christoph Bartelmus <lirc@bartelmus.de>,
	Maxim Levitsky <maximlevitsky@gmail.com>
Subject: [PATCH 04/13] IR: replace workqueue with kthread
Date: Sat, 31 Jul 2010 17:59:17 +0300	[thread overview]
Message-ID: <1280588366-26101-5-git-send-email-maximlevitsky@gmail.com> (raw)
In-Reply-To: <1280588366-26101-1-git-send-email-maximlevitsky@gmail.com>

It is perfectly possible to have ir_raw_event_work
running concurently on two cpus, thus we must protect
it from that situation.

This stems from the fact that if hardware sends short packets of samples
we might end up queueing the work item more times that nessesary.

Such job isn't well suited for a workqueue, so use a kernel thread.

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
 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 <linux/workqueue.h>
+#include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
+#include <linux/freezer.h>
 #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);
-- 
1.7.0.4


  parent reply	other threads:[~2010-07-31 14:59 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-31 14:59 [PATCH 0/9 v4] IR: few fixes, additions and ENE driver Maxim Levitsky
2010-07-31 14:59 ` [PATCH 01/13] IR: Kconfig fixes Maxim Levitsky
2010-07-31 14:59 ` [PATCH 02/13] IR: minor fixes: Maxim Levitsky
2010-07-31 14:59 ` [PATCH 03/13] IR: replace spinlock with mutex Maxim Levitsky
2010-07-31 14:59 ` Maxim Levitsky [this message]
2010-07-31 14:59 ` [PATCH 05/13] IR: JVC: make repeat work Maxim Levitsky
2010-07-31 14:59 ` [PATCH 06/13] IR: nec decoder: fix repeat Maxim Levitsky
2010-07-31 14:59 ` [PATCH 07/13] IR: NECX: support repeat Maxim Levitsky
2010-07-31 14:59 ` [PATCH 08/13] IR: Allow not to compile keymaps in Maxim Levitsky
2010-07-31 14:59 ` [PATCH 09/13] IR: add helper function for hardware with small o/b buffer Maxim Levitsky
2010-08-02  2:11   ` Andy Walls
2010-08-02 10:49     ` Maxim Levitsky
2010-08-02 15:54     ` Jarod Wilson
2010-07-31 14:59 ` [PATCH 10/13] IR: extend interfaces to support more device settings Maxim Levitsky
2010-07-31 14:59 ` [PATCH 11/13] IR: report unknown scancodes the in-kernel decoders found Maxim Levitsky
2010-07-31 14:59 ` [PATCH 12/13] STAGING: remove lirc_ene0100 driver Maxim Levitsky
2010-07-31 14:59 ` [PATCH 13/13] IR: Port ene driver to new IR subsystem and enable it Maxim Levitsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1280588366-26101-5-git-send-email-maximlevitsky@gmail.com \
    --to=maximlevitsky@gmail.com \
    --cc=jarod@wilsonet.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=lirc-list@lists.sourceforge.net \
    --cc=lirc@bartelmus.de \
    --cc=mchehab@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.