Skip to content

Commit 520c228

Browse files
committed
ACPI: scan: Rework Device Check and Bus Check notification handling
The underlying problem is the handling of the enabled bit in device status (bit 1 of _STA return value) which is required by the ACPI specification to be observed in addition to the present bit (bit 0 of _STA return value) [1], but Linux does not observe it. Since Linux has not looked at that bit for a long time, it is generally risky to start obseving it in all device enumeration cases, especially at the system initialization time, but it can be observed when the kernel receives a Bus Check or Device Check notification indicating a change in device configuration. In those cases, seeing the enabled bit clear may be regarded as an indication that the device at hand should not be used any more. For this reason, rework the handling of Device Check and Bus Check notifications in the ACPI core device enumeration code in the following way: 1. Rename acpi_bus_trim_one() to acpi_scan_check_and_detach() and make it check device status if its second argument is not NULL, in which case it will detach scan handlers or ACPI drivers from devices whose _STA returns the enabled bit clear. 2. Make acpi_scan_device_check() and acpi_scan_bus_check() invoke acpi_scan_check_and_detach() with a non-NULL second argument unconditionally, so scan handlers and ACPI drivers are detached from the target device and its ancestors if their _STA returns the enabled bit clear. Link: https://uefi.org/specs/ACPI/6.5/06_Device_Configuration.html#sta-device-status # [1] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 1b4f02a commit 520c228

File tree

1 file changed

+45
-39
lines changed

1 file changed

+45
-39
lines changed

drivers/acpi/scan.c

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,27 @@ static int acpi_scan_try_to_offline(struct acpi_device *device)
244244
return 0;
245245
}
246246

247-
static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
247+
static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
248248
{
249249
struct acpi_scan_handler *handler = adev->handler;
250250

251-
acpi_dev_for_each_child_reverse(adev, acpi_bus_trim_one, NULL);
251+
acpi_dev_for_each_child_reverse(adev, acpi_scan_check_and_detach, check);
252+
253+
if (check) {
254+
acpi_bus_get_status(adev);
255+
/*
256+
* Skip devices that are still there and take the enabled
257+
* flag into account.
258+
*/
259+
if (acpi_device_is_enabled(adev))
260+
return 0;
261+
262+
/* Skip device that have not been enumerated. */
263+
if (!acpi_device_enumerated(adev)) {
264+
dev_dbg(&adev->dev, "Still not enumerated\n");
265+
return 0;
266+
}
267+
}
252268

253269
adev->flags.match_driver = false;
254270
if (handler) {
@@ -270,6 +286,11 @@ static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
270286
return 0;
271287
}
272288

289+
static void acpi_scan_check_subtree(struct acpi_device *adev)
290+
{
291+
acpi_scan_check_and_detach(adev, (void *)true);
292+
}
293+
273294
static int acpi_scan_hot_remove(struct acpi_device *device)
274295
{
275296
acpi_handle handle = device->handle;
@@ -315,42 +336,30 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
315336
return 0;
316337
}
317338

318-
static int acpi_scan_device_not_enumerated(struct acpi_device *adev)
319-
{
320-
if (!acpi_device_enumerated(adev)) {
321-
dev_warn(&adev->dev, "Still not enumerated\n");
322-
return -EALREADY;
323-
}
324-
acpi_bus_trim(adev);
325-
return 0;
326-
}
327-
328339
static int acpi_scan_device_check(struct acpi_device *adev)
329340
{
330341
int error;
331342

332-
acpi_bus_get_status(adev);
333-
if (acpi_device_is_present(adev)) {
334-
/*
335-
* This function is only called for device objects for which
336-
* matching scan handlers exist. The only situation in which
337-
* the scan handler is not attached to this device object yet
338-
* is when the device has just appeared (either it wasn't
339-
* present at all before or it was removed and then added
340-
* again).
341-
*/
342-
if (adev->handler) {
343-
dev_dbg(&adev->dev, "Already enumerated\n");
344-
return 0;
345-
}
346-
error = acpi_bus_scan(adev->handle);
347-
if (error) {
348-
dev_warn(&adev->dev, "Namespace scan failure\n");
349-
return error;
350-
}
351-
} else {
352-
error = acpi_scan_device_not_enumerated(adev);
343+
acpi_scan_check_subtree(adev);
344+
345+
if (!acpi_device_is_present(adev))
346+
return 0;
347+
348+
/*
349+
* This function is only called for device objects for which matching
350+
* scan handlers exist. The only situation in which the scan handler
351+
* is not attached to this device object yet is when the device has
352+
* just appeared (either it wasn't present at all before or it was
353+
* removed and then added again).
354+
*/
355+
if (adev->handler) {
356+
dev_dbg(&adev->dev, "Already enumerated\n");
357+
return 0;
353358
}
359+
error = acpi_bus_scan(adev->handle);
360+
if (error)
361+
dev_warn(&adev->dev, "Namespace scan failure\n");
362+
354363
return error;
355364
}
356365

@@ -359,11 +368,8 @@ static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
359368
struct acpi_scan_handler *handler = adev->handler;
360369
int error;
361370

362-
acpi_bus_get_status(adev);
363-
if (!acpi_device_is_present(adev)) {
364-
acpi_scan_device_not_enumerated(adev);
365-
return 0;
366-
}
371+
acpi_scan_check_subtree(adev);
372+
367373
if (handler && handler->hotplug.scan_dependent)
368374
return handler->hotplug.scan_dependent(adev);
369375

@@ -2586,7 +2592,7 @@ EXPORT_SYMBOL(acpi_bus_scan);
25862592
*/
25872593
void acpi_bus_trim(struct acpi_device *adev)
25882594
{
2589-
acpi_bus_trim_one(adev, NULL);
2595+
acpi_scan_check_and_detach(adev, NULL);
25902596
}
25912597
EXPORT_SYMBOL_GPL(acpi_bus_trim);
25922598

0 commit comments

Comments
 (0)