diff options
author | Barry Song <Baohua.Song@csr.com> | 2014-12-10 15:53:51 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 17:41:15 -0800 |
commit | e9bc7363d634e8d2ef1955106c53f8266d724353 (patch) | |
tree | 9a68c5601a6ea0d4622882f1d40197a6991fb119 /drivers/rtc/rtc-sirfsoc.c | |
parent | 09e427f87d345967503bb3c64854e11412c584f5 (diff) | |
download | lwn-e9bc7363d634e8d2ef1955106c53f8266d724353.tar.gz lwn-e9bc7363d634e8d2ef1955106c53f8266d724353.zip |
drivers/rtc/rtc-sirfsoc.c: replace local_irq_disable by spin_lock_irq for SMP safety
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: hao liu <hao.liu@csr.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-sirfsoc.c')
-rw-r--r-- | drivers/rtc/rtc-sirfsoc.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c index a9ea7d181380..d2ac6688e5c7 100644 --- a/drivers/rtc/rtc-sirfsoc.c +++ b/drivers/rtc/rtc-sirfsoc.c @@ -47,6 +47,7 @@ struct sirfsoc_rtc_drv { unsigned irq_wake; /* Overflow for every 8 years extra time */ u32 overflow_rtc; + spinlock_t lock; #ifdef CONFIG_PM u32 saved_counter; u32 saved_overflow_rtc; @@ -61,7 +62,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, rtcdrv = dev_get_drvdata(dev); - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_count = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); @@ -84,7 +85,8 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, if (sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E) alrm->enabled = 1; - local_irq_enable(); + + spin_unlock_irq(&rtcdrv->lock); return 0; } @@ -99,7 +101,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, if (alrm->enabled) { rtc_tm_to_time(&(alrm->time), &rtc_alarm); - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS); @@ -123,14 +125,15 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, rtc_status_reg |= SIRFSOC_RTC_AL0E; sirfsoc_rtc_iobrg_writel( rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); - local_irq_enable(); + + spin_unlock_irq(&rtcdrv->lock); } else { /* * if this function was called with enabled=0 * then it could mean that the application is * trying to cancel an ongoing alarm */ - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS); @@ -146,7 +149,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, rtcdrv->rtc_base + RTC_STATUS); } - local_irq_enable(); + spin_unlock_irq(&rtcdrv->lock); } return 0; @@ -217,7 +220,7 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev, rtcdrv = dev_get_drvdata(dev); - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS); @@ -227,7 +230,8 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev, rtc_status_reg &= ~SIRFSOC_RTC_AL0E; sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); - local_irq_enable(); + + spin_unlock_irq(&rtcdrv->lock); return 0; @@ -248,6 +252,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) unsigned long rtc_status_reg = 0x0; unsigned long events = 0x0; + spin_lock(&rtcdrv->lock); + rtc_status_reg = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_STATUS); /* this bit will be set ONLY if an alarm was active * and it expired NOW @@ -265,6 +271,9 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) rtc_status_reg &= ~(SIRFSOC_RTC_AL0E); } sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); + + spin_unlock(&rtcdrv->lock); + /* this should wake up any apps polling/waiting on the read * after setting the alarm */ @@ -292,6 +301,8 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) if (rtcdrv == NULL) return -ENOMEM; + spin_lock_init(&rtcdrv->lock); + err = of_property_read_u32(np, "reg", &rtcdrv->rtc_base); if (err) { dev_err(&pdev->dev, "unable to find base address of rtc node in dtb\n"); |