diff options
author | Dominik Brodowski | 2006-01-27 19:15:02 +0100 |
---|---|---|
committer | Dominik Brodowski | 2006-03-01 10:52:11 +0100 |
commit | 82d56e6d2e616bee0e712330bad06b634f007a46 (patch) | |
tree | e18a81cbe959428aa75e1d99e0760ce827d2c366 | |
parent | 96789ac4b3943fec27fb6bf2713633b01a3903ad (diff) |
[PATCH] pcmcia: properly handle pseudo multi-function devices
The second pseudo multi-function device of a PCMCIA card may only be
configured once the first one is initialized. Therefore, delay the
registration of the second device until the first one is initialized.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net
-rw-r--r-- | drivers/pcmcia/ds.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0a424a4e8187..54ad93daca3c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -352,11 +352,20 @@ static void pcmcia_release_dev(struct device *dev) kfree(p_dev); } +static void pcmcia_add_pseudo_device(struct pcmcia_socket *s) +{ + if (!s->pcmcia_state.device_add_pending) { + s->pcmcia_state.device_add_pending = 1; + schedule_work(&s->device_add); + } + return; +} static int pcmcia_device_probe(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; + struct pcmcia_device_id *did; struct pcmcia_socket *s; int ret = 0; @@ -392,6 +401,19 @@ static int pcmcia_device_probe(struct device * dev) } ret = p_drv->probe(p_dev); + if (ret) + goto put_module; + + /* handle pseudo multifunction devices: + * there are at most two pseudo multifunction devices. + * if we're matching against the first, schedule a + * call which will then check whether there are two + * pseudo devices, and if not, add the second one. + */ + did = (struct pcmcia_device_id *) p_dev->dev.driver_data; + if ((did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && + (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) + pcmcia_add_pseudo_device(p_dev->socket); put_module: if (ret) @@ -660,15 +682,6 @@ static void pcmcia_delayed_add_pseudo_device(void *data) s->pcmcia_state.device_add_pending = 0; } -static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) -{ - if (!s->pcmcia_state.device_add_pending) { - s->pcmcia_state.device_add_pending = 1; - schedule_work(&s->device_add); - } - return; -} - static int pcmcia_requery(struct device *dev, void * _data) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); @@ -755,15 +768,6 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, } if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { - /* handle pseudo multifunction devices: - * there are at most two pseudo multifunction devices. - * if we're matching against the first, schedule a - * call which will then check whether there are two - * pseudo devices, and if not, add the second one. - */ - if (dev->device_no == 0) - pcmcia_add_pseudo_device(dev->socket); - if (dev->device_no != did->device_no) return 0; } |