189 lines
7.6 KiB
Diff
189 lines
7.6 KiB
Diff
|
From f2aff55d0bc51db7e541fa5a753d1e6e4ee07fde Mon Sep 17 00:00:00 2001
|
||
|
From: Steven Rostedt <rostedt@goodmis.org>
|
||
|
Date: Wed, 13 Feb 2013 09:26:05 -0500
|
||
|
Subject: [PATCH 273/365] acpi/rt: Convert acpi_gbl_hardware lock back to a
|
||
|
raw_spinlock_t
|
||
|
|
||
|
We hit the following bug with 3.6-rt:
|
||
|
|
||
|
[ 5.898990] BUG: scheduling while atomic: swapper/3/0/0x00000002
|
||
|
[ 5.898991] no locks held by swapper/3/0.
|
||
|
[ 5.898993] Modules linked in:
|
||
|
[ 5.898996] Pid: 0, comm: swapper/3 Not tainted 3.6.11-rt28.19.el6rt.x86_64.debug #1
|
||
|
[ 5.898997] Call Trace:
|
||
|
[ 5.899011] [<ffffffff810804e7>] __schedule_bug+0x67/0x90
|
||
|
[ 5.899028] [<ffffffff81577923>] __schedule+0x793/0x7a0
|
||
|
[ 5.899032] [<ffffffff810b4e40>] ? debug_rt_mutex_print_deadlock+0x50/0x200
|
||
|
[ 5.899034] [<ffffffff81577b89>] schedule+0x29/0x70
|
||
|
[ 5.899036] BUG: scheduling while atomic: swapper/7/0/0x00000002
|
||
|
[ 5.899037] no locks held by swapper/7/0.
|
||
|
[ 5.899039] [<ffffffff81578525>] rt_spin_lock_slowlock+0xe5/0x2f0
|
||
|
[ 5.899040] Modules linked in:
|
||
|
[ 5.899041]
|
||
|
[ 5.899045] [<ffffffff81579a58>] ? _raw_spin_unlock_irqrestore+0x38/0x90
|
||
|
[ 5.899046] Pid: 0, comm: swapper/7 Not tainted 3.6.11-rt28.19.el6rt.x86_64.debug #1
|
||
|
[ 5.899047] Call Trace:
|
||
|
[ 5.899049] [<ffffffff81578bc6>] rt_spin_lock+0x16/0x40
|
||
|
[ 5.899052] [<ffffffff810804e7>] __schedule_bug+0x67/0x90
|
||
|
[ 5.899054] [<ffffffff8157d3f0>] ? notifier_call_chain+0x80/0x80
|
||
|
[ 5.899056] [<ffffffff81577923>] __schedule+0x793/0x7a0
|
||
|
[ 5.899059] [<ffffffff812f2034>] acpi_os_acquire_lock+0x1f/0x23
|
||
|
[ 5.899062] [<ffffffff810b4e40>] ? debug_rt_mutex_print_deadlock+0x50/0x200
|
||
|
[ 5.899068] [<ffffffff8130be64>] acpi_write_bit_register+0x33/0xb0
|
||
|
[ 5.899071] [<ffffffff81577b89>] schedule+0x29/0x70
|
||
|
[ 5.899072] [<ffffffff8130be13>] ? acpi_read_bit_register+0x33/0x51
|
||
|
[ 5.899074] [<ffffffff81578525>] rt_spin_lock_slowlock+0xe5/0x2f0
|
||
|
[ 5.899077] [<ffffffff8131d1fc>] acpi_idle_enter_bm+0x8a/0x28e
|
||
|
[ 5.899079] [<ffffffff81579a58>] ? _raw_spin_unlock_irqrestore+0x38/0x90
|
||
|
[ 5.899081] [<ffffffff8107e5da>] ? this_cpu_load+0x1a/0x30
|
||
|
[ 5.899083] [<ffffffff81578bc6>] rt_spin_lock+0x16/0x40
|
||
|
[ 5.899087] [<ffffffff8144c759>] cpuidle_enter+0x19/0x20
|
||
|
[ 5.899088] [<ffffffff8157d3f0>] ? notifier_call_chain+0x80/0x80
|
||
|
[ 5.899090] [<ffffffff8144c777>] cpuidle_enter_state+0x17/0x50
|
||
|
[ 5.899092] [<ffffffff812f2034>] acpi_os_acquire_lock+0x1f/0x23
|
||
|
[ 5.899094] [<ffffffff8144d1a1>] cpuidle899101] [<ffffffff8130be13>] ?
|
||
|
|
||
|
As the acpi code disables interrupts in acpi_idle_enter_bm, and calls
|
||
|
code that grabs the acpi lock, it causes issues as the lock is currently
|
||
|
in RT a sleeping lock.
|
||
|
|
||
|
The lock was converted from a raw to a sleeping lock due to some
|
||
|
previous issues, and tests that showed it didn't seem to matter.
|
||
|
Unfortunately, it did matter for one of our boxes.
|
||
|
|
||
|
This patch converts the lock back to a raw lock. I've run this code on a
|
||
|
few of my own machines, one being my laptop that uses the acpi quite
|
||
|
extensively. I've been able to suspend and resume without issues.
|
||
|
|
||
|
[ tglx: Made the change exclusive for acpi_gbl_hardware_lock ]
|
||
|
|
||
|
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||
|
Cc: John Kacur <jkacur@gmail.com>
|
||
|
Cc: Clark Williams <clark@redhat.com>
|
||
|
Link: http://lkml.kernel.org/r/1360765565.23152.5.camel@gandalf.local.home
|
||
|
|
||
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||
|
---
|
||
|
drivers/acpi/acpica/acglobal.h | 2 +-
|
||
|
drivers/acpi/acpica/hwregs.c | 4 ++--
|
||
|
drivers/acpi/acpica/hwxface.c | 4 ++--
|
||
|
drivers/acpi/acpica/utmutex.c | 4 ++--
|
||
|
include/acpi/platform/aclinux.h | 15 +++++++++++++++
|
||
|
5 files changed, 22 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
|
||
|
index 750fa824d42c..441edf51484a 100644
|
||
|
--- a/drivers/acpi/acpica/acglobal.h
|
||
|
+++ b/drivers/acpi/acpica/acglobal.h
|
||
|
@@ -116,7 +116,7 @@ ACPI_GLOBAL(u8, acpi_gbl_global_lock_pending);
|
||
|
* interrupt level
|
||
|
*/
|
||
|
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_gpe_lock); /* For GPE data structs and registers */
|
||
|
-ACPI_GLOBAL(acpi_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
|
||
|
+ACPI_GLOBAL(acpi_raw_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
|
||
|
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock);
|
||
|
|
||
|
/* Mutex for _OSI support */
|
||
|
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
|
||
|
index 3b7fb99362b6..696bf8e62afb 100644
|
||
|
--- a/drivers/acpi/acpica/hwregs.c
|
||
|
+++ b/drivers/acpi/acpica/hwregs.c
|
||
|
@@ -363,14 +363,14 @@ acpi_status acpi_hw_clear_acpi_status(void)
|
||
|
ACPI_BITMASK_ALL_FIXED_STATUS,
|
||
|
ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
|
||
|
|
||
|
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
|
||
|
+ raw_spin_lock_irqsave(acpi_gbl_hardware_lock, lock_flags);
|
||
|
|
||
|
/* Clear the fixed events in PM1 A/B */
|
||
|
|
||
|
status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
|
||
|
ACPI_BITMASK_ALL_FIXED_STATUS);
|
||
|
|
||
|
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
|
||
|
+ raw_spin_unlock_irqrestore(acpi_gbl_hardware_lock, lock_flags);
|
||
|
|
||
|
if (ACPI_FAILURE(status)) {
|
||
|
goto exit;
|
||
|
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
|
||
|
index 98c26ff39409..6e236f2ea791 100644
|
||
|
--- a/drivers/acpi/acpica/hwxface.c
|
||
|
+++ b/drivers/acpi/acpica/hwxface.c
|
||
|
@@ -373,7 +373,7 @@ acpi_status acpi_write_bit_register(u32 register_id, u32 value)
|
||
|
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||
|
}
|
||
|
|
||
|
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
|
||
|
+ raw_spin_lock_irqsave(acpi_gbl_hardware_lock, lock_flags);
|
||
|
|
||
|
/*
|
||
|
* At this point, we know that the parent register is one of the
|
||
|
@@ -434,7 +434,7 @@ acpi_status acpi_write_bit_register(u32 register_id, u32 value)
|
||
|
|
||
|
unlock_and_exit:
|
||
|
|
||
|
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
|
||
|
+ raw_spin_unlock_irqrestore(acpi_gbl_hardware_lock, lock_flags);
|
||
|
return_ACPI_STATUS(status);
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
|
||
|
index 15073375bd00..357e7ca5a587 100644
|
||
|
--- a/drivers/acpi/acpica/utmutex.c
|
||
|
+++ b/drivers/acpi/acpica/utmutex.c
|
||
|
@@ -88,7 +88,7 @@ acpi_status acpi_ut_mutex_initialize(void)
|
||
|
return_ACPI_STATUS (status);
|
||
|
}
|
||
|
|
||
|
- status = acpi_os_create_lock (&acpi_gbl_hardware_lock);
|
||
|
+ status = acpi_os_create_raw_lock (&acpi_gbl_hardware_lock);
|
||
|
if (ACPI_FAILURE (status)) {
|
||
|
return_ACPI_STATUS (status);
|
||
|
}
|
||
|
@@ -145,7 +145,7 @@ void acpi_ut_mutex_terminate(void)
|
||
|
/* Delete the spinlocks */
|
||
|
|
||
|
acpi_os_delete_lock(acpi_gbl_gpe_lock);
|
||
|
- acpi_os_delete_lock(acpi_gbl_hardware_lock);
|
||
|
+ acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
|
||
|
acpi_os_delete_lock(acpi_gbl_reference_count_lock);
|
||
|
|
||
|
/* Delete the reader/writer lock */
|
||
|
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
|
||
|
index e861a24f06f2..b5c97d3059c7 100644
|
||
|
--- a/include/acpi/platform/aclinux.h
|
||
|
+++ b/include/acpi/platform/aclinux.h
|
||
|
@@ -133,6 +133,7 @@
|
||
|
|
||
|
#define acpi_cache_t struct kmem_cache
|
||
|
#define acpi_spinlock spinlock_t *
|
||
|
+#define acpi_raw_spinlock raw_spinlock_t *
|
||
|
#define acpi_cpu_flags unsigned long
|
||
|
|
||
|
/* Use native linux version of acpi_os_allocate_zeroed */
|
||
|
@@ -151,6 +152,20 @@
|
||
|
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id
|
||
|
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock
|
||
|
|
||
|
+#define acpi_os_create_raw_lock(__handle) \
|
||
|
+({ \
|
||
|
+ raw_spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \
|
||
|
+ \
|
||
|
+ if (lock) { \
|
||
|
+ *(__handle) = lock; \
|
||
|
+ raw_spin_lock_init(*(__handle)); \
|
||
|
+ } \
|
||
|
+ lock ? AE_OK : AE_NO_MEMORY; \
|
||
|
+ })
|
||
|
+
|
||
|
+#define acpi_os_delete_raw_lock(__handle) kfree(__handle)
|
||
|
+
|
||
|
+
|
||
|
/*
|
||
|
* OSL interfaces used by debugger/disassembler
|
||
|
*/
|
||
|
--
|
||
|
2.28.0
|
||
|
|