[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