summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2006-11-05 22:39:56 -0500
committerDmitry Torokhov <dtor@insightbb.com>2006-11-05 22:39:56 -0500
commit2b03b60e6b8635fffdd15d5d24943950f2bbf96e (patch)
tree17f0354b7edb08920a89e663ef724c84518c49fa /drivers
parent41ad5fbabda0c3930136bb40cfc7a0c23013365f (diff)
downloadlinux-2b03b60e6b8635fffdd15d5d24943950f2bbf96e.tar.gz
Input: keyboards - handle errors when registering input devices
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/amikbd.c22
-rw-r--r--drivers/input/keyboard/atkbd.c159
-rw-r--r--drivers/input/keyboard/corgikbd.c17
-rw-r--r--drivers/input/keyboard/lkkbd.c14
-rw-r--r--drivers/input/keyboard/locomokbd.c28
-rw-r--r--drivers/input/keyboard/maple_keyb.c14
-rw-r--r--drivers/input/keyboard/newtonkbd.c14
-rw-r--r--drivers/input/keyboard/spitzkbd.c24
-rw-r--r--drivers/input/keyboard/sunkbd.c20
-rw-r--r--drivers/input/keyboard/xtkbd.c14
10 files changed, 234 insertions, 92 deletions
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 8abdbd0ee8f9..16583d71753b 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -190,7 +190,7 @@ static int __init amikbd_init(void)
 	int i, j;
 
 	if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
-		return -EIO;
+		return -ENODEV;
 
 	if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
 		return -EBUSY;
@@ -198,8 +198,8 @@ static int __init amikbd_init(void)
 	amikbd_dev = input_allocate_device();
 	if (!amikbd_dev) {
 		printk(KERN_ERR "amikbd: not enough memory for input device\n");
-		release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto fail1;
 	}
 
 	amikbd_dev->name = "Amiga Keyboard";
@@ -231,10 +231,22 @@ static int __init amikbd_init(void)
 		memcpy(key_maps[i], temp_map, sizeof(temp_map));
 	}
 	ciaa.cra &= ~0x41;	 /* serial data in, turn off TA */
-	request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
+	if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd",
+			amikbd_interrupt)) {
+		err = -EBUSY;
+		goto fail2;
+	}
+
+	err = input_register_device(amikbd_dev);
+	if (err)
+		goto fail3;
 
-	input_register_device(amikbd_dev);
 	return 0;
+
+ fail3:	free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
+ fail2:	input_free_device(amikbd_dev);
+ fail1:	release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
+	return err;
 }
 
 static void __exit amikbd_exit(void)
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index cbb93669d1ce..73c6946b2d92 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -939,7 +939,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 	atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
 	dev = input_allocate_device();
 	if (!atkbd || !dev)
-		goto fail;
+		goto fail1;
 
 	atkbd->dev = dev;
 	ps2_init(&atkbd->ps2dev, serio);
@@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
 	if (atkbd->write) {
 
 		if (atkbd_probe(atkbd)) {
-			serio_close(serio);
 			err = -ENODEV;
-			goto fail;
+			goto fail3;
 		}
 
 		atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 	atkbd_set_keycode_table(atkbd);
 	atkbd_set_device_attrs(atkbd);
 
-	sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
+	err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
+	if (err)
+		goto fail3;
 
 	atkbd_enable(atkbd);
 
-	input_register_device(atkbd->dev);
+	err = input_register_device(atkbd->dev);
+	if (err)
+		goto fail4;
 
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(dev);
+ fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(dev);
 	kfree(atkbd);
 	return err;
 }
@@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
 {
-	struct input_dev *new_dev;
+	struct input_dev *old_dev, *new_dev;
 	unsigned long value;
 	char *rest;
+	int err;
+	unsigned char old_extra, old_set;
 
 	if (!atkbd->write)
 		return -EIO;
@@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
 	if (atkbd->extra != value) {
 		/*
 		 * Since device's properties will change we need to
-		 * unregister old device. But allocate new one first
-		 * to make sure we have it.
+		 * unregister old device. But allocate and register
+		 * new one first to make sure we have it.
 		 */
-		if (!(new_dev = input_allocate_device()))
+		old_dev = atkbd->dev;
+		old_extra = atkbd->extra;
+		old_set = atkbd->set;
+
+		new_dev = input_allocate_device();
+		if (!new_dev)
 			return -ENOMEM;
-		input_unregister_device(atkbd->dev);
+
 		atkbd->dev = new_dev;
 		atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
 		atkbd_activate(atkbd);
+		atkbd_set_keycode_table(atkbd);
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(atkbd->dev);
+
+		err = input_register_device(atkbd->dev);
+		if (err) {
+			input_free_device(new_dev);
+
+			atkbd->dev = old_dev;
+			atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
+			atkbd_set_keycode_table(atkbd);
+			atkbd_set_device_attrs(atkbd);
+
+			return err;
+		}
+		input_unregister_device(old_dev);
+
 	}
 	return count;
 }
@@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
 {
-	struct input_dev *new_dev;
+	struct input_dev *old_dev, *new_dev;
 	unsigned long value;
 	char *rest;
+	int err;
+	unsigned char old_scroll;
 
 	value = simple_strtoul(buf, &rest, 10);
 	if (*rest || value > 1)
 		return -EINVAL;
 
 	if (atkbd->scroll != value) {
-		if (!(new_dev = input_allocate_device()))
+		old_dev = atkbd->dev;
+		old_scroll = atkbd->scroll;
+
+		new_dev = input_allocate_device();
+		if (!new_dev)
 			return -ENOMEM;
-		input_unregister_device(atkbd->dev);
+
 		atkbd->dev = new_dev;
 		atkbd->scroll = value;
 		atkbd_set_keycode_table(atkbd);
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(atkbd->dev);
+
+		err = input_register_device(atkbd->dev);
+		if (err) {
+			input_free_device(new_dev);
+
+			atkbd->scroll = old_scroll;
+			atkbd->dev = old_dev;
+			atkbd_set_keycode_table(atkbd);
+			atkbd_set_device_attrs(atkbd);
+
+			return err;
+		}
+		input_unregister_device(old_dev);
 	}
 	return count;
 }
@@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 {
-	struct input_dev *new_dev;
+	struct input_dev *old_dev, *new_dev;
 	unsigned long value;
 	char *rest;
+	int err;
+	unsigned char old_set, old_extra;
 
 	if (!atkbd->write)
 		return -EIO;
@@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 		return -EINVAL;
 
 	if (atkbd->set != value) {
-		if (!(new_dev = input_allocate_device()))
+		old_dev = atkbd->dev;
+		old_extra = atkbd->extra;
+		old_set = atkbd->set;
+
+		new_dev = input_allocate_device();
+		if (!new_dev)
 			return -ENOMEM;
-		input_unregister_device(atkbd->dev);
+
 		atkbd->dev = new_dev;
 		atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
 		atkbd_activate(atkbd);
 		atkbd_set_keycode_table(atkbd);
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(atkbd->dev);
+
+		err = input_register_device(atkbd->dev);
+		if (err) {
+			input_free_device(new_dev);
+
+			atkbd->dev = old_dev;
+			atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
+			atkbd_set_keycode_table(atkbd);
+			atkbd_set_device_attrs(atkbd);
+
+			return err;
+		}
+		input_unregister_device(old_dev);
 	}
 	return count;
 }
@@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
 {
-	struct input_dev *new_dev;
+	struct input_dev *old_dev, *new_dev;
 	unsigned long value;
 	char *rest;
+	int err;
+	unsigned char old_softrepeat, old_softraw;
 
 	if (!atkbd->write)
 		return -EIO;
@@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
 		return -EINVAL;
 
 	if (atkbd->softrepeat != value) {
-		if (!(new_dev = input_allocate_device()))
+		old_dev = atkbd->dev;
+		old_softrepeat = atkbd->softrepeat;
+		old_softraw = atkbd->softraw;
+
+		new_dev = input_allocate_device();
+		if (!new_dev)
 			return -ENOMEM;
-		input_unregister_device(atkbd->dev);
+
 		atkbd->dev = new_dev;
 		atkbd->softrepeat = value;
 		if (atkbd->softrepeat)
 			atkbd->softraw = 1;
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(atkbd->dev);
+
+		err = input_register_device(atkbd->dev);
+		if (err) {
+			input_free_device(new_dev);
+
+			atkbd->dev = old_dev;
+			atkbd->softrepeat = old_softrepeat;
+			atkbd->softraw = old_softraw;
+			atkbd_set_device_attrs(atkbd);
+
+			return err;
+		}
+		input_unregister_device(old_dev);
 	}
 	return count;
 }
@@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
 {
-	struct input_dev *new_dev;
+	struct input_dev *old_dev, *new_dev;
 	unsigned long value;
 	char *rest;
+	int err;
+	unsigned char old_softraw;
 
 	value = simple_strtoul(buf, &rest, 10);
 	if (*rest || value > 1)
 		return -EINVAL;
 
 	if (atkbd->softraw != value) {
-		if (!(new_dev = input_allocate_device()))
+		old_dev = atkbd->dev;
+		old_softraw = atkbd->softraw;
+
+		new_dev = input_allocate_device();
+		if (!new_dev)
 			return -ENOMEM;
-		input_unregister_device(atkbd->dev);
+
 		atkbd->dev = new_dev;
 		atkbd->softraw = value;
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(atkbd->dev);
+
+		err = input_register_device(atkbd->dev);
+		if (err) {
+			input_free_device(new_dev);
+
+			atkbd->dev = old_dev;
+			atkbd->softraw = old_softraw;
+			atkbd_set_device_attrs(atkbd);
+
+			return err;
+		}
+		input_unregister_device(old_dev);
 	}
 	return count;
 }
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index befdd6006b50..1016c94e65db 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -291,15 +291,12 @@ static int __init corgikbd_probe(struct platform_device *pdev)
 {
 	struct corgikbd *corgikbd;
 	struct input_dev *input_dev;
-	int i;
+	int i, err = -ENOMEM;
 
 	corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
 	input_dev = input_allocate_device();
-	if (!corgikbd || !input_dev) {
-		kfree(corgikbd);
-		input_free_device(input_dev);
-		return -ENOMEM;
-	}
+	if (!corgikbd || !input_dev)
+		goto fail;
 
 	platform_set_drvdata(pdev, corgikbd);
 
@@ -341,7 +338,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
 	set_bit(SW_TABLET_MODE, input_dev->swbit);
 	set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
 
-	input_register_device(corgikbd->input);
+	err = input_register_device(corgikbd->input);
+	if (err)
+		goto fail;
 
 	mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
@@ -362,6 +361,10 @@ static int __init corgikbd_probe(struct platform_device *pdev)
 	pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
 
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(corgikbd);
+	return err;
 }
 
 static int corgikbd_remove(struct platform_device *pdev)
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 708d5a1bc3d2..0067c1fe3d4e 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -651,7 +651,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 	input_dev = input_allocate_device ();
 	if (!lk || !input_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto fail1;
 	}
 
 	lk->serio = serio;
@@ -696,15 +696,19 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 
 	err = serio_open (serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
+
+	err = input_register_device (lk->dev);
+	if (err)
+		goto fail3;
 
-	input_register_device (lk->dev);
 	lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
 
 	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 (lk);
 	return err;
 }
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 5788dbc317bb..2ade5186cc41 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -193,22 +193,22 @@ static int locomokbd_probe(struct locomo_dev *dev)
 {
 	struct locomokbd *locomokbd;
 	struct input_dev *input_dev;
-	int i, ret;
+	int i, err;
 
 	locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!locomokbd || !input_dev) {
-		ret = -ENOMEM;
-		goto free;
+		err = -ENOMEM;
+		goto err_free_mem;
 	}
 
 	/* try and claim memory region */
 	if (!request_mem_region((unsigned long) dev->mapbase,
 				dev->length,
 				LOCOMO_DRIVER_NAME(dev))) {
-		ret = -EBUSY;
+		err = -EBUSY;
 		printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
-		goto free;
+		goto err_free_mem;
 	}
 
 	locomokbd->ldev = dev;
@@ -244,24 +244,28 @@ static int locomokbd_probe(struct locomo_dev *dev)
 	clear_bit(0, input_dev->keybit);
 
 	/* attempt to get the interrupt */
-	ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
-	if (ret) {
+	err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
+	if (err) {
 		printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
-		goto out;
+		goto err_release_region;
 	}
 
-	input_register_device(locomokbd->input);
+	err = input_register_device(locomokbd->input);
+	if (err)
+		goto err_free_irq;
 
 	return 0;
 
-out:
+ err_free_irq:
+	free_irq(dev->irq[0], locomokbd);
+ err_release_region:
 	release_mem_region((unsigned long) dev->mapbase, dev->length);
 	locomo_set_drvdata(dev, NULL);
-free:
+ err_free_mem:
 	input_free_device(input_dev);
 	kfree(locomokbd);
 
-	return ret;
+	return err;
 }
 
 static int locomokbd_remove(struct locomo_dev *dev)
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
index cc6aaf9e85be..99836b3af47b 100644
--- a/drivers/input/keyboard/maple_keyb.c
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -94,13 +94,13 @@ static int dc_kbd_connect(struct maple_device *dev)
 	struct input_dev *input_dev;
 	unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
 	int i;
+	int err;
 
 	dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!kbd || !input_dev) {
-		kfree(kbd);
-		input_free_device(input_dev);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto fail;
 	}
 
 	kbd->dev = input_dev;
@@ -113,10 +113,16 @@ static int dc_kbd_connect(struct maple_device *dev)
 		set_bit(dc_kbd_keycode[i], input_dev->keybit);
 	clear_bit(0, input_dev->keybit);
 
-	input_register_device(kbd->dev);
+	err = input_register_device(kbd->dev);
+	if (err)
+		goto fail;
 
 	maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(kbd);
+	return err;
 }
 
 
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 9282e4e082bd..33e813948d6f 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -91,7 +91,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
 	nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!nkbd || !input_dev)
-		goto fail;
+		goto fail1;
 
 	nkbd->serio = serio;
 	nkbd->dev = input_dev;
@@ -119,13 +119,17 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
+
+	err = input_register_device(nkbd->dev);
+	if (err)
+		goto fail3;
 
-	input_register_device(nkbd->dev);
 	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(nkbd);
 	return err;
 }
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 28b2748e82d0..8a2166c77ff4 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -346,17 +346,12 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 {
 	struct spitzkbd *spitzkbd;
 	struct input_dev *input_dev;
-	int i;
+	int i, err = -ENOMEM;
 
 	spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
-	if (!spitzkbd)
-		return -ENOMEM;
-
 	input_dev = input_allocate_device();
-	if (!input_dev) {
-		kfree(spitzkbd);
-		return -ENOMEM;
-	}
+	if (!spitzkbd || !input_dev)
+		goto fail;
 
 	platform_set_drvdata(dev, spitzkbd);
 	strcpy(spitzkbd->phys, "spitzkbd/input0");
@@ -400,7 +395,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 	set_bit(SW_TABLET_MODE, input_dev->swbit);
 	set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
 
-	input_register_device(input_dev);
+	err = input_register_device(input_dev);
+	if (err)
+		goto fail;
 
 	mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
@@ -434,13 +431,15 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 	request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
 		    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 		    "Spitzkbd SWB", spitzkbd);
- 	request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
+	request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
 		    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 		    "Spitzkbd HP", spitzkbd);
 
-	printk(KERN_INFO "input: Spitz Keyboard Registered\n");
-
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(spitzkbd);
+	return err;
 }
 
 static int spitzkbd_remove(struct platform_device *dev)
@@ -474,6 +473,7 @@ static struct platform_driver spitzkbd_driver = {
 	.resume		= spitzkbd_resume,
 	.driver		= {
 		.name	= "spitz-keyboard",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index cac4781103c3..d1b62f77a716 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -243,7 +243,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 	sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!sunkbd || !input_dev)
-		goto fail;
+		goto fail1;
 
 	sunkbd->serio = serio;
 	sunkbd->dev = input_dev;
@@ -255,11 +255,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
 
 	if (sunkbd_initialize(sunkbd) < 0) {
-		serio_close(serio);
-		goto fail;
+		err = -ENODEV;
+		goto fail3;
 	}
 
 	snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type);
@@ -287,11 +287,17 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 	clear_bit(0, input_dev->keybit);
 
 	sunkbd_enable(sunkbd, 1);
-	input_register_device(sunkbd->dev);
+
+	err = input_register_device(sunkbd->dev);
+	if (err)
+		goto fail4;
+
 	return 0;
 
- fail:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+ fail4:	sunkbd_enable(sunkbd, 0);
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
 	kfree(sunkbd);
 	return err;
 }
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 8c11dc935454..b53f71638583 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -95,7 +95,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 	xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!xtkbd || !input_dev)
-		goto fail;
+		goto fail1;
 
 	xtkbd->serio = serio;
 	xtkbd->dev = input_dev;
@@ -124,13 +124,17 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail;
+		goto fail2;
+
+	err = input_register_device(xtkbd->dev);
+	if (err)
+		goto fail3;
 
-	input_register_device(xtkbd->dev);
 	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(xtkbd);
 	return err;
 }