diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/bus.c | 8 | ||||
-rw-r--r-- | drivers/acpi/button.c | 13 | ||||
-rw-r--r-- | drivers/acpi/fan.c | 22 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 135 | ||||
-rw-r--r-- | drivers/acpi/hed.c | 20 | ||||
-rw-r--r-- | drivers/acpi/proc.c | 57 | ||||
-rw-r--r-- | drivers/acpi/sbshc.c | 18 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 56 | ||||
-rw-r--r-- | drivers/acpi/tables.c | 18 |
9 files changed, 201 insertions, 146 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e0596954290b..d59175efc428 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -994,8 +994,6 @@ static int __init acpi_bus_init(void) | |||
994 | status = acpi_ec_ecdt_probe(); | 994 | status = acpi_ec_ecdt_probe(); |
995 | /* Ignore result. Not having an ECDT is not fatal. */ | 995 | /* Ignore result. Not having an ECDT is not fatal. */ |
996 | 996 | ||
997 | acpi_bus_osc_support(); | ||
998 | |||
999 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); | 997 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); |
1000 | if (ACPI_FAILURE(status)) { | 998 | if (ACPI_FAILURE(status)) { |
1001 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); | 999 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); |
@@ -1003,6 +1001,12 @@ static int __init acpi_bus_init(void) | |||
1003 | } | 1001 | } |
1004 | 1002 | ||
1005 | /* | 1003 | /* |
1004 | * _OSC method may exist in module level code, | ||
1005 | * so it must be run after ACPI_FULL_INITIALIZATION | ||
1006 | */ | ||
1007 | acpi_bus_osc_support(); | ||
1008 | |||
1009 | /* | ||
1006 | * _PDC control method may load dynamic SSDT tables, | 1010 | * _PDC control method may load dynamic SSDT tables, |
1007 | * and we need to install the table handler before that. | 1011 | * and we need to install the table handler before that. |
1008 | */ | 1012 | */ |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 314a3b84bbc7..f0d936b65e37 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -450,15 +450,4 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
450 | return 0; | 450 | return 0; |
451 | } | 451 | } |
452 | 452 | ||
453 | static int __init acpi_button_init(void) | 453 | module_acpi_driver(acpi_button_driver); |
454 | { | ||
455 | return acpi_bus_register_driver(&acpi_button_driver); | ||
456 | } | ||
457 | |||
458 | static void __exit acpi_button_exit(void) | ||
459 | { | ||
460 | acpi_bus_unregister_driver(&acpi_button_driver); | ||
461 | } | ||
462 | |||
463 | module_init(acpi_button_init); | ||
464 | module_exit(acpi_button_exit); | ||
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index bc36a476f1ab..3bd6a54702d6 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
@@ -212,24 +212,4 @@ static int acpi_fan_resume(struct device *dev) | |||
212 | } | 212 | } |
213 | #endif | 213 | #endif |
214 | 214 | ||
215 | static int __init acpi_fan_init(void) | 215 | module_acpi_driver(acpi_fan_driver); |
216 | { | ||
217 | int result = 0; | ||
218 | |||
219 | result = acpi_bus_register_driver(&acpi_fan_driver); | ||
220 | if (result < 0) | ||
221 | return -ENODEV; | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static void __exit acpi_fan_exit(void) | ||
227 | { | ||
228 | |||
229 | acpi_bus_unregister_driver(&acpi_fan_driver); | ||
230 | |||
231 | return; | ||
232 | } | ||
233 | |||
234 | module_init(acpi_fan_init); | ||
235 | module_exit(acpi_fan_exit); | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 243ee85e4d2e..d1a2d74033e9 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -25,6 +25,8 @@ | |||
25 | static LIST_HEAD(bus_type_list); | 25 | static LIST_HEAD(bus_type_list); |
26 | static DECLARE_RWSEM(bus_type_sem); | 26 | static DECLARE_RWSEM(bus_type_sem); |
27 | 27 | ||
28 | #define PHYSICAL_NODE_STRING "physical_node" | ||
29 | |||
28 | int register_acpi_bus_type(struct acpi_bus_type *type) | 30 | int register_acpi_bus_type(struct acpi_bus_type *type) |
29 | { | 31 | { |
30 | if (acpi_disabled) | 32 | if (acpi_disabled) |
@@ -124,84 +126,119 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address) | |||
124 | 126 | ||
125 | EXPORT_SYMBOL(acpi_get_child); | 127 | EXPORT_SYMBOL(acpi_get_child); |
126 | 128 | ||
127 | /* Link ACPI devices with physical devices */ | ||
128 | static void acpi_glue_data_handler(acpi_handle handle, | ||
129 | void *context) | ||
130 | { | ||
131 | /* we provide an empty handler */ | ||
132 | } | ||
133 | |||
134 | /* Note: a success call will increase reference count by one */ | ||
135 | struct device *acpi_get_physical_device(acpi_handle handle) | ||
136 | { | ||
137 | acpi_status status; | ||
138 | struct device *dev; | ||
139 | |||
140 | status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev); | ||
141 | if (ACPI_SUCCESS(status)) | ||
142 | return get_device(dev); | ||
143 | return NULL; | ||
144 | } | ||
145 | |||
146 | EXPORT_SYMBOL(acpi_get_physical_device); | ||
147 | |||
148 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 129 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
149 | { | 130 | { |
150 | struct acpi_device *acpi_dev; | 131 | struct acpi_device *acpi_dev; |
151 | acpi_status status; | 132 | acpi_status status; |
133 | struct acpi_device_physical_node *physical_node; | ||
134 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; | ||
135 | int retval = -EINVAL; | ||
152 | 136 | ||
153 | if (dev->archdata.acpi_handle) { | 137 | if (dev->archdata.acpi_handle) { |
154 | dev_warn(dev, "Drivers changed 'acpi_handle'\n"); | 138 | dev_warn(dev, "Drivers changed 'acpi_handle'\n"); |
155 | return -EINVAL; | 139 | return -EINVAL; |
156 | } | 140 | } |
141 | |||
157 | get_device(dev); | 142 | get_device(dev); |
158 | status = acpi_attach_data(handle, acpi_glue_data_handler, dev); | 143 | status = acpi_bus_get_device(handle, &acpi_dev); |
159 | if (ACPI_FAILURE(status)) { | 144 | if (ACPI_FAILURE(status)) |
160 | put_device(dev); | 145 | goto err; |
161 | return -EINVAL; | 146 | |
147 | physical_node = kzalloc(sizeof(struct acpi_device_physical_node), | ||
148 | GFP_KERNEL); | ||
149 | if (!physical_node) { | ||
150 | retval = -ENOMEM; | ||
151 | goto err; | ||
162 | } | 152 | } |
163 | dev->archdata.acpi_handle = handle; | ||
164 | 153 | ||
165 | status = acpi_bus_get_device(handle, &acpi_dev); | 154 | mutex_lock(&acpi_dev->physical_node_lock); |
166 | if (!ACPI_FAILURE(status)) { | 155 | /* allocate physical node id according to physical_node_id_bitmap */ |
167 | int ret; | 156 | physical_node->node_id = |
168 | 157 | find_first_zero_bit(acpi_dev->physical_node_id_bitmap, | |
169 | ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, | 158 | ACPI_MAX_PHYSICAL_NODE); |
170 | "firmware_node"); | 159 | if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { |
171 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | 160 | retval = -ENOSPC; |
172 | "physical_node"); | 161 | mutex_unlock(&acpi_dev->physical_node_lock); |
173 | if (acpi_dev->wakeup.flags.valid) | 162 | goto err; |
174 | device_set_wakeup_capable(dev, true); | ||
175 | } | 163 | } |
176 | 164 | ||
165 | set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); | ||
166 | physical_node->dev = dev; | ||
167 | list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); | ||
168 | acpi_dev->physical_node_count++; | ||
169 | mutex_unlock(&acpi_dev->physical_node_lock); | ||
170 | |||
171 | dev->archdata.acpi_handle = handle; | ||
172 | |||
173 | if (!physical_node->node_id) | ||
174 | strcpy(physical_node_name, PHYSICAL_NODE_STRING); | ||
175 | else | ||
176 | sprintf(physical_node_name, | ||
177 | "physical_node%d", physical_node->node_id); | ||
178 | retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | ||
179 | physical_node_name); | ||
180 | retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, | ||
181 | "firmware_node"); | ||
182 | |||
183 | if (acpi_dev->wakeup.flags.valid) | ||
184 | device_set_wakeup_capable(dev, true); | ||
185 | |||
177 | return 0; | 186 | return 0; |
187 | |||
188 | err: | ||
189 | put_device(dev); | ||
190 | return retval; | ||
178 | } | 191 | } |
179 | 192 | ||
180 | static int acpi_unbind_one(struct device *dev) | 193 | static int acpi_unbind_one(struct device *dev) |
181 | { | 194 | { |
195 | struct acpi_device_physical_node *entry; | ||
196 | struct acpi_device *acpi_dev; | ||
197 | acpi_status status; | ||
198 | struct list_head *node, *next; | ||
199 | |||
182 | if (!dev->archdata.acpi_handle) | 200 | if (!dev->archdata.acpi_handle) |
183 | return 0; | 201 | return 0; |
184 | if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { | ||
185 | struct acpi_device *acpi_dev; | ||
186 | 202 | ||
187 | /* acpi_get_physical_device increase refcnt by one */ | 203 | status = acpi_bus_get_device(dev->archdata.acpi_handle, |
188 | put_device(dev); | 204 | &acpi_dev); |
205 | if (ACPI_FAILURE(status)) | ||
206 | goto err; | ||
189 | 207 | ||
190 | if (!acpi_bus_get_device(dev->archdata.acpi_handle, | 208 | mutex_lock(&acpi_dev->physical_node_lock); |
191 | &acpi_dev)) { | 209 | list_for_each_safe(node, next, &acpi_dev->physical_node_list) { |
192 | sysfs_remove_link(&dev->kobj, "firmware_node"); | 210 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; |
193 | sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); | 211 | |
194 | } | 212 | entry = list_entry(node, struct acpi_device_physical_node, |
213 | node); | ||
214 | if (entry->dev != dev) | ||
215 | continue; | ||
216 | |||
217 | list_del(node); | ||
218 | clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap); | ||
195 | 219 | ||
196 | acpi_detach_data(dev->archdata.acpi_handle, | 220 | acpi_dev->physical_node_count--; |
197 | acpi_glue_data_handler); | 221 | |
222 | if (!entry->node_id) | ||
223 | strcpy(physical_node_name, PHYSICAL_NODE_STRING); | ||
224 | else | ||
225 | sprintf(physical_node_name, | ||
226 | "physical_node%d", entry->node_id); | ||
227 | |||
228 | sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); | ||
229 | sysfs_remove_link(&dev->kobj, "firmware_node"); | ||
198 | dev->archdata.acpi_handle = NULL; | 230 | dev->archdata.acpi_handle = NULL; |
199 | /* acpi_bind_one increase refcnt by one */ | 231 | /* acpi_bind_one increase refcnt by one */ |
200 | put_device(dev); | 232 | put_device(dev); |
201 | } else { | 233 | kfree(entry); |
202 | dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); | ||
203 | } | 234 | } |
235 | mutex_unlock(&acpi_dev->physical_node_lock); | ||
236 | |||
204 | return 0; | 237 | return 0; |
238 | |||
239 | err: | ||
240 | dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); | ||
241 | return -EINVAL; | ||
205 | } | 242 | } |
206 | 243 | ||
207 | static int acpi_platform_notify(struct device *dev) | 244 | static int acpi_platform_notify(struct device *dev) |
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index d0c1967f7597..20a0f2c3ca3b 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c | |||
@@ -86,25 +86,7 @@ static struct acpi_driver acpi_hed_driver = { | |||
86 | .notify = acpi_hed_notify, | 86 | .notify = acpi_hed_notify, |
87 | }, | 87 | }, |
88 | }; | 88 | }; |
89 | 89 | module_acpi_driver(acpi_hed_driver); | |
90 | static int __init acpi_hed_init(void) | ||
91 | { | ||
92 | if (acpi_disabled) | ||
93 | return -ENODEV; | ||
94 | |||
95 | if (acpi_bus_register_driver(&acpi_hed_driver) < 0) | ||
96 | return -ENODEV; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static void __exit acpi_hed_exit(void) | ||
102 | { | ||
103 | acpi_bus_unregister_driver(&acpi_hed_driver); | ||
104 | } | ||
105 | |||
106 | module_init(acpi_hed_init); | ||
107 | module_exit(acpi_hed_exit); | ||
108 | 90 | ||
109 | ACPI_MODULE_NAME("hed"); | 91 | ACPI_MODULE_NAME("hed"); |
110 | MODULE_AUTHOR("Huang Ying"); | 92 | MODULE_AUTHOR("Huang Ying"); |
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 251c7b6273a9..27adb090bb30 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
@@ -302,26 +302,41 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
302 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 302 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
303 | struct acpi_device *dev = | 303 | struct acpi_device *dev = |
304 | container_of(node, struct acpi_device, wakeup_list); | 304 | container_of(node, struct acpi_device, wakeup_list); |
305 | struct device *ldev; | 305 | struct acpi_device_physical_node *entry; |
306 | 306 | ||
307 | if (!dev->wakeup.flags.valid) | 307 | if (!dev->wakeup.flags.valid) |
308 | continue; | 308 | continue; |
309 | 309 | ||
310 | ldev = acpi_get_physical_device(dev->handle); | 310 | seq_printf(seq, "%s\t S%d\t", |
311 | seq_printf(seq, "%s\t S%d\t%c%-8s ", | ||
312 | dev->pnp.bus_id, | 311 | dev->pnp.bus_id, |
313 | (u32) dev->wakeup.sleep_state, | 312 | (u32) dev->wakeup.sleep_state); |
314 | dev->wakeup.flags.run_wake ? '*' : ' ', | 313 | |
315 | (device_may_wakeup(&dev->dev) | 314 | if (!dev->physical_node_count) |
316 | || (ldev && device_may_wakeup(ldev))) ? | 315 | seq_printf(seq, "%c%-8s\n", |
317 | "enabled" : "disabled"); | 316 | dev->wakeup.flags.run_wake ? |
318 | if (ldev) | 317 | '*' : ' ', "disabled"); |
319 | seq_printf(seq, "%s:%s", | 318 | else { |
320 | ldev->bus ? ldev->bus->name : "no-bus", | 319 | struct device *ldev; |
321 | dev_name(ldev)); | 320 | list_for_each_entry(entry, &dev->physical_node_list, |
322 | seq_printf(seq, "\n"); | 321 | node) { |
323 | put_device(ldev); | 322 | ldev = get_device(entry->dev); |
324 | 323 | if (!ldev) | |
324 | continue; | ||
325 | |||
326 | if (&entry->node != | ||
327 | dev->physical_node_list.next) | ||
328 | seq_printf(seq, "\t\t"); | ||
329 | |||
330 | seq_printf(seq, "%c%-8s %s:%s\n", | ||
331 | dev->wakeup.flags.run_wake ? '*' : ' ', | ||
332 | (device_may_wakeup(&dev->dev) || | ||
333 | (ldev && device_may_wakeup(ldev))) ? | ||
334 | "enabled" : "disabled", | ||
335 | ldev->bus ? ldev->bus->name : | ||
336 | "no-bus", dev_name(ldev)); | ||
337 | put_device(ldev); | ||
338 | } | ||
339 | } | ||
325 | } | 340 | } |
326 | mutex_unlock(&acpi_device_lock); | 341 | mutex_unlock(&acpi_device_lock); |
327 | return 0; | 342 | return 0; |
@@ -329,12 +344,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
329 | 344 | ||
330 | static void physical_device_enable_wakeup(struct acpi_device *adev) | 345 | static void physical_device_enable_wakeup(struct acpi_device *adev) |
331 | { | 346 | { |
332 | struct device *dev = acpi_get_physical_device(adev->handle); | 347 | struct acpi_device_physical_node *entry; |
333 | 348 | ||
334 | if (dev && device_can_wakeup(dev)) { | 349 | list_for_each_entry(entry, |
335 | bool enable = !device_may_wakeup(dev); | 350 | &adev->physical_node_list, node) |
336 | device_set_wakeup_enable(dev, enable); | 351 | if (entry->dev && device_can_wakeup(entry->dev)) { |
337 | } | 352 | bool enable = !device_may_wakeup(entry->dev); |
353 | device_set_wakeup_enable(entry->dev, enable); | ||
354 | } | ||
338 | } | 355 | } |
339 | 356 | ||
340 | static ssize_t | 357 | static ssize_t |
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index f8d2a472795c..cf6129a8af7c 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c | |||
@@ -310,23 +310,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type) | |||
310 | return 0; | 310 | return 0; |
311 | } | 311 | } |
312 | 312 | ||
313 | static int __init acpi_smb_hc_init(void) | 313 | module_acpi_driver(acpi_smb_hc_driver); |
314 | { | ||
315 | int result; | ||
316 | |||
317 | result = acpi_bus_register_driver(&acpi_smb_hc_driver); | ||
318 | if (result < 0) | ||
319 | return -ENODEV; | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static void __exit acpi_smb_hc_exit(void) | ||
324 | { | ||
325 | acpi_bus_unregister_driver(&acpi_smb_hc_driver); | ||
326 | } | ||
327 | |||
328 | module_init(acpi_smb_hc_init); | ||
329 | module_exit(acpi_smb_hc_exit); | ||
330 | 314 | ||
331 | MODULE_LICENSE("GPL"); | 315 | MODULE_LICENSE("GPL"); |
332 | MODULE_AUTHOR("Alexey Starikovskiy"); | 316 | MODULE_AUTHOR("Alexey Starikovskiy"); |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d1ecca2b641a..1fcb8678665c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/signal.h> | 10 | #include <linux/signal.h> |
11 | #include <linux/kthread.h> | 11 | #include <linux/kthread.h> |
12 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
13 | #include <linux/nls.h> | ||
13 | 14 | ||
14 | #include <acpi/acpi_drivers.h> | 15 | #include <acpi/acpi_drivers.h> |
15 | 16 | ||
@@ -232,8 +233,35 @@ end: | |||
232 | } | 233 | } |
233 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); | 234 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); |
234 | 235 | ||
236 | /* sysfs file that shows description text from the ACPI _STR method */ | ||
237 | static ssize_t description_show(struct device *dev, | ||
238 | struct device_attribute *attr, | ||
239 | char *buf) { | ||
240 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
241 | int result; | ||
242 | |||
243 | if (acpi_dev->pnp.str_obj == NULL) | ||
244 | return 0; | ||
245 | |||
246 | /* | ||
247 | * The _STR object contains a Unicode identifier for a device. | ||
248 | * We need to convert to utf-8 so it can be displayed. | ||
249 | */ | ||
250 | result = utf16s_to_utf8s( | ||
251 | (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer, | ||
252 | acpi_dev->pnp.str_obj->buffer.length, | ||
253 | UTF16_LITTLE_ENDIAN, buf, | ||
254 | PAGE_SIZE); | ||
255 | |||
256 | buf[result++] = '\n'; | ||
257 | |||
258 | return result; | ||
259 | } | ||
260 | static DEVICE_ATTR(description, 0444, description_show, NULL); | ||
261 | |||
235 | static int acpi_device_setup_files(struct acpi_device *dev) | 262 | static int acpi_device_setup_files(struct acpi_device *dev) |
236 | { | 263 | { |
264 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
237 | acpi_status status; | 265 | acpi_status status; |
238 | acpi_handle temp; | 266 | acpi_handle temp; |
239 | int result = 0; | 267 | int result = 0; |
@@ -257,6 +285,21 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
257 | goto end; | 285 | goto end; |
258 | } | 286 | } |
259 | 287 | ||
288 | /* | ||
289 | * If device has _STR, 'description' file is created | ||
290 | */ | ||
291 | status = acpi_get_handle(dev->handle, "_STR", &temp); | ||
292 | if (ACPI_SUCCESS(status)) { | ||
293 | status = acpi_evaluate_object(dev->handle, "_STR", | ||
294 | NULL, &buffer); | ||
295 | if (ACPI_FAILURE(status)) | ||
296 | buffer.pointer = NULL; | ||
297 | dev->pnp.str_obj = buffer.pointer; | ||
298 | result = device_create_file(&dev->dev, &dev_attr_description); | ||
299 | if (result) | ||
300 | goto end; | ||
301 | } | ||
302 | |||
260 | /* | 303 | /* |
261 | * If device has _EJ0, 'eject' file is created that is used to trigger | 304 | * If device has _EJ0, 'eject' file is created that is used to trigger |
262 | * hot-removal function from userland. | 305 | * hot-removal function from userland. |
@@ -274,8 +317,15 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
274 | acpi_handle temp; | 317 | acpi_handle temp; |
275 | 318 | ||
276 | /* | 319 | /* |
277 | * If device has _EJ0, 'eject' file is created that is used to trigger | 320 | * If device has _STR, remove 'description' file |
278 | * hot-removal function from userland. | 321 | */ |
322 | status = acpi_get_handle(dev->handle, "_STR", &temp); | ||
323 | if (ACPI_SUCCESS(status)) { | ||
324 | kfree(dev->pnp.str_obj); | ||
325 | device_remove_file(&dev->dev, &dev_attr_description); | ||
326 | } | ||
327 | /* | ||
328 | * If device has _EJ0, remove 'eject' file. | ||
279 | */ | 329 | */ |
280 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); | 330 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); |
281 | if (ACPI_SUCCESS(status)) | 331 | if (ACPI_SUCCESS(status)) |
@@ -481,6 +531,8 @@ static int acpi_device_register(struct acpi_device *device) | |||
481 | INIT_LIST_HEAD(&device->children); | 531 | INIT_LIST_HEAD(&device->children); |
482 | INIT_LIST_HEAD(&device->node); | 532 | INIT_LIST_HEAD(&device->node); |
483 | INIT_LIST_HEAD(&device->wakeup_list); | 533 | INIT_LIST_HEAD(&device->wakeup_list); |
534 | INIT_LIST_HEAD(&device->physical_node_list); | ||
535 | mutex_init(&device->physical_node_lock); | ||
484 | 536 | ||
485 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); | 537 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
486 | if (!new_bus_id) { | 538 | if (!new_bus_id) { |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index f336bca7c450..2572d9715bda 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
@@ -240,10 +240,17 @@ acpi_table_parse_entries(char *id, | |||
240 | table_end) { | 240 | table_end) { |
241 | if (entry->type == entry_id | 241 | if (entry->type == entry_id |
242 | && (!max_entries || count++ < max_entries)) | 242 | && (!max_entries || count++ < max_entries)) |
243 | if (handler(entry, table_end)) { | 243 | if (handler(entry, table_end)) |
244 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | 244 | goto err; |
245 | return -EINVAL; | 245 | |
246 | } | 246 | /* |
247 | * If entry->length is 0, break from this loop to avoid | ||
248 | * infinite loop. | ||
249 | */ | ||
250 | if (entry->length == 0) { | ||
251 | pr_err(PREFIX "[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); | ||
252 | goto err; | ||
253 | } | ||
247 | 254 | ||
248 | entry = (struct acpi_subtable_header *) | 255 | entry = (struct acpi_subtable_header *) |
249 | ((unsigned long)entry + entry->length); | 256 | ((unsigned long)entry + entry->length); |
@@ -255,6 +262,9 @@ acpi_table_parse_entries(char *id, | |||
255 | 262 | ||
256 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | 263 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); |
257 | return count; | 264 | return count; |
265 | err: | ||
266 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | ||
267 | return -EINVAL; | ||
258 | } | 268 | } |
259 | 269 | ||
260 | int __init | 270 | int __init |