diff options
Diffstat (limited to 'drivers/media/IR/ir-raw-event.c')
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 8e0e1b1f8c87..119b567feeab 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) | |||
39 | struct ir_raw_event ev; | 39 | struct ir_raw_event ev; |
40 | struct ir_raw_handler *handler; | 40 | struct ir_raw_handler *handler; |
41 | struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; | 41 | struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; |
42 | int retval; | ||
42 | 43 | ||
43 | while (!kthread_should_stop()) { | 44 | while (!kthread_should_stop()) { |
44 | try_to_freeze(); | ||
45 | 45 | ||
46 | mutex_lock(&ir_raw_handler_lock); | 46 | spin_lock_irq(&raw->lock); |
47 | retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); | ||
48 | |||
49 | if (!retval) { | ||
50 | set_current_state(TASK_INTERRUPTIBLE); | ||
47 | 51 | ||
48 | while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { | 52 | if (kthread_should_stop()) |
49 | list_for_each_entry(handler, &ir_raw_handler_list, list) | 53 | set_current_state(TASK_RUNNING); |
50 | handler->decode(raw->input_dev, ev); | 54 | |
51 | raw->prev_ev = ev; | 55 | spin_unlock_irq(&raw->lock); |
56 | schedule(); | ||
57 | continue; | ||
52 | } | 58 | } |
53 | 59 | ||
54 | mutex_unlock(&ir_raw_handler_lock); | 60 | spin_unlock_irq(&raw->lock); |
55 | 61 | ||
56 | set_current_state(TASK_INTERRUPTIBLE); | 62 | |
57 | schedule(); | 63 | BUG_ON(retval != sizeof(ev)); |
64 | |||
65 | mutex_lock(&ir_raw_handler_lock); | ||
66 | list_for_each_entry(handler, &ir_raw_handler_list, list) | ||
67 | handler->decode(raw->input_dev, ev); | ||
68 | raw->prev_ev = ev; | ||
69 | mutex_unlock(&ir_raw_handler_lock); | ||
58 | } | 70 | } |
59 | 71 | ||
60 | return 0; | 72 | return 0; |
@@ -232,11 +244,14 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); | |||
232 | void ir_raw_event_handle(struct input_dev *input_dev) | 244 | void ir_raw_event_handle(struct input_dev *input_dev) |
233 | { | 245 | { |
234 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | 246 | struct ir_input_dev *ir = input_get_drvdata(input_dev); |
247 | unsigned long flags; | ||
235 | 248 | ||
236 | if (!ir->raw) | 249 | if (!ir->raw) |
237 | return; | 250 | return; |
238 | 251 | ||
252 | spin_lock_irqsave(&ir->raw->lock, flags); | ||
239 | wake_up_process(ir->raw->thread); | 253 | wake_up_process(ir->raw->thread); |
254 | spin_unlock_irqrestore(&ir->raw->lock, flags); | ||
240 | } | 255 | } |
241 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | 256 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
242 | 257 | ||
@@ -275,6 +290,7 @@ int ir_raw_event_register(struct input_dev *input_dev) | |||
275 | return rc; | 290 | return rc; |
276 | } | 291 | } |
277 | 292 | ||
293 | spin_lock_init(&ir->raw->lock); | ||
278 | ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, | 294 | ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, |
279 | "rc%u", (unsigned int)ir->devno); | 295 | "rc%u", (unsigned int)ir->devno); |
280 | 296 | ||