From: Bjorn Helgaas Change acpi_bus_register_driver() to return zero on success, negative error on failure, like pci_register_driver() now does. Also fix the asus_acpi and thinkpad_acpi drivers, which had screwed up register/unregister behavior. (The driver should remain registered as long as it is loaded, regardless of whether devices were claimed at acpi_bus_register_driver()-time). Finally, the floppy and i8042 ACPI hooks need tweaking because they relied on the "number of devices claimed" return value. These are exceptions to the general rule in that they register/unregister immediately because all they need is presence and resource information and there's no hope of them dealing with hot-plug. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton --- 25-akpm/drivers/acpi/asus_acpi.c | 3 - 25-akpm/drivers/acpi/scan.c | 38 ++++++--------- 25-akpm/drivers/block/floppy.c | 56 +++++++++++------------ 25-akpm/drivers/input/serio/i8042-x86ia64io.h | 63 +++++++++++++------------- 4 files changed, 75 insertions(+), 85 deletions(-) diff -puN drivers/acpi/asus_acpi.c~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again drivers/acpi/asus_acpi.c --- 25/drivers/acpi/asus_acpi.c~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again 2004-11-30 01:24:11.827847616 -0800 +++ 25-akpm/drivers/acpi/asus_acpi.c 2004-11-30 01:24:11.837846096 -0800 @@ -1212,8 +1212,7 @@ static int __init asus_acpi_init(void) asus_proc_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&asus_hotk_driver); - if (result < 1) { - acpi_bus_unregister_driver(&asus_hotk_driver); + if (result < 0) { remove_proc_entry(PROC_ASUS, acpi_root_dir); return -ENODEV; } diff -puN drivers/acpi/scan.c~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again drivers/acpi/scan.c --- 25/drivers/acpi/scan.c~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again 2004-11-30 01:24:11.829847312 -0800 +++ 25-akpm/drivers/acpi/scan.c 2004-11-30 01:24:11.838845944 -0800 @@ -532,10 +532,9 @@ acpi_bus_driver_init ( return_VALUE(0); } -static int acpi_driver_attach(struct acpi_driver * drv) +static void acpi_driver_attach(struct acpi_driver * drv) { struct list_head * node, * next; - int count = 0; ACPI_FUNCTION_TRACE("acpi_driver_attach"); @@ -550,7 +549,6 @@ static int acpi_driver_attach(struct acp if (!acpi_bus_match(dev, drv)) { if (!acpi_bus_driver_init(dev, drv)) { atomic_inc(&drv->references); - count++; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", drv->name, dev->pnp.bus_id)); } @@ -558,7 +556,6 @@ static int acpi_driver_attach(struct acp spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); - return_VALUE(count); } static int acpi_driver_detach(struct acpi_driver * drv) @@ -589,16 +586,13 @@ static int acpi_driver_detach(struct acp * acpi_bus_register_driver * ------------------------ * Registers a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and binds. Returns the - * number of devices that were claimed by the driver, or a negative - * error status for failure. + * devices that match the driver's criteria and binds. Returns zero for + * success or a negative error status for failure. */ int acpi_bus_register_driver ( struct acpi_driver *driver) { - int count; - ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); if (acpi_disabled) @@ -610,9 +604,9 @@ acpi_bus_register_driver ( spin_lock(&acpi_device_lock); list_add_tail(&driver->node, &acpi_bus_drivers); spin_unlock(&acpi_device_lock); - count = acpi_driver_attach(driver); + acpi_driver_attach(driver); - return_VALUE(count); + return_VALUE(0); } @@ -626,21 +620,19 @@ int acpi_bus_unregister_driver ( struct acpi_driver *driver) { - int error = 0; - ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); - if (driver) { - acpi_driver_detach(driver); + if (!driver) + return_VALUE(-EINVAL); - if (!atomic_read(&driver->references)) { - spin_lock(&acpi_device_lock); - list_del_init(&driver->node); - spin_unlock(&acpi_device_lock); - } - } else - error = -EINVAL; - return_VALUE(error); + acpi_driver_detach(driver); + + if (!atomic_read(&driver->references)) { + spin_lock(&acpi_device_lock); + list_del_init(&driver->node); + spin_unlock(&acpi_device_lock); + } + return_VALUE(0); } /** diff -puN drivers/block/floppy.c~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again drivers/block/floppy.c --- 25/drivers/block/floppy.c~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again 2004-11-30 01:24:11.831847008 -0800 +++ 25-akpm/drivers/block/floppy.c 2004-11-30 01:24:11.842845336 -0800 @@ -4234,7 +4234,6 @@ static struct kobject *floppy_find(dev_t } #ifdef CONFIG_ACPI -static int acpi_floppy_registered; static int acpi_floppies; struct region { @@ -4249,7 +4248,7 @@ struct floppy_resources { unsigned int dma_channel; }; -static acpi_status acpi_floppy_resource(struct acpi_resource *res, void *data) +static acpi_status __init acpi_floppy_resource(struct acpi_resource *res, void *data) { struct floppy_resources *fd = (struct floppy_resources *) data; struct acpi_resource_io *io; @@ -4290,7 +4289,7 @@ static acpi_status acpi_floppy_resource( return AE_OK; } -static int acpi_floppy_add(struct acpi_device *device) +static int __init acpi_floppy_add(struct acpi_device *device) { struct floppy_resources fd; acpi_status status; @@ -4304,7 +4303,7 @@ static int acpi_floppy_add(struct acpi_d strncpy(acpi_device_name(device), "Floppy Controller", sizeof(acpi_device_name(device))); - printk("ACPI: %s [%s] at I/O 0x%x-0x%x", + printk(KERN_INFO "ACPI: %s [%s] at I/O 0x%x-0x%x", acpi_device_name(device), acpi_device_bid(device), fd.io_region[0].base, fd.io_region[0].base + fd.io_region[0].size - 1); @@ -4363,7 +4362,7 @@ static int acpi_floppy_add(struct acpi_d return 0; } -static struct acpi_driver acpi_floppy_driver = { +static struct acpi_driver acpi_floppy_driver __initdata = { .name = "floppy", .ids = "PNP0700", .ops = { @@ -4371,30 +4370,32 @@ static struct acpi_driver acpi_floppy_dr }, }; -static int acpi_floppy_init(void) +/* + * Return -ENODEV if ACPI claims no floppy controllers exist. Otherwise, + * return zero after possibly updating the default I/O port and IRQ resources. + */ +static int __init acpi_floppy_init(void) { int err; if (no_acpi_floppy) { - printk("%s: ACPI detection disabled\n", DEVICE_NAME); - return -ENODEV; + printk(KERN_INFO "%s: ACPI detection disabled\n", DEVICE_NAME); + return 0; } err = acpi_bus_register_driver(&acpi_floppy_driver); - if (err >= 0) - acpi_floppy_registered = 1; - return err; -} + if (err < 0) + return 0; /* can't tell anything from ACPI */ -static void acpi_floppy_exit(void) -{ - if (acpi_floppy_registered) { - acpi_bus_unregister_driver(&acpi_floppy_driver); - acpi_floppy_registered = 0; - } + /* + * All we needed was the number of floppy controllers and their + * resources, and we can't deal with any sort of hotplug, so might as + * well unregister now. + */ + acpi_bus_unregister_driver(&acpi_floppy_driver); + if (acpi_floppies == 0) + return -ENODEV; /* ACPI says "no floppies here" */ + return 0; } -#else -static inline int acpi_floppy_init(void) { return -ENODEV; } -static inline void acpi_floppy_exit(void) { } #endif int __init floppy_init(void) @@ -4402,10 +4403,11 @@ int __init floppy_init(void) int i, unit, drive; int err, dr; - if (acpi_floppy_init() == 0) { - err = -ENODEV; - goto out_put_acpi; - } +#ifdef CONFIG_ACPI + err = acpi_floppy_init(); + if (err < 0) + return err; +#endif raw_cmd = NULL; @@ -4597,8 +4599,6 @@ out_put_disk: del_timer(&motor_off_timer[dr]); put_disk(disks[dr]); } -out_put_acpi: - acpi_floppy_exit(); return err; } @@ -4815,8 +4815,6 @@ void cleanup_module(void) /* eject disk, if any */ fd_eject(0); - acpi_floppy_exit(); - wait_for_completion(&device_release); } diff -puN drivers/input/serio/i8042-x86ia64io.h~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again drivers/input/serio/i8042-x86ia64io.h --- 25/drivers/input/serio/i8042-x86ia64io.h~make-acpi_bus_register_driver-consistent-with-pci_register_driver-again 2004-11-30 01:24:11.833846704 -0800 +++ 25-akpm/drivers/input/serio/i8042-x86ia64io.h 2004-11-30 01:24:11.843845184 -0800 @@ -98,9 +98,6 @@ struct i8042_acpi_resources { unsigned int irq; }; -static int i8042_acpi_kbd_registered; -static int i8042_acpi_aux_registered; - static acpi_status i8042_acpi_parse_resource(struct acpi_resource *res, void *data) { struct i8042_acpi_resources *i8042_res = data; @@ -151,6 +148,8 @@ static acpi_status i8042_acpi_parse_reso return AE_OK; } +static int i8042_acpi_kbd_found; + static int i8042_acpi_kbd_add(struct acpi_device *device) { struct i8042_acpi_resources kbd_res; @@ -182,13 +181,16 @@ static int i8042_acpi_kbd_add(struct acp strncpy(acpi_device_name(device), "PS/2 Keyboard Controller", sizeof(acpi_device_name(device))); - printk("ACPI: %s [%s] at I/O 0x%x, 0x%x, irq %d\n", + printk(KERN_INFO "ACPI: %s [%s] at I/O 0x%x, 0x%x, irq %d\n", acpi_device_name(device), acpi_device_bid(device), i8042_data_reg, i8042_command_reg, i8042_kbd_irq); + i8042_acpi_kbd_found = 1; return 0; } +static int i8042_acpi_aux_found; + static int i8042_acpi_aux_add(struct acpi_device *device) { struct i8042_acpi_resources aux_res; @@ -208,8 +210,9 @@ static int i8042_acpi_aux_add(struct acp strncpy(acpi_device_name(device), "PS/2 Mouse Controller", sizeof(acpi_device_name(device))); - printk("ACPI: %s [%s] at irq %d\n", - acpi_device_name(device), acpi_device_bid(device), i8042_aux_irq); + printk(KERN_INFO "ACPI: %s [%s] at irq %d\n", acpi_device_name(device), + acpi_device_bid(device), i8042_aux_irq); + i8042_acpi_aux_found = 1; return 0; } @@ -230,41 +233,42 @@ static struct acpi_driver i8042_acpi_aux }, }; +/* + * Return -ENODEV if ACPI claims no i8042 controllers exist. Otherwise, + * return zero after possibly updating the default I/O port and IRQ resources. + */ static int i8042_acpi_init(void) { int result; - if (acpi_disabled || i8042_noacpi) { - printk("i8042: ACPI detection disabled\n"); + if (i8042_noacpi) { + printk(KERN_INFO "i8042: ACPI detection disabled\n"); return 0; } result = acpi_bus_register_driver(&i8042_acpi_kbd_driver); if (result < 0) - return result; + return 0; /* can't tell from ACPI */ - if (result == 0) { - acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); - return -ENODEV; - } - i8042_acpi_kbd_registered = 1; + /* + * All we needed was whether an i8042 is present and the resources, + * and we can't deal with any sort of hotplug, so might as well + * unregister now. + */ + acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); + if (i8042_acpi_kbd_found == 0) + return -ENODEV; /* ACPI says "no i8042 here" */ + i8042_noaux = 1; result = acpi_bus_register_driver(&i8042_acpi_aux_driver); - if (result >= 0) - i8042_acpi_aux_registered = 1; - if (result == 0) - i8042_noaux = 1; - - return 0; -} + if (result < 0) + return 0; -static void i8042_acpi_exit(void) -{ - if (i8042_acpi_kbd_registered) - acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); + acpi_bus_unregister_driver(&i8042_acpi_aux_driver); + if (i8042_acpi_aux_found) + i8042_noaux = 0; - if (i8042_acpi_aux_registered) - acpi_bus_unregister_driver(&i8042_acpi_aux_driver); + return 0; } #endif @@ -282,7 +286,7 @@ static inline int i8042_platform_init(vo i8042_aux_irq = I8042_MAP_IRQ(12); #ifdef CONFIG_ACPI - if (i8042_acpi_init()) + if (i8042_acpi_init() < 0) return -1; #endif @@ -300,9 +304,6 @@ static inline int i8042_platform_init(vo static inline void i8042_platform_exit(void) { -#ifdef CONFIG_ACPI - i8042_acpi_exit(); -#endif } #endif /* _I8042_X86IA64IO_H */ _