From: Jim Cromie Rework the module-init function to properly undo initialization steps on failures. Signed-off-by: Jim Cromie Signed-off-by: Andrew Morton --- drivers/char/pc8736x_gpio.c | 35 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff -puN drivers/char/pc8736x_gpio.c~chardev-gpio-for-scx200-pc-8736x-add-platform_device-request-region-series drivers/char/pc8736x_gpio.c --- a/drivers/char/pc8736x_gpio.c~chardev-gpio-for-scx200-pc-8736x-add-platform_device-request-region-series +++ a/drivers/char/pc8736x_gpio.c @@ -242,7 +242,7 @@ static struct file_operations pc8736x_gp static int __init pc8736x_gpio_init(void) { - int r, rc; + int rc = 0; pdev = platform_device_alloc(DEVNAME, 0); if (!pdev) @@ -250,15 +250,15 @@ static int __init pc8736x_gpio_init(void rc = platform_device_add(pdev); if (rc) { - platform_device_put(pdev); - return -ENODEV; + rc = -ENODEV; + goto undo_platform_dev_alloc; } dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n"); if (!pc8736x_superio_present()) { + rc = -ENODEV; dev_err(&pdev->dev, "no device found\n"); - platform_device_put(pdev); - return -ENODEV; + goto undo_platform_dev_add; } /* Verify that chip and it's GPIO unit are both enabled. @@ -266,13 +266,15 @@ static int __init pc8736x_gpio_init(void */ rc = superio_inb(SIO_CF1); if (!(rc & 0x01)) { + rc = -ENODEV; dev_err(&pdev->dev, "device not enabled\n"); - return -ENODEV; + goto undo_platform_dev_add; } device_select(SIO_GPIO_UNIT); if (!superio_inb(SIO_UNIT_ACT)) { + rc = -ENODEV; dev_err(&pdev->dev, "GPIO unit not enabled\n"); - return -ENODEV; + goto undo_platform_dev_add; } /* read the GPIO unit base addr that chip responds to */ @@ -280,24 +282,31 @@ static int __init pc8736x_gpio_init(void | superio_inb(SIO_BASE_LADDR)); if (!request_region(pc8736x_gpio_base, 16, DEVNAME)) { + rc = -ENODEV; dev_err(&pdev->dev, "GPIO ioport %x busy\n", pc8736x_gpio_base); - return -ENODEV; + goto undo_platform_dev_add; } dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base); - r = register_chrdev(major, DEVNAME, &pc8736x_gpio_fops); - if (r < 0) { - dev_err(&pdev->dev, "unable to register character device\n"); - return r; + rc = register_chrdev(major, DEVNAME, &pc8736x_gpio_fops); + if (rc < 0) { + dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc); + goto undo_platform_dev_add; } if (!major) { - major = r; + major = rc; dev_dbg(&pdev->dev, "got dynamic major %d\n", major); } pc8736x_init_shadow(); return 0; + +undo_platform_dev_add: + platform_device_put(pdev); +undo_platform_dev_alloc: + kfree(pdev); + return rc; } static void __exit pc8736x_gpio_cleanup(void) _