Commit graph

8 commits

Author SHA1 Message Date
Hannes Reinecke
ca2b94ba12 [PATCH] driver core: fix error handling in bus_add_device
The error handling in bus_add_device() and device_attach() is simply
non-existing. This patch propagates any error from device_attach to
the upper layers to allow for a proper recovery.

From: Hannes Reinecke <hare@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-06-20 15:15:31 -07:00
Alan Stern
c95a6b057b [PATCH] driver core: Fix races in driver_detach()
This patch is intended for your "driver" tree.  It fixes several subtle
races in driver_detach() and device_release_driver() in the driver-model
core.

The major change is to use klist_remove() rather than klist_del() when
taking a device off its driver's list.  There's no other way to guarantee
that the list pointers will be updated before some other driver binds to
the device.  For this to work driver_detach() can't use a klist iterator,
so the loop over the devices must be written out in full.  In addition the
patch protects against the possibility that, when a driver and a device
are unregistered at the same time, one may be unloaded from memory before
the other is finished using it.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-06-20 15:15:28 -07:00
Patrick Mochel
0d3e5a2e39 [PATCH] Driver Core: fix bk-driver-core kills ppc64
There's no check to see if the device is already bound to a driver, which
could do bad things.  The first thing to go wrong is that it will try to match
a driver with a device already bound to one.  In some cases (it appears with
USB with drivers/usb/core/usb.c::usb_match_id()), some drivers will match a
device based on the class type, so it would be common (especially for HID
devices) to match a device that is already bound.

The fun comes when ->probe() is called, it fails, then
driver_probe_device() does this:

	dev->driver = NULL;

Later on, that pointer could be be dereferenced without checking and cause
hell to break loose.

This problem could be nasty. It's very hardware dependent, since some
devices could have a different set of matching qualifiers than others.

Now, I don't quite see exactly where/how you were getting that crash.
You're dereferencing bad memory, but I'm not sure which pointer was bad
and where it came from, but it could have come from a couple of different
places.

The patch below will hopefully fix it all up for you. It's against
2.6.12-rc2-mm1, and does the following:

- Move logic to driver_probe_device() and comments uncommon returns:
  1 - If device is bound
  0 - If device not bound, and no error
  error - If there was an error.

- Move locking to caller of that function, since we want to lock a
  device for the entire time we're trying to bind it to a driver (to
  prevent against a driver being loaded at the same time).

- Update __device_attach() and __driver_attach() to do that locking.

- Check if device is already bound in __driver_attach()

- Update the converse device_release_driver() so it locks the device
  around all of the operations.

- Mark driver_probe_device() as static and remove export. It's an
  internal function, it should stay that way, and there are no other
  callers. If there is ever a need to export it, we can audit it as
  necessary.

Signed-off-by: Andrew Morton <akpm@osdl.org>
2005-06-20 15:15:27 -07:00
gregkh@suse.de
b86c1df1f9 [PATCH] Driver core: Fix up the driver and device iterators to be quieter
Also stops looping over the lists when a match is found.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de
2005-06-20 15:15:27 -07:00
mochel@digitalimplant.org
0956af53af [PATCH] Call klist_del() instead of klist_remove().
- Can't wait on removing the current item in the list (the positive refcount *because*
  we are using it causes it to deadlock).

Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-06-20 15:15:19 -07:00
mochel@digitalimplant.org
2287c322b6 [PATCH] Use bus_for_each_{dev,drv} for driver binding.
- Now possible, since the lists are locked using the klist lock and not the
  global rwsem.

Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-06-20 15:15:17 -07:00
mochel@digitalimplant.org
94e7b1c5ff [PATCH] Add a klist to struct device_driver for the devices bound to it.
- Use it in driver_for_each_device() instead of the regular list_head and stop using
  the bus's rwsem for protection.
- Use driver_for_each_device() in driver_detach() so we don't deadlock on the
  bus's rwsem.
- Remove ->devices.
- Move klist access and sysfs link access out from under device's semaphore, since
  they're synchronized through other means.

Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-06-20 15:15:16 -07:00
mochel@digitalimplant.org
07e4a3e27f [PATCH] Move device/driver code to drivers/base/dd.c
This relocates the driver binding/unbinding code to drivers/base/dd.c. This is done
for two reasons: One, it's not code related to the bus_type itself; it uses some from
that, some from devices, and some from drivers. And Two, it will make it easier to do
some of the upcoming lock removal on that code..

Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-06-20 15:15:13 -07:00