diff options
| -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 |
3 files changed, 58 insertions, 27 deletions
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 */ |
