Commit e647b532275b ("ACPI: Add early device probing infrastructure") introduced code that allows inserting driver specific struct acpi_probe_entry probe entries into ACPI linker sections (one per-subsystem, eg irqchip, clocksource) that are then walked to retrieve the data and function hooks required to probe the respective kernel components. Probing for all entries in a section is triggered through the __acpi_probe_device_table() function, that in turn, according to the table ID a given probe entry reports parses the table with the function retrieved from the respective section structures (ie struct acpi_probe_entry). Owing to the current ACPI table parsing implementation, the __acpi_probe_device_table() function has to share global variables with the acpi_match_madt() function, so in order to guarantee mutual exclusion locking is required between the two functions. Current kernel code implements the locking through the acpi_probe_lock spinlock; this has the side effect of requiring all code called within the lock (ie struct acpi_probe_entry.probe_{table/subtbl} hooks) not to sleep. However, kernel subsystems that make use of the early probing infrastructure are relying on kernel APIs that may sleep (eg irq_domain_alloc_fwnode(), among others) in the function calls pointed at by struct acpi_probe_entry.{probe_table/subtbl} entries (eg gic_v2_acpi_init()), which is a bug. Since __acpi_probe_device_table() is called from context that is allowed to sleep the acpi_probe_lock spinlock can be replaced with a mutex; this fixes the issue whilst still guaranteeing mutual exclusion.
Unified · Split
| @@ -2054,7 +2054,7 @@ int __init acpi_scan_init(void) · 2053 unmodified lines | ||
| 2054 | 2054 | |
| 2055 | 2055 | static struct acpi_probe_entry *ape; |
| 2056 | 2056 | static int acpi_probe_count; |
| 2057 | −static DEFINE_SPINLOCK(acpi_probe_lock); | |
| 2057 | +static DEFINE_MUTEX(acpi_probe_mutex); | |
| 2058 | 2058 | |
| 2059 | 2059 | static int __init acpi_match_madt(struct acpi_subtable_header *header, |
| 2060 | 2060 | const unsigned long end) |
| @@ -2073,7 +2073,7 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) · 12 unmodified lines | ||
| 2073 | 2073 | if (acpi_disabled) |
| 2074 | 2074 | return 0; |
| 2075 | 2075 | |
| 2076 | − spin_lock(&acpi_probe_lock); | |
| 2076 | + mutex_lock(&acpi_probe_mutex); | |
| 2077 | 2077 | for (ape = ap_head; nr; ape++, nr--) { |
| 2078 | 2078 | if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) { |
| 2079 | 2079 | acpi_probe_count = 0; |
| @@ -2086,7 +2086,7 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) · 6 unmodified lines | ||
| 2086 | 2086 | count++; |
| 2087 | 2087 | } |
| 2088 | 2088 | } |
| 2089 | − spin_unlock(&acpi_probe_lock); | |
| 2089 | + mutex_unlock(&acpi_probe_mutex); | |
| 2090 | 2090 | |
| 2091 | 2091 | return count; |
| 2092 | 2092 | } |