
From: Dominik Brodowski <linux@dominikbrodowski.de>

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

Signed-off-by: Dominik Brodowski <linux@brodo.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 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	2004-12-03 18:44:44.108077752 -0800
+++ 25-akpm/drivers/pcmcia/cs.c	2004-12-03 18:44:44.115076688 -0800
@@ -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->clients) {
-		client = socket->clients;
-		socket->clients = socket->clients->next;
-		kfree(client);
-	}
+	BUG_ON(socket->clients);
 
 	complete(&socket->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->config);
 	s->config = NULL;
     }
-    for (c = &s->clients; *c; ) {
-	if ((*c)->state & CLIENT_UNBOUND) {
-	    client_t *d = *c;
-	    *c = (*c)->next;
-	    kfree(d);
-	} else {
-	    c = &((*c)->next);
-	}
-    }
+    BUG_ON(s->clients);
     free_regions(&s->a_region);
     free_regions(&s->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	2004-12-03 18:44:44.109077600 -0800
+++ 25-akpm/drivers/pcmcia/ds.c	2004-12-03 18:44:44.117076384 -0800
@@ -903,15 +903,13 @@ int pcmcia_deregister_client(client_hand
 	s = SOCKET(handle);
 	ds_dbg(1, "deregister_client(%p)\n", handle);
 
-	if (handle->state &
-	    (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
-		return CS_IN_USE;
+	if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+		goto warn_out;
 	for (i = 0; i < MAX_WIN; i++)
 		if (handle->state & CLIENT_WIN_REQ(i))
-			return CS_IN_USE;
+			goto warn_out;
 
-	if ((handle->state & CLIENT_STALE) ||
-	    (handle->Attributes & INFO_MASTER_CLIENT)) {
+	if (handle->state & CLIENT_STALE) {
 		spin_lock_irqsave(&s->lock, flags);
 		client = &s->clients;
 		while ((*client) && ((*client) != handle))
@@ -930,6 +928,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);
 
_
