]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/pcmcia/cs.c
Merge branch 'ost' into release
[karo-tx-linux.git] / drivers / pcmcia / cs.c
index 934d4bee39a09b040d670fd35b656977ec5ac168..6d6f82b38a68c9ffaf341504a3dbdbac882a5496 100644 (file)
@@ -61,17 +61,6 @@ INT_MODULE_PARM(unreset_limit,       30);            /* unreset_check's */
 /* Access speed for attribute memory windows */
 INT_MODULE_PARM(cis_speed,     300);           /* ns */
 
-#ifdef CONFIG_PCMCIA_DEBUG
-static int pc_debug;
-
-module_param(pc_debug, int, 0644);
-
-int cs_debug_level(int level)
-{
-       return pc_debug > level;
-}
-#endif
-
 
 socket_state_t dead_socket = {
        .csc_mask       = SS_DETECT,
@@ -98,10 +87,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
  * These functions check for the appropriate struct pcmcia_soket arrays,
  * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
  */
+static int socket_early_resume(struct pcmcia_socket *skt);
+static int socket_late_resume(struct pcmcia_socket *skt);
 static int socket_resume(struct pcmcia_socket *skt);
 static int socket_suspend(struct pcmcia_socket *skt);
 
-int pcmcia_socket_dev_suspend(struct device *dev)
+static void pcmcia_socket_dev_run(struct device *dev,
+                                 int (*cb)(struct pcmcia_socket *))
 {
        struct pcmcia_socket *socket;
 
@@ -110,35 +102,40 @@ int pcmcia_socket_dev_suspend(struct device *dev)
                if (socket->dev.parent != dev)
                        continue;
                mutex_lock(&socket->skt_mutex);
-               socket_suspend(socket);
+               cb(socket);
                mutex_unlock(&socket->skt_mutex);
        }
        up_read(&pcmcia_socket_list_rwsem);
+}
 
+int pcmcia_socket_dev_suspend(struct device *dev)
+{
+       pcmcia_socket_dev_run(dev, socket_suspend);
        return 0;
 }
 EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
 
-int pcmcia_socket_dev_resume(struct device *dev)
+void pcmcia_socket_dev_early_resume(struct device *dev)
 {
-       struct pcmcia_socket *socket;
+       pcmcia_socket_dev_run(dev, socket_early_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
 
-       down_read(&pcmcia_socket_list_rwsem);
-       list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
-               if (socket->dev.parent != dev)
-                       continue;
-               mutex_lock(&socket->skt_mutex);
-               socket_resume(socket);
-               mutex_unlock(&socket->skt_mutex);
-       }
-       up_read(&pcmcia_socket_list_rwsem);
+void pcmcia_socket_dev_late_resume(struct device *dev)
+{
+       pcmcia_socket_dev_run(dev, socket_late_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
 
+int pcmcia_socket_dev_resume(struct device *dev)
+{
+       pcmcia_socket_dev_run(dev, socket_resume);
        return 0;
 }
 EXPORT_SYMBOL(pcmcia_socket_dev_resume);
 
 
-struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt)
+struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt)
 {
        struct device *dev = get_device(&skt->dev);
        if (!dev)
@@ -148,7 +145,7 @@ struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt)
                put_device(&skt->dev);
                return NULL;
        }
-       return (skt);
+       return skt;
 }
 EXPORT_SYMBOL(pcmcia_get_socket);
 
@@ -182,7 +179,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
        if (!socket || !socket->ops || !socket->dev.parent || !socket->resource_ops)
                return -EINVAL;
 
-       cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
+       dev_dbg(&socket->dev, "pcmcia_register_socket(0x%p)\n", socket->ops);
 
        spin_lock_init(&socket->lock);
 
@@ -254,6 +251,13 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 
        pcmcia_parse_events(socket, SS_DETECT);
 
+       /*
+        * Let's try to get the PCMCIA module for 16-bit PCMCIA support.
+        * If it fails, it doesn't matter -- we still have 32-bit CardBus
+        * support to offer, so this is not a failure mode.
+        */
+       request_module_nowait("pcmcia");
+
        return 0;
 
  err:
@@ -274,7 +278,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
        if (!socket)
                return;
 
-       cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops);
+       dev_dbg(&socket->dev, "pcmcia_unregister_socket(0x%p)\n", socket->ops);
 
        if (socket->thread)
                kthread_stop(socket->thread);
@@ -293,7 +297,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
 EXPORT_SYMBOL(pcmcia_unregister_socket);
 
 
-struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
+struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr)
 {
        struct pcmcia_socket *s;
 
@@ -327,7 +331,7 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
        if (s->state & SOCKET_CARDBUS)
                return 0;
 
-       cs_dbg(s, 1, "send_event(event %d, pri %d, callback 0x%p)\n",
+       dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n",
           event, priority, s->callback);
 
        if (!s->callback)
@@ -344,7 +348,7 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
 
 static void socket_remove_drivers(struct pcmcia_socket *skt)
 {
-       cs_dbg(skt, 4, "remove_drivers\n");
+       dev_dbg(&skt->dev, "remove_drivers\n");
 
        send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
 }
@@ -353,7 +357,7 @@ static int socket_reset(struct pcmcia_socket *skt)
 {
        int status, i;
 
-       cs_dbg(skt, 4, "reset\n");
+       dev_dbg(&skt->dev, "reset\n");
 
        skt->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
        skt->ops->set_socket(skt, &skt->socket);
@@ -375,7 +379,7 @@ static int socket_reset(struct pcmcia_socket *skt)
                msleep(unreset_check * 10);
        }
 
-       cs_err(skt, "time out after reset.\n");
+       dev_printk(KERN_ERR, &skt->dev, "time out after reset.\n");
        return -ETIMEDOUT;
 }
 
@@ -389,7 +393,7 @@ static void socket_shutdown(struct pcmcia_socket *s)
 {
        int status;
 
-       cs_dbg(s, 4, "shutdown\n");
+       dev_dbg(&s->dev, "shutdown\n");
 
        socket_remove_drivers(s);
        s->state &= SOCKET_INUSE | SOCKET_PRESENT;
@@ -424,7 +428,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 {
        int status, i;
 
-       cs_dbg(skt, 4, "setup\n");
+       dev_dbg(&skt->dev, "setup\n");
 
        skt->ops->get_status(skt, &status);
        if (!(status & SS_DETECT))
@@ -444,13 +448,15 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
        }
 
        if (status & SS_PENDING) {
-               cs_err(skt, "voltage interrogation timed out.\n");
+               dev_printk(KERN_ERR, &skt->dev,
+                          "voltage interrogation timed out.\n");
                return -ETIMEDOUT;
        }
 
        if (status & SS_CARDBUS) {
                if (!(skt->features & SS_CAP_CARDBUS)) {
-                       cs_err(skt, "cardbus cards are not supported.\n");
+                       dev_printk(KERN_ERR, &skt->dev,
+                               "cardbus cards are not supported.\n");
                        return -EINVAL;
                }
                skt->state |= SOCKET_CARDBUS;
@@ -464,7 +470,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
        else if (!(status & SS_XVCARD))
                skt->socket.Vcc = skt->socket.Vpp = 50;
        else {
-               cs_err(skt, "unsupported voltage key.\n");
+               dev_printk(KERN_ERR, &skt->dev, "unsupported voltage key.\n");
                return -EIO;
        }
 
@@ -481,7 +487,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 
        skt->ops->get_status(skt, &status);
        if (!(status & SS_POWERON)) {
-               cs_err(skt, "unable to apply power.\n");
+               dev_printk(KERN_ERR, &skt->dev, "unable to apply power.\n");
                return -EIO;
        }
 
@@ -501,7 +507,7 @@ static int socket_insert(struct pcmcia_socket *skt)
 {
        int ret;
 
-       cs_dbg(skt, 4, "insert\n");
+       dev_dbg(&skt->dev, "insert\n");
 
        if (!cs_socket_get(skt))
                return -ENODEV;
@@ -521,7 +527,7 @@ static int socket_insert(struct pcmcia_socket *skt)
                        skt->state |= SOCKET_CARDBUS_CONFIG;
                }
 #endif
-               cs_dbg(skt, 4, "insert done\n");
+               dev_dbg(&skt->dev, "insert done\n");
 
                send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
        } else {
@@ -546,34 +552,29 @@ static int socket_suspend(struct pcmcia_socket *skt)
        return 0;
 }
 
-/*
- * Resume a socket.  If a card is present, verify its CIS against
- * our cached copy.  If they are different, the card has been
- * replaced, and we need to tell the drivers.
- */
-static int socket_resume(struct pcmcia_socket *skt)
+static int socket_early_resume(struct pcmcia_socket *skt)
 {
-       int ret;
-
-       if (!(skt->state & SOCKET_SUSPEND))
-               return -EBUSY;
-
        skt->socket = dead_socket;
        skt->ops->init(skt);
        skt->ops->set_socket(skt, &skt->socket);
+       if (skt->state & SOCKET_PRESENT)
+               skt->resume_status = socket_setup(skt, resume_delay);
+       return 0;
+}
 
+static int socket_late_resume(struct pcmcia_socket *skt)
+{
        if (!(skt->state & SOCKET_PRESENT)) {
                skt->state &= ~SOCKET_SUSPEND;
                return socket_insert(skt);
        }
 
-       ret = socket_setup(skt, resume_delay);
-       if (ret == 0) {
+       if (skt->resume_status == 0) {
                /*
                 * FIXME: need a better check here for cardbus cards.
                 */
                if (verify_cis_cache(skt) != 0) {
-                       cs_dbg(skt, 4, "cis mismatch - different card\n");
+                       dev_dbg(&skt->dev, "cis mismatch - different card\n");
                        socket_remove_drivers(skt);
                        destroy_cis_cache(skt);
                        /*
@@ -584,7 +585,7 @@ static int socket_resume(struct pcmcia_socket *skt)
                        msleep(200);
                        send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
                } else {
-                       cs_dbg(skt, 4, "cis matches cache\n");
+                       dev_dbg(&skt->dev, "cis matches cache\n");
                        send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
                }
        } else {
@@ -596,6 +597,20 @@ static int socket_resume(struct pcmcia_socket *skt)
        return 0;
 }
 
+/*
+ * Resume a socket.  If a card is present, verify its CIS against
+ * our cached copy.  If they are different, the card has been
+ * replaced, and we need to tell the drivers.
+ */
+static int socket_resume(struct pcmcia_socket *skt)
+{
+       if (!(skt->state & SOCKET_SUSPEND))
+               return -EBUSY;
+
+       socket_early_resume(skt);
+       return socket_late_resume(skt);
+}
+
 static void socket_remove(struct pcmcia_socket *skt)
 {
        dev_printk(KERN_NOTICE, &skt->dev,
@@ -706,7 +721,7 @@ static int pccardd(void *__skt)
 void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
 {
        unsigned long flags;
-       cs_dbg(s, 4, "parse_events: events %08x\n", events);
+       dev_dbg(&s->dev, "parse_events: events %08x\n", events);
        if (s->thread) {
                spin_lock_irqsave(&s->thread_lock, flags);
                s->thread_events |= events;
@@ -721,7 +736,7 @@ EXPORT_SYMBOL(pcmcia_parse_events);
 /* register pcmcia_callback */
 int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
 {
-        int ret = 0;
+       int ret = 0;
 
        /* s->skt_mutex also protects s->callback */
        mutex_lock(&s->skt_mutex);
@@ -756,19 +771,22 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
 {
        int ret;
 
-       cs_dbg(skt, 1, "resetting socket\n");
+       dev_dbg(&skt->dev, "resetting socket\n");
 
        mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
+                       dev_dbg(&skt->dev, "can't reset, not present\n");
                        ret = -ENODEV;
                        break;
                }
                if (skt->state & SOCKET_SUSPEND) {
+                       dev_dbg(&skt->dev, "can't reset, suspended\n");
                        ret = -EBUSY;
                        break;
                }
                if (skt->state & SOCKET_CARDBUS) {
+                       dev_dbg(&skt->dev, "can't reset, is cardbus\n");
                        ret = -EPERM;
                        break;
                }
@@ -801,7 +819,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
 {
        int ret;
 
-       cs_dbg(skt, 1, "suspending socket\n");
+       dev_dbg(&skt->dev, "suspending socket\n");
 
        mutex_lock(&skt->skt_mutex);
        do {
@@ -830,8 +848,8 @@ EXPORT_SYMBOL(pcmcia_suspend_card);
 int pcmcia_resume_card(struct pcmcia_socket *skt)
 {
        int ret;
-    
-       cs_dbg(skt, 1, "waking up socket\n");
+
+       dev_dbg(&skt->dev, "waking up socket\n");
 
        mutex_lock(&skt->skt_mutex);
        do {
@@ -858,8 +876,8 @@ EXPORT_SYMBOL(pcmcia_resume_card);
 int pcmcia_eject_card(struct pcmcia_socket *skt)
 {
        int ret;
-    
-       cs_dbg(skt, 1, "user eject request\n");
+
+       dev_dbg(&skt->dev, "user eject request\n");
 
        mutex_lock(&skt->skt_mutex);
        do {
@@ -888,7 +906,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
 {
        int ret;
 
-       cs_dbg(skt, 1, "user insert request\n");
+       dev_dbg(&skt->dev, "user insert request\n");
 
        mutex_lock(&skt->skt_mutex);
        do {