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>
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 316c4be..28100d4 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -84,6 +84,7 @@
 	char phys[7][32];
 	int sticks;
 	int used;
+	struct semaphore sem;
 } *tgfx_base[3];
 
 /*
@@ -123,22 +124,33 @@
 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 @@
 		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);