From akpm@osdl.org Thu Apr 28 00:28:59 2005 Subject: [patch 17/20] acpi hotplug: decouple slot power state changes from physical hotplug To: greg@kroah.com Cc: akpm@osdl.org, rajesh.shah@intel.com From: akpm@osdl.org Date: Thu, 28 Apr 2005 00:25:57 -0700 From: Rajesh Shah Current acpiphp code does not distinguish between the physical presence and power state of a device/slot. That is, if a device has to be disabled, it also tries to physically ejects the device. This patch decouples power state from physical presence. You can now echo to the corresponding sysfs power control file to repeatedly enable and disable a device without having to physically re-insert it. Signed-off-by: Rajesh Shah Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 69 ++++++++++++++++++++----------------- 1 files changed, 38 insertions(+), 31 deletions(-) --- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c 2005-05-03 22:28:48.000000000 -0700 +++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c 2005-05-03 22:28:50.000000000 -0700 @@ -592,8 +592,6 @@ acpi_status status; struct acpiphp_func *func; struct list_head *l; - struct acpi_object_list arg_list; - union acpi_object arg; int retval = 0; @@ -615,27 +613,6 @@ } } - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); - - /* We don't want to call _EJ0 on non-existing functions. */ - if (func->flags & FUNC_HAS_EJ0) { - /* _EJ0 method take one argument */ - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _EJ0 failed\n", __FUNCTION__); - retval = -1; - goto err_exit; - } else - break; - } - } - /* TBD: evaluate _STA to check if the slot is disabled */ slot->flags &= (~SLOT_POWEREDON); @@ -782,6 +759,39 @@ } /** + * acpiphp_eject_slot - physically eject the slot + */ +static int acpiphp_eject_slot(struct acpiphp_slot *slot) +{ + acpi_status status; + struct acpiphp_func *func; + struct list_head *l; + struct acpi_object_list arg_list; + union acpi_object arg; + + list_for_each (l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + /* We don't want to call _EJ0 on non-existing functions. */ + if ((func->flags & FUNC_HAS_EJ0)) { + /* _EJ0 method take one argument */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); + if (ACPI_FAILURE(status)) { + warn("%s: _EJ0 failed\n", __FUNCTION__); + return -1; + } else + break; + } + } + return 0; +} + +/** * acpiphp_check_bridge - re-enumerate devices * * Iterate over all slots under this bridge and make sure that if a @@ -804,6 +814,8 @@ if (retval) { err("Error occurred in disabling\n"); goto err_exit; + } else { + acpiphp_eject_slot(slot); } disabled++; } else { @@ -1041,7 +1053,6 @@ } } - /** * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) * @@ -1084,7 +1095,8 @@ case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); - acpiphp_disable_slot(func->slot); + if (!(acpiphp_disable_slot(func->slot))) + acpiphp_eject_slot(func->slot); break; default: @@ -1268,7 +1280,6 @@ return retval; } - /** * acpiphp_disable_slot - power off slot */ @@ -1300,11 +1311,7 @@ */ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) { - unsigned int sta; - - sta = get_slot_status(slot); - - return (sta & ACPI_STA_ENABLED) ? 1 : 0; + return (slot->flags & SLOT_POWEREDON); }