aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRajesh Shah <rajesh.shah@intel.com>2005-04-28 03:25:57 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-28 00:52:43 -0400
commit8d50e332c8bd4f4e8cc76e8ed7326aa6f18182aa (patch)
treedd9caa96f0b5d5bff3d4fccc4be410c4ecad03aa /drivers
parent8e7561cfbdf00fb1cee694cef0e825d0548aedbc (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c69
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 */
764static 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 */
1301u8 acpiphp_get_power_status(struct acpiphp_slot *slot) 1312u8 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