summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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)
}
EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
-/*
- * The central event handler. Send_event() sends an event to the
- * 16-bit subsystem, which then calls the relevant device drivers.
- * Parse_events() interprets the event bits from
- * a card status change report. Do_shutdown() handles the high
- * priority stuff associated with a card removal.
- */
-
-/* NOTE: send_event needs to be called with skt->sem held. */
-
-static int send_event(struct pcmcia_socket *s, event_t event, int priority)
-{
- if ((s->state & SOCKET_CARDBUS) && (event != CS_EVENT_CARD_REMOVAL))
- return 0;
-
- dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n",
- event, priority, s->callback);
-
- if (!s->callback)
- return 0;
-
- return s->callback->event(s, event, priority);
-}
-
static int socket_reset(struct pcmcia_socket *skt)
{
int status, i;
@@ -318,7 +294,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
dev_dbg(&s->dev, "shutdown\n");
- send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
+ if (s->callback)
+ s->callback->remove(s);
mutex_lock(&s->ops_mutex);
s->state &= SOCKET_INUSE | SOCKET_PRESENT;
@@ -469,7 +446,8 @@ static int socket_insert(struct pcmcia_socket *skt)
dev_dbg(&skt->dev, "insert done\n");
mutex_unlock(&skt->ops_mutex);
- send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
+ skt->callback->add(skt);
} else {
mutex_unlock(&skt->ops_mutex);
socket_shutdown(skt);
@@ -546,8 +524,8 @@ static int socket_late_resume(struct pcmcia_socket *skt)
return 0;
}
#endif
-
- send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
+ if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
+ skt->callback->early_resume(skt);
return 0;
}
@@ -766,7 +744,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
s->callback = c;
if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT)
- send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ s->callback->add(s);
} else
s->callback = NULL;
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 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2008 Dominik Brodowski
+ * (C) 2003 - 2010 Dominik Brodowski
*
*
* This file contains definitions _only_ needed by the PCMCIA core modules.
@@ -106,11 +106,12 @@ void cb_free(struct pcmcia_socket *s);
struct pcmcia_callback{
struct module *owner;
- int (*event) (struct pcmcia_socket *s,
- event_t event, int priority);
+ int (*add) (struct pcmcia_socket *s);
+ int (*remove) (struct pcmcia_socket *s);
void (*requery) (struct pcmcia_socket *s);
int (*validate) (struct pcmcia_socket *s, unsigned int *i);
int (*suspend) (struct pcmcia_socket *s);
+ int (*early_resume) (struct pcmcia_socket *s);
int (*resume) (struct pcmcia_socket *s);
};
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 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2006 Dominik Brodowski
+ * (C) 2003 - 2010 Dominik Brodowski
*/
#include <linux/kernel.h>
@@ -1208,76 +1208,57 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
return 0;
}
+static int pcmcia_bus_remove(struct pcmcia_socket *skt)
+{
+ atomic_set(&skt->present, 0);
+ pcmcia_card_remove(skt, NULL);
-/*======================================================================
+ mutex_lock(&skt->ops_mutex);
+ destroy_cis_cache(skt);
+ pcmcia_cleanup_irq(skt);
+ mutex_unlock(&skt->ops_mutex);
- The card status event handler.
+ return 0;
+}
-======================================================================*/
+static int pcmcia_bus_add(struct pcmcia_socket *skt)
+{
+ atomic_set(&skt->present, 1);
-/* Normally, the event is passed to individual drivers after
- * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
- * is inversed to maintain historic compatibility.
- */
+ mutex_lock(&skt->ops_mutex);
+ skt->pcmcia_state.has_pfc = 0;
+ destroy_cis_cache(skt); /* to be on the safe side... */
+ mutex_unlock(&skt->ops_mutex);
-static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
-{
- struct pcmcia_socket *s = pcmcia_get_socket(skt);
+ pcmcia_card_add(skt);
- if (!s) {
- dev_printk(KERN_ERR, &skt->dev,
- "PCMCIA obtaining reference to socket " \
- "failed, event 0x%x lost!\n", event);
- return -ENODEV;
- }
+ return 0;
+}
- dev_dbg(&skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, skt);
+static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
+{
+ if (!verify_cis_cache(skt)) {
+ pcmcia_put_socket(skt);
+ return 0;
+ }
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- atomic_set(&skt->present, 0);
- pcmcia_card_remove(skt, NULL);
- mutex_lock(&s->ops_mutex);
- destroy_cis_cache(s);
- pcmcia_cleanup_irq(s);
- mutex_unlock(&s->ops_mutex);
- break;
+ dev_dbg(&skt->dev, "cis mismatch - different card\n");
- case CS_EVENT_CARD_INSERTION:
- atomic_set(&skt->present, 1);
- mutex_lock(&s->ops_mutex);
- s->pcmcia_state.has_pfc = 0;
- destroy_cis_cache(s); /* to be on the safe side... */
- mutex_unlock(&s->ops_mutex);
- pcmcia_card_add(skt);
- break;
-
- case CS_EVENT_PM_RESUME:
- if (verify_cis_cache(skt) != 0) {
- dev_dbg(&skt->dev, "cis mismatch - different card\n");
- /* first, remove the card */
- ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
- mutex_lock(&s->ops_mutex);
- destroy_cis_cache(skt);
- kfree(skt->fake_cis);
- skt->fake_cis = NULL;
- s->functions = 0;
- mutex_unlock(&s->ops_mutex);
- /* now, add the new card */
- ds_event(skt, CS_EVENT_CARD_INSERTION,
- CS_EVENT_PRI_LOW);
- }
- break;
+ /* first, remove the card */
+ pcmcia_bus_remove(skt);
- default:
- break;
- }
+ mutex_lock(&skt->ops_mutex);
+ destroy_cis_cache(skt);
+ kfree(skt->fake_cis);
+ skt->fake_cis = NULL;
+ skt->functions = 0;
+ mutex_unlock(&skt->ops_mutex);
- pcmcia_put_socket(s);
+ /* now, add the new card */
+ pcmcia_bus_add(skt);
+ return 0;
+}
- return 0;
-} /* ds_event */
/*
* NOTE: This is racy. There's no guarantee the card will still be
@@ -1306,10 +1287,12 @@ EXPORT_SYMBOL(pcmcia_dev_present);
static struct pcmcia_callback pcmcia_bus_callback = {
.owner = THIS_MODULE,
- .event = ds_event,
+ .add = pcmcia_bus_add,
+ .remove = pcmcia_bus_remove,
.requery = pcmcia_requery,
.validate = pccard_validate_cis,
.suspend = pcmcia_bus_suspend,
+ .early_resume = pcmcia_bus_early_resume,
.resume = pcmcia_bus_resume,
};