summaryrefslogtreecommitdiff
path: root/drivers/pcmcia/cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/cs.c')
-rw-r--r--drivers/pcmcia/cs.c118
1 files changed, 63 insertions, 55 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 234cdca6fe13..613f2f1fbfdd 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -309,41 +309,6 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
}
EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
-
-/**
- * socket_setup() and shutdown_socket() are called by the main event
- * handler when card insertion and removal events are received.
- * socket_setup() turns on socket power and resets the socket, in two stages.
- * shutdown_socket() unconfigures a socket and turns off socket power.
- */
-static void shutdown_socket(struct pcmcia_socket *s)
-{
- cs_dbg(s, 1, "shutdown_socket\n");
-
- /* Blank out the socket state */
- s->socket = dead_socket;
- s->ops->init(s);
- s->ops->set_socket(s, &s->socket);
- s->irq.AssignedIRQ = s->irq.Config = 0;
- s->lock_count = 0;
- destroy_cis_cache(s);
-#ifdef CONFIG_CARDBUS
- cb_free(s);
-#endif
- s->functions = 0;
- kfree(s->config);
- s->config = NULL;
-
- {
- int status;
- s->ops->get_status(s, &status);
- if (status & SS_POWERON) {
- printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
- }
- }
-} /* shutdown_socket */
-
-
/**
* The central event handler. Send_event() sends an event to the
* 16-bit subsystem, which then calls the relevant device drivers.
@@ -383,17 +348,6 @@ static void socket_remove_drivers(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
}
-static void socket_shutdown(struct pcmcia_socket *skt)
-{
- cs_dbg(skt, 4, "shutdown\n");
-
- socket_remove_drivers(skt);
- skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
- msleep(shutdown_delay * 10);
- skt->state &= SOCKET_INUSE;
- shutdown_socket(skt);
-}
-
static int socket_reset(struct pcmcia_socket *skt)
{
int status, i;
@@ -424,6 +378,45 @@ static int socket_reset(struct pcmcia_socket *skt)
return CS_GENERAL_FAILURE;
}
+/**
+ * socket_setup() and socket_shutdown() are called by the main event handler
+ * when card insertion and removal events are received.
+ * socket_setup() turns on socket power and resets the socket, in two stages.
+ * socket_shutdown() unconfigures a socket and turns off socket power.
+ */
+static void socket_shutdown(struct pcmcia_socket *s)
+{
+ int status;
+
+ cs_dbg(s, 4, "shutdown\n");
+
+ socket_remove_drivers(s);
+ s->state &= SOCKET_INUSE | SOCKET_PRESENT;
+ msleep(shutdown_delay * 10);
+ s->state &= SOCKET_INUSE;
+
+ /* Blank out the socket state */
+ s->socket = dead_socket;
+ s->ops->init(s);
+ s->ops->set_socket(s, &s->socket);
+ s->irq.AssignedIRQ = s->irq.Config = 0;
+ s->lock_count = 0;
+ destroy_cis_cache(s);
+#ifdef CONFIG_CARDBUS
+ cb_free(s);
+#endif
+ s->functions = 0;
+ kfree(s->config);
+ s->config = NULL;
+
+ s->ops->get_status(s, &status);
+ if (status & SS_POWERON) {
+ printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
+ }
+
+ cs_socket_put(s);
+}
+
static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
{
int status, i;
@@ -513,6 +506,11 @@ static int socket_insert(struct pcmcia_socket *skt)
ret = socket_setup(skt, setup_delay);
if (ret == CS_SUCCESS) {
skt->state |= SOCKET_PRESENT;
+
+ printk(KERN_NOTICE "pccard: %s card inserted into slot %d\n",
+ (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA",
+ skt->sock);
+
#ifdef CONFIG_CARDBUS
if (skt->state & SOCKET_CARDBUS) {
cb_alloc(skt);
@@ -524,7 +522,6 @@ static int socket_insert(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
} else {
socket_shutdown(skt);
- cs_socket_put(skt);
}
return ret;
@@ -588,7 +585,6 @@ static int socket_resume(struct pcmcia_socket *skt)
}
} else {
socket_shutdown(skt);
- cs_socket_put(skt);
}
skt->state &= ~SOCKET_SUSPEND;
@@ -598,8 +594,8 @@ static int socket_resume(struct pcmcia_socket *skt)
static void socket_remove(struct pcmcia_socket *skt)
{
+ printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
socket_shutdown(skt);
- cs_socket_put(skt);
}
/*
@@ -774,8 +770,13 @@ int pccard_reset_card(struct pcmcia_socket *skt)
ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
if (ret == 0) {
send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
- if (socket_reset(skt) == CS_SUCCESS)
+ if (skt->callback)
+ skt->callback->suspend(skt);
+ if (socket_reset(skt) == CS_SUCCESS) {
send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
+ if (skt->callback)
+ skt->callback->resume(skt);
+ }
}
ret = CS_SUCCESS;
@@ -806,6 +807,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
ret = CS_UNSUPPORTED_FUNCTION;
break;
}
+ if (skt->callback) {
+ ret = skt->callback->suspend(skt);
+ if (ret)
+ break;
+ }
ret = socket_suspend(skt);
} while (0);
up(&skt->skt_sem);
@@ -832,6 +838,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
break;
}
ret = socket_resume(skt);
+ if (!ret && skt->callback)
+ skt->callback->resume(skt);
} while (0);
up(&skt->skt_sem);
@@ -895,14 +903,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
EXPORT_SYMBOL(pcmcia_insert_card);
-static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
int i = 0, length = 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "SOCKET_NO=%u", s->sock))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "SOCKET_NO=%u", s->sock))
return -ENOMEM;
envp[i] = NULL;
@@ -921,7 +929,7 @@ static void pcmcia_release_socket_class(struct class *data)
struct class pcmcia_socket_class = {
.name = "pcmcia_socket",
- .hotplug = pcmcia_socket_hotplug,
+ .uevent = pcmcia_socket_uevent,
.release = pcmcia_release_socket,
.class_release = pcmcia_release_socket_class,
};