From 3feca13e9a44a714f06415a18cf8e6f50b0c74db Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Jun 2014 14:16:01 -0700 Subject: [PATCH] 3.15-stable patches added patches: rtc-rtc-at91rm9200-fix-infinite-wait-for-ackupd-irq.patch --- ...200-fix-infinite-wait-for-ackupd-irq.patch | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 queue-3.15/rtc-rtc-at91rm9200-fix-infinite-wait-for-ackupd-irq.patch diff --git a/queue-3.15/rtc-rtc-at91rm9200-fix-infinite-wait-for-ackupd-irq.patch b/queue-3.15/rtc-rtc-at91rm9200-fix-infinite-wait-for-ackupd-irq.patch new file mode 100644 index 00000000000..960b4364728 --- /dev/null +++ b/queue-3.15/rtc-rtc-at91rm9200-fix-infinite-wait-for-ackupd-irq.patch @@ -0,0 +1,89 @@ +From 2fe121e1f5aa3bf31b418a9790db6c400e922291 Mon Sep 17 00:00:00 2001 +From: Boris BREZILLON +Date: Fri, 6 Jun 2014 14:36:09 -0700 +Subject: rtc: rtc-at91rm9200: fix infinite wait for ACKUPD irq + +From: Boris BREZILLON + +commit 2fe121e1f5aa3bf31b418a9790db6c400e922291 upstream. + +The rtc user must wait at least 1 sec between each time/calandar update +(see atmel's datasheet chapter "Updating Time/Calendar"). + +Use the 1Hz interrupt to update the at91_rtc_upd_rdy flag and wait for +the at91_rtc_wait_upd_rdy event if the rtc is not ready. + +This patch fixes a deadlock in an uninterruptible wait when the RTC is +updated more than once every second. AFAICT the bug is here from the +beginning, but I think we should at least backport this fix to 3.10 and +the following longterm and stable releases. + +Signed-off-by: Boris BREZILLON +Reported-by: Bryan Evenson +Tested-by: Bryan Evenson +Cc: Andrew Victor +Cc: Nicolas Ferre +Cc: Jean-Christophe Plagniol-Villard +Cc: Alessandro Zummo +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rtc/rtc-at91rm9200.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/rtc-at91rm9200.c ++++ b/drivers/rtc/rtc-at91rm9200.c +@@ -48,6 +48,7 @@ struct at91_rtc_config { + + static const struct at91_rtc_config *at91_rtc_config; + static DECLARE_COMPLETION(at91_rtc_updated); ++static DECLARE_COMPLETION(at91_rtc_upd_rdy); + static unsigned int at91_alarm_year = AT91_RTC_EPOCH; + static void __iomem *at91_rtc_regs; + static int irq; +@@ -161,6 +162,8 @@ static int at91_rtc_settime(struct devic + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + ++ wait_for_completion(&at91_rtc_upd_rdy); ++ + /* Stop Time/Calendar from counting */ + cr = at91_rtc_read(AT91_RTC_CR); + at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); +@@ -183,7 +186,9 @@ static int at91_rtc_settime(struct devic + + /* Restart Time/Calendar */ + cr = at91_rtc_read(AT91_RTC_CR); ++ at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_SECEV); + at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); ++ at91_rtc_write_ier(AT91_RTC_SECEV); + + return 0; + } +@@ -290,8 +295,10 @@ static irqreturn_t at91_rtc_interrupt(in + if (rtsr) { /* this interrupt is shared! Is it ours? */ + if (rtsr & AT91_RTC_ALARM) + events |= (RTC_AF | RTC_IRQF); +- if (rtsr & AT91_RTC_SECEV) +- events |= (RTC_UF | RTC_IRQF); ++ if (rtsr & AT91_RTC_SECEV) { ++ complete(&at91_rtc_upd_rdy); ++ at91_rtc_write_idr(AT91_RTC_SECEV); ++ } + if (rtsr & AT91_RTC_ACKUPD) + complete(&at91_rtc_updated); + +@@ -413,6 +420,11 @@ static int __init at91_rtc_probe(struct + return PTR_ERR(rtc); + platform_set_drvdata(pdev, rtc); + ++ /* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy ++ * completion. ++ */ ++ at91_rtc_write_ier(AT91_RTC_SECEV); ++ + dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); + return 0; + } -- 2.47.3