diff options
author | Rajesh Shah <rajesh.shah@intel.com> | 2005-04-28 03:25:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-28 00:52:43 -0400 |
commit | 8d50e332c8bd4f4e8cc76e8ed7326aa6f18182aa (patch) | |
tree | dd9caa96f0b5d5bff3d4fccc4be410c4ecad03aa | |
parent | 8e7561cfbdf00fb1cee694cef0e825d0548aedbc (diff) |
[PATCH] acpi hotplug: decouple slot power state changes from physical hotplug
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 <rajesh.shah@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a6270cc218f6..b4a921236252 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -592,8 +592,6 @@ static int power_off_slot(struct acpiphp_slot *slot) | |||
592 | acpi_status status; | 592 | acpi_status status; |
593 | struct acpiphp_func *func; | 593 | struct acpiphp_func *func; |
594 | struct list_head *l; | 594 | struct list_head *l; |
595 | struct acpi_object_list arg_list; | ||
596 | union acpi_object arg; | ||
597 | 595 | ||
598 | int retval = 0; | 596 | int retval = 0; |
599 | 597 | ||
@@ -615,27 +613,6 @@ static int power_off_slot(struct acpiphp_slot *slot) | |||
615 | } | 613 | } |
616 | } | 614 | } |
617 | 615 | ||
618 | list_for_each (l, &slot->funcs) { | ||
619 | func = list_entry(l, struct acpiphp_func, sibling); | ||
620 | |||
621 | /* We don't want to call _EJ0 on non-existing functions. */ | ||
622 | if (func->flags & FUNC_HAS_EJ0) { | ||
623 | /* _EJ0 method take one argument */ | ||
624 | arg_list.count = 1; | ||
625 | arg_list.pointer = &arg; | ||
626 | arg.type = ACPI_TYPE_INTEGER; | ||
627 | arg.integer.value = 1; | ||
628 | |||
629 | status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); | ||
630 | if (ACPI_FAILURE(status)) { | ||
631 | warn("%s: _EJ0 failed\n", __FUNCTION__); | ||
632 | retval = -1; | ||
633 | goto err_exit; | ||
634 | } else | ||
635 | break; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | /* TBD: evaluate _STA to check if the slot is disabled */ | 616 | /* TBD: evaluate _STA to check if the slot is disabled */ |
640 | 617 | ||
641 | slot->flags &= (~SLOT_POWEREDON); | 618 | slot->flags &= (~SLOT_POWEREDON); |
@@ -782,6 +759,39 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) | |||
782 | } | 759 | } |
783 | 760 | ||
784 | /** | 761 | /** |
762 | * acpiphp_eject_slot - physically eject the slot | ||
763 | */ | ||
764 | static int acpiphp_eject_slot(struct acpiphp_slot *slot) | ||
765 | { | ||
766 | acpi_status status; | ||
767 | struct acpiphp_func *func; | ||
768 | struct list_head *l; | ||
769 | struct acpi_object_list arg_list; | ||
770 | union acpi_object arg; | ||
771 | |||
772 | list_for_each (l, &slot->funcs) { | ||
773 | func = list_entry(l, struct acpiphp_func, sibling); | ||
774 | |||
775 | /* We don't want to call _EJ0 on non-existing functions. */ | ||
776 | if ((func->flags & FUNC_HAS_EJ0)) { | ||
777 | /* _EJ0 method take one argument */ | ||
778 | arg_list.count = 1; | ||
779 | arg_list.pointer = &arg; | ||
780 | arg.type = ACPI_TYPE_INTEGER; | ||
781 | arg.integer.value = 1; | ||
782 | |||
783 | status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); | ||
784 | if (ACPI_FAILURE(status)) { | ||
785 | warn("%s: _EJ0 failed\n", __FUNCTION__); | ||
786 | return -1; | ||
787 | } else | ||
788 | break; | ||
789 | } | ||
790 | } | ||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | /** | ||
785 | * acpiphp_check_bridge - re-enumerate devices | 795 | * acpiphp_check_bridge - re-enumerate devices |
786 | * | 796 | * |
787 | * Iterate over all slots under this bridge and make sure that if a | 797 | * Iterate over all slots under this bridge and make sure that if a |
@@ -804,6 +814,8 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
804 | if (retval) { | 814 | if (retval) { |
805 | err("Error occurred in disabling\n"); | 815 | err("Error occurred in disabling\n"); |
806 | goto err_exit; | 816 | goto err_exit; |
817 | } else { | ||
818 | acpiphp_eject_slot(slot); | ||
807 | } | 819 | } |
808 | disabled++; | 820 | disabled++; |
809 | } else { | 821 | } else { |
@@ -1041,7 +1053,6 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1041 | } | 1053 | } |
1042 | } | 1054 | } |
1043 | 1055 | ||
1044 | |||
1045 | /** | 1056 | /** |
1046 | * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) | 1057 | * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) |
1047 | * | 1058 | * |
@@ -1084,7 +1095,8 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex | |||
1084 | case ACPI_NOTIFY_EJECT_REQUEST: | 1095 | case ACPI_NOTIFY_EJECT_REQUEST: |
1085 | /* request device eject */ | 1096 | /* request device eject */ |
1086 | dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); | 1097 | dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); |
1087 | acpiphp_disable_slot(func->slot); | 1098 | if (!(acpiphp_disable_slot(func->slot))) |
1099 | acpiphp_eject_slot(func->slot); | ||
1088 | break; | 1100 | break; |
1089 | 1101 | ||
1090 | default: | 1102 | default: |
@@ -1268,7 +1280,6 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
1268 | return retval; | 1280 | return retval; |
1269 | } | 1281 | } |
1270 | 1282 | ||
1271 | |||
1272 | /** | 1283 | /** |
1273 | * acpiphp_disable_slot - power off slot | 1284 | * acpiphp_disable_slot - power off slot |
1274 | */ | 1285 | */ |
@@ -1300,11 +1311,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) | |||
1300 | */ | 1311 | */ |
1301 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | 1312 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot) |
1302 | { | 1313 | { |
1303 | unsigned int sta; | 1314 | return (slot->flags & SLOT_POWEREDON); |
1304 | |||
1305 | sta = get_slot_status(slot); | ||
1306 | |||
1307 | return (sta & ACPI_STA_ENABLED) ? 1 : 0; | ||
1308 | } | 1315 | } |
1309 | 1316 | ||
1310 | 1317 | ||