ARM: hwmod: RTC: Don't assume lock/unlock will be called with irq enabled
authorDave Gerlach <d-gerlach@ti.com>
Thu, 21 Jun 2018 09:13:08 +0000 (14:43 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Oct 2018 00:00:48 +0000 (17:00 -0700)
[ Upstream commit 6d609b35c815ba20132b7b64bcca04516bb17c56 ]

When the RTC lock and unlock functions were introduced it was likely
assumed that they would always be called from irq enabled context, hence
the use of local_irq_disable/enable. This is no longer true as the
RTC+DDR path makes a late call during the suspend path after irqs
have been disabled to enable the RTC hwmod which calls both unlock and
lock, leading to IRQs being reenabled through the local_irq_enable call
in omap_hwmod_rtc_lock call.

To avoid this change the local_irq_disable/enable to
local_irq_save/restore to ensure that from whatever context this is
called the proper IRQ configuration is maintained.

Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/mach-omap2/omap_hwmod_reset.c

index b68f9c0aff0b594d97af0c004c2525a7072197f0..d5ddba00bb7310bf0120902e2837dbddc4e90713 100644 (file)
@@ -92,11 +92,13 @@ static void omap_rtc_wait_not_busy(struct omap_hwmod *oh)
  */
 void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
 {
-       local_irq_disable();
+       unsigned long flags;
+
+       local_irq_save(flags);
        omap_rtc_wait_not_busy(oh);
        omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG);
        omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG);
-       local_irq_enable();
+       local_irq_restore(flags);
 }
 
 /**
@@ -110,9 +112,11 @@ void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
  */
 void omap_hwmod_rtc_lock(struct omap_hwmod *oh)
 {
-       local_irq_disable();
+       unsigned long flags;
+
+       local_irq_save(flags);
        omap_rtc_wait_not_busy(oh);
        omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG);
        omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG);
-       local_irq_enable();
+       local_irq_restore(flags);
 }