Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177529862
D60781.1794639507.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None
D60781.1794639507.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D60781: acpi: avoid stale child pointers during driver-added scans
Attached
Detach File
Event Timeline