Page MenuHomeFreeBSD

D60781.1794639507.diff
No OneTemporary

Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None

D60781.1794639507.diff

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -1024,27 +1024,24 @@
* XXX Disabled for now (see acpi_probe_nomatch for details).
*/
static void
-acpi_driver_added(device_t dev, driver_t *driver)
+acpi_driver_added_action(device_t child, void *arg __unused)
{
- device_t child, *devlist;
- int i, numdevs;
-
- DEVICE_IDENTIFY(driver, dev);
- if (device_get_children(dev, &devlist, &numdevs))
- return;
- for (i = 0; i < numdevs; i++) {
- child = devlist[i];
- if (device_get_state(child) == DS_NOTPRESENT) {
+ if (device_get_state(child) != DS_NOTPRESENT)
+ return;
#ifdef ACPI_ENABLE_POWERDOWN_NODRIVER
- acpi_set_powerstate(child, ACPI_STATE_D0);
- if (device_probe_and_attach(child) != 0)
+ acpi_set_powerstate(child, ACPI_STATE_D0);
+ if (device_probe_and_attach(child) != 0)
acpi_set_powerstate(child, ACPI_STATE_D3);
#else
- device_probe_and_attach(child);
+ device_probe_and_attach(child);
#endif
- }
- }
- free(devlist, M_TEMP);
+}
+
+static void
+acpi_driver_added(device_t dev, driver_t *driver)
+{
+ DEVICE_IDENTIFY(driver, dev);
+ bus_foreach_child_safe(dev, acpi_driver_added_action, NULL);
}
/* Location hint for devctl(8) */
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -410,6 +410,15 @@
static struct device_list bus_data_devices;
static int bus_data_generation = 1;
+/* Active child snapshots, protected by the bus topology lock. */
+struct bus_child_walk {
+ LIST_ENTRY(bus_child_walk) link;
+ device_t *children;
+ int count;
+};
+static LIST_HEAD(, bus_child_walk) bus_child_walks =
+ LIST_HEAD_INITIALIZER(bus_child_walks);
+
static kobj_method_t null_methods[] = {
KOBJMETHOD_END
};
@@ -1538,7 +1547,8 @@
int
device_delete_child(device_t dev, device_t child)
{
- int error;
+ struct bus_child_walk *walk;
+ int error, i;
device_t grandchild;
PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
@@ -1564,6 +1574,13 @@
BUS_CHILD_DELETED(dev, child);
TAILQ_REMOVE(&dev->children, child, link);
TAILQ_REMOVE(&bus_data_devices, child, devlink);
+
+ /* Invalidate pending entries before the device address can be reused. */
+ LIST_FOREACH(walk, &bus_child_walks, link) {
+ for (i = 0; i < walk->count; i++)
+ if (walk->children[i] == child)
+ walk->children[i] = NULL;
+ }
kobj_delete((kobj_t) child, M_BUS);
bus_data_generation_update();
@@ -3484,6 +3501,49 @@
return (0);
}
+/**
+ * @brief Invoke a callback on each surviving child in a snapshot
+ *
+ * The caller must hold the bus topology lock. Children deleted by a
+ * callback are removed from all active snapshots before they are freed,
+ * including snapshots belonging to an outer, nested walk. Children added
+ * during the walk are not visited. The callback must not delete the parent
+ * or use a child after deleting it. This does not provide device references
+ * or protection against concurrent topology changes while the lock is dropped.
+ *
+ * As with device_get_children(), allocation failure leaves the children
+ * unvisited.
+ *
+ * @param dev the parent device
+ * @param action callback to invoke on each surviving child
+ * @param arg argument passed through to @p action
+ * @retval 0 success
+ * @retval ENOMEM snapshot allocation failed
+ */
+int
+bus_foreach_child_safe(device_t dev, bus_child_action_t action, void *arg)
+{
+ struct bus_child_walk walk;
+ device_t child;
+ int error, i;
+
+ bus_topo_assert();
+ error = device_get_children(dev, &walk.children, &walk.count);
+ if (error != 0)
+ return (error);
+
+ LIST_INSERT_HEAD(&bus_child_walks, &walk, link);
+ for (i = 0; i < walk.count; i++) {
+ child = walk.children[i];
+ walk.children[i] = NULL;
+ if (child != NULL && device_get_parent(child) == dev)
+ action(child, arg);
+ }
+ LIST_REMOVE(&walk, link);
+ free(walk.children, M_TEMP);
+ return (0);
+}
+
/**
* @brief Probe and attach all children of the given device
*
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -596,6 +596,15 @@
int bus_child_pnpinfo(device_t child, struct sbuf *sb);
int bus_child_location(device_t child, struct sbuf *sb);
+/**
+ * @brief Callback invoked for each surviving child in a snapshot
+ *
+ * @param child the child device
+ * @param arg the arg passed to bus_foreach_child_safe()
+ */
+typedef void bus_child_action_t(device_t child, void *arg);
+
+int bus_foreach_child_safe(device_t dev, bus_child_action_t action, void *arg);
void bus_attach_children(device_t dev);
void bus_delayed_attach_children(device_t bus);
int bus_detach_children(device_t dev);

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 14, 6:58 AM (3 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41702786
Default Alt Text
D60781.1794639507.diff (4 KB)

Event Timeline