diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2016-08-16 11:59:53 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-09-02 16:22:21 -0400 |
commit | 5331d9cab32ef640b4cd38a43b0858874fbb7168 (patch) | |
tree | 0b97fceaed00589ec8b5a23c5df35dfa31e1cdd6 | |
parent | 3feab13c919f99b0a17d0ca22ae00cf90f5d3fd1 (diff) |
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.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Fixes: e647b532275b (ACPI: Add early device probing infrastructure)
Cc: 4.4+ <stable@vger.kernel.org> # 4.4+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/scan.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ad9fc84a8601..e878fc799af7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -2054,7 +2054,7 @@ int __init acpi_scan_init(void) | |||
2054 | 2054 | ||
2055 | static struct acpi_probe_entry *ape; | 2055 | static struct acpi_probe_entry *ape; |
2056 | static int acpi_probe_count; | 2056 | static int acpi_probe_count; |
2057 | static DEFINE_SPINLOCK(acpi_probe_lock); | 2057 | static DEFINE_MUTEX(acpi_probe_mutex); |
2058 | 2058 | ||
2059 | static int __init acpi_match_madt(struct acpi_subtable_header *header, | 2059 | static int __init acpi_match_madt(struct acpi_subtable_header *header, |
2060 | const unsigned long end) | 2060 | const unsigned long end) |
@@ -2073,7 +2073,7 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) | |||
2073 | if (acpi_disabled) | 2073 | if (acpi_disabled) |
2074 | return 0; | 2074 | return 0; |
2075 | 2075 | ||
2076 | spin_lock(&acpi_probe_lock); | 2076 | mutex_lock(&acpi_probe_mutex); |
2077 | for (ape = ap_head; nr; ape++, nr--) { | 2077 | for (ape = ap_head; nr; ape++, nr--) { |
2078 | if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) { | 2078 | if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) { |
2079 | acpi_probe_count = 0; | 2079 | acpi_probe_count = 0; |
@@ -2086,7 +2086,7 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) | |||
2086 | count++; | 2086 | count++; |
2087 | } | 2087 | } |
2088 | } | 2088 | } |
2089 | spin_unlock(&acpi_probe_lock); | 2089 | mutex_unlock(&acpi_probe_mutex); |
2090 | 2090 | ||
2091 | return count; | 2091 | return count; |
2092 | } | 2092 | } |