serial: stm32: fix a deadlock condition with wakeup event
authorErwan Le Ray <erwan.leray@foss.st.com>
Thu, 4 Mar 2021 16:23:00 +0000 (17:23 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 May 2021 07:50:08 +0000 (09:50 +0200)
commitea627af3ddddc326a9a87800d630def9608d05ed
tree91c681ff1299755ed71e036fba0dda963afa4197
parent69ac7b3b893cff08dccced90545b42316abd7ed5
serial: stm32: fix a deadlock condition with wakeup event

[ Upstream commit ad7676812437a00a4c6be155fc17926069f99084 ]

Deadlock issue is seen when enabling CONFIG_PROVE_LOCKING=Y, and uart
console as wakeup source. Deadlock occurs when resuming from low power
mode if system is waked up via usart console.
The deadlock is triggered 100% when also disabling console suspend prior
to go to suspend.

Simplified call stack, deadlock condition:
- stm32_console_write <-- spin_lock already held
- print_circular_bug
- pm_wakeup_dev_event <-- triggers lockdep as seen above
- stm32_receive_chars
- stm32_interrupt <-- wakeup via uart console, takes the lock

So, revisit spin_lock in stm32-usart driver:
- there is no need to hold the lock to access ICR (atomic clear of status
  flags)
- only hold the lock inside stm32_receive_chars() routine (no need to
  call pm_wakeup_dev_event with lock held)
- keep stm32_transmit_chars() routine called with lock held

Fixes: 48a6092fb41f ("serial: stm32-usart: Add STM32 USART Driver")
Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/20210304162308.8984-6-erwan.leray@foss.st.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/tty/serial/stm32-usart.c