diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cs.c | 36 | ||||
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 7 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 103 |
3 files changed, 54 insertions, 92 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 5ea196724f5b..efa30b84a75a 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -252,30 +252,6 @@ struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr) | |||
252 | } | 252 | } |
253 | EXPORT_SYMBOL(pcmcia_get_socket_by_nr); | 253 | EXPORT_SYMBOL(pcmcia_get_socket_by_nr); |
254 | 254 | ||
255 | /* | ||
256 | * The central event handler. Send_event() sends an event to the | ||
257 | * 16-bit subsystem, which then calls the relevant device drivers. | ||
258 | * Parse_events() interprets the event bits from | ||
259 | * a card status change report. Do_shutdown() handles the high | ||
260 | * priority stuff associated with a card removal. | ||
261 | */ | ||
262 | |||
263 | /* NOTE: send_event needs to be called with skt->sem held. */ | ||
264 | |||
265 | static int send_event(struct pcmcia_socket *s, event_t event, int priority) | ||
266 | { | ||
267 | if ((s->state & SOCKET_CARDBUS) && (event != CS_EVENT_CARD_REMOVAL)) | ||
268 | return 0; | ||
269 | |||
270 | dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n", | ||
271 | event, priority, s->callback); | ||
272 | |||
273 | if (!s->callback) | ||
274 | return 0; | ||
275 | |||
276 | return s->callback->event(s, event, priority); | ||
277 | } | ||
278 | |||
279 | static int socket_reset(struct pcmcia_socket *skt) | 255 | static int socket_reset(struct pcmcia_socket *skt) |
280 | { | 256 | { |
281 | int status, i; | 257 | int status, i; |
@@ -318,7 +294,8 @@ static void socket_shutdown(struct pcmcia_socket *s) | |||
318 | 294 | ||
319 | dev_dbg(&s->dev, "shutdown\n"); | 295 | dev_dbg(&s->dev, "shutdown\n"); |
320 | 296 | ||
321 | send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); | 297 | if (s->callback) |
298 | s->callback->remove(s); | ||
322 | 299 | ||
323 | mutex_lock(&s->ops_mutex); | 300 | mutex_lock(&s->ops_mutex); |
324 | s->state &= SOCKET_INUSE | SOCKET_PRESENT; | 301 | s->state &= SOCKET_INUSE | SOCKET_PRESENT; |
@@ -469,7 +446,8 @@ static int socket_insert(struct pcmcia_socket *skt) | |||
469 | dev_dbg(&skt->dev, "insert done\n"); | 446 | dev_dbg(&skt->dev, "insert done\n"); |
470 | mutex_unlock(&skt->ops_mutex); | 447 | mutex_unlock(&skt->ops_mutex); |
471 | 448 | ||
472 | send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); | 449 | if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) |
450 | skt->callback->add(skt); | ||
473 | } else { | 451 | } else { |
474 | mutex_unlock(&skt->ops_mutex); | 452 | mutex_unlock(&skt->ops_mutex); |
475 | socket_shutdown(skt); | 453 | socket_shutdown(skt); |
@@ -546,8 +524,8 @@ static int socket_late_resume(struct pcmcia_socket *skt) | |||
546 | return 0; | 524 | return 0; |
547 | } | 525 | } |
548 | #endif | 526 | #endif |
549 | 527 | if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) | |
550 | send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); | 528 | skt->callback->early_resume(skt); |
551 | return 0; | 529 | return 0; |
552 | } | 530 | } |
553 | 531 | ||
@@ -766,7 +744,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) | |||
766 | s->callback = c; | 744 | s->callback = c; |
767 | 745 | ||
768 | if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) | 746 | if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) |
769 | send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); | 747 | s->callback->add(s); |
770 | } else | 748 | } else |
771 | s->callback = NULL; | 749 | s->callback = NULL; |
772 | err: | 750 | err: |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index a6cc63db8c8e..45e7fd1aa0bf 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
11 | * | 11 | * |
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | * (C) 2003 - 2008 Dominik Brodowski | 13 | * (C) 2003 - 2010 Dominik Brodowski |
14 | * | 14 | * |
15 | * | 15 | * |
16 | * This file contains definitions _only_ needed by the PCMCIA core modules. | 16 | * This file contains definitions _only_ needed by the PCMCIA core modules. |
@@ -106,11 +106,12 @@ void cb_free(struct pcmcia_socket *s); | |||
106 | 106 | ||
107 | struct pcmcia_callback{ | 107 | struct pcmcia_callback{ |
108 | struct module *owner; | 108 | struct module *owner; |
109 | int (*event) (struct pcmcia_socket *s, | 109 | int (*add) (struct pcmcia_socket *s); |
110 | event_t event, int priority); | 110 | int (*remove) (struct pcmcia_socket *s); |
111 | void (*requery) (struct pcmcia_socket *s); | 111 | void (*requery) (struct pcmcia_socket *s); |
112 | int (*validate) (struct pcmcia_socket *s, unsigned int *i); | 112 | int (*validate) (struct pcmcia_socket *s, unsigned int *i); |
113 | int (*suspend) (struct pcmcia_socket *s); | 113 | int (*suspend) (struct pcmcia_socket *s); |
114 | int (*early_resume) (struct pcmcia_socket *s); | ||
114 | int (*resume) (struct pcmcia_socket *s); | 115 | int (*resume) (struct pcmcia_socket *s); |
115 | }; | 116 | }; |
116 | 117 | ||
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index bd58650b2736..78b5b65f9f7e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
11 | * | 11 | * |
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | * (C) 2003 - 2006 Dominik Brodowski | 13 | * (C) 2003 - 2010 Dominik Brodowski |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
@@ -1208,76 +1208,57 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt) | |||
1208 | return 0; | 1208 | return 0; |
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | static int pcmcia_bus_remove(struct pcmcia_socket *skt) | ||
1212 | { | ||
1213 | atomic_set(&skt->present, 0); | ||
1214 | pcmcia_card_remove(skt, NULL); | ||
1211 | 1215 | ||
1212 | /*====================================================================== | 1216 | mutex_lock(&skt->ops_mutex); |
1217 | destroy_cis_cache(skt); | ||
1218 | pcmcia_cleanup_irq(skt); | ||
1219 | mutex_unlock(&skt->ops_mutex); | ||
1213 | 1220 | ||
1214 | The card status event handler. | 1221 | return 0; |
1222 | } | ||
1215 | 1223 | ||
1216 | ======================================================================*/ | 1224 | static int pcmcia_bus_add(struct pcmcia_socket *skt) |
1225 | { | ||
1226 | atomic_set(&skt->present, 1); | ||
1217 | 1227 | ||
1218 | /* Normally, the event is passed to individual drivers after | 1228 | mutex_lock(&skt->ops_mutex); |
1219 | * informing userspace. Only for CS_EVENT_CARD_REMOVAL this | 1229 | skt->pcmcia_state.has_pfc = 0; |
1220 | * is inversed to maintain historic compatibility. | 1230 | destroy_cis_cache(skt); /* to be on the safe side... */ |
1221 | */ | 1231 | mutex_unlock(&skt->ops_mutex); |
1222 | 1232 | ||
1223 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | 1233 | pcmcia_card_add(skt); |
1224 | { | ||
1225 | struct pcmcia_socket *s = pcmcia_get_socket(skt); | ||
1226 | 1234 | ||
1227 | if (!s) { | 1235 | return 0; |
1228 | dev_printk(KERN_ERR, &skt->dev, | 1236 | } |
1229 | "PCMCIA obtaining reference to socket " \ | ||
1230 | "failed, event 0x%x lost!\n", event); | ||
1231 | return -ENODEV; | ||
1232 | } | ||
1233 | 1237 | ||
1234 | dev_dbg(&skt->dev, "ds_event(0x%06x, %d, 0x%p)\n", | 1238 | static int pcmcia_bus_early_resume(struct pcmcia_socket *skt) |
1235 | event, priority, skt); | 1239 | { |
1240 | if (!verify_cis_cache(skt)) { | ||
1241 | pcmcia_put_socket(skt); | ||
1242 | return 0; | ||
1243 | } | ||
1236 | 1244 | ||
1237 | switch (event) { | 1245 | dev_dbg(&skt->dev, "cis mismatch - different card\n"); |
1238 | case CS_EVENT_CARD_REMOVAL: | ||
1239 | atomic_set(&skt->present, 0); | ||
1240 | pcmcia_card_remove(skt, NULL); | ||
1241 | mutex_lock(&s->ops_mutex); | ||
1242 | destroy_cis_cache(s); | ||
1243 | pcmcia_cleanup_irq(s); | ||
1244 | mutex_unlock(&s->ops_mutex); | ||
1245 | break; | ||
1246 | 1246 | ||
1247 | case CS_EVENT_CARD_INSERTION: | 1247 | /* first, remove the card */ |
1248 | atomic_set(&skt->present, 1); | 1248 | pcmcia_bus_remove(skt); |
1249 | mutex_lock(&s->ops_mutex); | ||
1250 | s->pcmcia_state.has_pfc = 0; | ||
1251 | destroy_cis_cache(s); /* to be on the safe side... */ | ||
1252 | mutex_unlock(&s->ops_mutex); | ||
1253 | pcmcia_card_add(skt); | ||
1254 | break; | ||
1255 | |||
1256 | case CS_EVENT_PM_RESUME: | ||
1257 | if (verify_cis_cache(skt) != 0) { | ||
1258 | dev_dbg(&skt->dev, "cis mismatch - different card\n"); | ||
1259 | /* first, remove the card */ | ||
1260 | ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); | ||
1261 | mutex_lock(&s->ops_mutex); | ||
1262 | destroy_cis_cache(skt); | ||
1263 | kfree(skt->fake_cis); | ||
1264 | skt->fake_cis = NULL; | ||
1265 | s->functions = 0; | ||
1266 | mutex_unlock(&s->ops_mutex); | ||
1267 | /* now, add the new card */ | ||
1268 | ds_event(skt, CS_EVENT_CARD_INSERTION, | ||
1269 | CS_EVENT_PRI_LOW); | ||
1270 | } | ||
1271 | break; | ||
1272 | 1249 | ||
1273 | default: | 1250 | mutex_lock(&skt->ops_mutex); |
1274 | break; | 1251 | destroy_cis_cache(skt); |
1275 | } | 1252 | kfree(skt->fake_cis); |
1253 | skt->fake_cis = NULL; | ||
1254 | skt->functions = 0; | ||
1255 | mutex_unlock(&skt->ops_mutex); | ||
1276 | 1256 | ||
1277 | pcmcia_put_socket(s); | 1257 | /* now, add the new card */ |
1258 | pcmcia_bus_add(skt); | ||
1259 | return 0; | ||
1260 | } | ||
1278 | 1261 | ||
1279 | return 0; | ||
1280 | } /* ds_event */ | ||
1281 | 1262 | ||
1282 | /* | 1263 | /* |
1283 | * NOTE: This is racy. There's no guarantee the card will still be | 1264 | * NOTE: This is racy. There's no guarantee the card will still be |
@@ -1306,10 +1287,12 @@ EXPORT_SYMBOL(pcmcia_dev_present); | |||
1306 | 1287 | ||
1307 | static struct pcmcia_callback pcmcia_bus_callback = { | 1288 | static struct pcmcia_callback pcmcia_bus_callback = { |
1308 | .owner = THIS_MODULE, | 1289 | .owner = THIS_MODULE, |
1309 | .event = ds_event, | 1290 | .add = pcmcia_bus_add, |
1291 | .remove = pcmcia_bus_remove, | ||
1310 | .requery = pcmcia_requery, | 1292 | .requery = pcmcia_requery, |
1311 | .validate = pccard_validate_cis, | 1293 | .validate = pccard_validate_cis, |
1312 | .suspend = pcmcia_bus_suspend, | 1294 | .suspend = pcmcia_bus_suspend, |
1295 | .early_resume = pcmcia_bus_early_resume, | ||
1313 | .resume = pcmcia_bus_resume, | 1296 | .resume = pcmcia_bus_resume, |
1314 | }; | 1297 | }; |
1315 | 1298 | ||