Commit 7054c2c1 authored by Patrick Mochel's avatar Patrick Mochel

driver model: fix bogus driver binding error reporting and handling.

Some error checking was added ca. 2.5.58 that would remove a device from 
its bus's list of devices if device_attach() returned an error. This 
included errors returned from drv->probe(), and the -ENODEV error returned
if the device wasn't bound to any driver.

This was BAD since it was perfectly fine for a device not to bind to a 
driver immediately, and for drivers to return an error on probe() if the 
device doesn't exactly qualify as one it supports. 

This changes device_attach() and driver_attach() to both return void, 
instead of an error, since they really can never fail hard enough to cause
the device or driver to be removed from the bus. 
parent 45e8bb50
...@@ -282,26 +282,23 @@ static int bus_match(struct device * dev, struct device_driver * drv) ...@@ -282,26 +282,23 @@ static int bus_match(struct device * dev, struct device_driver * drv)
* Walk the list of drivers that the bus has and call bus_match() * Walk the list of drivers that the bus has and call bus_match()
* for each pair. If a compatible pair is found, break out and return. * for each pair. If a compatible pair is found, break out and return.
*/ */
static int device_attach(struct device * dev) static void device_attach(struct device * dev)
{ {
struct bus_type * bus = dev->bus; struct bus_type * bus = dev->bus;
struct list_head * entry; struct list_head * entry;
int error = 0;
if (dev->driver) { if (dev->driver) {
device_bind_driver(dev); device_bind_driver(dev);
return 0; return;
} }
if (!bus->match) if (bus->match) {
return 0; list_for_each(entry,&bus->drivers.list) {
struct device_driver * drv = to_drv(entry);
list_for_each(entry,&bus->drivers.list) { if (!bus_match(dev,drv))
struct device_driver * drv = to_drv(entry); break;
if (!(error = bus_match(dev,drv))) }
break;
} }
return error;
} }
...@@ -318,22 +315,21 @@ static int device_attach(struct device * dev) ...@@ -318,22 +315,21 @@ static int device_attach(struct device * dev)
* Note that we ignore the error from bus_match(), since it's perfectly * Note that we ignore the error from bus_match(), since it's perfectly
* valid for a driver not to bind to any devices. * valid for a driver not to bind to any devices.
*/ */
static int driver_attach(struct device_driver * drv) static void driver_attach(struct device_driver * drv)
{ {
struct bus_type * bus = drv->bus; struct bus_type * bus = drv->bus;
struct list_head * entry; struct list_head * entry;
if (!bus->match) if (!bus->match)
return 0; return;
list_for_each(entry,&bus->devices.list) { list_for_each(entry,&bus->devices.list) {
struct device * dev = container_of(entry,struct device,bus_list); struct device * dev = container_of(entry,struct device,bus_list);
if (!dev->driver) { if (!dev->driver) {
if (!bus_match(dev,drv) && dev->driver) if (!bus_match(dev,drv))
devclass_add_device(dev); devclass_add_device(dev);
} }
} }
return 0;
} }
...@@ -393,8 +389,7 @@ int bus_add_device(struct device * dev) ...@@ -393,8 +389,7 @@ int bus_add_device(struct device * dev)
down_write(&dev->bus->subsys.rwsem); down_write(&dev->bus->subsys.rwsem);
pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id); pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id);
list_add_tail(&dev->bus_list,&dev->bus->devices.list); list_add_tail(&dev->bus_list,&dev->bus->devices.list);
if ((error = device_attach(dev))) device_attach(dev);
list_del_init(&dev->bus_list);
up_write(&dev->bus->subsys.rwsem); up_write(&dev->bus->subsys.rwsem);
sysfs_create_link(&bus->devices.kobj,&dev->kobj,dev->bus_id); sysfs_create_link(&bus->devices.kobj,&dev->kobj,dev->bus_id);
} }
...@@ -446,11 +441,8 @@ int bus_add_driver(struct device_driver * drv) ...@@ -446,11 +441,8 @@ int bus_add_driver(struct device_driver * drv)
} }
down_write(&bus->subsys.rwsem); down_write(&bus->subsys.rwsem);
if (!(error = devclass_add_driver(drv))) { if (!(error = devclass_add_driver(drv)))
if ((error = driver_attach(drv))) { driver_attach(drv);
devclass_remove_driver(drv);
}
}
up_write(&bus->subsys.rwsem); up_write(&bus->subsys.rwsem);
if (error) { if (error) {
......
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