Commit cec5eb7b authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

pcmcia: Fix broken abuse of dev->driver_data

PCMCIA abuses dev->private_data in the probe methods. Unfortunately it
continues to abuse it after calling drv->probe() which leads to crashes and
other nasties (such as bogus probes of multifunction devices) giving errors like

pcmcia: registering new device pcmcia0.1
kernel: 0.1: GetNextTuple: No more items

Extract the passed data before calling the driver probe function that way
we don't blow up when the driver reuses dev->private_data as its right.

As its close to the final release just move the hack so it works out,
hopefully someone will be sufficiently embarrassed to produce a nice rework
for 2.6.28.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ae911191
...@@ -427,6 +427,18 @@ static int pcmcia_device_probe(struct device * dev) ...@@ -427,6 +427,18 @@ static int pcmcia_device_probe(struct device * dev)
p_drv = to_pcmcia_drv(dev->driver); p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket; s = p_dev->socket;
/* The PCMCIA code passes the match data in via dev->driver_data
* which is an ugly hack. Once the driver probe is called it may
* and often will overwrite the match data so we must save it first
*
* 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 = p_dev->dev.driver_data;
ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id, ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id,
p_drv->drv.name); p_drv->drv.name);
...@@ -455,21 +467,14 @@ static int pcmcia_device_probe(struct device * dev) ...@@ -455,21 +467,14 @@ static int pcmcia_device_probe(struct device * dev)
goto put_module; 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 = p_dev->dev.driver_data;
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_device_later(p_dev->socket, 0); pcmcia_add_device_later(p_dev->socket, 0);
put_module: put_module:
if (ret) if (ret)
module_put(p_drv->owner); module_put(p_drv->owner);
put_dev: put_dev:
if (ret) if (ret)
put_device(dev); put_device(dev);
return (ret); return (ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment