Re: [RFC PATCH] ACPICA: Convert acpi_gbl_hardware lock back to a raw_spinlock_t

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 24, 2018 at 6:02 PM, Sebastian Andrzej Siewior
<bigeasy@xxxxxxxxxxxxx> wrote:
> From: Steven Rostedt <rostedt@xxxxxxxxxxx>
>
> 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 <rostedt@xxxxxxxxxxx>
> Cc: John Kacur <jkacur@xxxxxxxxx>
> Cc: Clark Williams <clark@xxxxxxxxxx>
> Link: http://lkml.kernel.org/r/1360765565.23152.5.camel@xxxxxxxxxxxxxxxxxx
>
> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> [bigeasy: shorten the backtrace]
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
> ---
>  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 | 14 ++++++++++++++
>  5 files changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
> index 0bc550072a21..1e6204518496 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 27a86ad55b58..4c792f3e6135 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);
> +       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 5d1396870bd0..8efeae8f3a8d 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);
> +       raw_spin_lock_irqsave(acpi_gbl_hardware_lock, lock_flags);
>
>         /*
>          * 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);
> +       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 d2d93e388f40..2e465e6a0ab6 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 */
> diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
> index a0b232703302..38eaa3235210 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 *

I would prefer to redefine acpi_spinlock as raw_spinlock_t and then
acpi_os_acquire/release_lock() as
raw_spin_lock_irqsave/unlock_irqrestore(), respectively.

>  #define acpi_cpu_flags                      unsigned long
>
>  /* Use native linux version of acpi_os_allocate_zeroed */
> @@ -120,6 +121,19 @@
>  #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
>   */
> --
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux