History

ACPI / drivers: replace acpi_probe_lock spinlock with mutex

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.

Lorenzo Pieralisi committed 10 years ago

Commit 5331d9c1 parent 3feab131 file · +3 −3Browse files

Unified · Split

drivers/acpi/scan.c+3−3
@@ -2054,7 +2054,7 @@ int __init acpi_scan_init(void) · 2053 unmodified lines
20542054
20552055 static struct acpi_probe_entry *ape;
20562056 static int acpi_probe_count;
2057−static DEFINE_SPINLOCK(acpi_probe_lock);
2057+static DEFINE_MUTEX(acpi_probe_mutex);
20582058
20592059 static int __init acpi_match_madt(struct acpi_subtable_header *header,
20602060 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
20732073 if (acpi_disabled)
20742074 return 0;
20752075
2076− spin_lock(&acpi_probe_lock);
2076+ mutex_lock(&acpi_probe_mutex);
20772077 for (ape = ap_head; nr; ape++, nr--) {
20782078 if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) {
20792079 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
20862086 count++;
20872087 }
20882088 }
2089− spin_unlock(&acpi_probe_lock);
2089+ mutex_unlock(&acpi_probe_mutex);
20902090
20912091 return count;
20922092 }