summaryrefslogtreecommitdiff
path: root/drivers/input/joystick/turbografx.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2005-05-29 11:29:52 +0400
committerDmitry Torokhov <dtor_core@ameritech.net>2005-05-29 11:29:52 +0400
commit8b1a198bf14d59b67e47dc7b133ec5ea443fb40d (patch)
tree11d80109ddc2f61de6a75a37941346100a67a0d1 /drivers/input/joystick/turbografx.c
parentaf246041277674854383cf91b8f0b01217b521e8 (diff)
downloadlinux-8b1a198bf14d59b67e47dc7b133ec5ea443fb40d.tar.xz
Input: fix open/close races in joystick drivers - add a semaphore
to the ones that register more than one input device. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/joystick/turbografx.c')
-rw-r--r--drivers/input/joystick/turbografx.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 316c4bebfed2..28100d461cb7 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -84,6 +84,7 @@ static struct tgfx {
char phys[7][32];
int sticks;
int used;
+ struct semaphore sem;
} *tgfx_base[3];
/*
@@ -123,22 +124,33 @@ static void tgfx_timer(unsigned long private)
static int tgfx_open(struct input_dev *dev)
{
struct tgfx *tgfx = dev->private;
+ int err;
+
+ err = down_interruptible(&tgfx->sem);
+ if (err)
+ return err;
+
if (!tgfx->used++) {
parport_claim(tgfx->pd);
parport_write_control(tgfx->pd->port, 0x04);
mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
}
+
+ up(&tgfx->sem);
return 0;
}
static void tgfx_close(struct input_dev *dev)
{
struct tgfx *tgfx = dev->private;
+
+ down(&tgfx->sem);
if (!--tgfx->used) {
- del_timer(&tgfx->timer);
+ del_timer_sync(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00);
parport_release(tgfx->pd);
}
+ up(&tgfx->sem);
}
/*
@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
return NULL;
}
- if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) {
+ if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
- memset(tgfx, 0, sizeof(struct tgfx));
+
+ init_MUTEX(&tgfx->sem);
tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);