aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Brodowski2006-01-27 19:15:02 +0100
committerDominik Brodowski2006-03-01 10:52:11 +0100
commit82d56e6d2e616bee0e712330bad06b634f007a46 (patch)
treee18a81cbe959428aa75e1d99e0760ce827d2c366
parent96789ac4b3943fec27fb6bf2713633b01a3903ad (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.c40
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;
}