diff options
Diffstat (limited to 'drivers/pcmcia/cs.c')
-rw-r--r-- | drivers/pcmcia/cs.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 673c14ea11e3..5292db69c426 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -484,7 +484,7 @@ static int socket_early_resume(struct pcmcia_socket *skt) | |||
484 | 484 | ||
485 | static int socket_late_resume(struct pcmcia_socket *skt) | 485 | static int socket_late_resume(struct pcmcia_socket *skt) |
486 | { | 486 | { |
487 | int ret; | 487 | int ret = 0; |
488 | 488 | ||
489 | mutex_lock(&skt->ops_mutex); | 489 | mutex_lock(&skt->ops_mutex); |
490 | skt->state &= ~SOCKET_SUSPEND; | 490 | skt->state &= ~SOCKET_SUSPEND; |
@@ -511,19 +511,31 @@ static int socket_late_resume(struct pcmcia_socket *skt) | |||
511 | return socket_insert(skt); | 511 | return socket_insert(skt); |
512 | } | 512 | } |
513 | 513 | ||
514 | if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) | ||
515 | ret = skt->callback->early_resume(skt); | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * Finalize the resume. In case of a cardbus socket, we have | ||
521 | * to rebind the devices as we can't be certain that it has been | ||
522 | * replaced, or not. | ||
523 | */ | ||
524 | static int socket_complete_resume(struct pcmcia_socket *skt) | ||
525 | { | ||
526 | int ret = 0; | ||
514 | #ifdef CONFIG_CARDBUS | 527 | #ifdef CONFIG_CARDBUS |
515 | if (skt->state & SOCKET_CARDBUS) { | 528 | if (skt->state & SOCKET_CARDBUS) { |
516 | /* We can't be sure the CardBus card is the same | 529 | /* We can't be sure the CardBus card is the same |
517 | * as the one previously inserted. Therefore, remove | 530 | * as the one previously inserted. Therefore, remove |
518 | * and re-add... */ | 531 | * and re-add... */ |
519 | cb_free(skt); | 532 | cb_free(skt); |
520 | cb_alloc(skt); | 533 | ret = cb_alloc(skt); |
521 | return 0; | 534 | if (ret) |
535 | cb_free(skt); | ||
522 | } | 536 | } |
523 | #endif | 537 | #endif |
524 | if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) | 538 | return ret; |
525 | skt->callback->early_resume(skt); | ||
526 | return 0; | ||
527 | } | 539 | } |
528 | 540 | ||
529 | /* | 541 | /* |
@@ -533,11 +545,15 @@ static int socket_late_resume(struct pcmcia_socket *skt) | |||
533 | */ | 545 | */ |
534 | static int socket_resume(struct pcmcia_socket *skt) | 546 | static int socket_resume(struct pcmcia_socket *skt) |
535 | { | 547 | { |
548 | int err; | ||
536 | if (!(skt->state & SOCKET_SUSPEND)) | 549 | if (!(skt->state & SOCKET_SUSPEND)) |
537 | return -EBUSY; | 550 | return -EBUSY; |
538 | 551 | ||
539 | socket_early_resume(skt); | 552 | socket_early_resume(skt); |
540 | return socket_late_resume(skt); | 553 | err = socket_late_resume(skt); |
554 | if (!err) | ||
555 | err = socket_complete_resume(skt); | ||
556 | return err; | ||
541 | } | 557 | } |
542 | 558 | ||
543 | static void socket_remove(struct pcmcia_socket *skt) | 559 | static void socket_remove(struct pcmcia_socket *skt) |
@@ -848,6 +864,12 @@ static int __used pcmcia_socket_dev_resume(struct device *dev) | |||
848 | return __pcmcia_pm_op(dev, socket_late_resume); | 864 | return __pcmcia_pm_op(dev, socket_late_resume); |
849 | } | 865 | } |
850 | 866 | ||
867 | static void __used pcmcia_socket_dev_complete(struct device *dev) | ||
868 | { | ||
869 | WARN(__pcmcia_pm_op(dev, socket_complete_resume), | ||
870 | "failed to complete resume"); | ||
871 | } | ||
872 | |||
851 | static const struct dev_pm_ops pcmcia_socket_pm_ops = { | 873 | static const struct dev_pm_ops pcmcia_socket_pm_ops = { |
852 | /* dev_resume may be called with IRQs enabled */ | 874 | /* dev_resume may be called with IRQs enabled */ |
853 | SET_SYSTEM_SLEEP_PM_OPS(NULL, | 875 | SET_SYSTEM_SLEEP_PM_OPS(NULL, |
@@ -862,6 +884,7 @@ static const struct dev_pm_ops pcmcia_socket_pm_ops = { | |||
862 | .resume_noirq = pcmcia_socket_dev_resume_noirq, | 884 | .resume_noirq = pcmcia_socket_dev_resume_noirq, |
863 | .thaw_noirq = pcmcia_socket_dev_resume_noirq, | 885 | .thaw_noirq = pcmcia_socket_dev_resume_noirq, |
864 | .restore_noirq = pcmcia_socket_dev_resume_noirq, | 886 | .restore_noirq = pcmcia_socket_dev_resume_noirq, |
887 | .complete = pcmcia_socket_dev_complete, | ||
865 | }; | 888 | }; |
866 | 889 | ||
867 | #define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) | 890 | #define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) |