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: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Alan Cox 2008-09-22 15:58:14 +01:00 committed by Linus Torvalds
parent ae91119125
commit cec5eb7be3
1 changed files with 14 additions and 9 deletions

View File

@ -427,6 +427,18 @@ static int pcmcia_device_probe(struct device * dev)
p_drv = to_pcmcia_drv(dev->driver);
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,
p_drv->drv.name);
@ -455,21 +467,14 @@ static int pcmcia_device_probe(struct device * dev)
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) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_device_later(p_dev->socket, 0);
put_module:
put_module:
if (ret)
module_put(p_drv->owner);
put_dev:
put_dev:
if (ret)
put_device(dev);
return (ret);