Skip to content

Commit

Permalink
rtc: pm8xxx: fix set-alarm race
Browse files Browse the repository at this point in the history
commit c88db0eff9722fc2b6c4d172a50471d20e08ecc6 upstream.

Make sure to disable the alarm before updating the four alarm time
registers to avoid spurious alarms during the update.

Note that the disable needs to be done outside of the ctrl_reg_lock
section to prevent a racing alarm interrupt from disabling the newly set
alarm when the lock is released.

Fixes: 9a9a54a ("drivers/rtc: add support for Qualcomm PMIC8xxx RTC")
Cc: stable@vger.kernel.org      # 3.1
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Reviewed-by: David Collins <quic_collinsd@quicinc.com>
Link: https://lore.kernel.org/r/20230202155448.6715-2-johan+linaro@kernel.org
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ulrich Hecht <uli+cip@fpond.eu>
  • Loading branch information
jhovold authored and Ulrich Hecht committed Apr 3, 2023
1 parent ab3b760 commit f205733
Showing 1 changed file with 10 additions and 14 deletions.
24 changes: 10 additions & 14 deletions drivers/rtc/rtc-pm8xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
int rc, i;
u8 value[NUM_8_BIT_RTC_REGS];
unsigned int ctrl_reg;
unsigned long secs, irq_flags;
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
Expand All @@ -247,6 +246,11 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
secs >>= 8;
}

rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,
regs->alarm_en, 0);
if (rc)
return rc;

spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);

rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,
Expand All @@ -256,19 +260,11 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
goto rtc_rw_fail;
}

rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
if (rc)
goto rtc_rw_fail;

if (alarm->enabled)
ctrl_reg |= regs->alarm_en;
else
ctrl_reg &= ~regs->alarm_en;

rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
if (rc) {
dev_err(dev, "Write to RTC alarm control register failed\n");
goto rtc_rw_fail;
if (alarm->enabled) {
rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,
regs->alarm_en, regs->alarm_en);
if (rc)
goto rtc_rw_fail;
}

dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
Expand Down

0 comments on commit f205733

Please sign in to comment.