From 24ef92f0974bf26cf8ca949b7ae21286cbca3fd3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 09:39:30 +0000 Subject: Fix race in infrared polling on rmmod From: Jean Delvare The race on rmmod I just fixed in cx88-input affects 3 other drivers. Fix these the same way. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'linux/drivers/media/video/ir-kbd-i2c.c') diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index a99aea49a..fa5480f64 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -280,13 +280,13 @@ static void ir_key_poll(struct IR_i2c *ir) } } +#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 *work) #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 *work) 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 *adap, int addr, /* 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 *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); -- cgit v1.2.3 From d7673f843f104186787be352493d8660570163ab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Mar 2009 07:51:41 -0300 Subject: Revert the last changeset, since there are a rev 2 of those changes From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'linux/drivers/media/video/ir-kbd-i2c.c') diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index fa5480f64..a99aea49a 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -280,13 +280,13 @@ static void ir_key_poll(struct IR_i2c *ir) } } -#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,9 +295,7 @@ static void ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct IR_i2c *ir = data; #else - struct delayed_work *dwork = container_of(work, struct delayed_work, - work); - struct IR_i2c *ir = container_of(dwork, struct IR_i2c, work); + struct IR_i2c *ir = container_of(work, struct IR_i2c, work); #endif int polling_interval = 100; @@ -307,11 +305,7 @@ static void ir_work(struct work_struct *work) 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 } /* ----------------------------------------------------------------------- */ @@ -469,14 +463,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr, /* 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; @@ -493,12 +486,8 @@ static int ir_detach(struct i2c_client *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); -- cgit v1.2.3 From c698fbc627c51ba8ad0e434848499cb4412072da Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Mar 2009 10:43:43 +0000 Subject: ir-kbd-i2c: Prevent general protection fault on rmmod From: Jean Delvare The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'linux/drivers/media/video/ir-kbd-i2c.c') diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index a99aea49a..a0b78706d 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -280,12 +280,6 @@ static void ir_key_poll(struct IR_i2c *ir) } } -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 @@ -295,7 +289,7 @@ static void ir_work(struct work_struct *work) #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 IR_i2c *ir = container_of(work, struct IR_i2c, work.work); #endif int polling_interval = 100; @@ -305,7 +299,7 @@ static void ir_work(struct work_struct *work) polling_interval = 50; ir_key_poll(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(polling_interval)); } /* ----------------------------------------------------------------------- */ @@ -462,14 +456,11 @@ static int ir_attach(struct i2c_adapter *adap, int addr, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&ir->work, ir_work, ir); + INIT_DELAYED_WORK(&ir->work, ir_work, ir); #else - INIT_WORK(&ir->work, ir_work); + INIT_DELAYED_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); + schedule_delayed_work(&ir->work, 0); return 0; @@ -486,8 +477,7 @@ static int ir_detach(struct i2c_client *client) struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ - del_timer_sync(&ir->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&ir->work); /* unregister devices */ input_unregister_device(ir->input); -- cgit v1.2.3 From 4c282610aefee1fbf050e390ad0f1cccbb245e7a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 22:37:06 +0100 Subject: ir-kbd-i2c: fix compat for old kernels. From: Hans Verkuil compat.h was included too late. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ir-kbd-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers/media/video/ir-kbd-i2c.c') diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index a0b78706d..7bae57ad3 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -47,9 +47,9 @@ #include #include +#include "compat.h" #include #include -#include "compat.h" /* ----------------------------------------------------------------------- */ /* insmod parameters */ -- cgit v1.2.3