diff options
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r-- | drivers/pcmcia/ds.c | 103 |
1 files changed, 43 insertions, 60 deletions
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 | ||