Skip to content

Commit

Permalink
V4L/DVB (10940): saa6588: Prevent general protection fault on rmmod
Browse files Browse the repository at this point in the history
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 <khali@linux-fr.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Jean Delvare authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent c1089bd commit fb6991d
Showing 1 changed file with 6 additions and 18 deletions.
24 changes: 6 additions & 18 deletions drivers/media/video/saa6588.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ MODULE_LICENSE("GPL");

struct saa6588 {
struct v4l2_subdev sd;
struct work_struct work;
struct timer_list timer;
struct delayed_work work;
spinlock_t lock;
unsigned char *buffer;
unsigned int buf_size;
Expand Down Expand Up @@ -322,19 +321,12 @@ static void saa6588_i2c_poll(struct saa6588 *s)
wake_up_interruptible(&s->read_queue);
}

static void saa6588_timer(unsigned long data)
{
struct saa6588 *s = (struct saa6588 *)data;

schedule_work(&s->work);
}

static void saa6588_work(struct work_struct *work)
{
struct saa6588 *s = container_of(work, struct saa6588, work);
struct saa6588 *s = container_of(work, struct saa6588, work.work);

saa6588_i2c_poll(s);
mod_timer(&s->timer, jiffies + msecs_to_jiffies(20));
schedule_delayed_work(&s->work, msecs_to_jiffies(20));
}

static int saa6588_configure(struct saa6588 *s)
Expand Down Expand Up @@ -490,11 +482,8 @@ static int saa6588_probe(struct i2c_client *client,
saa6588_configure(s);

/* start polling via eventd */
INIT_WORK(&s->work, saa6588_work);
init_timer(&s->timer);
s->timer.function = saa6588_timer;
s->timer.data = (unsigned long)s;
schedule_work(&s->work);
INIT_DELAYED_WORK(&s->work, saa6588_work);
schedule_delayed_work(&s->work, 0);
return 0;
}

Expand All @@ -505,8 +494,7 @@ static int saa6588_remove(struct i2c_client *client)

v4l2_device_unregister_subdev(sd);

del_timer_sync(&s->timer);
flush_scheduled_work();
cancel_delayed_work_sync(&s->work);

kfree(s->buffer);
kfree(s);
Expand Down

0 comments on commit fb6991d

Please sign in to comment.