Index: linux-2.6.18-rc7/drivers/acpi/battery.c =================================================================== --- linux-2.6.18-rc7.orig/drivers/acpi/battery.c +++ linux-2.6.18-rc7/drivers/acpi/battery.c @@ -64,6 +64,7 @@ extern void *acpi_unlock_battery_dir(str static int acpi_battery_add(struct acpi_device *device); static int acpi_battery_remove(struct acpi_device *device, int type); +static void acpi_battery_notify(acpi_handle handle, u32 event, void *data); static struct acpi_driver acpi_battery_driver = { .name = ACPI_BATTERY_DRIVER_NAME, @@ -72,6 +73,7 @@ static struct acpi_driver acpi_battery_d .ops = { .add = acpi_battery_add, .remove = acpi_battery_remove, + .notify_handler = acpi_battery_notify, }, }; @@ -685,7 +687,7 @@ static void acpi_battery_notify(acpi_han static int acpi_battery_add(struct acpi_device *device) { int result = 0; - acpi_status status = 0; + // acpi_status status = 0; struct acpi_battery *battery = NULL; @@ -710,13 +712,16 @@ static int acpi_battery_add(struct acpi_ if (result) goto end; + /* Not needed any more... status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); + if (ACPI_FAILURE(status)) { result = -ENODEV; goto end; } + */ printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), @@ -733,7 +738,7 @@ static int acpi_battery_add(struct acpi_ static int acpi_battery_remove(struct acpi_device *device, int type) { - acpi_status status = 0; + // acpi_status status = 0; struct acpi_battery *battery = NULL; @@ -742,9 +747,11 @@ static int acpi_battery_remove(struct ac battery = (struct acpi_battery *)acpi_driver_data(device); + /* status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); + */ acpi_battery_remove_fs(device); Index: linux-2.6.18-rc7/drivers/acpi/scan.c =================================================================== --- linux-2.6.18-rc7.orig/drivers/acpi/scan.c +++ linux-2.6.18-rc7/drivers/acpi/scan.c @@ -478,6 +478,60 @@ acpi_bus_match(struct acpi_device *devic return acpi_match_ids(device, driver->ids); } +static void acpi_generic_notify(acpi_handle handle, u32 event, void *data){ + + struct acpi_device *device = (struct acpi_device*)data; + int present = device->status.present; + acpi_status status; + + printk (KERN_INFO "Generic notifier for %s called", + acpi_device_bid(device)); + if (device->driver->ops.notify_handler){ + printk (KERN_INFO "Calling specific notifier for %s called", + acpi_device_bid(device)); + device->driver->ops.notify_handler(handle, event, + acpi_driver_data(device)); + } + + /* call start/stop before or after calling notify handler + or not at all if there is a handler? */ + if (device->flags.dynamic_status){ + status = acpi_bus_get_status(device); + if (ACPI_FAILURE(status)){ + ACPI_EXCEPTION ((AE_INFO, status, "Error getting" + "status of device %s", + acpi_device_bid(device))); + } + if (present != device->status.present){ + if (device->status.present && device->driver->ops.start) + device->driver->ops.start(device); + else if (device->driver->ops.start) + /* we might want to pass separate stop reasons... + switch(event){ + */ + device->driver->ops.stop(device, ACPI_BUS_REMOVAL_NORMAL); + } + } +} + +int acpi_driver_install_notifier(struct acpi_device *device){ + + acpi_status status; + + if (device->driver->ops.notify_handler){ + status = acpi_install_notify_handler(device->handle, + ACPI_ALL_NOTIFY, + acpi_generic_notify, + acpi_driver_data(device)); + if (ACPI_FAILURE(status)){ + ACPI_EXCEPTION ((AE_INFO, status, "Could not install notify" + "handler for %s", acpi_device_bid(device))); + return -ENODEV; + } + } + return 0; +} + /** * acpi_bus_driver_init - add a device to a driver * @device: the device to add and initialize @@ -490,7 +544,8 @@ static int acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) { int result = 0; - + int type; + acpi_status status; if (!device || !driver) return -EINVAL; @@ -507,6 +562,21 @@ acpi_bus_driver_init(struct acpi_device device->driver = driver; + status = acpi_get_type(device->handle, &type); + + if (ACPI_FAILURE(status)){ + ACPI_EXCEPTION ((AE_INFO, status, "Could not get type for" + "device %s will not install notify handler", + acpi_device_bid(device))); + } + + /* fixed feature stuff has extra handlers... see below */ + if (type != ACPI_BUS_TYPE_POWER_BUTTON && + type != ACPI_BUS_TYPE_SLEEP_BUTTON) { + if (driver->ops.notify_handler) + acpi_driver_install_notifier(device); + } + /* * TBD - Configuration Management: Assign resources to device based * upon possible configuration and currently allocated resources. @@ -545,17 +615,21 @@ static void acpi_driver_attach(struct ac struct acpi_device *dev = container_of(node, struct acpi_device, g_list); - if (dev->driver || !dev->status.present) + if (dev->driver) continue; spin_unlock(&acpi_device_lock); if (!acpi_bus_match(dev, drv)) { if (!acpi_bus_driver_init(dev, drv)) { - acpi_start_single_object(dev); - atomic_inc(&drv->references); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found driver [%s] for device [%s]\n", - drv->name, dev->pnp.bus_id)); + if (dev->status.present){ + acpi_start_single_object(dev); + atomic_inc(&drv->references); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found driver [%s]" + " for device [%s]\n", + drv->name, + dev->pnp.bus_id)); + } } } spin_lock(&acpi_device_lock); @@ -604,7 +678,6 @@ int acpi_bus_register_driver(struct acpi list_add_tail(&driver->node, &acpi_bus_drivers); spin_unlock(&acpi_device_lock); acpi_driver_attach(driver); - return 0; } Index: linux-2.6.18-rc7/include/acpi/acpi_bus.h =================================================================== --- linux-2.6.18-rc7.orig/include/acpi/acpi_bus.h +++ linux-2.6.18-rc7/include/acpi/acpi_bus.h @@ -87,18 +87,20 @@ struct acpi_device; * ----------- */ -typedef int (*acpi_op_add) (struct acpi_device * device); -typedef int (*acpi_op_remove) (struct acpi_device * device, int type); -typedef int (*acpi_op_lock) (struct acpi_device * device, int type); -typedef int (*acpi_op_start) (struct acpi_device * device); -typedef int (*acpi_op_stop) (struct acpi_device * device, int type); -typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); -typedef int (*acpi_op_resume) (struct acpi_device * device, int state); -typedef int (*acpi_op_scan) (struct acpi_device * device); -typedef int (*acpi_op_bind) (struct acpi_device * device); -typedef int (*acpi_op_unbind) (struct acpi_device * device); -typedef int (*acpi_op_match) (struct acpi_device * device, +typedef int (*acpi_op_add) (struct acpi_device * device); +typedef int (*acpi_op_remove) (struct acpi_device * device, int type); +typedef int (*acpi_op_lock) (struct acpi_device * device, int type); +typedef int (*acpi_op_start) (struct acpi_device * device); +typedef int (*acpi_op_stop) (struct acpi_device * device, int type); +typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); +typedef int (*acpi_op_resume) (struct acpi_device * device, int state); +typedef int (*acpi_op_scan) (struct acpi_device * device); +typedef int (*acpi_op_bind) (struct acpi_device * device); +typedef int (*acpi_op_unbind) (struct acpi_device * device); +typedef int (*acpi_op_match) (struct acpi_device * device, struct acpi_driver * driver); +typedef void (*acpi_op_notify_handler) (acpi_handle handle, + u32 event, void *data); struct acpi_bus_ops { u32 acpi_op_add:1; @@ -112,7 +114,8 @@ struct acpi_bus_ops { u32 acpi_op_bind:1; u32 acpi_op_unbind:1; u32 acpi_op_match:1; - u32 reserved:21; + u32 acpi_op_notify_handler:1; + u32 reserved:20; }; struct acpi_device_ops { @@ -127,6 +130,7 @@ struct acpi_device_ops { acpi_op_bind bind; acpi_op_unbind unbind; acpi_op_match match; + acpi_op_notify_handler notify_handler; }; struct acpi_driver {