From c3052594c8ded984ceab3725f63990dfdea1e58f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 25 Apr 2018 16:28:26 +0200 Subject: ACPICA: provide abstraction for raw_spinlock_t Provide a new lock type acpi_raw_spinlock which is implemented as raw_spinlock_t on Linux. This type should be used in code which covers small areas of code and disables interrupts only for short time even on a realtime OS. There is a fallback to spinlock_t if an OS does not provide an implementation for acpi_raw_spinlock. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Rafael J. Wysocki --- include/acpi/acpiosxf.h | 21 +++++++++++++++++++++ include/acpi/actypes.h | 4 ++++ include/acpi/platform/aclinux.h | 5 +++++ include/acpi/platform/aclinuxex.h | 30 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 540d35f..eb1f21a 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -98,6 +98,27 @@ void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags); #endif /* + * RAW spinlock primitives. If the OS does not provide them, fallback to + * spinlock primitives + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_raw_lock +# define acpi_os_create_raw_lock(out_handle) acpi_os_create_lock(out_handle) +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock +# define acpi_os_delete_raw_lock(handle) acpi_os_delete_lock(handle) +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock +# define acpi_os_acquire_raw_lock(handle) acpi_os_acquire_lock(handle) +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock +# define acpi_os_release_raw_lock(handle, flags) \ + acpi_os_release_lock(handle, flags) +#endif + +/* * Semaphore primitives */ #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_semaphore diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 1c530f9..2b1bafa 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -245,6 +245,10 @@ typedef u64 acpi_physical_address; #define acpi_spinlock void * #endif +#ifndef acpi_raw_spinlock +#define acpi_raw_spinlock acpi_spinlock +#endif + #ifndef acpi_semaphore #define acpi_semaphore void * #endif diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index a0b2327..7451b3b 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -102,6 +102,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 */ @@ -119,6 +120,10 @@ #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_raw_lock +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock /* * OSL interfaces used by debugger/disassembler diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index 7e81475..d754a1b 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h @@ -90,6 +90,36 @@ static inline acpi_thread_id acpi_os_get_thread_id(void) lock ? AE_OK : AE_NO_MEMORY; \ }) + +#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; \ + }) + +static inline acpi_cpu_flags acpi_os_acquire_raw_lock(acpi_raw_spinlock lockp) +{ + acpi_cpu_flags flags; + + raw_spin_lock_irqsave(lockp, flags); + return flags; +} + +static inline void acpi_os_release_raw_lock(acpi_raw_spinlock lockp, + acpi_cpu_flags flags) +{ + raw_spin_unlock_irqrestore(lockp, flags); +} + +static inline void acpi_os_delete_raw_lock(acpi_raw_spinlock handle) +{ + ACPI_FREE(handle); +} + static inline u8 acpi_os_readable(void *pointer, acpi_size length) { return TRUE; -- cgit v1.1 From c57c0ad4a3ddd5cc697b1956c00d8c7c2cb7dc12 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 25 Apr 2018 16:28:27 +0200 Subject: ACPICA: Convert acpi_gbl_hardware lock back to an acpi_raw_spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We hit the following bug with -RT: |BUG: scheduling while atomic: swapper/7/0/0x00000002 |Pid: 0, comm: swapper/7 Not tainted 3.6.11-rt28.19.el6rt.x86_64.debug #1 |Call Trace: | rt_spin_lock+0x16/0x40 | __schedule_bug+0x67/0x90 | __schedule+0x793/0x7a0 | acpi_os_acquire_lock+0x1f/0x23 | acpi_write_bit_register+0x33/0xb0 | rt_spin_lock_slowlock+0xe5/0x2f0 | acpi_idle_enter_bm+0x8a/0x28e … 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 Link: http://lkml.kernel.org/r/1360765565.23152.5.camel@gandalf.local.home Signed-off-by: Thomas Gleixner [bigeasy: shorten the backtrace, use the type acpi_raw_spinlock incl. accessor] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 2 +- drivers/acpi/acpica/hwregs.c | 4 ++-- drivers/acpi/acpica/hwxface.c | 4 ++-- drivers/acpi/acpica/utmutex.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 0bc5500..1e62045 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -82,7 +82,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 27a86ad..3de794b 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -390,14 +390,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); + lock_flags = acpi_os_acquire_raw_lock(acpi_gbl_hardware_lock); /* 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); + acpi_os_release_raw_lock(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 5d13968..6e39a77 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -227,7 +227,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); + lock_flags = acpi_os_acquire_raw_lock(acpi_gbl_hardware_lock); /* * At this point, we know that the parent register is one of the @@ -288,7 +288,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); + acpi_os_release_raw_lock(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 d2d93e3..2e465e6 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -52,7 +52,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); } @@ -109,7 +109,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 */ -- cgit v1.1