Input: joysticks - handle errors when registering input devices

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 704bf70..6279ced 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -521,11 +521,19 @@
 	for (i = 0; i < 2; i++)
 		if (port->adi[i].length > 0) {
 			adi_init_center(port->adi + i);
-			input_register_device(port->adi[i].dev);
+			err = input_register_device(port->adi[i].dev);
+			if (err)
+				goto fail3;
 		}
 
 	return 0;
 
+ fail3: while (--i >= 0) {
+		if (port->adi[i].length > 0) {
+			input_unregister_device(port->adi[i].dev);
+			port->adi[i].dev = NULL;
+		}
+	}
  fail2:	for (i = 0; i < 2; i++)
 		if (port->adi[i].dev)
 			input_free_device(port->adi[i].dev);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 650acf3..e608691 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -147,7 +147,11 @@
 			amijoy_dev[i]->absmax[ABS_X + j] = 1;
 		}
 
-		input_register_device(amijoy_dev[i]);
+		err = input_register_device(amijoy_dev[i]);
+		if (err) {
+			input_free_device(amijoy_dev[i]);
+			goto fail;
+		}
 	}
 	return 0;
 
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index e9a02db..7ef6845 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -434,6 +434,7 @@
 {
 	struct input_dev *input_dev;
 	int i, j, t, v, w, x, y, z;
+	int error;
 
 	analog_name(analog);
 	snprintf(analog->phys, sizeof(analog->phys),
@@ -505,7 +506,11 @@
 
 	analog_decode(analog, port->axes, port->initial, port->buttons);
 
-	input_register_device(analog->dev);
+	error = input_register_device(analog->dev);
+	if (error) {
+		input_free_device(analog->dev);
+		return error;
+	}
 
 	return 0;
 }
@@ -668,7 +673,8 @@
 	return 0;
 
  fail3: while (--i >= 0)
-		input_unregister_device(port->analog[i].dev);
+		if (port->analog[i].mask)
+			input_unregister_device(port->analog[i].dev);
  fail2:	gameport_close(gameport);
  fail1:	gameport_set_drvdata(gameport, NULL);
 	kfree(port);
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index d5e42eb..034ec39 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -223,12 +223,15 @@
 		for (j = 0; cobra_btn[j]; j++)
 			set_bit(cobra_btn[j], input_dev->keybit);
 
-		input_register_device(cobra->dev[i]);
+		err = input_register_device(cobra->dev[i]);
+		if (err)
+			goto fail4;
 	}
 
 	return 0;
 
- fail3:	for (i = 0; i < 2; i++)
+ fail4:	input_free_device(cobra->dev[i]);
+ fail3:	while (--i >= 0)
 		if (cobra->dev[i])
 			input_unregister_device(cobra->dev[i]);
  fail2:	gameport_close(gameport);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index e4a699f..bacbab5 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -341,7 +341,9 @@
 		input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
 	}
 
-	input_register_device(gf2k->dev);
+	err = input_register_device(gf2k->dev);
+	if (err)
+		goto fail2;
 
 	return 0;
 
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 6243894..8120a9c 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -423,7 +423,10 @@
 
 		if (!port->registered) {
 			dbg("New Grip pad in multiport slot %d.\n", slot);
-			register_slot(slot, grip);
+			if (register_slot(slot, grip)) {
+				port->mode = GRIP_MODE_RESET;
+				port->dirty = 0;
+			}
 		}
 		return flags;
 	}
@@ -585,6 +588,7 @@
 	struct grip_port *port = grip->port[slot];
 	struct input_dev *input_dev;
 	int j, t;
+	int err;
 
 	port->dev = input_dev = input_allocate_device();
 	if (!input_dev)
@@ -610,7 +614,12 @@
 		if (t > 0)
 			set_bit(t, input_dev->keybit);
 
-	input_register_device(port->dev);
+	err = input_register_device(port->dev);
+	if (err) {
+		input_free_device(port->dev);
+		return err;
+	}
+
 	port->registered = 1;
 
 	if (port->dirty)	            /* report initial state, if any */
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 840ed9b..dbc5d92 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -250,7 +250,9 @@
 	for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
 		set_bit(t, input_dev->keybit);
 
-	input_register_device(guillemot->dev);
+	err = input_register_device(guillemot->dev);
+	if (err)
+		goto fail2;
 
 	return 0;
 
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 24c684b..706e0ae 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -325,8 +325,8 @@
 
 	if (i == 20) { /* 5 seconds */
 		printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
-		input_free_device(input_dev);
-		return -ENODEV;
+		error = -ENODEV;
+		goto fail;
 	}
 
 /*
@@ -439,10 +439,8 @@
 			set_bit(iforce->type->ff[i], input_dev->ffbit);
 
 		error = input_ff_create(input_dev, ff_effects);
-		if (error) {
-			input_free_device(input_dev);
-			return error;
-		}
+		if (error)
+			goto fail;
 
 		ff = input_dev->ff;
 		ff->upload = iforce_upload_effect;
@@ -455,11 +453,16 @@
  * Register input device.
  */
 
-	input_register_device(iforce->dev);
+	error = input_register_device(iforce->dev);
+	if (error)
+		goto fail;
 
 	printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
 
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	return error;
 }
 
 static int __init iforce_init(void)
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index ca08f45..ec4be53 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -141,21 +141,19 @@
 	serio_set_drvdata(serio, iforce);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(iforce);
-		return err;
-	}
+	if (err)
+		goto fail1;
 
 	err = iforce_init_device(iforce);
-	if (err) {
-		serio_close(serio);
-		serio_set_drvdata(serio, NULL);
-		kfree(iforce);
-		return -ENODEV;
-	}
+	if (err)
+		goto fail2;
 
 	return 0;
+
+ fail2:	serio_close(serio);
+ fail1:	serio_set_drvdata(serio, NULL);
+	kfree(iforce);
+	return err;
 }
 
 static void iforce_serio_disconnect(struct serio *serio)
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index bbfeb9c..fec8b3d 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -283,7 +283,9 @@
 	for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
 		set_bit(t, input_dev->keybit);
 
-	input_register_device(interact->dev);
+	err = input_register_device(interact->dev);
+	if (err)
+		goto fail2;
 
 	return 0;
 
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index e3d1944..d512b0a 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -157,7 +157,7 @@
 	magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!magellan || !input_dev)
-		goto fail;
+		goto fail1;
 
 	magellan->dev = input_dev;
 	snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys);
@@ -183,13 +183,17 @@
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
-	input_register_device(magellan->dev);
+	err = input_register_device(magellan->dev);
+	if (err)
+		goto fail3;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(magellan);
 	return err;
 }
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 2a9808c..9b35973 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -215,7 +215,7 @@
 	spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!spaceball || !input_dev)
-		goto fail;
+		goto fail1;
 
 	spaceball->dev = input_dev;
 	snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys);
@@ -252,13 +252,17 @@
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
-	input_register_device(spaceball->dev);
+	err = input_register_device(spaceball->dev);
+	if (err)
+		goto fail3;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(spaceball);
 	return err;
 }
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index c4db024..ea9d51e 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -172,7 +172,7 @@
 	spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!spaceorb || !input_dev)
-		goto fail;
+		goto fail1;
 
 	spaceorb->dev = input_dev;
 	snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys);
@@ -198,13 +198,17 @@
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
-	input_register_device(spaceorb->dev);
+	err = input_register_device(spaceorb->dev);
+	if (err)
+		goto fail3;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(spaceorb);
 	return err;
 }
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 1ffb032..b51a4a4 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -143,7 +143,7 @@
 	stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!stinger || !input_dev)
-		goto fail;
+		goto fail1;
 
 	stinger->dev = input_dev;
 	snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys);
@@ -168,13 +168,17 @@
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
-	input_register_device(stinger->dev);
+	err = input_register_device(stinger->dev);
+	if (err)
+		goto fail3;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(stinger);
 	return err;
 }
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 49085df..3c1c83e 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -194,7 +194,7 @@
 	twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!twidjoy || !input_dev)
-		goto fail;
+		goto fail1;
 
 	twidjoy->dev = input_dev;
 	snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys);
@@ -221,13 +221,17 @@
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
-	input_register_device(twidjoy->dev);
+	err = input_register_device(twidjoy->dev);
+	if (err)
+		goto fail3;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(twidjoy);
 	return err;
 }
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 35edea1..1e4828b 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -149,7 +149,7 @@
 	warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!warrior || !input_dev)
-		goto fail;
+		goto fail1;
 
 	warrior->dev = input_dev;
 	snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys);
@@ -176,13 +176,17 @@
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
-	input_register_device(warrior->dev);
+	err = input_register_device(warrior->dev);
+	if (err)
+		goto fail3;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(warrior);
 	return err;
 }