===================================================================
@@ -244,11 +244,27 @@ static int acpi_scan_try_to_offline(stru
return 0;
}
-static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
+static int acpi_bus_trim_one(struct acpi_device *adev, void *check_status)
{
struct acpi_scan_handler *handler = adev->handler;
- acpi_dev_for_each_child_reverse(adev, acpi_bus_trim_one, NULL);
+ acpi_dev_for_each_child_reverse(adev, acpi_bus_trim_one, check_status);
+
+ if (check_status) {
+ acpi_bus_get_status(adev);
+ /*
+ * Skip devices that are still there and take the enabled
+ * flag into account.
+ */
+ if (acpi_device_is_enabled(adev))
+ return 0;
+
+ /* Skip device that have not been enumerated. */
+ if (!acpi_device_enumerated(adev)) {
+ dev_dbg(&adev->dev, "Still not enumerated\n");
+ return 0;
+ }
+ }
adev->flags.match_driver = false;
if (handler) {
@@ -315,71 +331,67 @@ static int acpi_scan_hot_remove(struct a
return 0;
}
-static int acpi_scan_device_not_enumerated(struct acpi_device *adev)
+static void acpi_scan_check_gone(struct acpi_device *adev)
{
- if (!acpi_device_enumerated(adev)) {
- dev_warn(&adev->dev, "Still not enumerated\n");
- return -EALREADY;
- }
- acpi_bus_trim(adev);
- return 0;
+ acpi_bus_trim_one(adev, (void *)true);
}
-static int acpi_scan_device_check(struct acpi_device *adev)
+static int acpi_scan_rescan_bus(struct acpi_device *adev)
{
+ struct acpi_scan_handler *handler = adev->handler;
int error;
- acpi_bus_get_status(adev);
- if (acpi_device_is_present(adev)) {
- /*
- * This function is only called for device objects for which
- * matching scan handlers exist. The only situation in which
- * the scan handler is not attached to this device object yet
- * is when the device has just appeared (either it wasn't
- * present at all before or it was removed and then added
- * again).
- */
- if (adev->handler) {
- dev_dbg(&adev->dev, "Already enumerated\n");
- return 0;
- }
+ if (handler && handler->hotplug.scan_dependent)
+ error = handler->hotplug.scan_dependent(adev);
+ else
error = acpi_bus_scan(adev->handle);
- if (error) {
- dev_warn(&adev->dev, "Namespace scan failure\n");
- return error;
- }
- } else {
- error = acpi_scan_device_not_enumerated(adev);
- }
+
+ if (error)
+ dev_info(&adev->dev, "Namespace scan failure\n");
+
return error;
}
-static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
+static int acpi_scan_device_check(struct acpi_device *adev)
{
- struct acpi_scan_handler *handler = adev->handler;
- int error;
+ struct acpi_device *parent;
- acpi_bus_get_status(adev);
- if (!acpi_device_is_present(adev)) {
- acpi_scan_device_not_enumerated(adev);
+ acpi_scan_check_gone(adev);
+
+ if (!acpi_device_is_enabled(adev))
return 0;
- }
- if (handler && handler->hotplug.scan_dependent)
- return handler->hotplug.scan_dependent(adev);
- error = acpi_bus_scan(adev->handle);
- if (error) {
- dev_warn(&adev->dev, "Namespace scan failure\n");
- return error;
+ /*
+ * This function is only called for device objects for which matching
+ * scan handlers exist. The only situation in which the scan handler
+ * is not attached to this device object yet is when the device has
+ * just appeared (either it wasn't present or enabled at all before or
+ * it was removed and then added again).
+ */
+ if (adev->handler) {
+ dev_dbg(&adev->dev, "Already enumerated\n");
+ return 0;
}
- return acpi_dev_for_each_child(adev, acpi_scan_bus_check, NULL);
+
+ parent = acpi_dev_parent(adev);
+ if (!parent)
+ parent = adev;
+
+ return acpi_scan_rescan_bus(parent);
+}
+
+static int acpi_scan_bus_check(struct acpi_device *adev)
+{
+ acpi_scan_check_gone(adev);
+
+ return acpi_scan_rescan_bus(adev);
}
static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
{
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
- return acpi_scan_bus_check(adev, NULL);
+ return acpi_scan_bus_check(adev);
case ACPI_NOTIFY_DEVICE_CHECK:
return acpi_scan_device_check(adev);
case ACPI_NOTIFY_EJECT_REQUEST:
@@ -1945,6 +1957,11 @@ bool acpi_device_is_present(const struct
return adev->status.present || adev->status.functional;
}
+bool acpi_device_is_enabled(const struct acpi_device *adev)
+{
+ return acpi_device_is_present(adev) && adev->status.enabled;
+}
+
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
const char *idstr,
const struct acpi_device_id **matchid)
===================================================================
@@ -121,6 +121,7 @@ int acpi_device_setup_files(struct acpi_
void acpi_device_remove_files(struct acpi_device *dev);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
+bool acpi_device_is_enabled(const struct acpi_device *adev);
bool acpi_device_is_present(const struct acpi_device *adev);
bool acpi_device_is_battery(struct acpi_device *adev);
bool acpi_device_is_first_physical_node(struct acpi_device *adev,