Commit f73c2bbf authored by Alexander Motin's avatar Alexander Motin
Browse files

bus: Cleanup device_probe_child()

When device driver probe method returns 0, i.e. absolute priority, do
not remove its class from the device just to set it back few lines
later, that may change the device unit number, etc. and after which
we'd better call the probe again.

If during search we found some driver with absolute priority, we do
not need to set device driver and class since we haven't removed them
before.

It should not happen, but if second probe method call failed, remove
the driver and possibly the class from the device as it was when we
started.

Reviewed by:	imp, jhb
Differential Revision:	https://reviews.freebsd.org/D32125
parent e725ee7e
...@@ -2074,6 +2074,7 @@ device_probe_child(device_t dev, device_t child) ...@@ -2074,6 +2074,7 @@ device_probe_child(device_t dev, device_t child)
driverlink_t best = NULL; driverlink_t best = NULL;
driverlink_t dl; driverlink_t dl;
int result, pri = 0; int result, pri = 0;
/* We should preserve the devclass (or lack of) set by the bus. */
int hasclass = (child->devclass != NULL); int hasclass = (child->devclass != NULL);
GIANT_REQUIRED; GIANT_REQUIRED;
...@@ -2125,11 +2126,6 @@ device_probe_child(device_t dev, device_t child) ...@@ -2125,11 +2126,6 @@ device_probe_child(device_t dev, device_t child)
result = DEVICE_PROBE(child); result = DEVICE_PROBE(child);
/* Reset flags and devclass before the next probe. */
child->devflags = 0;
if (!hasclass)
(void)device_set_devclass(child, NULL);
/* /*
* If the driver returns SUCCESS, there can be * If the driver returns SUCCESS, there can be
* no higher match for this device. * no higher match for this device.
...@@ -2140,6 +2136,11 @@ device_probe_child(device_t dev, device_t child) ...@@ -2140,6 +2136,11 @@ device_probe_child(device_t dev, device_t child)
break; break;
} }
/* Reset flags and devclass before the next probe. */
child->devflags = 0;
if (!hasclass)
(void)device_set_devclass(child, NULL);
/* /*
* Reset DF_QUIET in case this driver doesn't * Reset DF_QUIET in case this driver doesn't
* end up as the best driver. * end up as the best driver.
...@@ -2184,36 +2185,43 @@ device_probe_child(device_t dev, device_t child) ...@@ -2184,36 +2185,43 @@ device_probe_child(device_t dev, device_t child)
break; break;
} }
if (best == NULL)
return (ENXIO);
/* /*
* If we found a driver, change state and initialise the devclass. * If we found a driver, change state and initialise the devclass.
*/ */
if (best) { if (pri < 0) {
/* Set the winning driver, devclass, and flags. */ /* Set the winning driver, devclass, and flags. */
result = device_set_driver(child, best->driver);
if (result != 0)
return (result);
if (!child->devclass) { if (!child->devclass) {
result = device_set_devclass(child, best->driver->name); result = device_set_devclass(child, best->driver->name);
if (result != 0) if (result != 0) {
(void)device_set_driver(child, NULL);
return (result); return (result);
}
} }
result = device_set_driver(child, best->driver);
if (result != 0)
return (result);
resource_int_value(best->driver->name, child->unit, resource_int_value(best->driver->name, child->unit,
"flags", &child->devflags); "flags", &child->devflags);
if (pri < 0) { /*
/* * A bit bogus. Call the probe method again to make sure
* A bit bogus. Call the probe method again to make * that we have the right description.
* sure that we have the right description. */
*/ result = DEVICE_PROBE(child);
DEVICE_PROBE(child); if (result > 0) {
if (!hasclass)
(void)device_set_devclass(child, NULL);
(void)device_set_driver(child, NULL);
return (result);
} }
child->state = DS_ALIVE;
bus_data_generation_update();
return (0);
} }
return (ENXIO); child->state = DS_ALIVE;
bus_data_generation_update();
return (0);
} }
/** /**
......
Supports Markdown
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