diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cs.c | 69 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 12 |
2 files changed, 54 insertions, 27 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index fc1c0c6baae2..790af87a922f 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -87,10 +87,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem); | |||
87 | * These functions check for the appropriate struct pcmcia_soket arrays, | 87 | * These functions check for the appropriate struct pcmcia_soket arrays, |
88 | * and pass them to the low-level functions pcmcia_{suspend,resume}_socket | 88 | * and pass them to the low-level functions pcmcia_{suspend,resume}_socket |
89 | */ | 89 | */ |
90 | static int socket_early_resume(struct pcmcia_socket *skt); | ||
91 | static int socket_late_resume(struct pcmcia_socket *skt); | ||
90 | static int socket_resume(struct pcmcia_socket *skt); | 92 | static int socket_resume(struct pcmcia_socket *skt); |
91 | static int socket_suspend(struct pcmcia_socket *skt); | 93 | static int socket_suspend(struct pcmcia_socket *skt); |
92 | 94 | ||
93 | int pcmcia_socket_dev_suspend(struct device *dev) | 95 | static void pcmcia_socket_dev_run(struct device *dev, |
96 | int (*cb)(struct pcmcia_socket *)) | ||
94 | { | 97 | { |
95 | struct pcmcia_socket *socket; | 98 | struct pcmcia_socket *socket; |
96 | 99 | ||
@@ -99,29 +102,34 @@ int pcmcia_socket_dev_suspend(struct device *dev) | |||
99 | if (socket->dev.parent != dev) | 102 | if (socket->dev.parent != dev) |
100 | continue; | 103 | continue; |
101 | mutex_lock(&socket->skt_mutex); | 104 | mutex_lock(&socket->skt_mutex); |
102 | socket_suspend(socket); | 105 | cb(socket); |
103 | mutex_unlock(&socket->skt_mutex); | 106 | mutex_unlock(&socket->skt_mutex); |
104 | } | 107 | } |
105 | up_read(&pcmcia_socket_list_rwsem); | 108 | up_read(&pcmcia_socket_list_rwsem); |
109 | } | ||
106 | 110 | ||
111 | int pcmcia_socket_dev_suspend(struct device *dev) | ||
112 | { | ||
113 | pcmcia_socket_dev_run(dev, socket_suspend); | ||
107 | return 0; | 114 | return 0; |
108 | } | 115 | } |
109 | EXPORT_SYMBOL(pcmcia_socket_dev_suspend); | 116 | EXPORT_SYMBOL(pcmcia_socket_dev_suspend); |
110 | 117 | ||
111 | int pcmcia_socket_dev_resume(struct device *dev) | 118 | void pcmcia_socket_dev_early_resume(struct device *dev) |
112 | { | 119 | { |
113 | struct pcmcia_socket *socket; | 120 | pcmcia_socket_dev_run(dev, socket_early_resume); |
121 | } | ||
122 | EXPORT_SYMBOL(pcmcia_socket_dev_early_resume); | ||
114 | 123 | ||
115 | down_read(&pcmcia_socket_list_rwsem); | 124 | void pcmcia_socket_dev_late_resume(struct device *dev) |
116 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { | 125 | { |
117 | if (socket->dev.parent != dev) | 126 | pcmcia_socket_dev_run(dev, socket_late_resume); |
118 | continue; | 127 | } |
119 | mutex_lock(&socket->skt_mutex); | 128 | EXPORT_SYMBOL(pcmcia_socket_dev_late_resume); |
120 | socket_resume(socket); | ||
121 | mutex_unlock(&socket->skt_mutex); | ||
122 | } | ||
123 | up_read(&pcmcia_socket_list_rwsem); | ||
124 | 129 | ||
130 | int pcmcia_socket_dev_resume(struct device *dev) | ||
131 | { | ||
132 | pcmcia_socket_dev_run(dev, socket_resume); | ||
125 | return 0; | 133 | return 0; |
126 | } | 134 | } |
127 | EXPORT_SYMBOL(pcmcia_socket_dev_resume); | 135 | EXPORT_SYMBOL(pcmcia_socket_dev_resume); |
@@ -544,29 +552,24 @@ static int socket_suspend(struct pcmcia_socket *skt) | |||
544 | return 0; | 552 | return 0; |
545 | } | 553 | } |
546 | 554 | ||
547 | /* | 555 | static int socket_early_resume(struct pcmcia_socket *skt) |
548 | * Resume a socket. If a card is present, verify its CIS against | ||
549 | * our cached copy. If they are different, the card has been | ||
550 | * replaced, and we need to tell the drivers. | ||
551 | */ | ||
552 | static int socket_resume(struct pcmcia_socket *skt) | ||
553 | { | 556 | { |
554 | int ret; | ||
555 | |||
556 | if (!(skt->state & SOCKET_SUSPEND)) | ||
557 | return -EBUSY; | ||
558 | |||
559 | skt->socket = dead_socket; | 557 | skt->socket = dead_socket; |
560 | skt->ops->init(skt); | 558 | skt->ops->init(skt); |
561 | skt->ops->set_socket(skt, &skt->socket); | 559 | skt->ops->set_socket(skt, &skt->socket); |
560 | if (skt->state & SOCKET_PRESENT) | ||
561 | skt->resume_status = socket_setup(skt, resume_delay); | ||
562 | return 0; | ||
563 | } | ||
562 | 564 | ||
565 | static int socket_late_resume(struct pcmcia_socket *skt) | ||
566 | { | ||
563 | if (!(skt->state & SOCKET_PRESENT)) { | 567 | if (!(skt->state & SOCKET_PRESENT)) { |
564 | skt->state &= ~SOCKET_SUSPEND; | 568 | skt->state &= ~SOCKET_SUSPEND; |
565 | return socket_insert(skt); | 569 | return socket_insert(skt); |
566 | } | 570 | } |
567 | 571 | ||
568 | ret = socket_setup(skt, resume_delay); | 572 | if (skt->resume_status == 0) { |
569 | if (ret == 0) { | ||
570 | /* | 573 | /* |
571 | * FIXME: need a better check here for cardbus cards. | 574 | * FIXME: need a better check here for cardbus cards. |
572 | */ | 575 | */ |
@@ -594,6 +597,20 @@ static int socket_resume(struct pcmcia_socket *skt) | |||
594 | return 0; | 597 | return 0; |
595 | } | 598 | } |
596 | 599 | ||
600 | /* | ||
601 | * Resume a socket. If a card is present, verify its CIS against | ||
602 | * our cached copy. If they are different, the card has been | ||
603 | * replaced, and we need to tell the drivers. | ||
604 | */ | ||
605 | static int socket_resume(struct pcmcia_socket *skt) | ||
606 | { | ||
607 | if (!(skt->state & SOCKET_SUSPEND)) | ||
608 | return -EBUSY; | ||
609 | |||
610 | socket_early_resume(skt); | ||
611 | return socket_late_resume(skt); | ||
612 | } | ||
613 | |||
597 | static void socket_remove(struct pcmcia_socket *skt) | 614 | static void socket_remove(struct pcmcia_socket *skt) |
598 | { | 615 | { |
599 | dev_printk(KERN_NOTICE, &skt->dev, | 616 | 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) |