diff mbox

RTC drivers need some love

Message ID 20140301003702.1f9619cd@linux.lan.towertech.it
State Not Applicable
Headers show

Commit Message

Alessandro Zummo Feb. 28, 2014, 11:37 p.m. UTC
Hello,

  you're receiving this email because you were involved in the
 development of one or more RTC drivers.

  Recently it has been brought to my attention that there's
 a race condition in some drivers [1].

  If your drivers bails out after the rtc_device_register() call,
 it may trigger the condition.

  There are two things that drivers often do after rtc_device_register():

  a) register sysfs entries
  b) request irqs

  It seems that most drivers could still work correctly
 if those do not succeed.

  The proposed course of action is to modify the drivers in
 order to avoid bailing out (and notify the user where appropriate).

  Any other action that might trigger a bail out should be done
 before rtc_device_register.

  I've modified 22 of them in order to provide an example
 of what the fix might look like (patch attached).

  Julia Lawall has been kind enough to write a semantic file
 for coccinelle that quickly found the affected files [2].

  I'd appreciate if you can give a look to your driver and
 provide a patch if appropriate. If you're lucky I've already patched it
 and you just have to check if my work makes sense to you.

  Thanks for your cooperation.

[1]  https://lkml.org/lkml/2014/2/26/185
[2]

drivers/rtc/rtc-ab8500.c
drivers/rtc/rtc-as3722.c
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-da9055.c
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-jz4740.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max8907.c
drivers/rtc/rtc-max8997.c
drivers/rtc/rtc-mc13xxx.c
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-nuc900.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-palmas.c
drivers/rtc/rtc-pcap.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-pm8xxx.c
drivers/rtc/rtc-rp5c01.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-s5m.c
drivers/rtc/rtc-sirfsoc.c
drivers/rtc/rtc-stk17ta8.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-tegra.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-tps6586x.c
drivers/rtc/rtc-tps80031.c
drivers/rtc/rtc-twl.c
drivers/rtc/rtc-tx4939.c
drivers/rtc/rtc-vr41xx.c
drivers/rtc/rtc-vt8500.c
drivers/rtc/rtc-x1205.c

Comments

Alexander Shiyan March 1, 2014, 5:14 a.m. UTC | #1
Суббота,  1 марта 2014, 0:37 +01:00 от Alessandro Zummo <a.zummo@towertech.it>:
> 
>  Hello,
> 
>   you're receiving this email because you were involved in the
>  development of one or more RTC drivers.
> 
>   Recently it has been brought to my attention that there's
>  a race condition in some drivers [1].
> 
>   If your drivers bails out after the rtc_device_register() call,
>  it may trigger the condition.
> 
>   There are two things that drivers often do after rtc_device_register():
> 
>   a) register sysfs entries
>   b) request irqs
> 
>   It seems that most drivers could still work correctly
>  if those do not succeed.
> 
>   The proposed course of action is to modify the drivers in
>  order to avoid bailing out (and notify the user where appropriate).
> 
>   Any other action that might trigger a bail out should be done
>  before rtc_device_register.
> 
>   I've modified 22 of them in order to provide an example
>  of what the fix might look like (patch attached).
> 
>   Julia Lawall has been kind enough to write a semantic file
>  for coccinelle that quickly found the affected files [2].
> 
>   I'd appreciate if you can give a look to your driver and
>  provide a patch if appropriate. If you're lucky I've already patched it
>  and you just have to check if my work makes sense to you.
> 
>   Thanks for your cooperation.

The patch for rtc-mc13xxx looks incorrect.
Interrupts are released regardless of the result of devm_rtc_device_register().

In any case linux-next branch already contains a slightly modified version of the driver.
https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/rtc/rtc-mc13xxx.c?id=06ad9825e7048f4385b77784286bf9595439e1bc

---
Alessandro Zummo March 1, 2014, 11:28 a.m. UTC | #2
On Sat, 01 Mar 2014 09:14:45 +0400
Alexander Shiyan <shc_work@mail.ru> wrote:

> The patch for rtc-mc13xxx looks incorrect.
> Interrupts are released regardless of the result of devm_rtc_device_register().

 Will drop it, thanks. Got confused by those goto labels within an if.
 
> In any case linux-next branch already contains a slightly modified version of the driver.
> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/rtc/rtc-mc13xxx.c?id=06ad9825e7048f4385b77784286bf9595439e1bc

 Can you make sure this new version behaves correctly wrto
 the race condition??
Atsushi Nemoto March 1, 2014, 12:52 p.m. UTC | #3
On Sat, 1 Mar 2014 00:37:02 +0100, Alessandro Zummo <a.zummo@towertech.it> wrote:
>   I've modified 22 of them in order to provide an example
>  of what the fix might look like (patch attached).
> 
>   Julia Lawall has been kind enough to write a semantic file
>  for coccinelle that quickly found the affected files [2].
> 
>   I'd appreciate if you can give a look to your driver and
>  provide a patch if appropriate. If you're lucky I've already patched it
>  and you just have to check if my work makes sense to you.

Thank you for example.

> @@ -278,7 +278,6 @@ static struct bin_attribute ds1553_nvram_attr = {
>  
>  static int ds1553_rtc_probe(struct platform_device *pdev)
>  {
> -	struct rtc_device *rtc;
>  	struct resource *res;
>  	unsigned int cen, sec;
>  	struct rtc_plat_data *pdata;
> @@ -321,15 +320,17 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
> +	pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
>  				  &ds1553_rtc_ops, THIS_MODULE);
> -	if (IS_ERR(rtc))
> -		return PTR_ERR(rtc);
> -	pdata->rtc = rtc;
> +	if (IS_ERR(pdata->rtc))
> +		return PTR_ERR(pdata->rtc);

Please do not do this cleanup.  With this cleanup, pdata->rtc will be
an errno value instead of NULL just after devm_rtc_device_register
error.  This breaks "if (likely(pdata->rtc))" checking in interrupt
handler.

>  	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
> +	if (ret) {
> +		dev_err(&pdev->dev, "unable to create sysfs file: %s\n", ds1553_nvram_attr.attr.name);
> +	}
>  
> -	return ret;
> +	return 0;
>  }

This part looks good for me.

Same for rtc-ds1511.c.

---
Atsushi Nemoto
Alexander Shiyan March 1, 2014, 2:07 p.m. UTC | #4
Суббота,  1 марта 2014, 12:28 +01:00 от Alessandro Zummo <a.zummo@towertech.it>:
> On Sat, 01 Mar 2014 09:14:45 +0400
> Alexander Shiyan <shc_work@mail.ru> wrote:
> 
> > The patch for rtc-mc13xxx looks incorrect.
> > Interrupts are released regardless of the result of devm_rtc_device_register().
> 
>  Will drop it, thanks. Got confused by those goto labels within an if.
>  
> > In any case linux-next branch already contains a slightly modified version of the driver.
> > https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/rtc/rtc-mc13xxx.c?id=06ad9825e7048f4385b77784286bf9595439e1bc
> 
>  Can you make sure this new version behaves correctly wrto
>  the race condition??

I am sure that I do not fully understand the race condition problem.
From my perspective, everything looks correct.

---
Alessandro Zummo March 1, 2014, 2:10 p.m. UTC | #5
On Sat, 01 Mar 2014 21:52:34 +0900 (JST)
Atsushi Nemoto <anemo@mba.ocn.ne.jp> wrote:

> Please do not do this cleanup.  With this cleanup, pdata->rtc will be
> an errno value instead of NULL just after devm_rtc_device_register
> error.  This breaks "if (likely(pdata->rtc))" checking in interrupt
> handler.

 Ok. Will the handler be called even if the rtc device is not registered?
Alessandro Zummo March 1, 2014, 2:27 p.m. UTC | #6
On Sat, 01 Mar 2014 18:07:51 +0400
Alexander Shiyan <shc_work@mail.ru> wrote:

> >  Can you make sure this new version behaves correctly wrto
> >  the race condition?
> 
> I am sure that I do not fully understand the race condition problem.
> From my perspective, everything looks correct.

 Basically your driver should NOT fail after

  priv->rtc = devm_rtc_device_register()

 if you can work without IRQs, just return 0 at the end of the probe
 function
Atsushi Nemoto March 1, 2014, 2:36 p.m. UTC | #7
On Sat, 1 Mar 2014 15:10:52 +0100, Alessandro Zummo <a.zummo@towertech.it> wrote:
>  Ok. Will the handler be called even if the rtc device is not registered?

I guess so.  Since request_irq is called before rtc_device_register,
the handler might be called by alarm or something or interrupt from
other devices shareing the irq line.
Alexander Shiyan March 1, 2014, 2:40 p.m. UTC | #8
Суббота,  1 марта 2014, 15:27 +01:00 от Alessandro Zummo <a.zummo@towertech.it>:
> On Sat, 01 Mar 2014 18:07:51 +0400
> Alexander Shiyan <shc_work@mail.ru> wrote:
> 
> > >  Can you make sure this new version behaves correctly wrto
> > >  the race condition?
> > 
> > I am sure that I do not fully understand the race condition problem.
> > From my perspective, everything looks correct.
> 
>  Basically your driver should NOT fail after
> 
>   priv->rtc = devm_rtc_device_register()
> 
>  if you can work without IRQs, just return 0 at the end of the probe
>  function

Yeah, okay. In this case, the driver can operate without interrupts,
we only need to make dynamic assignment of alarm functions (read_alarm(),
set_alarm() and alarm_irq_enable()) if mc13xxx_irq_request_nounmask()
for the alarm IRQ success.
If it's not too important, I'll make a patch a bit later.

---
Alessandro Zummo March 1, 2014, 2:45 p.m. UTC | #9
On Sat, 01 Mar 2014 18:40:41 +0400
Alexander Shiyan <shc_work@mail.ru> wrote:

> >  if you can work without IRQs, just return 0 at the end of the probe
> >  function  
> 
> Yeah, okay. In this case, the driver can operate without interrupts,
> we only need to make dynamic assignment of alarm functions (read_alarm(),
> set_alarm() and alarm_irq_enable()) if mc13xxx_irq_request_nounmask()
> for the alarm IRQ success.
> If it's not too important, I'll make a patch a bit later.

 or you can request the irqs before the rtc_device_register call.

 no hurry, just drop me a note when you're done so I can keep track
 of the while process.

 thanks!
Alessandro Zummo March 1, 2014, 2:51 p.m. UTC | #10
On Sat, 01 Mar 2014 23:36:57 +0900 (JST)
Atsushi Nemoto <anemo@mba.ocn.ne.jp> wrote:

> I guess so.  Since request_irq is called before rtc_device_register,
> the handler might be called by alarm or something or interrupt from
> other devices shareing the irq line.

 Ok, then it would be better to move the request_irq after the registration
 call. I have no access to systems with the two rtc you can working
 on, any chance you can make such a mod?
Alexander Shiyan March 1, 2014, 2:56 p.m. UTC | #11
Суббота,  1 марта 2014, 15:45 +01:00 от Alessandro Zummo <a.zummo@towertech.it>:
> On Sat, 01 Mar 2014 18:40:41 +0400
> Alexander Shiyan <shc_work@mail.ru> wrote:
> 
> > >  if you can work without IRQs, just return 0 at the end of the probe
> > >  function  
> > 
> > Yeah, okay. In this case, the driver can operate without interrupts,
> > we only need to make dynamic assignment of alarm functions (read_alarm(),
> > set_alarm() and alarm_irq_enable()) if mc13xxx_irq_request_nounmask()
> > for the alarm IRQ success.
> > If it's not too important, I'll make a patch a bit later.
> 
>  or you can request the irqs before the rtc_device_register call.

This was the reason why I moved IRQ initialization interrupt after RTC registration.
This can be redone back if we have the ability to add !IS_ERR_OR_NULL(rtc)
check in the begin of rtc_update_irq().

>  no hurry, just drop me a note when you're done so I can keep track
>  of the while process.

OK.

---
Alessandro Zummo March 1, 2014, 3:05 p.m. UTC | #12
On Sat, 01 Mar 2014 18:56:29 +0400
Alexander Shiyan <shc_work@mail.ru> wrote:

> This was the reason why I moved IRQ initialization interrupt after RTC registration.
> This can be redone back if we have the ability to add !IS_ERR_OR_NULL(rtc)
> check in the begin of rtc_update_irq().

 good catch, ty.

void rtc_update_irq(struct rtc_device *rtc,
                unsigned long num, unsigned long events)
{
        if (unlikely(IS_ERR_OR_NULL(rtc)))
                return;

        pm_stay_awake(rtc->dev.parent);
        schedule_work(&rtc->irqwork);
}
Alexander Shiyan March 1, 2014, 3:14 p.m. UTC | #13
Суббота,  1 марта 2014, 16:05 +01:00 от Alessandro Zummo <a.zummo@towertech.it>:
> On Sat, 01 Mar 2014 18:56:29 +0400
> Alexander Shiyan <shc_work@mail.ru> wrote:
> 
> > This was the reason why I moved IRQ initialization interrupt after RTC registration.
> > This can be redone back if we have the ability to add !IS_ERR_OR_NULL(rtc)
> > check in the begin of rtc_update_irq().
> 
>  good catch, ty.
> 
> void rtc_update_irq(struct rtc_device *rtc,
>                 unsigned long num, unsigned long events)
> {
>         if (unlikely(IS_ERR_OR_NULL(rtc)))
>                 return;
> 
>         pm_stay_awake(rtc->dev.parent);
>         schedule_work(&rtc->irqwork);
> }

Yes, that's very good.
Can You send this into mainline and make signed tag?
It can also eliminate such bugs in other drivers.

---
Atsushi Nemoto March 4, 2014, 3:55 p.m. UTC | #14
On Sat, 1 Mar 2014 15:51:53 +0100, Alessandro Zummo <a.zummo@towertech.it> wrote:
>  Ok, then it would be better to move the request_irq after the registration
>  call. I have no access to systems with the two rtc you can working
>  on, any chance you can make such a mod?

I'm bit uncomfortable if rtc_device_register() was called before all
setup (including request_irq) have completed.

Now your "rtc: verify a critical argument to rtc_update_irq() before
using it" patch is available, I'm happy with your first example patch.

---
Atsushi Nemoto
Alessandro Zummo March 4, 2014, 5:55 p.m. UTC | #15
On Wed, 05 Mar 2014 00:55:38 +0900 (JST)
Atsushi Nemoto <anemo@mba.ocn.ne.jp> wrote:

> Now your "rtc: verify a critical argument to rtc_update_irq() before
> using it" patch is available, I'm happy with your first example patch.

 Ack, ty.
Mike Frysinger May 8, 2014, 2:16 a.m. UTC | #16
On Fri, Feb 28, 2014 at 6:37 PM, Alessandro Zummo wrote:
>   you're receiving this email because you were involved in the
>  development of one or more RTC drivers.
>
>   Recently it has been brought to my attention that there's
>  a race condition in some drivers [1].
>
>   If your drivers bails out after the rtc_device_register() call,
>  it may trigger the condition.
>
>   There are two things that drivers often do after rtc_device_register():
>
>   a) register sysfs entries
>   b) request irqs
>
>   It seems that most drivers could still work correctly
>  if those do not succeed.

the Blackfin RTC can't provide alarms and such sanely w/out the IRQ.
it could provide set/get of the time, but i'm not sure that's even
desirable.  if something else has requested the RTC IRQ, it kind of
means something else is using that hardware, so it kind of should
bail.  but the likelyhood of that is probably remote to the point
where it can be ignored.

>   The proposed course of action is to modify the drivers in
>  order to avoid bailing out (and notify the user where appropriate).
>
>   Any other action that might trigger a bail out should be done
>  before rtc_device_register.
>
>   I've modified 22 of them in order to provide an example
>  of what the fix might look like (patch attached).

full of dos ^M gremlins ;)
-mike
diff mbox

Patch

diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 727e2f5..3fabe3c 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -485,23 +485,21 @@  static int ab8500_rtc_probe(struct platform_device *pdev)
 				(struct rtc_class_ops *)platid->driver_data,
 				THIS_MODULE);
 	if (IS_ERR(rtc)) {
-		dev_err(&pdev->dev, "Registration failed\n");
-		err = PTR_ERR(rtc);
-		return err;
+		return PTR_ERR(rtc);
 	}
 
 	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
 			rtc_alarm_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
 			"ab8500-rtc", rtc);
-	if (err < 0)
-		return err;
+	if (err) {
+		dev_err(&pdev->dev, "unable to request IRQ, alarm not available\n");
+	}
 
 	platform_set_drvdata(pdev, rtc);
 
 	err = ab8500_sysfs_rtc_register(&pdev->dev);
 	if (err) {
 		dev_err(&pdev->dev, "sysfs RTC failed to register\n");
-		return err;
 	}
 
 	return 0;
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c
index 48cb2ac3..04a2157 100644
--- a/drivers/rtc/rtc-da9055.c
+++ b/drivers/rtc/rtc-da9055.c
@@ -283,11 +283,11 @@  static int da9055_rtc_probe(struct platform_device *pdev)
 
 	ret = da9055_rtc_device_init(rtc->da9055, pdata);
 	if (ret < 0)
-		goto err_rtc;
+		return ret;
 
 	ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y);
 	if (ret < 0)
-		goto err_rtc;
+		return ret;
 
 	if (ret & DA9055_RTC_ALM_EN)
 		rtc->alarm_enable = 1;
@@ -297,8 +297,7 @@  static int da9055_rtc_probe(struct platform_device *pdev)
 	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 					&da9055_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
-		ret = PTR_ERR(rtc->rtc);
-		goto err_rtc;
+		return PTR_ERR(rtc->rtc);
 	}
 
 	alm_irq = platform_get_irq_byname(pdev, "ALM");
@@ -310,9 +309,7 @@  static int da9055_rtc_probe(struct platform_device *pdev)
 	if (ret != 0)
 		dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret);
 
-err_rtc:
-	return ret;
-
+	return 0;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 2dd586a..129add77 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -756,19 +756,17 @@  static int ds1305_probe(struct spi_device *spi)
 		status = devm_request_irq(&spi->dev, spi->irq, ds1305_irq,
 				0, dev_name(&ds1305->rtc->dev), ds1305);
 		if (status < 0) {
-			dev_dbg(&spi->dev, "request_irq %d --> %d\n",
+			dev_err(&spi->dev, "request_irq %d --> %d\n",
 					spi->irq, status);
-			return status;
+		} else {
+			device_set_wakeup_capable(&spi->dev, 1);
 		}
-
-		device_set_wakeup_capable(&spi->dev, 1);
 	}
 
 	/* export NVRAM */
 	status = sysfs_create_bin_file(&spi->dev.kobj, &nvram);
 	if (status < 0) {
-		dev_dbg(&spi->dev, "register nvram --> %d\n", status);
-		return status;
+		dev_err(&spi->dev, "register nvram --> %d\n", status);
 	}
 
 	return 0;
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 4e75345..2c65081 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -930,52 +930,54 @@  read_rtc:
 	ds1307->rtc = devm_rtc_device_register(&client->dev, client->name,
 				&ds13xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(ds1307->rtc)) {
-		err = PTR_ERR(ds1307->rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
-		goto exit;
+		return PTR_ERR(ds1307->rtc);
 	}
 
 	if (want_irq) {
 		err = request_irq(client->irq, ds1307_irq, IRQF_SHARED,
 			  ds1307->rtc->name, client);
 		if (err) {
-			dev_err(&client->dev,
-				"unable to request IRQ!\n");
-			goto exit;
-		}
+			client->irq = 0;
+			dev_err(&client->dev, "unable to request IRQ!\n");
+		} else {
 
-		device_set_wakeup_capable(&client->dev, 1);
-		set_bit(HAS_ALARM, &ds1307->flags);
-		dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+			device_set_wakeup_capable(&client->dev, 1);
+			set_bit(HAS_ALARM, &ds1307->flags);
+			dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+		}
 	}
 
 	if (chip->nvram_size) {
+
 		ds1307->nvram = devm_kzalloc(&client->dev,
 					sizeof(struct bin_attribute),
 					GFP_KERNEL);
 		if (!ds1307->nvram) {
-			err = -ENOMEM;
-			goto err_irq;
+			dev_err(&client->dev, "cannot allocate memory for nvram sysfs\n");
+		} else {
+
+			ds1307->nvram->attr.name = "nvram";
+			ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
+
+			sysfs_bin_attr_init(ds1307->nvram);
+
+			ds1307->nvram->read = ds1307_nvram_read;
+			ds1307->nvram->write = ds1307_nvram_write;
+			ds1307->nvram->size = chip->nvram_size;
+			ds1307->nvram_offset = chip->nvram_offset;
+
+			err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram);
+			if (err) {
+				dev_err(&client->dev, "unable to create sysfs file: %s\n", ds1307->nvram->attr.name);
+			} else {
+				set_bit(HAS_NVRAM, &ds1307->flags);
+				dev_info(&client->dev, "%zu bytes nvram\n", ds1307->nvram->size);
+			}
 		}
-		ds1307->nvram->attr.name = "nvram";
-		ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
-		sysfs_bin_attr_init(ds1307->nvram);
-		ds1307->nvram->read = ds1307_nvram_read;
-		ds1307->nvram->write = ds1307_nvram_write;
-		ds1307->nvram->size = chip->nvram_size;
-		ds1307->nvram_offset = chip->nvram_offset;
-		err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram);
-		if (err)
-			goto err_irq;
-		set_bit(HAS_NVRAM, &ds1307->flags);
-		dev_info(&client->dev, "%zu bytes nvram\n", ds1307->nvram->size);
 	}
 
 	return 0;
 
-err_irq:
-	free_irq(client->irq, client);
 exit:
 	return err;
 }
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index bc7b4fc..d1c3120 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -473,7 +473,6 @@  static struct bin_attribute ds1511_nvram_attr = {
 
 static int ds1511_rtc_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc;
 	struct resource *res;
 	struct rtc_plat_data *pdata;
 	int ret = 0;
@@ -526,15 +525,17 @@  static int ds1511_rtc_probe(struct platform_device *pdev)
 		}
 	}
 
-	rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1511_rtc_ops,
+	pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1511_rtc_ops,
 					THIS_MODULE);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
-	pdata->rtc = rtc;
+	if (IS_ERR(pdata->rtc))
+		return PTR_ERR(pdata->rtc);
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", ds1511_nvram_attr.attr.name);
+	}
 
-	return ret;
+	return 0;
 }
 
 static int ds1511_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index fd31571..c4a87f6 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -278,7 +278,6 @@  static struct bin_attribute ds1553_nvram_attr = {
 
 static int ds1553_rtc_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc;
 	struct resource *res;
 	unsigned int cen, sec;
 	struct rtc_plat_data *pdata;
@@ -321,15 +320,17 @@  static int ds1553_rtc_probe(struct platform_device *pdev)
 		}
 	}
 
-	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+	pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &ds1553_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
-	pdata->rtc = rtc;
+	if (IS_ERR(pdata->rtc))
+		return PTR_ERR(pdata->rtc);
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to create sysfs file: %s\n", ds1553_nvram_attr.attr.name);
+	}
 
-	return ret;
+	return 0;
 }
 
 static int ds1553_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 18e2d84..927d119 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -177,8 +177,9 @@  static int ds1672_probe(struct i2c_client *client,
 
 	/* read control register */
 	err = ds1672_get_control(client, &control);
-	if (err)
-		goto exit_devreg;
+	if (err) {
+		dev_warn(&client->dev, "Unable to read the control register\n");
+	}
 
 	if (control & DS1672_REG_CONTROL_EOSC)
 		dev_warn(&client->dev, "Oscillator not enabled. "
@@ -186,13 +187,11 @@  static int ds1672_probe(struct i2c_client *client,
 
 	/* Register sysfs hooks */
 	err = device_create_file(&client->dev, &dev_attr_control);
-	if (err)
-		goto exit_devreg;
+	if (err) {
+		dev_err(&client->dev, "Unable to create sysfs entry: %s\n", dev_attr_control.attr.name);
+	}
 
 	return 0;
-
- exit_devreg:
-	return err;
 }
 
 static struct i2c_device_id ds1672_id[] = {
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 5a1f3b2..99f00f6 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -204,8 +204,11 @@  static int ds1742_rtc_probe(struct platform_device *pdev)
 		return PTR_ERR(rtc);
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", pdata->nvram_attr.attr.name);
+	}
 
-	return ret;
+	return 0;
 }
 
 static int ds1742_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index b83bb5a5..15497c5 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -414,7 +414,6 @@  static int ds3232_probe(struct i2c_client *client,
 	ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
 					  &ds3232_rtc_ops, THIS_MODULE);
 	if (IS_ERR(ds3232->rtc)) {
-		dev_err(&client->dev, "unable to register the class device\n");
 		return PTR_ERR(ds3232->rtc);
 	}
 
@@ -423,7 +422,6 @@  static int ds3232_probe(struct i2c_client *client,
 				 "ds3232", client);
 		if (ret) {
 			dev_err(&client->dev, "unable to request IRQ\n");
-			return ret;
 		}
 	}
 
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 5e4f5dc..843fb29 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -153,8 +153,9 @@  static int ep93xx_rtc_probe(struct platform_device *pdev)
 	}
 
 	err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
-	if (err)
-		goto exit;
+	if (err) {
+		dev_err(&pdev->dev, "Unable to create sysfs entries\n");
+	}
 
 	return 0;
 
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index c3c549d..db35428 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -642,6 +642,17 @@  isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	dev_info(&client->dev,
 		 "chip found, driver version " DRV_VERSION "\n");
 
+	rc = isl1208_i2c_get_sr(client);
+	if (rc < 0) {
+		dev_err(&client->dev, "reading status failed\n");
+		return rc;
+	}
+
+	if (rc & ISL1208_REG_SR_RTCF)
+		dev_warn(&client->dev, "rtc power failure detected, "
+			 "please set clock.\n");
+
+
 	if (client->irq > 0) {
 		rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
 					       isl1208_rtc_interrupt,
@@ -667,19 +678,10 @@  isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	i2c_set_clientdata(client, rtc);
 
-	rc = isl1208_i2c_get_sr(client);
-	if (rc < 0) {
-		dev_err(&client->dev, "reading status failed\n");
-		return rc;
-	}
-
-	if (rc & ISL1208_REG_SR_RTCF)
-		dev_warn(&client->dev, "rtc power failure detected, "
-			 "please set clock.\n");
-
 	rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
-	if (rc)
-		return rc;
+	if (rc) {
+		dev_err(&client->dev, "Unable to create sysfs entries\n");
+	}
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
index 1b126d2..819f008 100644
--- a/drivers/rtc/rtc-jz4740.c
+++ b/drivers/rtc/rtc-jz4740.c
@@ -247,6 +247,16 @@  static int jz4740_rtc_probe(struct platform_device *pdev)
 		return -EBUSY;
 	}
 
+	scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
+	if (scratchpad != 0x12345678) {
+		ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
+		ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
+		if (ret) {
+			dev_err(&pdev->dev, "Could not write write to RTC registers\n");
+			return ret;
+		}
+	}
+
 	spin_lock_init(&rtc->lock);
 
 	platform_set_drvdata(pdev, rtc);
@@ -256,26 +266,13 @@  static int jz4740_rtc_probe(struct platform_device *pdev)
 	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 					&jz4740_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
-		ret = PTR_ERR(rtc->rtc);
-		dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
-		return ret;
+		return PTR_ERR(rtc->rtc);
 	}
 
 	ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0,
 				pdev->name, rtc);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
-		return ret;
-	}
-
-	scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
-	if (scratchpad != 0x12345678) {
-		ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
-		ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
-		if (ret) {
-			dev_err(&pdev->dev, "Could not write write to RTC registers\n");
-			return ret;
-		}
 	}
 
 	return 0;
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 77ea989..25ff1f6 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -355,22 +355,22 @@  static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
 					&mc13xxx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(priv->rtc)) {
 		ret = PTR_ERR(priv->rtc);
+	}
 
-		mc13xxx_lock(mc13xxx);
+	mc13xxx_lock(mc13xxx);
 
-		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
+	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
 err_alarm_irq_request:
 
-		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
+	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
 err_update_irq_request:
 
 err_reset_irq_status:
 
-		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
+	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 err_reset_irq_request:
 
-		mc13xxx_unlock(mc13xxx);
-	}
+	mc13xxx_unlock(mc13xxx);
 
 	return ret;
 }
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 99181fff..a830c42 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -376,7 +376,7 @@  static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
 	if (IS_ERR(ldata->rtc)) {
 		ret = PTR_ERR(ldata->rtc);
 		goto out_no_rtc;
-	}
+	}	
 
 	if (request_irq(adev->irq[0], pl031_interrupt,
 			vendor->irqflags, "rtc-pl031", ldata)) {
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index 03f8f75..3dfac16 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -454,8 +454,6 @@  static int pm8xxx_rtc_probe(struct platform_device *pdev)
 	rtc_dd->rtc = devm_rtc_device_register(&pdev->dev, "pm8xxx_rtc",
 				&pm8xxx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc_dd->rtc)) {
-		dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n",
-					__func__, PTR_ERR(rtc_dd->rtc));
 		return PTR_ERR(rtc_dd->rtc);
 	}
 
@@ -465,13 +463,10 @@  static int pm8xxx_rtc_probe(struct platform_device *pdev)
 				 "pm8xxx_rtc_alarm", rtc_dd);
 	if (rc < 0) {
 		dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc);
-		return rc;
 	}
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	dev_dbg(&pdev->dev, "Probe success !!\n");
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index ccf54f0..c5ca929 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -577,16 +577,14 @@  static int rs5c372_probe(struct i2c_client *client,
 			smbus_mode = 1;
 		else {
 			/* Still no good, give up */
-			err = -ENODEV;
-			goto exit;
+			return -ENODEV;
 		}
 	}
 
 	rs5c372 = devm_kzalloc(&client->dev, sizeof(struct rs5c372),
 				GFP_KERNEL);
 	if (!rs5c372) {
-		err = -ENOMEM;
-		goto exit;
+		return -ENOMEM;
 	}
 
 	rs5c372->client = client;
@@ -598,8 +596,8 @@  static int rs5c372_probe(struct i2c_client *client,
 	rs5c372->smbus = smbus_mode;
 
 	err = rs5c_get_regs(rs5c372);
-	if (err < 0)
-		goto exit;
+	if (err)
+		return err;
 
 	/* clock may be set for am/pm or 24 hr time */
 	switch (rs5c372->type) {
@@ -623,7 +621,7 @@  static int rs5c372_probe(struct i2c_client *client,
 		break;
 	default:
 		dev_err(&client->dev, "unknown RTC type\n");
-		goto exit;
+		return -ENODEV;
 	}
 
 	/* if the oscillator lost power and no other software (like
@@ -635,7 +633,7 @@  static int rs5c372_probe(struct i2c_client *client,
 	err = rs5c_oscillator_setup(rs5c372);
 	if (unlikely(err < 0)) {
 		dev_err(&client->dev, "setup error\n");
-		goto exit;
+		return err;
 	}
 
 	if (rs5c372_get_datetime(client, &tm) < 0)
@@ -660,18 +658,15 @@  static int rs5c372_probe(struct i2c_client *client,
 					&rs5c372_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rs5c372->rtc)) {
-		err = PTR_ERR(rs5c372->rtc);
-		goto exit;
+		return PTR_ERR(rs5c372->rtc);
 	}
 
 	err = rs5c_sysfs_register(&client->dev);
-	if (err)
-		goto exit;
+	if (err) {
+		dev_err(&client->dev, "Unable to create sysfs entries\n");
+	}
 
 	return 0;
-
-exit:
-	return err;
 }
 
 static int rs5c372_remove(struct i2c_client *client)
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 8fa23ea..dae9d1a 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -545,15 +545,13 @@  static int rx8025_probe(struct i2c_client *client,
 				     | I2C_FUNC_SMBUS_I2C_BLOCK)) {
 		dev_err(&adapter->dev,
 			"doesn't support required functionality\n");
-		err = -EIO;
-		goto errout;
+		return -EIO;
 	}
 
 	rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
 	if (!rx8025) {
 		dev_err(&adapter->dev, "failed to alloc memory\n");
-		err = -ENOMEM;
-		goto errout;
+		return -ENOMEM;
 	}
 
 	rx8025->client = client;
@@ -562,7 +560,7 @@  static int rx8025_probe(struct i2c_client *client,
 
 	err = rx8025_init_client(client, &need_reset);
 	if (err)
-		goto errout;
+		return err;
 
 	if (need_reset) {
 		struct rtc_time tm;
@@ -575,9 +573,7 @@  static int rx8025_probe(struct i2c_client *client,
 	rx8025->rtc = devm_rtc_device_register(&client->dev, client->name,
 					  &rx8025_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rx8025->rtc)) {
-		err = PTR_ERR(rx8025->rtc);
-		dev_err(&client->dev, "unable to register the class device\n");
-		goto errout;
+		return PTR_ERR(rx8025->rtc);
 	}
 
 	if (client->irq > 0) {
@@ -585,8 +581,8 @@  static int rx8025_probe(struct i2c_client *client,
 		err = request_irq(client->irq, rx8025_irq,
 				  0, "rx8025", client);
 		if (err) {
-			dev_err(&client->dev, "unable to request IRQ\n");
-			goto errout;
+			client->irq = 0;
+			dev_err(&client->dev, "Unable to request IRQ\n");
 		}
 	}
 
@@ -594,18 +590,11 @@  static int rx8025_probe(struct i2c_client *client,
 	rx8025->rtc->max_user_freq = 1;
 
 	err = rx8025_sysfs_register(&client->dev);
-	if (err)
-		goto errout_irq;
+	if (err) {
+		dev_err(&client->dev, "Unable to create sysfs entries\n");
+	}
 
 	return 0;
-
-errout_irq:
-	if (client->irq > 0)
-		free_irq(client->irq, client);
-
-errout:
-	dev_err(&adapter->dev, "probing for rx8025 failed\n");
-	return err;
 }
 
 static int rx8025_remove(struct i2c_client *client)
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c
index 3eb3642..a4bab3d 100644
--- a/drivers/rtc/rtc-sirfsoc.c
+++ b/drivers/rtc/rtc-sirfsoc.c
@@ -293,9 +293,7 @@  static int sirfsoc_rtc_probe(struct platform_device *pdev)
 	rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 			&sirfsoc_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtcdrv->rtc)) {
-		err = PTR_ERR(rtcdrv->rtc);
-		dev_err(&pdev->dev, "can't register RTC device\n");
-		return err;
+		return PTR_ERR(rtcdrv->rtc);
 	}
 
 	/* 0x3 -> RTC_CLK */
@@ -322,7 +320,6 @@  static int sirfsoc_rtc_probe(struct platform_device *pdev)
 			rtcdrv);
 	if (err) {
 		dev_err(&pdev->dev, "Unable to register for the SiRF SOC RTC IRQ\n");
-		return err;
 	}
 
 	return 0;
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index 7746e65..b9b4d00 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -104,20 +104,17 @@  static int test_probe(struct platform_device *plat_dev)
 	rtc = devm_rtc_device_register(&plat_dev->dev, "test",
 				&test_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
-		err = PTR_ERR(rtc);
-		return err;
+		return PTR_ERR(rtc);
 	}
 
 	err = device_create_file(&plat_dev->dev, &dev_attr_irq);
-	if (err)
-		goto err;
+	if (err) {
+		dev_err(&plat_dev->dev, "Unable to create sysfs entry: %s\n", dev_attr_irq.attr.name);
+	}
 
 	platform_set_drvdata(plat_dev, rtc);
 
 	return 0;
-
-err:
-	return err;
 }
 
 static int test_remove(struct platform_device *plat_dev)
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 1915464..0a37c6c 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -529,8 +529,6 @@  static int twl_rtc_probe(struct platform_device *pdev)
 	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 					&twl_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
-		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
-			PTR_ERR(rtc));
 		return PTR_ERR(rtc);
 	}
 
@@ -540,7 +538,6 @@  static int twl_rtc_probe(struct platform_device *pdev)
 					dev_name(&rtc->dev), rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ is not free.\n");
-		return ret;
 	}
 
 	platform_set_drvdata(pdev, rtc);
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 365dc65..e0ec42c 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -659,8 +659,9 @@  static int x1205_probe(struct i2c_client *client,
 	}
 
 	err = x1205_sysfs_register(&client->dev);
-	if (err)
-		return err;
+	if (err) {
+		dev_err(&client->dev, "Unable to create sysfs entries\n");
+	}
 
 	return 0;
 }