[patches 9/12] pcmcia: use bus_rescan_devices

Dominik Brodowski linux at dominikbrodowski.net
Thu Feb 10 14:48:01 EST 2005


Use bus_rescan_devices() and a pcmcia_bus_match() function to match
pcmcia devices and drivers based on cardmgr's wishes.

Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---

 drivers/pcmcia/ds.c |   45 +++++++++++++++++++++++++++------------------
 include/pcmcia/ds.h |    4 ++--
 2 files changed, 29 insertions(+), 20 deletions(-)

Index: 2.6.11-rc3+/drivers/pcmcia/ds.c
===================================================================
--- 2.6.11-rc3+.orig/drivers/pcmcia/ds.c	2005-02-10 20:24:57.000000000 +0100
+++ 2.6.11-rc3+/drivers/pcmcia/ds.c	2005-02-10 20:24:58.000000000 +0100
@@ -438,9 +438,9 @@
  */
 static DECLARE_MUTEX(device_add_lock);
 
-static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function, struct pcmcia_driver *p_drv)
+static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function)
 {
-	struct pcmcia_device *p_dev, *tmp_dev;
+	struct pcmcia_device *p_dev;
 	unsigned long flags;
 
 	s = pcmcia_get_bus_socket(s);
@@ -463,25 +463,14 @@
 	p_dev->dev.release = pcmcia_release_dev;
 	sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
 
-	/* temporary workaround */
-	p_dev->dev.driver = &p_drv->drv;
-
 	/* compat */
 	p_dev->client.client_magic = CLIENT_MAGIC;
 	p_dev->client.Socket = s->parent;
 	p_dev->client.Function = function;
 	p_dev->client.state = CLIENT_UNBOUND;
 
-	/* Add to the list in pcmcia_bus_socket, but only if no device
-	 * with the same func _and_ driver exists */
+	/* Add to the list in pcmcia_bus_socket */
 	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-	list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) {
-		if ((tmp_dev->func == function) &&
-		    (tmp_dev->dev.driver == p_dev->dev.driver)){
-			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-			goto err_free;
-		}
-	}
 	list_add_tail(&p_dev->socket_device_list, &s->devices_list);
 	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
@@ -493,8 +482,6 @@
 		goto err_free;
        }
 
-	pcmcia_device_probe(&p_dev->dev);
-
 	up(&device_add_lock);
 
 	return p_dev;
@@ -509,6 +496,18 @@
 	return NULL;
 }
 
+
+static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
+	struct pcmcia_device * p_dev = to_pcmcia_dev(dev);
+	struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
+
+	/* matching by cardmgr */
+	if (p_dev->cardmgr == p_drv)
+		return 1;
+
+	return 0;
+}
+
 /*======================================================================
 
     These manage a ring buffer of events pending for one user process
@@ -716,12 +715,21 @@
 	}
 	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
-	p_dev = pcmcia_device_add(s, bind_info->function, p_drv);
+	p_dev = pcmcia_device_add(s, bind_info->function);
 	if (!p_dev) {
 		ret = -EIO;
 		goto err_put_module;
 	}
-	p_dev->cardmgr++;
+	p_dev->cardmgr = p_drv;
+
+	bus_rescan_devices(&pcmcia_bus_type);
+
+	/* check whether the driver indeed matched. I don't care if this
+	 * is racy or not, because it can only happen on cardmgr access
+	 * paths...
+	 */
+	if (!(p_dev->dev.driver == &p_drv->drv))
+		p_dev->cardmgr = NULL;
 
  err_put_module:
 	module_put(p_drv->owner);
@@ -1451,6 +1459,7 @@
 
 struct bus_type pcmcia_bus_type = {
 	.name = "pcmcia",
+	.match = pcmcia_bus_match,
 };
 EXPORT_SYMBOL(pcmcia_bus_type);
 
Index: 2.6.11-rc3+/include/pcmcia/ds.h
===================================================================
--- 2.6.11-rc3+.orig/include/pcmcia/ds.h	2005-02-10 20:24:57.000000000 +0100
+++ 2.6.11-rc3+/include/pcmcia/ds.h	2005-02-10 20:24:58.000000000 +0100
@@ -169,8 +169,8 @@
 		event_callback_args_t 	event_callback_args;
 	}			client;
 
-	/* registration by cardmgr done? */
-	unsigned int		cardmgr;
+	/* device driver wanted by cardmgr */
+	struct pcmcia_driver *	cardmgr;
 
 	struct device		dev;
 };



More information about the linux-pcmcia mailing list