The patch number 10936 was added via Mauro Carvalho Chehab <mche...@redhat.com>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        Linux Media Mailing List <linux-me...@vger.kernel.org>

------

From: Jean Delvare  <kh...@linux-fr.org>
Fix race in infrared polling on rmmod


The race on rmmod I just fixed in cx88-input affects 3 other drivers.
Fix these the same way.

Signed-off-by: Jean Delvare <kh...@linux-fr.org>
Signed-off-by: Mauro Carvalho Chehab <mche...@redhat.com>


---

 linux/drivers/media/video/em28xx/em28xx-input.c |   27 ++++++++++++----
 linux/drivers/media/video/ir-kbd-i2c.c          |   21 +++++++++---
 linux/drivers/media/video/saa6588.c             |   25 +++++++++++---
 linux/include/media/ir-kbd-i2c.h                |    4 ++
 4 files changed, 61 insertions(+), 16 deletions(-)

diff -r 46412997b3c0 -r 4e445255c3f5 
linux/drivers/media/video/em28xx/em28xx-input.c
--- a/linux/drivers/media/video/em28xx/em28xx-input.c   Thu Mar 05 09:38:24 
2009 +0000
+++ b/linux/drivers/media/video/em28xx/em28xx-input.c   Thu Mar 05 09:39:30 
2009 +0000
@@ -69,8 +69,12 @@ struct em28xx_IR {
 
        /* poll external decoder */
        int polling;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        struct work_struct work;
        struct timer_list timer;
+#else
+       struct delayed_work work;
+#endif
        unsigned int last_toggle:1;
        unsigned int last_readcount;
        unsigned int repeat_interval;
@@ -298,6 +302,7 @@ static void em28xx_ir_handle_key(struct 
        return;
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
 static void ir_timer(unsigned long data)
 {
        struct em28xx_IR *ir = (struct em28xx_IR *)data;
@@ -305,7 +310,6 @@ static void ir_timer(unsigned long data)
        schedule_work(&ir->work);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
 static void em28xx_ir_work(void *data)
 #else
 static void em28xx_ir_work(struct work_struct *work)
@@ -314,28 +318,39 @@ static void em28xx_ir_work(struct work_s
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        struct em28xx_IR *ir = data;
 #else
-       struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work);
+       struct delayed_work *dwork = container_of(work, struct delayed_work,
+                                                 work);
+       struct em28xx_IR *ir = container_of(dwork, struct em28xx_IR, work);
 #endif
 
        em28xx_ir_handle_key(ir);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+#else
+       schedule_delayed_work(dwork, msecs_to_jiffies(ir->polling));
+#endif
 }
 
 static void em28xx_ir_start(struct em28xx_IR *ir)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        INIT_WORK(&ir->work, em28xx_ir_work, ir);
-#else
-       INIT_WORK(&ir->work, em28xx_ir_work);
-#endif
        schedule_work(&ir->work);
+#else
+       INIT_DELAYED_WORK(&ir->work, em28xx_ir_work);
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+#endif
 }
 
 static void em28xx_ir_stop(struct em28xx_IR *ir)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        del_timer_sync(&ir->timer);
        flush_scheduled_work();
+#else
+       cancel_delayed_work_sync(&ir->work);
+#endif
 }
 
 int em28xx_ir_init(struct em28xx *dev)
diff -r 46412997b3c0 -r 4e445255c3f5 linux/drivers/media/video/ir-kbd-i2c.c
--- a/linux/drivers/media/video/ir-kbd-i2c.c    Thu Mar 05 09:38:24 2009 +0000
+++ b/linux/drivers/media/video/ir-kbd-i2c.c    Thu Mar 05 09:39:30 2009 +0000
@@ -280,13 +280,13 @@ static void ir_key_poll(struct IR_i2c *i
        }
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
 static void ir_timer(unsigned long data)
 {
        struct IR_i2c *ir = (struct IR_i2c*)data;
        schedule_work(&ir->work);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
 static void ir_work(void *data)
 #else
 static void ir_work(struct work_struct *work)
@@ -295,7 +295,9 @@ static void ir_work(struct work_struct *
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        struct IR_i2c *ir = data;
 #else
-       struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
+       struct delayed_work *dwork = container_of(work, struct delayed_work,
+                                                 work);
+       struct IR_i2c *ir = container_of(dwork, struct IR_i2c, work);
 #endif
        int polling_interval = 100;
 
@@ -305,7 +307,11 @@ static void ir_work(struct work_struct *
                polling_interval = 50;
 
        ir_key_poll(ir);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval));
+#else
+       schedule_delayed_work(dwork, msecs_to_jiffies(polling_interval));
+#endif
 }
 
 /* ----------------------------------------------------------------------- */
@@ -463,13 +469,14 @@ static int ir_attach(struct i2c_adapter 
        /* start polling via eventd */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        INIT_WORK(&ir->work, ir_work, ir);
-#else
-       INIT_WORK(&ir->work, ir_work);
-#endif
        init_timer(&ir->timer);
        ir->timer.function = ir_timer;
        ir->timer.data     = (unsigned long)ir;
        schedule_work(&ir->work);
+#else
+       INIT_DELAYED_WORK(&ir->work, ir_work);
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(100));
+#endif
 
        return 0;
 
@@ -486,8 +493,12 @@ static int ir_detach(struct i2c_client *
        struct IR_i2c *ir = i2c_get_clientdata(client);
 
        /* kill outstanding polls */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        del_timer_sync(&ir->timer);
        flush_scheduled_work();
+#else
+       cancel_delayed_work_sync(&ir->work);
+#endif
 
        /* unregister devices */
        input_unregister_device(ir->input);
diff -r 46412997b3c0 -r 4e445255c3f5 linux/drivers/media/video/saa6588.c
--- a/linux/drivers/media/video/saa6588.c       Thu Mar 05 09:38:24 2009 +0000
+++ b/linux/drivers/media/video/saa6588.c       Thu Mar 05 09:39:30 2009 +0000
@@ -77,8 +77,12 @@ MODULE_LICENSE("GPL");
 
 struct saa6588 {
        struct v4l2_subdev sd;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        struct work_struct work;
        struct timer_list timer;
+#else
+       struct delayed_work work;
+#endif
        spinlock_t lock;
        unsigned char *buffer;
        unsigned int buf_size;
@@ -323,6 +327,7 @@ static void saa6588_i2c_poll(struct saa6
        wake_up_interruptible(&s->read_queue);
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
 static void saa6588_timer(unsigned long data)
 {
        struct saa6588 *s = (struct saa6588 *)data;
@@ -330,7 +335,6 @@ static void saa6588_timer(unsigned long 
        schedule_work(&s->work);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
 static void saa6588_work(void *data)
 #else
 static void saa6588_work(struct work_struct *work)
@@ -339,11 +343,17 @@ static void saa6588_work(struct work_str
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        struct saa6588 *s = (struct saa6588 *)data;
 #else
-       struct saa6588 *s = container_of(work, struct saa6588, work);
+       struct delayed_work *dwork = container_of(work, struct delayed_work,
+                                                 work);
+       struct saa6588 *s = container_of(dwork, struct saa6588, work);
 #endif
 
        saa6588_i2c_poll(s);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        mod_timer(&s->timer, jiffies + msecs_to_jiffies(20));
+#else
+       schedule_delayed_work(dwork, msecs_to_jiffies(20));
+#endif
 }
 
 static int saa6588_configure(struct saa6588 *s)
@@ -501,13 +511,14 @@ static int saa6588_probe(struct i2c_clie
        /* start polling via eventd */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        INIT_WORK(&s->work, saa6588_work, s);
-#else
-       INIT_WORK(&s->work, saa6588_work);
-#endif
        init_timer(&s->timer);
        s->timer.function = saa6588_timer;
        s->timer.data = (unsigned long)s;
        schedule_work(&s->work);
+#else
+       INIT_DELAYED_WORK(&s->work, saa6588_work);
+       schedule_delayed_work(&s->work, msecs_to_jiffies(20));
+#endif
        return 0;
 }
 
@@ -518,8 +529,12 @@ static int saa6588_remove(struct i2c_cli
 
        v4l2_device_unregister_subdev(sd);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
        del_timer_sync(&s->timer);
        flush_scheduled_work();
+#else
+       cancel_delayed_work_sync(&s->work);
+#endif
 
        kfree(s->buffer);
        kfree(s);
diff -r 46412997b3c0 -r 4e445255c3f5 linux/include/media/ir-kbd-i2c.h
--- a/linux/include/media/ir-kbd-i2c.h  Thu Mar 05 09:38:24 2009 +0000
+++ b/linux/include/media/ir-kbd-i2c.h  Thu Mar 05 09:39:30 2009 +0000
@@ -14,8 +14,12 @@ struct IR_i2c {
        /* Used to avoid fast repeating */
        unsigned char          old;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        struct work_struct     work;
        struct timer_list      timer;
+#else
+       struct delayed_work     work;
+#endif
        char                   phys[32];
        int                    (*get_key)(struct IR_i2c*, u32*, u32*);
 };


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/4e445255c3f53d6940ab9ea21e31b039351a5c34

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to