aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-07-11 04:26:53 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2010-07-30 15:07:34 -0400
commit7b24e7988263d3cae25ff35cfeae8a5657d93051 (patch)
tree2a2c78ed6d21c19bdf9d2261f6d04648e894571b /drivers/pcmcia
parent216d7cdd3b060518a2d4faf584eb15ef5af862b6 (diff)
pcmcia: split up central event handler
Split up the central event handler for 16bit cards into three individual functions. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/cs.c36
-rw-r--r--drivers/pcmcia/cs_internal.h7
-rw-r--r--drivers/pcmcia/ds.c103
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}
253EXPORT_SYMBOL(pcmcia_get_socket_by_nr); 253EXPORT_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
265static 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
279static int socket_reset(struct pcmcia_socket *skt) 255static 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
107struct pcmcia_callback{ 107struct 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
1211static 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======================================================================*/ 1224static 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
1223static 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", 1238static 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
1307static struct pcmcia_callback pcmcia_bus_callback = { 1288static 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