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 */ |