]> git.hungrycats.org Git - linux/commitdiff
[PCMCIA] Ref-count the socket driver module on card insertion/removal.
authorRussell King <rmk@flint.arm.linux.org.uk>
Mon, 30 Jun 2003 22:04:09 +0000 (23:04 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Mon, 30 Jun 2003 22:04:09 +0000 (23:04 +0100)
Get/Put module when we insert and remove a card.  This avoids a
potential deadlock when socket drivers are unloaded, and we have
a cardbus card known to the system.

drivers/pcmcia/cs.c

index fb4365e969f57e579153c7e670fda47fea49b500..42b7751864a39dcf15be57cbfecd67a1ad46338b 100644 (file)
@@ -723,6 +723,9 @@ static int socket_insert(struct pcmcia_socket *skt)
 {
        int ret;
 
+       if (!try_module_get(skt->owner))
+               return CS_NO_CARD;
+
        ret = socket_setup(skt, setup_delay);
        if (ret == CS_SUCCESS) {
 #ifdef CONFIG_CARDBUS
@@ -733,8 +736,10 @@ static int socket_insert(struct pcmcia_socket *skt)
 #endif
                send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
                skt->socket.flags &= ~SS_DEBOUNCED;
-       } else
+       } else {
                socket_shutdown(skt);
+               module_put(skt->owner);
+       }
 
        return ret;
 }
@@ -778,14 +783,24 @@ static int socket_resume(struct pcmcia_socket *skt)
                        send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
                }
                skt->socket.flags &= ~SS_DEBOUNCED;
-       } else
+       } else {
+               unsigned int old_state = skt->state;
                socket_shutdown(skt);
+               if (old_state & SOCKET_PRESENT)
+                       module_put(skt->owner);
+       }
 
        skt->state &= ~SOCKET_SUSPEND;
 
        return CS_SUCCESS;
 }
 
+static void socket_remove(struct pcmcia_socket *skt)
+{
+       socket_shutdown(skt);
+       module_put(skt->owner);
+}
+
 static int pccardd(void *__skt)
 {
        struct pcmcia_socket *skt = __skt;
@@ -815,7 +830,7 @@ static int pccardd(void *__skt)
                                get_socket_status(skt, &status);
                                if ((skt->state & SOCKET_PRESENT) &&
                                     !(status & SS_DETECT))
-                                       socket_shutdown(skt);
+                                       socket_remove(skt);
                                if (!(skt->state & SOCKET_PRESENT) &&
                                    (status & SS_DETECT))
                                        socket_insert(skt);
@@ -839,8 +854,6 @@ static int pccardd(void *__skt)
        }
        remove_wait_queue(&skt->thread_wait, &wait);
 
-       socket_shutdown(skt);
-
        complete_and_exit(&skt->thread_done, 0);
 }
 
@@ -2213,7 +2226,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
                if (ret != 0)
                        break;
 
-               socket_shutdown(skt);
+               socket_remove(skt);
                ret = CS_SUCCESS;
        } while (0);
        up(&skt->skt_sem);