<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Dominik Brodowski &lt;linux@dominikbrodowski.de&gt;

BUG if the socket's list of clients is not empty on shutdown and/or removal.

Signed-off-by: Dominik Brodowski &lt;linux@brodo.de&gt;
Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

 25-akpm/drivers/pcmcia/cs.c |   19 ++-----------------
 25-akpm/drivers/pcmcia/ds.c |   13 +++++++------
 2 files changed, 9 insertions(+), 23 deletions(-)

diff -puN drivers/pcmcia/cs.c~pcmcia-bug-if-clients-are-kept-too-long drivers/pcmcia/cs.c
--- 25/drivers/pcmcia/cs.c~pcmcia-bug-if-clients-are-kept-too-long	Mon Dec 13 14:39:04 2004
+++ 25-akpm/drivers/pcmcia/cs.c	Mon Dec 13 14:39:04 2004
@@ -198,13 +198,8 @@ EXPORT_SYMBOL(pcmcia_put_socket);
 static void pcmcia_release_socket(struct class_device *class_dev)
 {
 	struct pcmcia_socket *socket = class_get_devdata(class_dev);
-	client_t *client;
 
-	while (socket-&gt;clients) {
-		client = socket-&gt;clients;
-		socket-&gt;clients = socket-&gt;clients-&gt;next;
-		kfree(client);
-	}
+	BUG_ON(socket-&gt;clients);
 
 	complete(&amp;socket-&gt;socket_released);
 }
@@ -357,8 +352,6 @@ static void free_regions(memory_handle_t
 
 static void shutdown_socket(struct pcmcia_socket *s)
 {
-    client_t **c;
-    
     cs_dbg(s, 1, "shutdown_socket\n");
 
     /* Blank out the socket state */
@@ -376,15 +369,7 @@ static void shutdown_socket(struct pcmci
 	kfree(s-&gt;config);
 	s-&gt;config = NULL;
     }
-    for (c = &amp;s-&gt;clients; *c; ) {
-	if ((*c)-&gt;state &amp; CLIENT_UNBOUND) {
-	    client_t *d = *c;
-	    *c = (*c)-&gt;next;
-	    kfree(d);
-	} else {
-	    c = &amp;((*c)-&gt;next);
-	}
-    }
+    BUG_ON(s-&gt;clients);
     free_regions(&amp;s-&gt;a_region);
     free_regions(&amp;s-&gt;c_region);
 
diff -puN drivers/pcmcia/ds.c~pcmcia-bug-if-clients-are-kept-too-long drivers/pcmcia/ds.c
--- 25/drivers/pcmcia/ds.c~pcmcia-bug-if-clients-are-kept-too-long	Mon Dec 13 14:39:04 2004
+++ 25-akpm/drivers/pcmcia/ds.c	Mon Dec 13 14:39:04 2004
@@ -907,15 +907,13 @@ int pcmcia_deregister_client(client_hand
 	s = SOCKET(handle);
 	ds_dbg(1, "deregister_client(%p)\n", handle);
 
-	if (handle-&gt;state &amp;
-	    (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
-		return CS_IN_USE;
+	if (handle-&gt;state &amp; (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+		goto warn_out;
 	for (i = 0; i &lt; MAX_WIN; i++)
 		if (handle-&gt;state &amp; CLIENT_WIN_REQ(i))
-			return CS_IN_USE;
+			goto warn_out;
 
-	if ((handle-&gt;state &amp; CLIENT_STALE) ||
-	    (handle-&gt;Attributes &amp; INFO_MASTER_CLIENT)) {
+	if (handle-&gt;state &amp; CLIENT_STALE) {
 		spin_lock_irqsave(&amp;s-&gt;lock, flags);
 		client = &amp;s-&gt;clients;
 		while ((*client) &amp;&amp; ((*client) != handle))
@@ -934,6 +932,9 @@ int pcmcia_deregister_client(client_hand
 	}
 
 	return CS_SUCCESS;
+ warn_out:
+	printk(KERN_WARNING "ds: deregister_client was called too early.\n");
+	return CS_IN_USE;
 } /* deregister_client */
 EXPORT_SYMBOL(pcmcia_deregister_client);
 
_
</pre></body></html>