diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/evgpe.c | 17 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 42 | ||||
-rw-r--r-- | drivers/acpi/button.c | 11 | ||||
-rw-r--r-- | drivers/acpi/debugfs.c | 20 | ||||
-rw-r--r-- | drivers/acpi/nvs.c | 22 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 139 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 1 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 28 |
9 files changed, 176 insertions, 111 deletions
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 01bcab1c5cc4..c7f743ca395b 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -397,10 +397,15 @@ struct acpi_gpe_handler_info { | |||
397 | u8 originally_enabled; /* True if GPE was originally enabled */ | 397 | u8 originally_enabled; /* True if GPE was originally enabled */ |
398 | }; | 398 | }; |
399 | 399 | ||
400 | struct acpi_gpe_notify_object { | ||
401 | struct acpi_namespace_node *node; | ||
402 | struct acpi_gpe_notify_object *next; | ||
403 | }; | ||
404 | |||
400 | union acpi_gpe_dispatch_info { | 405 | union acpi_gpe_dispatch_info { |
401 | struct acpi_namespace_node *method_node; /* Method node for this GPE level */ | 406 | struct acpi_namespace_node *method_node; /* Method node for this GPE level */ |
402 | struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ | 407 | struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ |
403 | struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */ | 408 | struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */ |
404 | }; | 409 | }; |
405 | 410 | ||
406 | /* | 411 | /* |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 67d44ef2fbc1..65c79add3b19 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -466,6 +466,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
466 | acpi_status status; | 466 | acpi_status status; |
467 | struct acpi_gpe_event_info *local_gpe_event_info; | 467 | struct acpi_gpe_event_info *local_gpe_event_info; |
468 | struct acpi_evaluate_info *info; | 468 | struct acpi_evaluate_info *info; |
469 | struct acpi_gpe_notify_object *notify_object; | ||
469 | 470 | ||
470 | ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); | 471 | ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); |
471 | 472 | ||
@@ -517,10 +518,18 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
517 | * from this thread -- because handlers may in turn run other | 518 | * from this thread -- because handlers may in turn run other |
518 | * control methods. | 519 | * control methods. |
519 | */ | 520 | */ |
520 | status = | 521 | status = acpi_ev_queue_notify_request( |
521 | acpi_ev_queue_notify_request(local_gpe_event_info->dispatch. | 522 | local_gpe_event_info->dispatch.device.node, |
522 | device_node, | 523 | ACPI_NOTIFY_DEVICE_WAKE); |
523 | ACPI_NOTIFY_DEVICE_WAKE); | 524 | |
525 | notify_object = local_gpe_event_info->dispatch.device.next; | ||
526 | while (ACPI_SUCCESS(status) && notify_object) { | ||
527 | status = acpi_ev_queue_notify_request( | ||
528 | notify_object->node, | ||
529 | ACPI_NOTIFY_DEVICE_WAKE); | ||
530 | notify_object = notify_object->next; | ||
531 | } | ||
532 | |||
524 | break; | 533 | break; |
525 | 534 | ||
526 | case ACPI_GPE_DISPATCH_METHOD: | 535 | case ACPI_GPE_DISPATCH_METHOD: |
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 3b20a3401b64..52aaff3df562 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -198,7 +198,9 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, | |||
198 | acpi_status status = AE_BAD_PARAMETER; | 198 | acpi_status status = AE_BAD_PARAMETER; |
199 | struct acpi_gpe_event_info *gpe_event_info; | 199 | struct acpi_gpe_event_info *gpe_event_info; |
200 | struct acpi_namespace_node *device_node; | 200 | struct acpi_namespace_node *device_node; |
201 | struct acpi_gpe_notify_object *notify_object; | ||
201 | acpi_cpu_flags flags; | 202 | acpi_cpu_flags flags; |
203 | u8 gpe_dispatch_mask; | ||
202 | 204 | ||
203 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); | 205 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); |
204 | 206 | ||
@@ -221,27 +223,49 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, | |||
221 | goto unlock_and_exit; | 223 | goto unlock_and_exit; |
222 | } | 224 | } |
223 | 225 | ||
226 | if (wake_device == ACPI_ROOT_OBJECT) { | ||
227 | goto out; | ||
228 | } | ||
229 | |||
224 | /* | 230 | /* |
225 | * If there is no method or handler for this GPE, then the | 231 | * If there is no method or handler for this GPE, then the |
226 | * wake_device will be notified whenever this GPE fires (aka | 232 | * wake_device will be notified whenever this GPE fires (aka |
227 | * "implicit notify") Note: The GPE is assumed to be | 233 | * "implicit notify") Note: The GPE is assumed to be |
228 | * level-triggered (for windows compatibility). | 234 | * level-triggered (for windows compatibility). |
229 | */ | 235 | */ |
230 | if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | 236 | gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; |
231 | ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) { | 237 | if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE |
238 | && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { | ||
239 | goto out; | ||
240 | } | ||
232 | 241 | ||
233 | /* Validate wake_device is of type Device */ | 242 | /* Validate wake_device is of type Device */ |
234 | 243 | ||
235 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, | 244 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); |
236 | wake_device); | 245 | if (device_node->type != ACPI_TYPE_DEVICE) { |
237 | if (device_node->type != ACPI_TYPE_DEVICE) { | 246 | goto unlock_and_exit; |
238 | goto unlock_and_exit; | 247 | } |
239 | } | 248 | |
249 | if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { | ||
240 | gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | | 250 | gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | |
241 | ACPI_GPE_LEVEL_TRIGGERED); | 251 | ACPI_GPE_LEVEL_TRIGGERED); |
242 | gpe_event_info->dispatch.device_node = device_node; | 252 | gpe_event_info->dispatch.device.node = device_node; |
253 | gpe_event_info->dispatch.device.next = NULL; | ||
254 | } else { | ||
255 | /* There are multiple devices to notify implicitly. */ | ||
256 | |||
257 | notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); | ||
258 | if (!notify_object) { | ||
259 | status = AE_NO_MEMORY; | ||
260 | goto unlock_and_exit; | ||
261 | } | ||
262 | |||
263 | notify_object->node = device_node; | ||
264 | notify_object->next = gpe_event_info->dispatch.device.next; | ||
265 | gpe_event_info->dispatch.device.next = notify_object; | ||
243 | } | 266 | } |
244 | 267 | ||
268 | out: | ||
245 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 269 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
246 | status = AE_OK; | 270 | status = AE_OK; |
247 | 271 | ||
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 76bbb78a5ad9..12c28f4adb67 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -98,6 +98,7 @@ struct acpi_button { | |||
98 | struct input_dev *input; | 98 | struct input_dev *input; |
99 | char phys[32]; /* for input device */ | 99 | char phys[32]; /* for input device */ |
100 | unsigned long pushed; | 100 | unsigned long pushed; |
101 | bool wakeup_enabled; | ||
101 | }; | 102 | }; |
102 | 103 | ||
103 | static const struct file_operations acpi_button_info_fops = { | 104 | static const struct file_operations acpi_button_info_fops = { |
@@ -430,8 +431,10 @@ static int acpi_button_add(struct acpi_device *device) | |||
430 | /* Button's GPE is run-wake GPE */ | 431 | /* Button's GPE is run-wake GPE */ |
431 | acpi_enable_gpe(device->wakeup.gpe_device, | 432 | acpi_enable_gpe(device->wakeup.gpe_device, |
432 | device->wakeup.gpe_number); | 433 | device->wakeup.gpe_number); |
433 | device->wakeup.run_wake_count++; | 434 | if (!device_may_wakeup(&device->dev)) { |
434 | device_set_wakeup_enable(&device->dev, true); | 435 | device_set_wakeup_enable(&device->dev, true); |
436 | button->wakeup_enabled = true; | ||
437 | } | ||
435 | } | 438 | } |
436 | 439 | ||
437 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); | 440 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); |
@@ -453,8 +456,8 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
453 | if (device->wakeup.flags.valid) { | 456 | if (device->wakeup.flags.valid) { |
454 | acpi_disable_gpe(device->wakeup.gpe_device, | 457 | acpi_disable_gpe(device->wakeup.gpe_device, |
455 | device->wakeup.gpe_number); | 458 | device->wakeup.gpe_number); |
456 | device->wakeup.run_wake_count--; | 459 | if (button->wakeup_enabled) |
457 | device_set_wakeup_enable(&device->dev, false); | 460 | device_set_wakeup_enable(&device->dev, false); |
458 | } | 461 | } |
459 | 462 | ||
460 | acpi_button_remove_fs(device); | 463 | acpi_button_remove_fs(device); |
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c index 5df67f1d6c61..384f7abcff77 100644 --- a/drivers/acpi/debugfs.c +++ b/drivers/acpi/debugfs.c | |||
@@ -26,7 +26,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, | |||
26 | size_t count, loff_t *ppos) | 26 | size_t count, loff_t *ppos) |
27 | { | 27 | { |
28 | static char *buf; | 28 | static char *buf; |
29 | static int uncopied_bytes; | 29 | static u32 max_size; |
30 | static u32 uncopied_bytes; | ||
31 | |||
30 | struct acpi_table_header table; | 32 | struct acpi_table_header table; |
31 | acpi_status status; | 33 | acpi_status status; |
32 | 34 | ||
@@ -37,19 +39,24 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, | |||
37 | if (copy_from_user(&table, user_buf, | 39 | if (copy_from_user(&table, user_buf, |
38 | sizeof(struct acpi_table_header))) | 40 | sizeof(struct acpi_table_header))) |
39 | return -EFAULT; | 41 | return -EFAULT; |
40 | uncopied_bytes = table.length; | 42 | uncopied_bytes = max_size = table.length; |
41 | buf = kzalloc(uncopied_bytes, GFP_KERNEL); | 43 | buf = kzalloc(max_size, GFP_KERNEL); |
42 | if (!buf) | 44 | if (!buf) |
43 | return -ENOMEM; | 45 | return -ENOMEM; |
44 | } | 46 | } |
45 | 47 | ||
46 | if (uncopied_bytes < count) { | 48 | if (buf == NULL) |
47 | kfree(buf); | 49 | return -EINVAL; |
50 | |||
51 | if ((*ppos > max_size) || | ||
52 | (*ppos + count > max_size) || | ||
53 | (*ppos + count < count) || | ||
54 | (count > uncopied_bytes)) | ||
48 | return -EINVAL; | 55 | return -EINVAL; |
49 | } | ||
50 | 56 | ||
51 | if (copy_from_user(buf + (*ppos), user_buf, count)) { | 57 | if (copy_from_user(buf + (*ppos), user_buf, count)) { |
52 | kfree(buf); | 58 | kfree(buf); |
59 | buf = NULL; | ||
53 | return -EFAULT; | 60 | return -EFAULT; |
54 | } | 61 | } |
55 | 62 | ||
@@ -59,6 +66,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, | |||
59 | if (!uncopied_bytes) { | 66 | if (!uncopied_bytes) { |
60 | status = acpi_install_method(buf); | 67 | status = acpi_install_method(buf); |
61 | kfree(buf); | 68 | kfree(buf); |
69 | buf = NULL; | ||
62 | if (ACPI_FAILURE(status)) | 70 | if (ACPI_FAILURE(status)) |
63 | return -EINVAL; | 71 | return -EINVAL; |
64 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); | 72 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); |
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index fa5a1df42b79..096787b43c96 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c | |||
@@ -26,6 +26,7 @@ struct nvs_page { | |||
26 | unsigned int size; | 26 | unsigned int size; |
27 | void *kaddr; | 27 | void *kaddr; |
28 | void *data; | 28 | void *data; |
29 | bool unmap; | ||
29 | struct list_head node; | 30 | struct list_head node; |
30 | }; | 31 | }; |
31 | 32 | ||
@@ -44,6 +45,9 @@ int suspend_nvs_register(unsigned long start, unsigned long size) | |||
44 | { | 45 | { |
45 | struct nvs_page *entry, *next; | 46 | struct nvs_page *entry, *next; |
46 | 47 | ||
48 | pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n", | ||
49 | start, size); | ||
50 | |||
47 | while (size > 0) { | 51 | while (size > 0) { |
48 | unsigned int nr_bytes; | 52 | unsigned int nr_bytes; |
49 | 53 | ||
@@ -81,7 +85,13 @@ void suspend_nvs_free(void) | |||
81 | free_page((unsigned long)entry->data); | 85 | free_page((unsigned long)entry->data); |
82 | entry->data = NULL; | 86 | entry->data = NULL; |
83 | if (entry->kaddr) { | 87 | if (entry->kaddr) { |
84 | iounmap(entry->kaddr); | 88 | if (entry->unmap) { |
89 | iounmap(entry->kaddr); | ||
90 | entry->unmap = false; | ||
91 | } else { | ||
92 | acpi_os_unmap_memory(entry->kaddr, | ||
93 | entry->size); | ||
94 | } | ||
85 | entry->kaddr = NULL; | 95 | entry->kaddr = NULL; |
86 | } | 96 | } |
87 | } | 97 | } |
@@ -115,8 +125,14 @@ int suspend_nvs_save(void) | |||
115 | 125 | ||
116 | list_for_each_entry(entry, &nvs_list, node) | 126 | list_for_each_entry(entry, &nvs_list, node) |
117 | if (entry->data) { | 127 | if (entry->data) { |
118 | entry->kaddr = acpi_os_ioremap(entry->phys_start, | 128 | unsigned long phys = entry->phys_start; |
119 | entry->size); | 129 | unsigned int size = entry->size; |
130 | |||
131 | entry->kaddr = acpi_os_get_iomem(phys, size); | ||
132 | if (!entry->kaddr) { | ||
133 | entry->kaddr = acpi_os_ioremap(phys, size); | ||
134 | entry->unmap = !!entry->kaddr; | ||
135 | } | ||
120 | if (!entry->kaddr) { | 136 | if (!entry->kaddr) { |
121 | suspend_nvs_free(); | 137 | suspend_nvs_free(); |
122 | return -ENOMEM; | 138 | return -ENOMEM; |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c90c76aa7f8b..45c6ac8790d7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(acpi_in_debugger); | |||
76 | extern char line_buf[80]; | 76 | extern char line_buf[80]; |
77 | #endif /*ENABLE_DEBUGGER */ | 77 | #endif /*ENABLE_DEBUGGER */ |
78 | 78 | ||
79 | static unsigned int acpi_irq_irq; | ||
80 | static acpi_osd_handler acpi_irq_handler; | 79 | static acpi_osd_handler acpi_irq_handler; |
81 | static void *acpi_irq_context; | 80 | static void *acpi_irq_context; |
82 | static struct workqueue_struct *kacpid_wq; | 81 | static struct workqueue_struct *kacpid_wq; |
@@ -105,11 +104,11 @@ struct acpi_ioremap { | |||
105 | void __iomem *virt; | 104 | void __iomem *virt; |
106 | acpi_physical_address phys; | 105 | acpi_physical_address phys; |
107 | acpi_size size; | 106 | acpi_size size; |
108 | struct kref ref; | 107 | unsigned long refcount; |
109 | }; | 108 | }; |
110 | 109 | ||
111 | static LIST_HEAD(acpi_ioremaps); | 110 | static LIST_HEAD(acpi_ioremaps); |
112 | static DEFINE_SPINLOCK(acpi_ioremap_lock); | 111 | static DEFINE_MUTEX(acpi_ioremap_lock); |
113 | 112 | ||
114 | static void __init acpi_osi_setup_late(void); | 113 | static void __init acpi_osi_setup_late(void); |
115 | 114 | ||
@@ -285,6 +284,22 @@ acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size) | |||
285 | return NULL; | 284 | return NULL; |
286 | } | 285 | } |
287 | 286 | ||
287 | void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size) | ||
288 | { | ||
289 | struct acpi_ioremap *map; | ||
290 | void __iomem *virt = NULL; | ||
291 | |||
292 | mutex_lock(&acpi_ioremap_lock); | ||
293 | map = acpi_map_lookup(phys, size); | ||
294 | if (map) { | ||
295 | virt = map->virt + (phys - map->phys); | ||
296 | map->refcount++; | ||
297 | } | ||
298 | mutex_unlock(&acpi_ioremap_lock); | ||
299 | return virt; | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(acpi_os_get_iomem); | ||
302 | |||
288 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ | 303 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ |
289 | static struct acpi_ioremap * | 304 | static struct acpi_ioremap * |
290 | acpi_map_lookup_virt(void __iomem *virt, acpi_size size) | 305 | acpi_map_lookup_virt(void __iomem *virt, acpi_size size) |
@@ -302,8 +317,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) | |||
302 | void __iomem *__init_refok | 317 | void __iomem *__init_refok |
303 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 318 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
304 | { | 319 | { |
305 | struct acpi_ioremap *map, *tmp_map; | 320 | struct acpi_ioremap *map; |
306 | unsigned long flags; | ||
307 | void __iomem *virt; | 321 | void __iomem *virt; |
308 | acpi_physical_address pg_off; | 322 | acpi_physical_address pg_off; |
309 | acpi_size pg_sz; | 323 | acpi_size pg_sz; |
@@ -316,14 +330,25 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
316 | if (!acpi_gbl_permanent_mmap) | 330 | if (!acpi_gbl_permanent_mmap) |
317 | return __acpi_map_table((unsigned long)phys, size); | 331 | return __acpi_map_table((unsigned long)phys, size); |
318 | 332 | ||
333 | mutex_lock(&acpi_ioremap_lock); | ||
334 | /* Check if there's a suitable mapping already. */ | ||
335 | map = acpi_map_lookup(phys, size); | ||
336 | if (map) { | ||
337 | map->refcount++; | ||
338 | goto out; | ||
339 | } | ||
340 | |||
319 | map = kzalloc(sizeof(*map), GFP_KERNEL); | 341 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
320 | if (!map) | 342 | if (!map) { |
343 | mutex_unlock(&acpi_ioremap_lock); | ||
321 | return NULL; | 344 | return NULL; |
345 | } | ||
322 | 346 | ||
323 | pg_off = round_down(phys, PAGE_SIZE); | 347 | pg_off = round_down(phys, PAGE_SIZE); |
324 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; | 348 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; |
325 | virt = acpi_os_ioremap(pg_off, pg_sz); | 349 | virt = acpi_os_ioremap(pg_off, pg_sz); |
326 | if (!virt) { | 350 | if (!virt) { |
351 | mutex_unlock(&acpi_ioremap_lock); | ||
327 | kfree(map); | 352 | kfree(map); |
328 | return NULL; | 353 | return NULL; |
329 | } | 354 | } |
@@ -332,62 +357,51 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
332 | map->virt = virt; | 357 | map->virt = virt; |
333 | map->phys = pg_off; | 358 | map->phys = pg_off; |
334 | map->size = pg_sz; | 359 | map->size = pg_sz; |
335 | kref_init(&map->ref); | 360 | map->refcount = 1; |
336 | 361 | ||
337 | spin_lock_irqsave(&acpi_ioremap_lock, flags); | ||
338 | /* Check if page has already been mapped. */ | ||
339 | tmp_map = acpi_map_lookup(phys, size); | ||
340 | if (tmp_map) { | ||
341 | kref_get(&tmp_map->ref); | ||
342 | spin_unlock_irqrestore(&acpi_ioremap_lock, flags); | ||
343 | iounmap(map->virt); | ||
344 | kfree(map); | ||
345 | return tmp_map->virt + (phys - tmp_map->phys); | ||
346 | } | ||
347 | list_add_tail_rcu(&map->list, &acpi_ioremaps); | 362 | list_add_tail_rcu(&map->list, &acpi_ioremaps); |
348 | spin_unlock_irqrestore(&acpi_ioremap_lock, flags); | ||
349 | 363 | ||
364 | out: | ||
365 | mutex_unlock(&acpi_ioremap_lock); | ||
350 | return map->virt + (phys - map->phys); | 366 | return map->virt + (phys - map->phys); |
351 | } | 367 | } |
352 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); | 368 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); |
353 | 369 | ||
354 | static void acpi_kref_del_iomap(struct kref *ref) | 370 | static void acpi_os_drop_map_ref(struct acpi_ioremap *map) |
355 | { | 371 | { |
356 | struct acpi_ioremap *map; | 372 | if (!--map->refcount) |
373 | list_del_rcu(&map->list); | ||
374 | } | ||
357 | 375 | ||
358 | map = container_of(ref, struct acpi_ioremap, ref); | 376 | static void acpi_os_map_cleanup(struct acpi_ioremap *map) |
359 | list_del_rcu(&map->list); | 377 | { |
378 | if (!map->refcount) { | ||
379 | synchronize_rcu(); | ||
380 | iounmap(map->virt); | ||
381 | kfree(map); | ||
382 | } | ||
360 | } | 383 | } |
361 | 384 | ||
362 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | 385 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) |
363 | { | 386 | { |
364 | struct acpi_ioremap *map; | 387 | struct acpi_ioremap *map; |
365 | unsigned long flags; | ||
366 | int del; | ||
367 | 388 | ||
368 | if (!acpi_gbl_permanent_mmap) { | 389 | if (!acpi_gbl_permanent_mmap) { |
369 | __acpi_unmap_table(virt, size); | 390 | __acpi_unmap_table(virt, size); |
370 | return; | 391 | return; |
371 | } | 392 | } |
372 | 393 | ||
373 | spin_lock_irqsave(&acpi_ioremap_lock, flags); | 394 | mutex_lock(&acpi_ioremap_lock); |
374 | map = acpi_map_lookup_virt(virt, size); | 395 | map = acpi_map_lookup_virt(virt, size); |
375 | if (!map) { | 396 | if (!map) { |
376 | spin_unlock_irqrestore(&acpi_ioremap_lock, flags); | 397 | mutex_unlock(&acpi_ioremap_lock); |
377 | printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt); | 398 | WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); |
378 | dump_stack(); | ||
379 | return; | 399 | return; |
380 | } | 400 | } |
401 | acpi_os_drop_map_ref(map); | ||
402 | mutex_unlock(&acpi_ioremap_lock); | ||
381 | 403 | ||
382 | del = kref_put(&map->ref, acpi_kref_del_iomap); | 404 | acpi_os_map_cleanup(map); |
383 | spin_unlock_irqrestore(&acpi_ioremap_lock, flags); | ||
384 | |||
385 | if (!del) | ||
386 | return; | ||
387 | |||
388 | synchronize_rcu(); | ||
389 | iounmap(map->virt); | ||
390 | kfree(map); | ||
391 | } | 405 | } |
392 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); | 406 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); |
393 | 407 | ||
@@ -397,7 +411,7 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | |||
397 | __acpi_unmap_table(virt, size); | 411 | __acpi_unmap_table(virt, size); |
398 | } | 412 | } |
399 | 413 | ||
400 | int acpi_os_map_generic_address(struct acpi_generic_address *addr) | 414 | static int acpi_os_map_generic_address(struct acpi_generic_address *addr) |
401 | { | 415 | { |
402 | void __iomem *virt; | 416 | void __iomem *virt; |
403 | 417 | ||
@@ -413,13 +427,10 @@ int acpi_os_map_generic_address(struct acpi_generic_address *addr) | |||
413 | 427 | ||
414 | return 0; | 428 | return 0; |
415 | } | 429 | } |
416 | EXPORT_SYMBOL_GPL(acpi_os_map_generic_address); | ||
417 | 430 | ||
418 | void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) | 431 | static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) |
419 | { | 432 | { |
420 | void __iomem *virt; | 433 | struct acpi_ioremap *map; |
421 | unsigned long flags; | ||
422 | acpi_size size = addr->bit_width / 8; | ||
423 | 434 | ||
424 | if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) | 435 | if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) |
425 | return; | 436 | return; |
@@ -427,13 +438,17 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) | |||
427 | if (!addr->address || !addr->bit_width) | 438 | if (!addr->address || !addr->bit_width) |
428 | return; | 439 | return; |
429 | 440 | ||
430 | spin_lock_irqsave(&acpi_ioremap_lock, flags); | 441 | mutex_lock(&acpi_ioremap_lock); |
431 | virt = acpi_map_vaddr_lookup(addr->address, size); | 442 | map = acpi_map_lookup(addr->address, addr->bit_width / 8); |
432 | spin_unlock_irqrestore(&acpi_ioremap_lock, flags); | 443 | if (!map) { |
444 | mutex_unlock(&acpi_ioremap_lock); | ||
445 | return; | ||
446 | } | ||
447 | acpi_os_drop_map_ref(map); | ||
448 | mutex_unlock(&acpi_ioremap_lock); | ||
433 | 449 | ||
434 | acpi_os_unmap_memory(virt, size); | 450 | acpi_os_map_cleanup(map); |
435 | } | 451 | } |
436 | EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address); | ||
437 | 452 | ||
438 | #ifdef ACPI_FUTURE_USAGE | 453 | #ifdef ACPI_FUTURE_USAGE |
439 | acpi_status | 454 | acpi_status |
@@ -516,11 +531,15 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
516 | acpi_irq_stats_init(); | 531 | acpi_irq_stats_init(); |
517 | 532 | ||
518 | /* | 533 | /* |
519 | * Ignore the GSI from the core, and use the value in our copy of the | 534 | * ACPI interrupts different from the SCI in our copy of the FADT are |
520 | * FADT. It may not be the same if an interrupt source override exists | 535 | * not supported. |
521 | * for the SCI. | ||
522 | */ | 536 | */ |
523 | gsi = acpi_gbl_FADT.sci_interrupt; | 537 | if (gsi != acpi_gbl_FADT.sci_interrupt) |
538 | return AE_BAD_PARAMETER; | ||
539 | |||
540 | if (acpi_irq_handler) | ||
541 | return AE_ALREADY_ACQUIRED; | ||
542 | |||
524 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { | 543 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { |
525 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", | 544 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", |
526 | gsi); | 545 | gsi); |
@@ -531,20 +550,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
531 | acpi_irq_context = context; | 550 | acpi_irq_context = context; |
532 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { | 551 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { |
533 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); | 552 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); |
553 | acpi_irq_handler = NULL; | ||
534 | return AE_NOT_ACQUIRED; | 554 | return AE_NOT_ACQUIRED; |
535 | } | 555 | } |
536 | acpi_irq_irq = irq; | ||
537 | 556 | ||
538 | return AE_OK; | 557 | return AE_OK; |
539 | } | 558 | } |
540 | 559 | ||
541 | acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) | 560 | acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) |
542 | { | 561 | { |
543 | if (irq) { | 562 | if (irq != acpi_gbl_FADT.sci_interrupt) |
544 | free_irq(irq, acpi_irq); | 563 | return AE_BAD_PARAMETER; |
545 | acpi_irq_handler = NULL; | 564 | |
546 | acpi_irq_irq = 0; | 565 | free_irq(irq, acpi_irq); |
547 | } | 566 | acpi_irq_handler = NULL; |
548 | 567 | ||
549 | return AE_OK; | 568 | return AE_OK; |
550 | } | 569 | } |
@@ -1603,7 +1622,7 @@ acpi_status __init acpi_os_initialize1(void) | |||
1603 | acpi_status acpi_os_terminate(void) | 1622 | acpi_status acpi_os_terminate(void) |
1604 | { | 1623 | { |
1605 | if (acpi_irq_handler) { | 1624 | if (acpi_irq_handler) { |
1606 | acpi_os_remove_interrupt_handler(acpi_irq_irq, | 1625 | acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt, |
1607 | acpi_irq_handler); | 1626 | acpi_irq_handler); |
1608 | } | 1627 | } |
1609 | 1628 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b99e62494607..b136c9c1e531 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -797,7 +797,6 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) | |||
797 | acpi_status status; | 797 | acpi_status status; |
798 | acpi_event_status event_status; | 798 | acpi_event_status event_status; |
799 | 799 | ||
800 | device->wakeup.run_wake_count = 0; | ||
801 | device->wakeup.flags.notifier_present = 0; | 800 | device->wakeup.flags.notifier_present = 0; |
802 | 801 | ||
803 | /* Power button, Lid switch always enable wakeup */ | 802 | /* Power button, Lid switch always enable wakeup */ |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index d6a8cd14de2e..84f57143ad7c 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -199,8 +199,6 @@ static void acpi_pm_end(void) | |||
199 | #endif /* CONFIG_ACPI_SLEEP */ | 199 | #endif /* CONFIG_ACPI_SLEEP */ |
200 | 200 | ||
201 | #ifdef CONFIG_SUSPEND | 201 | #ifdef CONFIG_SUSPEND |
202 | extern void do_suspend_lowlevel(void); | ||
203 | |||
204 | static u32 acpi_suspend_states[] = { | 202 | static u32 acpi_suspend_states[] = { |
205 | [PM_SUSPEND_ON] = ACPI_STATE_S0, | 203 | [PM_SUSPEND_ON] = ACPI_STATE_S0, |
206 | [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, | 204 | [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, |
@@ -243,20 +241,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
243 | static int acpi_suspend_enter(suspend_state_t pm_state) | 241 | static int acpi_suspend_enter(suspend_state_t pm_state) |
244 | { | 242 | { |
245 | acpi_status status = AE_OK; | 243 | acpi_status status = AE_OK; |
246 | unsigned long flags = 0; | ||
247 | u32 acpi_state = acpi_target_sleep_state; | 244 | u32 acpi_state = acpi_target_sleep_state; |
245 | int error; | ||
248 | 246 | ||
249 | ACPI_FLUSH_CPU_CACHE(); | 247 | ACPI_FLUSH_CPU_CACHE(); |
250 | 248 | ||
251 | /* Do arch specific saving of state. */ | ||
252 | if (acpi_state == ACPI_STATE_S3) { | ||
253 | int error = acpi_save_state_mem(); | ||
254 | |||
255 | if (error) | ||
256 | return error; | ||
257 | } | ||
258 | |||
259 | local_irq_save(flags); | ||
260 | switch (acpi_state) { | 249 | switch (acpi_state) { |
261 | case ACPI_STATE_S1: | 250 | case ACPI_STATE_S1: |
262 | barrier(); | 251 | barrier(); |
@@ -264,7 +253,10 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
264 | break; | 253 | break; |
265 | 254 | ||
266 | case ACPI_STATE_S3: | 255 | case ACPI_STATE_S3: |
267 | do_suspend_lowlevel(); | 256 | error = acpi_suspend_lowlevel(); |
257 | if (error) | ||
258 | return error; | ||
259 | pr_info(PREFIX "Low-level resume complete\n"); | ||
268 | break; | 260 | break; |
269 | } | 261 | } |
270 | 262 | ||
@@ -290,13 +282,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
290 | /* Allow EC transactions to happen. */ | 282 | /* Allow EC transactions to happen. */ |
291 | acpi_ec_unblock_transactions_early(); | 283 | acpi_ec_unblock_transactions_early(); |
292 | 284 | ||
293 | local_irq_restore(flags); | ||
294 | printk(KERN_DEBUG "Back to C!\n"); | ||
295 | |||
296 | /* restore processor state */ | ||
297 | if (acpi_state == ACPI_STATE_S3) | ||
298 | acpi_restore_state_mem(); | ||
299 | |||
300 | suspend_nvs_restore(); | 285 | suspend_nvs_restore(); |
301 | 286 | ||
302 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 287 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
@@ -472,16 +457,13 @@ static int acpi_hibernation_begin(void) | |||
472 | static int acpi_hibernation_enter(void) | 457 | static int acpi_hibernation_enter(void) |
473 | { | 458 | { |
474 | acpi_status status = AE_OK; | 459 | acpi_status status = AE_OK; |
475 | unsigned long flags = 0; | ||
476 | 460 | ||
477 | ACPI_FLUSH_CPU_CACHE(); | 461 | ACPI_FLUSH_CPU_CACHE(); |
478 | 462 | ||
479 | local_irq_save(flags); | ||
480 | /* This shouldn't return. If it returns, we have a problem */ | 463 | /* This shouldn't return. If it returns, we have a problem */ |
481 | status = acpi_enter_sleep_state(ACPI_STATE_S4); | 464 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
482 | /* Reprogram control registers and execute _BFS */ | 465 | /* Reprogram control registers and execute _BFS */ |
483 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | 466 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); |
484 | local_irq_restore(flags); | ||
485 | 467 | ||
486 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 468 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
487 | } | 469 | } |