diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-03 02:26:33 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-03 02:26:33 -0400 |
commit | c50e86ce7c2961a41f2f7aa6e4fd6c99229ba205 (patch) | |
tree | 4ea36009719bd8fc523239fe1bdccb90f0dce3ae /drivers/acpi/scan.c | |
parent | 14d33d384693eb6083396199de516fdef320f7af (diff) | |
parent | 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d (diff) |
Merge tag 'v3.6-rc4'
Merge 3.6-rc4 to get latest OMAP and device tree fixes.
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 80 |
1 files changed, 49 insertions, 31 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c8a1f3b68110..d1ecca2b641a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -83,19 +83,29 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
83 | } | 83 | } |
84 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 84 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
85 | 85 | ||
86 | static void acpi_bus_hot_remove_device(void *context) | 86 | /** |
87 | * acpi_bus_hot_remove_device: hot-remove a device and its children | ||
88 | * @context: struct acpi_eject_event pointer (freed in this func) | ||
89 | * | ||
90 | * Hot-remove a device and its children. This function frees up the | ||
91 | * memory space passed by arg context, so that the caller may call | ||
92 | * this function asynchronously through acpi_os_hotplug_execute(). | ||
93 | */ | ||
94 | void acpi_bus_hot_remove_device(void *context) | ||
87 | { | 95 | { |
96 | struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; | ||
88 | struct acpi_device *device; | 97 | struct acpi_device *device; |
89 | acpi_handle handle = context; | 98 | acpi_handle handle = ej_event->handle; |
90 | struct acpi_object_list arg_list; | 99 | struct acpi_object_list arg_list; |
91 | union acpi_object arg; | 100 | union acpi_object arg; |
92 | acpi_status status = AE_OK; | 101 | acpi_status status = AE_OK; |
102 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ | ||
93 | 103 | ||
94 | if (acpi_bus_get_device(handle, &device)) | 104 | if (acpi_bus_get_device(handle, &device)) |
95 | return; | 105 | goto err_out; |
96 | 106 | ||
97 | if (!device) | 107 | if (!device) |
98 | return; | 108 | goto err_out; |
99 | 109 | ||
100 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 110 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
101 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 111 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
@@ -103,7 +113,7 @@ static void acpi_bus_hot_remove_device(void *context) | |||
103 | if (acpi_bus_trim(device, 1)) { | 113 | if (acpi_bus_trim(device, 1)) { |
104 | printk(KERN_ERR PREFIX | 114 | printk(KERN_ERR PREFIX |
105 | "Removing device failed\n"); | 115 | "Removing device failed\n"); |
106 | return; | 116 | goto err_out; |
107 | } | 117 | } |
108 | 118 | ||
109 | /* power off device */ | 119 | /* power off device */ |
@@ -129,10 +139,21 @@ static void acpi_bus_hot_remove_device(void *context) | |||
129 | * TBD: _EJD support. | 139 | * TBD: _EJD support. |
130 | */ | 140 | */ |
131 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); | 141 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); |
132 | if (ACPI_FAILURE(status)) | 142 | if (ACPI_FAILURE(status)) { |
133 | printk(KERN_WARNING PREFIX | 143 | if (status != AE_NOT_FOUND) |
134 | "Eject device failed\n"); | 144 | printk(KERN_WARNING PREFIX |
145 | "Eject device failed\n"); | ||
146 | goto err_out; | ||
147 | } | ||
148 | |||
149 | kfree(context); | ||
150 | return; | ||
135 | 151 | ||
152 | err_out: | ||
153 | /* Inform firmware the hot-remove operation has completed w/ error */ | ||
154 | (void) acpi_evaluate_hotplug_ost(handle, | ||
155 | ej_event->event, ost_code, NULL); | ||
156 | kfree(context); | ||
136 | return; | 157 | return; |
137 | } | 158 | } |
138 | 159 | ||
@@ -144,6 +165,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
144 | acpi_status status; | 165 | acpi_status status; |
145 | acpi_object_type type = 0; | 166 | acpi_object_type type = 0; |
146 | struct acpi_device *acpi_device = to_acpi_device(d); | 167 | struct acpi_device *acpi_device = to_acpi_device(d); |
168 | struct acpi_eject_event *ej_event; | ||
147 | 169 | ||
148 | if ((!count) || (buf[0] != '1')) { | 170 | if ((!count) || (buf[0] != '1')) { |
149 | return -EINVAL; | 171 | return -EINVAL; |
@@ -160,7 +182,25 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
160 | goto err; | 182 | goto err; |
161 | } | 183 | } |
162 | 184 | ||
163 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle); | 185 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); |
186 | if (!ej_event) { | ||
187 | ret = -ENOMEM; | ||
188 | goto err; | ||
189 | } | ||
190 | |||
191 | ej_event->handle = acpi_device->handle; | ||
192 | if (acpi_device->flags.eject_pending) { | ||
193 | /* event originated from ACPI eject notification */ | ||
194 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
195 | acpi_device->flags.eject_pending = 0; | ||
196 | } else { | ||
197 | /* event originated from user */ | ||
198 | ej_event->event = ACPI_OST_EC_OSPM_EJECT; | ||
199 | (void) acpi_evaluate_hotplug_ost(ej_event->handle, | ||
200 | ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
201 | } | ||
202 | |||
203 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); | ||
164 | err: | 204 | err: |
165 | return ret; | 205 | return ret; |
166 | } | 206 | } |
@@ -290,26 +330,6 @@ static void acpi_device_release(struct device *dev) | |||
290 | kfree(acpi_dev); | 330 | kfree(acpi_dev); |
291 | } | 331 | } |
292 | 332 | ||
293 | static int acpi_device_suspend(struct device *dev, pm_message_t state) | ||
294 | { | ||
295 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
296 | struct acpi_driver *acpi_drv = acpi_dev->driver; | ||
297 | |||
298 | if (acpi_drv && acpi_drv->ops.suspend) | ||
299 | return acpi_drv->ops.suspend(acpi_dev, state); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int acpi_device_resume(struct device *dev) | ||
304 | { | ||
305 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
306 | struct acpi_driver *acpi_drv = acpi_dev->driver; | ||
307 | |||
308 | if (acpi_drv && acpi_drv->ops.resume) | ||
309 | return acpi_drv->ops.resume(acpi_dev); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int acpi_bus_match(struct device *dev, struct device_driver *drv) | 333 | static int acpi_bus_match(struct device *dev, struct device_driver *drv) |
314 | { | 334 | { |
315 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 335 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
@@ -441,8 +461,6 @@ static int acpi_device_remove(struct device * dev) | |||
441 | 461 | ||
442 | struct bus_type acpi_bus_type = { | 462 | struct bus_type acpi_bus_type = { |
443 | .name = "acpi", | 463 | .name = "acpi", |
444 | .suspend = acpi_device_suspend, | ||
445 | .resume = acpi_device_resume, | ||
446 | .match = acpi_bus_match, | 464 | .match = acpi_bus_match, |
447 | .probe = acpi_device_probe, | 465 | .probe = acpi_device_probe, |
448 | .remove = acpi_device_remove, | 466 | .remove = acpi_device_remove, |