diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-03 10:52:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-03 10:52:57 -0500 |
commit | 38dc63459f185795b24a39f3f4921a433ea9980b (patch) | |
tree | 205a8abc9b20c4f5573e4d2fbc03e74388cef2bc | |
parent | 1d510750941a53a1d3049c1d33c75d6dfcd78618 (diff) | |
parent | 2ddac2a6a8f13e95664fe7ad1b728ac84fb1bd07 (diff) |
Merge branch 'pm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'pm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
PM: Remove some debug messages producing too much noise
PM: Fix warning on suspend errors
PM / Hibernate: Add newline to load_image() fail path
PM / Hibernate: Fix error handling in save_image()
PM / Hibernate: Fix blkdev refleaks
PM / yenta: Split resume into early and late parts (rev. 4)
-rw-r--r-- | drivers/base/power/main.c | 1 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 4 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 69 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 12 | ||||
-rw-r--r-- | include/pcmcia/ss.h | 4 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 11 | ||||
-rw-r--r-- | kernel/power/swap.c | 43 |
7 files changed, 89 insertions, 55 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e0dc4071e088..8aa2443182d5 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -511,6 +511,7 @@ static void dpm_complete(pm_message_t state) | |||
511 | 511 | ||
512 | INIT_LIST_HEAD(&list); | 512 | INIT_LIST_HEAD(&list); |
513 | mutex_lock(&dpm_list_mtx); | 513 | mutex_lock(&dpm_list_mtx); |
514 | transition_started = false; | ||
514 | while (!list_empty(&dpm_list)) { | 515 | while (!list_empty(&dpm_list)) { |
515 | struct device *dev = to_device(dpm_list.prev); | 516 | struct device *dev = to_device(dpm_list.prev); |
516 | 517 | ||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 38556f6cc22d..a770498a74ec 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -51,8 +51,6 @@ static int __pm_runtime_idle(struct device *dev) | |||
51 | { | 51 | { |
52 | int retval = 0; | 52 | int retval = 0; |
53 | 53 | ||
54 | dev_dbg(dev, "__pm_runtime_idle()!\n"); | ||
55 | |||
56 | if (dev->power.runtime_error) | 54 | if (dev->power.runtime_error) |
57 | retval = -EINVAL; | 55 | retval = -EINVAL; |
58 | else if (dev->power.idle_notification) | 56 | else if (dev->power.idle_notification) |
@@ -93,8 +91,6 @@ static int __pm_runtime_idle(struct device *dev) | |||
93 | wake_up_all(&dev->power.wait_queue); | 91 | wake_up_all(&dev->power.wait_queue); |
94 | 92 | ||
95 | out: | 93 | out: |
96 | dev_dbg(dev, "__pm_runtime_idle() returns %d!\n", retval); | ||
97 | |||
98 | return retval; | 94 | return retval; |
99 | } | 95 | } |
100 | 96 | ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 934d4bee39a0..698d75cda084 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -98,10 +98,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem); | |||
98 | * These functions check for the appropriate struct pcmcia_soket arrays, | 98 | * These functions check for the appropriate struct pcmcia_soket arrays, |
99 | * and pass them to the low-level functions pcmcia_{suspend,resume}_socket | 99 | * and pass them to the low-level functions pcmcia_{suspend,resume}_socket |
100 | */ | 100 | */ |
101 | static int socket_early_resume(struct pcmcia_socket *skt); | ||
102 | static int socket_late_resume(struct pcmcia_socket *skt); | ||
101 | static int socket_resume(struct pcmcia_socket *skt); | 103 | static int socket_resume(struct pcmcia_socket *skt); |
102 | static int socket_suspend(struct pcmcia_socket *skt); | 104 | static int socket_suspend(struct pcmcia_socket *skt); |
103 | 105 | ||
104 | int pcmcia_socket_dev_suspend(struct device *dev) | 106 | static void pcmcia_socket_dev_run(struct device *dev, |
107 | int (*cb)(struct pcmcia_socket *)) | ||
105 | { | 108 | { |
106 | struct pcmcia_socket *socket; | 109 | struct pcmcia_socket *socket; |
107 | 110 | ||
@@ -110,29 +113,34 @@ int pcmcia_socket_dev_suspend(struct device *dev) | |||
110 | if (socket->dev.parent != dev) | 113 | if (socket->dev.parent != dev) |
111 | continue; | 114 | continue; |
112 | mutex_lock(&socket->skt_mutex); | 115 | mutex_lock(&socket->skt_mutex); |
113 | socket_suspend(socket); | 116 | cb(socket); |
114 | mutex_unlock(&socket->skt_mutex); | 117 | mutex_unlock(&socket->skt_mutex); |
115 | } | 118 | } |
116 | up_read(&pcmcia_socket_list_rwsem); | 119 | up_read(&pcmcia_socket_list_rwsem); |
120 | } | ||
117 | 121 | ||
122 | int pcmcia_socket_dev_suspend(struct device *dev) | ||
123 | { | ||
124 | pcmcia_socket_dev_run(dev, socket_suspend); | ||
118 | return 0; | 125 | return 0; |
119 | } | 126 | } |
120 | EXPORT_SYMBOL(pcmcia_socket_dev_suspend); | 127 | EXPORT_SYMBOL(pcmcia_socket_dev_suspend); |
121 | 128 | ||
122 | int pcmcia_socket_dev_resume(struct device *dev) | 129 | void pcmcia_socket_dev_early_resume(struct device *dev) |
123 | { | 130 | { |
124 | struct pcmcia_socket *socket; | 131 | pcmcia_socket_dev_run(dev, socket_early_resume); |
132 | } | ||
133 | EXPORT_SYMBOL(pcmcia_socket_dev_early_resume); | ||
125 | 134 | ||
126 | down_read(&pcmcia_socket_list_rwsem); | 135 | void pcmcia_socket_dev_late_resume(struct device *dev) |
127 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { | 136 | { |
128 | if (socket->dev.parent != dev) | 137 | pcmcia_socket_dev_run(dev, socket_late_resume); |
129 | continue; | 138 | } |
130 | mutex_lock(&socket->skt_mutex); | 139 | EXPORT_SYMBOL(pcmcia_socket_dev_late_resume); |
131 | socket_resume(socket); | ||
132 | mutex_unlock(&socket->skt_mutex); | ||
133 | } | ||
134 | up_read(&pcmcia_socket_list_rwsem); | ||
135 | 140 | ||
141 | int pcmcia_socket_dev_resume(struct device *dev) | ||
142 | { | ||
143 | pcmcia_socket_dev_run(dev, socket_resume); | ||
136 | return 0; | 144 | return 0; |
137 | } | 145 | } |
138 | EXPORT_SYMBOL(pcmcia_socket_dev_resume); | 146 | EXPORT_SYMBOL(pcmcia_socket_dev_resume); |
@@ -546,29 +554,24 @@ static int socket_suspend(struct pcmcia_socket *skt) | |||
546 | return 0; | 554 | return 0; |
547 | } | 555 | } |
548 | 556 | ||
549 | /* | 557 | static int socket_early_resume(struct pcmcia_socket *skt) |
550 | * Resume a socket. If a card is present, verify its CIS against | ||
551 | * our cached copy. If they are different, the card has been | ||
552 | * replaced, and we need to tell the drivers. | ||
553 | */ | ||
554 | static int socket_resume(struct pcmcia_socket *skt) | ||
555 | { | 558 | { |
556 | int ret; | ||
557 | |||
558 | if (!(skt->state & SOCKET_SUSPEND)) | ||
559 | return -EBUSY; | ||
560 | |||
561 | skt->socket = dead_socket; | 559 | skt->socket = dead_socket; |
562 | skt->ops->init(skt); | 560 | skt->ops->init(skt); |
563 | skt->ops->set_socket(skt, &skt->socket); | 561 | skt->ops->set_socket(skt, &skt->socket); |
562 | if (skt->state & SOCKET_PRESENT) | ||
563 | skt->resume_status = socket_setup(skt, resume_delay); | ||
564 | return 0; | ||
565 | } | ||
564 | 566 | ||
567 | static int socket_late_resume(struct pcmcia_socket *skt) | ||
568 | { | ||
565 | if (!(skt->state & SOCKET_PRESENT)) { | 569 | if (!(skt->state & SOCKET_PRESENT)) { |
566 | skt->state &= ~SOCKET_SUSPEND; | 570 | skt->state &= ~SOCKET_SUSPEND; |
567 | return socket_insert(skt); | 571 | return socket_insert(skt); |
568 | } | 572 | } |
569 | 573 | ||
570 | ret = socket_setup(skt, resume_delay); | 574 | if (skt->resume_status == 0) { |
571 | if (ret == 0) { | ||
572 | /* | 575 | /* |
573 | * FIXME: need a better check here for cardbus cards. | 576 | * FIXME: need a better check here for cardbus cards. |
574 | */ | 577 | */ |
@@ -596,6 +599,20 @@ static int socket_resume(struct pcmcia_socket *skt) | |||
596 | return 0; | 599 | return 0; |
597 | } | 600 | } |
598 | 601 | ||
602 | /* | ||
603 | * Resume a socket. If a card is present, verify its CIS against | ||
604 | * our cached copy. If they are different, the card has been | ||
605 | * replaced, and we need to tell the drivers. | ||
606 | */ | ||
607 | static int socket_resume(struct pcmcia_socket *skt) | ||
608 | { | ||
609 | if (!(skt->state & SOCKET_SUSPEND)) | ||
610 | return -EBUSY; | ||
611 | |||
612 | socket_early_resume(skt); | ||
613 | return socket_late_resume(skt); | ||
614 | } | ||
615 | |||
599 | static void socket_remove(struct pcmcia_socket *skt) | 616 | static void socket_remove(struct pcmcia_socket *skt) |
600 | { | 617 | { |
601 | dev_printk(KERN_NOTICE, &skt->dev, | 618 | dev_printk(KERN_NOTICE, &skt->dev, |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index abe0e44c6e9e..8be4cc447a17 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -1275,16 +1275,26 @@ static int yenta_dev_resume_noirq(struct device *dev) | |||
1275 | if (socket->type && socket->type->restore_state) | 1275 | if (socket->type && socket->type->restore_state) |
1276 | socket->type->restore_state(socket); | 1276 | socket->type->restore_state(socket); |
1277 | 1277 | ||
1278 | return pcmcia_socket_dev_resume(dev); | 1278 | pcmcia_socket_dev_early_resume(dev); |
1279 | return 0; | ||
1280 | } | ||
1281 | |||
1282 | static int yenta_dev_resume(struct device *dev) | ||
1283 | { | ||
1284 | pcmcia_socket_dev_late_resume(dev); | ||
1285 | return 0; | ||
1279 | } | 1286 | } |
1280 | 1287 | ||
1281 | static struct dev_pm_ops yenta_pm_ops = { | 1288 | static struct dev_pm_ops yenta_pm_ops = { |
1282 | .suspend_noirq = yenta_dev_suspend_noirq, | 1289 | .suspend_noirq = yenta_dev_suspend_noirq, |
1283 | .resume_noirq = yenta_dev_resume_noirq, | 1290 | .resume_noirq = yenta_dev_resume_noirq, |
1291 | .resume = yenta_dev_resume, | ||
1284 | .freeze_noirq = yenta_dev_suspend_noirq, | 1292 | .freeze_noirq = yenta_dev_suspend_noirq, |
1285 | .thaw_noirq = yenta_dev_resume_noirq, | 1293 | .thaw_noirq = yenta_dev_resume_noirq, |
1294 | .thaw = yenta_dev_resume, | ||
1286 | .poweroff_noirq = yenta_dev_suspend_noirq, | 1295 | .poweroff_noirq = yenta_dev_suspend_noirq, |
1287 | .restore_noirq = yenta_dev_resume_noirq, | 1296 | .restore_noirq = yenta_dev_resume_noirq, |
1297 | .restore = yenta_dev_resume, | ||
1288 | }; | 1298 | }; |
1289 | 1299 | ||
1290 | #define YENTA_PM_OPS (¥ta_pm_ops) | 1300 | #define YENTA_PM_OPS (¥ta_pm_ops) |
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index d696a692d94a..e0f6feb8588c 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h | |||
@@ -262,6 +262,8 @@ struct pcmcia_socket { | |||
262 | struct device dev; | 262 | struct device dev; |
263 | /* data internal to the socket driver */ | 263 | /* data internal to the socket driver */ |
264 | void *driver_data; | 264 | void *driver_data; |
265 | /* status of the card during resume from a system sleep state */ | ||
266 | int resume_status; | ||
265 | }; | 267 | }; |
266 | 268 | ||
267 | 269 | ||
@@ -280,6 +282,8 @@ extern struct pccard_resource_ops pccard_nonstatic_ops; | |||
280 | 282 | ||
281 | /* socket drivers are expected to use these callbacks in their .drv struct */ | 283 | /* socket drivers are expected to use these callbacks in their .drv struct */ |
282 | extern int pcmcia_socket_dev_suspend(struct device *dev); | 284 | extern int pcmcia_socket_dev_suspend(struct device *dev); |
285 | extern void pcmcia_socket_dev_early_resume(struct device *dev); | ||
286 | extern void pcmcia_socket_dev_late_resume(struct device *dev); | ||
283 | extern int pcmcia_socket_dev_resume(struct device *dev); | 287 | extern int pcmcia_socket_dev_resume(struct device *dev); |
284 | 288 | ||
285 | /* socket drivers use this callback in their IRQ handler */ | 289 | /* socket drivers use this callback in their IRQ handler */ |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 04b3a83d686f..04a9e90d248f 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -693,21 +693,22 @@ static int software_resume(void) | |||
693 | /* The snapshot device should not be opened while we're running */ | 693 | /* The snapshot device should not be opened while we're running */ |
694 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { | 694 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { |
695 | error = -EBUSY; | 695 | error = -EBUSY; |
696 | swsusp_close(FMODE_READ); | ||
696 | goto Unlock; | 697 | goto Unlock; |
697 | } | 698 | } |
698 | 699 | ||
699 | pm_prepare_console(); | 700 | pm_prepare_console(); |
700 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | 701 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); |
701 | if (error) | 702 | if (error) |
702 | goto Finish; | 703 | goto close_finish; |
703 | 704 | ||
704 | error = usermodehelper_disable(); | 705 | error = usermodehelper_disable(); |
705 | if (error) | 706 | if (error) |
706 | goto Finish; | 707 | goto close_finish; |
707 | 708 | ||
708 | error = create_basic_memory_bitmaps(); | 709 | error = create_basic_memory_bitmaps(); |
709 | if (error) | 710 | if (error) |
710 | goto Finish; | 711 | goto close_finish; |
711 | 712 | ||
712 | pr_debug("PM: Preparing processes for restore.\n"); | 713 | pr_debug("PM: Preparing processes for restore.\n"); |
713 | error = prepare_processes(); | 714 | error = prepare_processes(); |
@@ -719,6 +720,7 @@ static int software_resume(void) | |||
719 | pr_debug("PM: Reading hibernation image.\n"); | 720 | pr_debug("PM: Reading hibernation image.\n"); |
720 | 721 | ||
721 | error = swsusp_read(&flags); | 722 | error = swsusp_read(&flags); |
723 | swsusp_close(FMODE_READ); | ||
722 | if (!error) | 724 | if (!error) |
723 | hibernation_restore(flags & SF_PLATFORM_MODE); | 725 | hibernation_restore(flags & SF_PLATFORM_MODE); |
724 | 726 | ||
@@ -737,6 +739,9 @@ static int software_resume(void) | |||
737 | mutex_unlock(&pm_mutex); | 739 | mutex_unlock(&pm_mutex); |
738 | pr_debug("PM: Resume from disk failed.\n"); | 740 | pr_debug("PM: Resume from disk failed.\n"); |
739 | return error; | 741 | return error; |
742 | close_finish: | ||
743 | swsusp_close(FMODE_READ); | ||
744 | goto Finish; | ||
740 | } | 745 | } |
741 | 746 | ||
742 | late_initcall(software_resume); | 747 | late_initcall(software_resume); |
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index b101cdc4df3f..890f6b11b1d3 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -314,7 +314,6 @@ static int save_image(struct swap_map_handle *handle, | |||
314 | { | 314 | { |
315 | unsigned int m; | 315 | unsigned int m; |
316 | int ret; | 316 | int ret; |
317 | int error = 0; | ||
318 | int nr_pages; | 317 | int nr_pages; |
319 | int err2; | 318 | int err2; |
320 | struct bio *bio; | 319 | struct bio *bio; |
@@ -329,26 +328,27 @@ static int save_image(struct swap_map_handle *handle, | |||
329 | nr_pages = 0; | 328 | nr_pages = 0; |
330 | bio = NULL; | 329 | bio = NULL; |
331 | do_gettimeofday(&start); | 330 | do_gettimeofday(&start); |
332 | do { | 331 | while (1) { |
333 | ret = snapshot_read_next(snapshot, PAGE_SIZE); | 332 | ret = snapshot_read_next(snapshot, PAGE_SIZE); |
334 | if (ret > 0) { | 333 | if (ret <= 0) |
335 | error = swap_write_page(handle, data_of(*snapshot), | 334 | break; |
336 | &bio); | 335 | ret = swap_write_page(handle, data_of(*snapshot), &bio); |
337 | if (error) | 336 | if (ret) |
338 | break; | 337 | break; |
339 | if (!(nr_pages % m)) | 338 | if (!(nr_pages % m)) |
340 | printk("\b\b\b\b%3d%%", nr_pages / m); | 339 | printk("\b\b\b\b%3d%%", nr_pages / m); |
341 | nr_pages++; | 340 | nr_pages++; |
342 | } | 341 | } |
343 | } while (ret > 0); | ||
344 | err2 = wait_on_bio_chain(&bio); | 342 | err2 = wait_on_bio_chain(&bio); |
345 | do_gettimeofday(&stop); | 343 | do_gettimeofday(&stop); |
346 | if (!error) | 344 | if (!ret) |
347 | error = err2; | 345 | ret = err2; |
348 | if (!error) | 346 | if (!ret) |
349 | printk("\b\b\b\bdone\n"); | 347 | printk("\b\b\b\bdone\n"); |
348 | else | ||
349 | printk("\n"); | ||
350 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); | 350 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); |
351 | return error; | 351 | return ret; |
352 | } | 352 | } |
353 | 353 | ||
354 | /** | 354 | /** |
@@ -536,7 +536,8 @@ static int load_image(struct swap_map_handle *handle, | |||
536 | snapshot_write_finalize(snapshot); | 536 | snapshot_write_finalize(snapshot); |
537 | if (!snapshot_image_loaded(snapshot)) | 537 | if (!snapshot_image_loaded(snapshot)) |
538 | error = -ENODATA; | 538 | error = -ENODATA; |
539 | } | 539 | } else |
540 | printk("\n"); | ||
540 | swsusp_show_speed(&start, &stop, nr_to_read, "Read"); | 541 | swsusp_show_speed(&start, &stop, nr_to_read, "Read"); |
541 | return error; | 542 | return error; |
542 | } | 543 | } |
@@ -572,8 +573,6 @@ int swsusp_read(unsigned int *flags_p) | |||
572 | error = load_image(&handle, &snapshot, header->pages - 1); | 573 | error = load_image(&handle, &snapshot, header->pages - 1); |
573 | release_swap_reader(&handle); | 574 | release_swap_reader(&handle); |
574 | 575 | ||
575 | blkdev_put(resume_bdev, FMODE_READ); | ||
576 | |||
577 | if (!error) | 576 | if (!error) |
578 | pr_debug("PM: Image successfully loaded\n"); | 577 | pr_debug("PM: Image successfully loaded\n"); |
579 | else | 578 | else |
@@ -596,7 +595,7 @@ int swsusp_check(void) | |||
596 | error = bio_read_page(swsusp_resume_block, | 595 | error = bio_read_page(swsusp_resume_block, |
597 | swsusp_header, NULL); | 596 | swsusp_header, NULL); |
598 | if (error) | 597 | if (error) |
599 | return error; | 598 | goto put; |
600 | 599 | ||
601 | if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) { | 600 | if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) { |
602 | memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); | 601 | memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); |
@@ -604,8 +603,10 @@ int swsusp_check(void) | |||
604 | error = bio_write_page(swsusp_resume_block, | 603 | error = bio_write_page(swsusp_resume_block, |
605 | swsusp_header, NULL); | 604 | swsusp_header, NULL); |
606 | } else { | 605 | } else { |
607 | return -EINVAL; | 606 | error = -EINVAL; |
608 | } | 607 | } |
608 | |||
609 | put: | ||
609 | if (error) | 610 | if (error) |
610 | blkdev_put(resume_bdev, FMODE_READ); | 611 | blkdev_put(resume_bdev, FMODE_READ); |
611 | else | 612 | else |