Add undock attribute to dock sysfs Add an undock attribute to the dock_station kobject and export it via sysfs. Anything written to this file will cause an undock event to be triggered. Warning: Compile tested only Signed-off-by: Brandon Philips --- drivers/acpi/dock.c | 78 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 17 deletions(-) Index: linux-2.6-rc/drivers/acpi/dock.c =================================================================== --- linux-2.6-rc.orig/drivers/acpi/dock.c +++ linux-2.6-rc/drivers/acpi/dock.c @@ -511,6 +511,37 @@ void unregister_hotplug_dock_device(acpi EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); /** + * handle_eject_request - handle an undock request checking for error conditions + * + * Check to make sure the dock device is still present, then undock and + * hotremove all the devices that may need removing. + */ +static int handle_eject_request(struct dock_station *ds, u32 event) +{ + if (!dock_present(ds)) + return -ENODEV; + + if (dock_in_progress(ds)) + return -EBUSY; + + /* + * here we need to generate the undock + * event prior to actually doing the undock + * so that the device struct still exists. + */ + dock_event(ds, event, UNDOCK_EVENT); + hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); + undock(ds); + eject_dock(ds); + if (dock_present(ds)) { + printk(KERN_ERR PREFIX "Unable to undock!\n"); + return -EBUSY; + } + + return 0; +} + +/** * dock_notify - act upon an acpi dock notification * @handle: the dock station handle * @event: the acpi event @@ -518,9 +549,7 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_doc * * If we are notified to dock, then check to see if the dock is * present and then dock. Notify all drivers of the dock event, - * and then hotplug and devices that may need hotplugging. For undock - * check to make sure the dock device is still present, then undock - * and hotremove all the devices that may need removing. + * and then hotplug and devices that may need hotplugging. */ static void dock_notify(acpi_handle handle, u32 event, void *data) { @@ -552,19 +581,7 @@ static void dock_notify(acpi_handle hand * to the driver who wish to hotplug. */ case ACPI_NOTIFY_EJECT_REQUEST: - if (!dock_in_progress(ds) && dock_present(ds)) { - /* - * here we need to generate the undock - * event prior to actually doing the undock - * so that the device struct still exists. - */ - dock_event(ds, event, UNDOCK_EVENT); - hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); - undock(ds); - eject_dock(ds); - if (dock_present(ds)) - printk(KERN_ERR PREFIX "Unable to undock!\n"); - } + handle_eject_request(ds, event); break; default: printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); @@ -617,9 +634,29 @@ static ssize_t show_docked(struct acpi_d } ACPI_DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); +/* + * write_undock - write method for "undock" file in sysfs + * + * anything written to this file will cause an undock to be written + */ +static ssize_t write_undock(struct acpi_device *dev, const char *buf, size_t count) +{ + struct dock_station *ds = (struct dock_station *)dev->driver_data; + int ret; + + if (!count) + return -EINVAL; + + ret = handle_eject_request(ds, ACPI_NOTIFY_EJECT_REQUEST); + + return ret ? ret: count; +} +ACPI_DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); + static void dock_remove_sysfs_files(struct acpi_device *ad) { sysfs_remove_file(&ad->kobj, &acpi_device_attr_docked.attr); + sysfs_remove_file(&ad->kobj, &acpi_device_attr_undock.attr); } static int dock_add_sysfs_files(struct acpi_device *ad) @@ -628,8 +665,15 @@ static int dock_add_sysfs_files(struct a ret = sysfs_create_file(&ad->kobj, &acpi_device_attr_docked.attr); if (ret) - dock_remove_sysfs_files(ad);; + goto error; + ret = sysfs_create_file(&ad->kobj, &acpi_device_attr_undock.attr); + if (ret) + goto error; + + return 0; +error: + dock_remove_sysfs_files(ad);; return ret; }