diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/acpi/container.c | 2 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 6 | ||||
-rw-r--r-- | drivers/acpi/pci_bind.c | 27 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 3 | ||||
-rw-r--r-- | drivers/acpi/pci_link.c | 45 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 24 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 2 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 130 | ||||
-rw-r--r-- | drivers/acpi/sleep/poweroff.c | 34 |
11 files changed, 195 insertions, 84 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 281a64040f38..ba13896cae40 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -55,8 +55,8 @@ if ACPI_INTERPRETER | |||
55 | 55 | ||
56 | config ACPI_SLEEP | 56 | config ACPI_SLEEP |
57 | bool "Sleep States (EXPERIMENTAL)" | 57 | bool "Sleep States (EXPERIMENTAL)" |
58 | depends on X86 | 58 | depends on X86 && (!SMP || SUSPEND_SMP) |
59 | depends on EXPERIMENTAL | 59 | depends on EXPERIMENTAL && PM |
60 | default y | 60 | default y |
61 | ---help--- | 61 | ---help--- |
62 | This option adds support for ACPI suspend states. | 62 | This option adds support for ACPI suspend states. |
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 5a0adbf8bc04..97013ddfa202 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
@@ -153,7 +153,7 @@ container_device_add(struct acpi_device **device, acpi_handle handle) | |||
153 | return_VALUE(-ENODEV); | 153 | return_VALUE(-ENODEV); |
154 | } | 154 | } |
155 | 155 | ||
156 | result = acpi_bus_scan(*device); | 156 | result = acpi_bus_start(*device); |
157 | 157 | ||
158 | return_VALUE(result); | 158 | return_VALUE(result); |
159 | } | 159 | } |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index cb16cc11fee8..0d11d6e6abd6 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args) | |||
145 | #endif | 145 | #endif |
146 | } | 146 | } |
147 | 147 | ||
148 | extern int acpi_in_resume; | ||
148 | void * | 149 | void * |
149 | acpi_os_allocate(acpi_size size) | 150 | acpi_os_allocate(acpi_size size) |
150 | { | 151 | { |
151 | return kmalloc(size, GFP_KERNEL); | 152 | if (acpi_in_resume) |
153 | return kmalloc(size, GFP_ATOMIC); | ||
154 | else | ||
155 | return kmalloc(size, GFP_KERNEL); | ||
152 | } | 156 | } |
153 | 157 | ||
154 | void | 158 | void |
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 5d19b39e9e2b..5148f3c10b5c 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
@@ -61,15 +61,14 @@ acpi_pci_data_handler ( | |||
61 | 61 | ||
62 | 62 | ||
63 | /** | 63 | /** |
64 | * acpi_os_get_pci_id | 64 | * acpi_get_pci_id |
65 | * ------------------ | 65 | * ------------------ |
66 | * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem) | 66 | * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem) |
67 | * to resolve PCI information for ACPI-PCI devices defined in the namespace. | 67 | * to resolve PCI information for ACPI-PCI devices defined in the namespace. |
68 | * This typically occurs when resolving PCI operation region information. | 68 | * This typically occurs when resolving PCI operation region information. |
69 | */ | 69 | */ |
70 | #ifdef ACPI_FUTURE_USAGE | ||
71 | acpi_status | 70 | acpi_status |
72 | acpi_os_get_pci_id ( | 71 | acpi_get_pci_id ( |
73 | acpi_handle handle, | 72 | acpi_handle handle, |
74 | struct acpi_pci_id *id) | 73 | struct acpi_pci_id *id) |
75 | { | 74 | { |
@@ -78,7 +77,7 @@ acpi_os_get_pci_id ( | |||
78 | struct acpi_device *device = NULL; | 77 | struct acpi_device *device = NULL; |
79 | struct acpi_pci_data *data = NULL; | 78 | struct acpi_pci_data *data = NULL; |
80 | 79 | ||
81 | ACPI_FUNCTION_TRACE("acpi_os_get_pci_id"); | 80 | ACPI_FUNCTION_TRACE("acpi_get_pci_id"); |
82 | 81 | ||
83 | if (!id) | 82 | if (!id) |
84 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 83 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
@@ -92,7 +91,7 @@ acpi_os_get_pci_id ( | |||
92 | } | 91 | } |
93 | 92 | ||
94 | status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data); | 93 | status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data); |
95 | if (ACPI_FAILURE(status) || !data || !data->dev) { | 94 | if (ACPI_FAILURE(status) || !data) { |
96 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 95 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
97 | "Invalid ACPI-PCI context for device %s\n", | 96 | "Invalid ACPI-PCI context for device %s\n", |
98 | acpi_device_bid(device))); | 97 | acpi_device_bid(device))); |
@@ -115,7 +114,7 @@ acpi_os_get_pci_id ( | |||
115 | 114 | ||
116 | return_ACPI_STATUS(AE_OK); | 115 | return_ACPI_STATUS(AE_OK); |
117 | } | 116 | } |
118 | #endif /* ACPI_FUTURE_USAGE */ | 117 | EXPORT_SYMBOL(acpi_get_pci_id); |
119 | 118 | ||
120 | 119 | ||
121 | int | 120 | int |
@@ -129,6 +128,8 @@ acpi_pci_bind ( | |||
129 | char *pathname = NULL; | 128 | char *pathname = NULL; |
130 | struct acpi_buffer buffer = {0, NULL}; | 129 | struct acpi_buffer buffer = {0, NULL}; |
131 | acpi_handle handle = NULL; | 130 | acpi_handle handle = NULL; |
131 | struct pci_dev *dev; | ||
132 | struct pci_bus *bus; | ||
132 | 133 | ||
133 | ACPI_FUNCTION_TRACE("acpi_pci_bind"); | 134 | ACPI_FUNCTION_TRACE("acpi_pci_bind"); |
134 | 135 | ||
@@ -193,8 +194,20 @@ acpi_pci_bind ( | |||
193 | * Locate matching device in PCI namespace. If it doesn't exist | 194 | * Locate matching device in PCI namespace. If it doesn't exist |
194 | * this typically means that the device isn't currently inserted | 195 | * this typically means that the device isn't currently inserted |
195 | * (e.g. docking station, port replicator, etc.). | 196 | * (e.g. docking station, port replicator, etc.). |
197 | * We cannot simply search the global pci device list, since | ||
198 | * PCI devices are added to the global pci list when the root | ||
199 | * bridge start ops are run, which may not have happened yet. | ||
196 | */ | 200 | */ |
197 | data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function)); | 201 | bus = pci_find_bus(data->id.segment, data->id.bus); |
202 | if (bus) { | ||
203 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
204 | if (dev->devfn == PCI_DEVFN(data->id.device, | ||
205 | data->id.function)) { | ||
206 | data->dev = dev; | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | } | ||
198 | if (!data->dev) { | 211 | if (!data->dev) { |
199 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 212 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
200 | "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", | 213 | "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index c536ccfc5413..bb973d2109a1 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -465,8 +465,9 @@ acpi_pci_irq_enable ( | |||
465 | printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI", | 465 | printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI", |
466 | pci_name(dev), ('A' + pin)); | 466 | pci_name(dev), ('A' + pin)); |
467 | /* Interrupt Line values above 0xF are forbidden */ | 467 | /* Interrupt Line values above 0xF are forbidden */ |
468 | if (dev->irq >= 0 && (dev->irq <= 0xF)) { | 468 | if (dev->irq > 0 && (dev->irq <= 0xF)) { |
469 | printk(" - using IRQ %d\n", dev->irq); | 469 | printk(" - using IRQ %d\n", dev->irq); |
470 | acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); | ||
470 | return_VALUE(0); | 471 | return_VALUE(0); |
471 | } | 472 | } |
472 | else { | 473 | else { |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 0091dbdf7ef9..834c2ceff1aa 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -787,16 +787,32 @@ end: | |||
787 | } | 787 | } |
788 | 788 | ||
789 | static int | 789 | static int |
790 | irqrouter_suspend( | 790 | acpi_pci_link_resume( |
791 | struct sys_device *dev, | 791 | struct acpi_pci_link *link) |
792 | u32 state) | 792 | { |
793 | ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); | ||
794 | |||
795 | if (link->refcnt && link->irq.active && link->irq.initialized) | ||
796 | return_VALUE(acpi_pci_link_set(link, link->irq.active)); | ||
797 | else | ||
798 | return_VALUE(0); | ||
799 | } | ||
800 | |||
801 | /* | ||
802 | * FIXME: this is a workaround to avoid nasty warning. It will be removed | ||
803 | * after every device calls pci_disable_device in .resume. | ||
804 | */ | ||
805 | int acpi_in_resume; | ||
806 | static int | ||
807 | irqrouter_resume( | ||
808 | struct sys_device *dev) | ||
793 | { | 809 | { |
794 | struct list_head *node = NULL; | 810 | struct list_head *node = NULL; |
795 | struct acpi_pci_link *link = NULL; | 811 | struct acpi_pci_link *link = NULL; |
796 | int ret = 0; | ||
797 | 812 | ||
798 | ACPI_FUNCTION_TRACE("irqrouter_suspend"); | 813 | ACPI_FUNCTION_TRACE("irqrouter_resume"); |
799 | 814 | ||
815 | acpi_in_resume = 1; | ||
800 | list_for_each(node, &acpi_link.entries) { | 816 | list_for_each(node, &acpi_link.entries) { |
801 | link = list_entry(node, struct acpi_pci_link, node); | 817 | link = list_entry(node, struct acpi_pci_link, node); |
802 | if (!link) { | 818 | if (!link) { |
@@ -804,21 +820,10 @@ irqrouter_suspend( | |||
804 | "Invalid link context\n")); | 820 | "Invalid link context\n")); |
805 | continue; | 821 | continue; |
806 | } | 822 | } |
807 | if (link->irq.initialized && link->refcnt != 0 | 823 | acpi_pci_link_resume(link); |
808 | /* We ignore legacy IDE device irq */ | ||
809 | && link->irq.active != 14 && link->irq.active !=15) { | ||
810 | printk(KERN_WARNING PREFIX | ||
811 | "%d drivers with interrupt %d neglected to call" | ||
812 | " pci_disable_device at .suspend\n", | ||
813 | link->refcnt, | ||
814 | link->irq.active); | ||
815 | printk(KERN_WARNING PREFIX | ||
816 | "Fix the driver, or rmmod before suspend\n"); | ||
817 | link->refcnt = 0; | ||
818 | ret = -EINVAL; | ||
819 | } | ||
820 | } | 824 | } |
821 | return_VALUE(ret); | 825 | acpi_in_resume = 0; |
826 | return_VALUE(0); | ||
822 | } | 827 | } |
823 | 828 | ||
824 | 829 | ||
@@ -933,7 +938,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set); | |||
933 | /* FIXME: we will remove this interface after all drivers call pci_disable_device */ | 938 | /* FIXME: we will remove this interface after all drivers call pci_disable_device */ |
934 | static struct sysdev_class irqrouter_sysdev_class = { | 939 | static struct sysdev_class irqrouter_sysdev_class = { |
935 | set_kset_name("irqrouter"), | 940 | set_kset_name("irqrouter"), |
936 | .suspend = irqrouter_suspend, | 941 | .resume = irqrouter_resume, |
937 | }; | 942 | }; |
938 | 943 | ||
939 | 944 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7e6b8e3b2ed4..5d2f77fcd50c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -46,6 +46,7 @@ ACPI_MODULE_NAME ("pci_root") | |||
46 | 46 | ||
47 | static int acpi_pci_root_add (struct acpi_device *device); | 47 | static int acpi_pci_root_add (struct acpi_device *device); |
48 | static int acpi_pci_root_remove (struct acpi_device *device, int type); | 48 | static int acpi_pci_root_remove (struct acpi_device *device, int type); |
49 | static int acpi_pci_root_start (struct acpi_device *device); | ||
49 | 50 | ||
50 | static struct acpi_driver acpi_pci_root_driver = { | 51 | static struct acpi_driver acpi_pci_root_driver = { |
51 | .name = ACPI_PCI_ROOT_DRIVER_NAME, | 52 | .name = ACPI_PCI_ROOT_DRIVER_NAME, |
@@ -54,6 +55,7 @@ static struct acpi_driver acpi_pci_root_driver = { | |||
54 | .ops = { | 55 | .ops = { |
55 | .add = acpi_pci_root_add, | 56 | .add = acpi_pci_root_add, |
56 | .remove = acpi_pci_root_remove, | 57 | .remove = acpi_pci_root_remove, |
58 | .start = acpi_pci_root_start, | ||
57 | }, | 59 | }, |
58 | }; | 60 | }; |
59 | 61 | ||
@@ -169,6 +171,7 @@ acpi_pci_root_add ( | |||
169 | if (!root) | 171 | if (!root) |
170 | return_VALUE(-ENOMEM); | 172 | return_VALUE(-ENOMEM); |
171 | memset(root, 0, sizeof(struct acpi_pci_root)); | 173 | memset(root, 0, sizeof(struct acpi_pci_root)); |
174 | INIT_LIST_HEAD(&root->node); | ||
172 | 175 | ||
173 | root->handle = device->handle; | 176 | root->handle = device->handle; |
174 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); | 177 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
@@ -298,12 +301,31 @@ acpi_pci_root_add ( | |||
298 | root->id.bus); | 301 | root->id.bus); |
299 | 302 | ||
300 | end: | 303 | end: |
301 | if (result) | 304 | if (result) { |
305 | if (!list_empty(&root->node)) | ||
306 | list_del(&root->node); | ||
302 | kfree(root); | 307 | kfree(root); |
308 | } | ||
303 | 309 | ||
304 | return_VALUE(result); | 310 | return_VALUE(result); |
305 | } | 311 | } |
306 | 312 | ||
313 | static int | ||
314 | acpi_pci_root_start ( | ||
315 | struct acpi_device *device) | ||
316 | { | ||
317 | struct acpi_pci_root *root; | ||
318 | |||
319 | ACPI_FUNCTION_TRACE("acpi_pci_root_start"); | ||
320 | |||
321 | list_for_each_entry(root, &acpi_pci_roots, node) { | ||
322 | if (root->handle == device->handle) { | ||
323 | pci_bus_add_devices(root->bus); | ||
324 | return_VALUE(0); | ||
325 | } | ||
326 | } | ||
327 | return_VALUE(-ENODEV); | ||
328 | } | ||
307 | 329 | ||
308 | static int | 330 | static int |
309 | acpi_pci_root_remove ( | 331 | acpi_pci_root_remove ( |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e421842888b9..d56a439ac614 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -760,7 +760,7 @@ int acpi_processor_device_add( | |||
760 | return_VALUE(-ENODEV); | 760 | return_VALUE(-ENODEV); |
761 | } | 761 | } |
762 | 762 | ||
763 | acpi_bus_scan(*device); | 763 | acpi_bus_start(*device); |
764 | 764 | ||
765 | pr = acpi_driver_data(*device); | 765 | pr = acpi_driver_data(*device); |
766 | if (!pr) | 766 | if (!pr) |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 8f7836678b29..2c04740c6543 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -178,7 +178,7 @@ static void acpi_processor_idle (void) | |||
178 | int sleep_ticks = 0; | 178 | int sleep_ticks = 0; |
179 | u32 t1, t2 = 0; | 179 | u32 t1, t2 = 0; |
180 | 180 | ||
181 | pr = processors[_smp_processor_id()]; | 181 | pr = processors[raw_smp_processor_id()]; |
182 | if (!pr) | 182 | if (!pr) |
183 | return; | 183 | return; |
184 | 184 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7c26fed0bdf0..cbcda30c172d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -65,14 +65,14 @@ static ssize_t acpi_device_attr_show(struct kobject *kobj, | |||
65 | { | 65 | { |
66 | struct acpi_device *device = to_acpi_device(kobj); | 66 | struct acpi_device *device = to_acpi_device(kobj); |
67 | struct acpi_device_attribute *attribute = to_handle_attr(attr); | 67 | struct acpi_device_attribute *attribute = to_handle_attr(attr); |
68 | return attribute->show ? attribute->show(device, buf) : 0; | 68 | return attribute->show ? attribute->show(device, buf) : -EIO; |
69 | } | 69 | } |
70 | static ssize_t acpi_device_attr_store(struct kobject *kobj, | 70 | static ssize_t acpi_device_attr_store(struct kobject *kobj, |
71 | struct attribute *attr, const char *buf, size_t len) | 71 | struct attribute *attr, const char *buf, size_t len) |
72 | { | 72 | { |
73 | struct acpi_device *device = to_acpi_device(kobj); | 73 | struct acpi_device *device = to_acpi_device(kobj); |
74 | struct acpi_device_attribute *attribute = to_handle_attr(attr); | 74 | struct acpi_device_attribute *attribute = to_handle_attr(attr); |
75 | return attribute->store ? attribute->store(device, buf, len) : len; | 75 | return attribute->store ? attribute->store(device, buf, len) : -EIO; |
76 | } | 76 | } |
77 | 77 | ||
78 | static struct sysfs_ops acpi_device_sysfs_ops = { | 78 | static struct sysfs_ops acpi_device_sysfs_ops = { |
@@ -553,20 +553,29 @@ acpi_bus_driver_init ( | |||
553 | * upon possible configuration and currently allocated resources. | 553 | * upon possible configuration and currently allocated resources. |
554 | */ | 554 | */ |
555 | 555 | ||
556 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); | ||
557 | return_VALUE(0); | ||
558 | } | ||
559 | |||
560 | int | ||
561 | acpi_start_single_object ( | ||
562 | struct acpi_device *device) | ||
563 | { | ||
564 | int result = 0; | ||
565 | struct acpi_driver *driver; | ||
566 | |||
567 | ACPI_FUNCTION_TRACE("acpi_start_single_object"); | ||
568 | |||
569 | if (!(driver = device->driver)) | ||
570 | return_VALUE(0); | ||
571 | |||
556 | if (driver->ops.start) { | 572 | if (driver->ops.start) { |
557 | result = driver->ops.start(device); | 573 | result = driver->ops.start(device); |
558 | if (result && driver->ops.remove) | 574 | if (result && driver->ops.remove) |
559 | driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); | 575 | driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); |
560 | return_VALUE(result); | ||
561 | } | 576 | } |
562 | 577 | ||
563 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); | 578 | return_VALUE(result); |
564 | |||
565 | if (driver->ops.scan) { | ||
566 | driver->ops.scan(device); | ||
567 | } | ||
568 | |||
569 | return_VALUE(0); | ||
570 | } | 579 | } |
571 | 580 | ||
572 | static int acpi_driver_attach(struct acpi_driver * drv) | 581 | static int acpi_driver_attach(struct acpi_driver * drv) |
@@ -586,6 +595,7 @@ static int acpi_driver_attach(struct acpi_driver * drv) | |||
586 | 595 | ||
587 | if (!acpi_bus_match(dev, drv)) { | 596 | if (!acpi_bus_match(dev, drv)) { |
588 | if (!acpi_bus_driver_init(dev, drv)) { | 597 | if (!acpi_bus_driver_init(dev, drv)) { |
598 | acpi_start_single_object(dev); | ||
589 | atomic_inc(&drv->references); | 599 | atomic_inc(&drv->references); |
590 | count++; | 600 | count++; |
591 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", | 601 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", |
@@ -1009,8 +1019,8 @@ acpi_bus_remove ( | |||
1009 | } | 1019 | } |
1010 | 1020 | ||
1011 | 1021 | ||
1012 | int | 1022 | static int |
1013 | acpi_bus_add ( | 1023 | acpi_add_single_object ( |
1014 | struct acpi_device **child, | 1024 | struct acpi_device **child, |
1015 | struct acpi_device *parent, | 1025 | struct acpi_device *parent, |
1016 | acpi_handle handle, | 1026 | acpi_handle handle, |
@@ -1019,7 +1029,7 @@ acpi_bus_add ( | |||
1019 | int result = 0; | 1029 | int result = 0; |
1020 | struct acpi_device *device = NULL; | 1030 | struct acpi_device *device = NULL; |
1021 | 1031 | ||
1022 | ACPI_FUNCTION_TRACE("acpi_bus_add"); | 1032 | ACPI_FUNCTION_TRACE("acpi_add_single_object"); |
1023 | 1033 | ||
1024 | if (!child) | 1034 | if (!child) |
1025 | return_VALUE(-EINVAL); | 1035 | return_VALUE(-EINVAL); |
@@ -1142,7 +1152,7 @@ acpi_bus_add ( | |||
1142 | * | 1152 | * |
1143 | * TBD: Assumes LDM provides driver hot-plug capability. | 1153 | * TBD: Assumes LDM provides driver hot-plug capability. |
1144 | */ | 1154 | */ |
1145 | acpi_bus_find_driver(device); | 1155 | result = acpi_bus_find_driver(device); |
1146 | 1156 | ||
1147 | end: | 1157 | end: |
1148 | if (!result) | 1158 | if (!result) |
@@ -1155,10 +1165,10 @@ end: | |||
1155 | 1165 | ||
1156 | return_VALUE(result); | 1166 | return_VALUE(result); |
1157 | } | 1167 | } |
1158 | EXPORT_SYMBOL(acpi_bus_add); | ||
1159 | 1168 | ||
1160 | 1169 | ||
1161 | int acpi_bus_scan (struct acpi_device *start) | 1170 | static int acpi_bus_scan (struct acpi_device *start, |
1171 | struct acpi_bus_ops *ops) | ||
1162 | { | 1172 | { |
1163 | acpi_status status = AE_OK; | 1173 | acpi_status status = AE_OK; |
1164 | struct acpi_device *parent = NULL; | 1174 | struct acpi_device *parent = NULL; |
@@ -1231,9 +1241,20 @@ int acpi_bus_scan (struct acpi_device *start) | |||
1231 | continue; | 1241 | continue; |
1232 | } | 1242 | } |
1233 | 1243 | ||
1234 | status = acpi_bus_add(&child, parent, chandle, type); | 1244 | if (ops->acpi_op_add) |
1235 | if (ACPI_FAILURE(status)) | 1245 | status = acpi_add_single_object(&child, parent, |
1236 | continue; | 1246 | chandle, type); |
1247 | else | ||
1248 | status = acpi_bus_get_device(chandle, &child); | ||
1249 | |||
1250 | if (ACPI_FAILURE(status)) | ||
1251 | continue; | ||
1252 | |||
1253 | if (ops->acpi_op_start) { | ||
1254 | status = acpi_start_single_object(child); | ||
1255 | if (ACPI_FAILURE(status)) | ||
1256 | continue; | ||
1257 | } | ||
1237 | 1258 | ||
1238 | /* | 1259 | /* |
1239 | * If the device is present, enabled, and functioning then | 1260 | * If the device is present, enabled, and functioning then |
@@ -1259,8 +1280,50 @@ int acpi_bus_scan (struct acpi_device *start) | |||
1259 | 1280 | ||
1260 | return_VALUE(0); | 1281 | return_VALUE(0); |
1261 | } | 1282 | } |
1262 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1263 | 1283 | ||
1284 | int | ||
1285 | acpi_bus_add ( | ||
1286 | struct acpi_device **child, | ||
1287 | struct acpi_device *parent, | ||
1288 | acpi_handle handle, | ||
1289 | int type) | ||
1290 | { | ||
1291 | int result; | ||
1292 | struct acpi_bus_ops ops; | ||
1293 | |||
1294 | ACPI_FUNCTION_TRACE("acpi_bus_add"); | ||
1295 | |||
1296 | result = acpi_add_single_object(child, parent, handle, type); | ||
1297 | if (!result) { | ||
1298 | memset(&ops, 0, sizeof(ops)); | ||
1299 | ops.acpi_op_add = 1; | ||
1300 | result = acpi_bus_scan(*child, &ops); | ||
1301 | } | ||
1302 | return_VALUE(result); | ||
1303 | } | ||
1304 | EXPORT_SYMBOL(acpi_bus_add); | ||
1305 | |||
1306 | int | ||
1307 | acpi_bus_start ( | ||
1308 | struct acpi_device *device) | ||
1309 | { | ||
1310 | int result; | ||
1311 | struct acpi_bus_ops ops; | ||
1312 | |||
1313 | ACPI_FUNCTION_TRACE("acpi_bus_start"); | ||
1314 | |||
1315 | if (!device) | ||
1316 | return_VALUE(-EINVAL); | ||
1317 | |||
1318 | result = acpi_start_single_object(device); | ||
1319 | if (!result) { | ||
1320 | memset(&ops, 0, sizeof(ops)); | ||
1321 | ops.acpi_op_start = 1; | ||
1322 | result = acpi_bus_scan(device, &ops); | ||
1323 | } | ||
1324 | return_VALUE(result); | ||
1325 | } | ||
1326 | EXPORT_SYMBOL(acpi_bus_start); | ||
1264 | 1327 | ||
1265 | static int | 1328 | static int |
1266 | acpi_bus_trim(struct acpi_device *start, | 1329 | acpi_bus_trim(struct acpi_device *start, |
@@ -1333,13 +1396,19 @@ acpi_bus_scan_fixed ( | |||
1333 | /* | 1396 | /* |
1334 | * Enumerate all fixed-feature devices. | 1397 | * Enumerate all fixed-feature devices. |
1335 | */ | 1398 | */ |
1336 | if (acpi_fadt.pwr_button == 0) | 1399 | if (acpi_fadt.pwr_button == 0) { |
1337 | result = acpi_bus_add(&device, acpi_root, | 1400 | result = acpi_add_single_object(&device, acpi_root, |
1338 | NULL, ACPI_BUS_TYPE_POWER_BUTTON); | 1401 | NULL, ACPI_BUS_TYPE_POWER_BUTTON); |
1402 | if (!result) | ||
1403 | result = acpi_start_single_object(device); | ||
1404 | } | ||
1339 | 1405 | ||
1340 | if (acpi_fadt.sleep_button == 0) | 1406 | if (acpi_fadt.sleep_button == 0) { |
1341 | result = acpi_bus_add(&device, acpi_root, | 1407 | result = acpi_add_single_object(&device, acpi_root, |
1342 | NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); | 1408 | NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); |
1409 | if (!result) | ||
1410 | result = acpi_start_single_object(device); | ||
1411 | } | ||
1343 | 1412 | ||
1344 | return_VALUE(result); | 1413 | return_VALUE(result); |
1345 | } | 1414 | } |
@@ -1348,6 +1417,7 @@ acpi_bus_scan_fixed ( | |||
1348 | static int __init acpi_scan_init(void) | 1417 | static int __init acpi_scan_init(void) |
1349 | { | 1418 | { |
1350 | int result; | 1419 | int result; |
1420 | struct acpi_bus_ops ops; | ||
1351 | 1421 | ||
1352 | ACPI_FUNCTION_TRACE("acpi_scan_init"); | 1422 | ACPI_FUNCTION_TRACE("acpi_scan_init"); |
1353 | 1423 | ||
@@ -1359,17 +1429,23 @@ static int __init acpi_scan_init(void) | |||
1359 | /* | 1429 | /* |
1360 | * Create the root device in the bus's device tree | 1430 | * Create the root device in the bus's device tree |
1361 | */ | 1431 | */ |
1362 | result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, | 1432 | result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, |
1363 | ACPI_BUS_TYPE_SYSTEM); | 1433 | ACPI_BUS_TYPE_SYSTEM); |
1364 | if (result) | 1434 | if (result) |
1365 | goto Done; | 1435 | goto Done; |
1366 | 1436 | ||
1437 | result = acpi_start_single_object(acpi_root); | ||
1438 | |||
1367 | /* | 1439 | /* |
1368 | * Enumerate devices in the ACPI namespace. | 1440 | * Enumerate devices in the ACPI namespace. |
1369 | */ | 1441 | */ |
1370 | result = acpi_bus_scan_fixed(acpi_root); | 1442 | result = acpi_bus_scan_fixed(acpi_root); |
1371 | if (!result) | 1443 | if (!result) { |
1372 | result = acpi_bus_scan(acpi_root); | 1444 | memset(&ops, 0, sizeof(ops)); |
1445 | ops.acpi_op_add = 1; | ||
1446 | ops.acpi_op_start = 1; | ||
1447 | result = acpi_bus_scan(acpi_root, &ops); | ||
1448 | } | ||
1373 | 1449 | ||
1374 | if (result) | 1450 | if (result) |
1375 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); | 1451 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); |
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c index 1fc86e6b5ab9..186b182c5825 100644 --- a/drivers/acpi/sleep/poweroff.c +++ b/drivers/acpi/sleep/poweroff.c | |||
@@ -19,8 +19,6 @@ | |||
19 | 19 | ||
20 | int acpi_sleep_prepare(u32 acpi_state) | 20 | int acpi_sleep_prepare(u32 acpi_state) |
21 | { | 21 | { |
22 | /* Flag to do not allow second time invocation for S5 state */ | ||
23 | static int shutdown_prepared = 0; | ||
24 | #ifdef CONFIG_ACPI_SLEEP | 22 | #ifdef CONFIG_ACPI_SLEEP |
25 | /* do we have a wakeup address for S2 and S3? */ | 23 | /* do we have a wakeup address for S2 and S3? */ |
26 | /* Here, we support only S4BIOS, those we set the wakeup address */ | 24 | /* Here, we support only S4BIOS, those we set the wakeup address */ |
@@ -38,28 +36,23 @@ int acpi_sleep_prepare(u32 acpi_state) | |||
38 | acpi_enable_wakeup_device_prep(acpi_state); | 36 | acpi_enable_wakeup_device_prep(acpi_state); |
39 | #endif | 37 | #endif |
40 | if (acpi_state == ACPI_STATE_S5) { | 38 | if (acpi_state == ACPI_STATE_S5) { |
41 | /* Check if we were already called */ | ||
42 | if (shutdown_prepared) | ||
43 | return 0; | ||
44 | acpi_wakeup_gpe_poweroff_prepare(); | 39 | acpi_wakeup_gpe_poweroff_prepare(); |
45 | shutdown_prepared = 1; | ||
46 | } | 40 | } |
47 | acpi_enter_sleep_state_prep(acpi_state); | 41 | acpi_enter_sleep_state_prep(acpi_state); |
48 | return 0; | 42 | return 0; |
49 | } | 43 | } |
50 | 44 | ||
45 | #ifdef CONFIG_PM | ||
46 | |||
51 | void acpi_power_off(void) | 47 | void acpi_power_off(void) |
52 | { | 48 | { |
49 | /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ | ||
53 | printk("%s called\n", __FUNCTION__); | 50 | printk("%s called\n", __FUNCTION__); |
54 | acpi_sleep_prepare(ACPI_STATE_S5); | ||
55 | local_irq_disable(); | 51 | local_irq_disable(); |
56 | /* Some SMP machines only can poweroff in boot CPU */ | 52 | /* Some SMP machines only can poweroff in boot CPU */ |
57 | set_cpus_allowed(current, cpumask_of_cpu(0)); | ||
58 | acpi_enter_sleep_state(ACPI_STATE_S5); | 53 | acpi_enter_sleep_state(ACPI_STATE_S5); |
59 | } | 54 | } |
60 | 55 | ||
61 | #ifdef CONFIG_PM | ||
62 | |||
63 | static int acpi_shutdown(struct sys_device *x) | 56 | static int acpi_shutdown(struct sys_device *x) |
64 | { | 57 | { |
65 | return acpi_sleep_prepare(ACPI_STATE_S5); | 58 | return acpi_sleep_prepare(ACPI_STATE_S5); |
@@ -75,8 +68,6 @@ static struct sys_device device_acpi = { | |||
75 | .cls = &acpi_sysclass, | 68 | .cls = &acpi_sysclass, |
76 | }; | 69 | }; |
77 | 70 | ||
78 | #endif | ||
79 | |||
80 | static int acpi_poweroff_init(void) | 71 | static int acpi_poweroff_init(void) |
81 | { | 72 | { |
82 | if (!acpi_disabled) { | 73 | if (!acpi_disabled) { |
@@ -86,19 +77,18 @@ static int acpi_poweroff_init(void) | |||
86 | status = | 77 | status = |
87 | acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | 78 | acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); |
88 | if (ACPI_SUCCESS(status)) { | 79 | if (ACPI_SUCCESS(status)) { |
89 | pm_power_off = acpi_power_off; | 80 | int error; |
90 | #ifdef CONFIG_PM | 81 | error = sysdev_class_register(&acpi_sysclass); |
91 | { | 82 | if (!error) |
92 | int error; | 83 | error = sysdev_register(&device_acpi); |
93 | error = sysdev_class_register(&acpi_sysclass); | 84 | if (!error) |
94 | if (!error) | 85 | pm_power_off = acpi_power_off; |
95 | error = sysdev_register(&device_acpi); | 86 | return error; |
96 | return error; | ||
97 | } | ||
98 | #endif | ||
99 | } | 87 | } |
100 | } | 88 | } |
101 | return 0; | 89 | return 0; |
102 | } | 90 | } |
103 | 91 | ||
104 | late_initcall(acpi_poweroff_init); | 92 | late_initcall(acpi_poweroff_init); |
93 | |||
94 | #endif /* CONFIG_PM */ | ||