
From: Dominik Brodowski <linux@dominikbrodowski.de>

Search the devices_list for an UNBOUND client in register_client,
instead of the single linked list clients.

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

 25-akpm/drivers/pcmcia/ds.c |   40 ++++++++++++++++++++++++++++++++--------
 1 files changed, 32 insertions(+), 8 deletions(-)

diff -puN drivers/pcmcia/ds.c~pcmcia-use-pcmcia_device-in-register_client drivers/pcmcia/ds.c
--- 25/drivers/pcmcia/ds.c~pcmcia-use-pcmcia_device-in-register_client	2004-12-03 18:44:41.110533448 -0800
+++ 25-akpm/drivers/pcmcia/ds.c	2004-12-03 18:44:41.114532840 -0800
@@ -672,21 +672,43 @@ int pcmcia_register_client(client_handle
 {
 	client_t *client = NULL;
 	struct pcmcia_socket *s;
+	struct pcmcia_bus_socket *skt = NULL;
+	struct pcmcia_device *p_dev = NULL;
 
 	/* Look for unbound client with matching dev_info */
 	down_read(&pcmcia_socket_list_rwsem);
 	list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
-		client = s->clients;
-		while (client != NULL) {
-			if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
-			    && (client->state & CLIENT_UNBOUND)) break;
-			client = client->next;
+		unsigned long flags;
+
+		if (s->state & SOCKET_CARDBUS)
+			continue;
+
+		skt = s->pcmcia;
+		if (!skt)
+			continue;
+		skt = pcmcia_get_bus_socket(skt);
+		if (!skt)
+			continue;
+		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+		list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) {
+			if ((p_dev->client->state & CLIENT_UNBOUND) &&
+			    (!strcmp(p_dev->client->dev_info, (char *)req->dev_info))) {
+				p_dev = pcmcia_get_dev(p_dev);
+				if (p_dev)
+					client = p_dev->client;
+				spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+				goto found;
+			}
 		}
-		if (client != NULL) break;
+		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+		pcmcia_put_bus_socket(skt);
 	}
+ found:
 	up_read(&pcmcia_socket_list_rwsem);
-	if (client == NULL)
-		return CS_OUT_OF_RESOURCE;
+	if (!p_dev || !client)
+		return -ENODEV;
+
+	pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */
 
 	/*
 	 * Prevent this racing with a card insertion.
@@ -732,10 +754,12 @@ int pcmcia_register_client(client_handle
 	}
 
 	up(&s->skt_sem);
+	pcmcia_put_dev(p_dev); /* FIXME: put in deregister_client. */
 	return CS_SUCCESS;
 
  out_no_resource:
 	up(&s->skt_sem);
+	pcmcia_put_dev(p_dev);
 	return CS_OUT_OF_RESOURCE;
 } /* register_client */
 EXPORT_SYMBOL(pcmcia_register_client);
_
