[patches 6/12] pcmcia: pcmcia_device_probe
Dominik Brodowski
linux at dominikbrodowski.net
Thu Feb 10 14:47:35 EST 2005
Move the probing of a device-driver pair (a.k.a. "attach") into
pcmcia_device_probe() conforming to the driver model.
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
drivers/pcmcia/ds.c | 72 +++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 55 insertions(+), 17 deletions(-)
Index: 2.6.11-rc3+/drivers/pcmcia/ds.c
===================================================================
--- 2.6.11-rc3+.orig/drivers/pcmcia/ds.c 2005-02-09 21:53:25.000000000 +0100
+++ 2.6.11-rc3+/drivers/pcmcia/ds.c 2005-02-10 20:24:51.000000000 +0100
@@ -285,13 +285,17 @@
*
* Registers a PCMCIA driver with the PCMCIA bus core.
*/
+static int pcmcia_device_probe(struct device *dev);
+
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
if (!driver)
return -EINVAL;
+ /* initialize common fields */
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
+ driver->drv.probe = pcmcia_device_probe;
return driver_register(&driver->drv);
}
@@ -364,6 +368,42 @@
}
+static int pcmcia_device_probe(struct device * dev)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
+ int ret = 0;
+
+ dev = get_device(dev);
+ if (!dev)
+ return -ENODEV;
+
+ p_dev = to_pcmcia_dev(dev);
+ p_drv = to_pcmcia_drv(dev->driver);
+
+ if (!try_module_get(p_drv->owner)) {
+ ret = -EINVAL;
+ goto put_dev;
+ }
+
+ if (p_drv->attach) {
+ p_dev->instance = p_drv->attach();
+ if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
+ printk(KERN_NOTICE "ds: unable to create instance "
+ "of '%s'!\n", p_drv->drv.name);
+ ret = -EINVAL;
+ }
+ }
+
+ if (ret)
+ module_put(p_drv->owner);
+ put_dev:
+ if ((ret) || !(p_drv->attach))
+ put_device(dev);
+ return (ret);
+}
+
+
/*======================================================================
These manage a ring buffer of events pending for one user process
@@ -583,12 +623,6 @@
p_dev->client.Function = bind_info->function;
p_dev->client.state = CLIENT_UNBOUND;
- ret = device_register(&p_dev->dev);
- if (ret) {
- kfree(p_dev);
- goto err_put_module;
- }
-
/* Add to the list in pcmcia_bus_socket, but only if no device
* with the same func _and_ driver exists */
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
@@ -598,22 +632,21 @@
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
bind_info->instance = tmp_dev->instance;
ret = -EBUSY;
- goto err_unregister;
+ goto err_free;
}
}
list_add_tail(&p_dev->socket_device_list, &s->devices_list);
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- if (p_drv->attach) {
- p_dev->instance = p_drv->attach();
- if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
- printk(KERN_NOTICE "ds: unable to create instance "
- "of '%s'!\n", (char *)bind_info->dev_info);
- ret = -ENODEV;
- goto err_unregister;
- }
- }
+ ret = device_register(&p_dev->dev);
+ if (ret)
+ goto err_free;
+
+ ret = pcmcia_device_probe(&p_dev->dev);
+ if (ret)
+ goto err_unregister;
+ module_put(p_drv->owner);
put_driver(&p_drv->drv);
return 0;
@@ -624,6 +657,8 @@
put_driver(&p_drv->drv);
return (ret);
+ err_free:
+ kfree(p_dev);
err_put_module:
module_put(p_drv->owner);
err_put_driver:
@@ -853,8 +888,11 @@
/* detach the "instance" */
p_drv = to_pcmcia_drv(p_dev->dev.driver);
if (p_drv) {
- if ((p_drv->detach) && (p_dev->instance))
+ if ((p_drv->detach) && (p_dev->instance)) {
p_drv->detach(p_dev->instance);
+ /* from pcmcia_probe_device */
+ put_device(&p_dev->dev);
+ }
module_put(p_drv->owner);
}
More information about the linux-pcmcia
mailing list