diff options
author | Raghavendra Ganiga <ravi23ganiga@gmail.com> | 2014-06-06 17:36:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-06 19:08:08 -0400 |
commit | 10b06b87b77e9fcd7d1282f8cacf9736fb5143b3 (patch) | |
tree | dce63ae7ddb4aa4439c64e5c82f6403ba082d39d /drivers/rtc | |
parent | 0dd449b1626c3db6b40fc2c7685bf9b0ac79ce00 (diff) |
drivers/rtc/rtc-ds1343.c: fix potential race condition
Avoid the potential race condition by avoiding bailing out of driver in
probe after registering with rtc subsystem
Also the set_alarm , read_alarm and alarm_irq_enable returns error if irq
registration fails in probe.
Also the sysfs will not create entry for alarm if irq registration fails
in probe.
Signed-off-by: Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>
Acked-by: 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')
-rw-r--r-- | drivers/rtc/rtc-ds1343.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 8ccc75021175..c3719189dd96 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c | |||
@@ -80,6 +80,7 @@ struct ds1343_priv { | |||
80 | struct regmap *map; | 80 | struct regmap *map; |
81 | struct mutex mutex; | 81 | struct mutex mutex; |
82 | unsigned int irqen; | 82 | unsigned int irqen; |
83 | int irq; | ||
83 | int alarm_sec; | 84 | int alarm_sec; |
84 | int alarm_min; | 85 | int alarm_min; |
85 | int alarm_hour; | 86 | int alarm_hour; |
@@ -262,28 +263,32 @@ static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL); | |||
262 | 263 | ||
263 | static int ds1343_sysfs_register(struct device *dev) | 264 | static int ds1343_sysfs_register(struct device *dev) |
264 | { | 265 | { |
266 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
265 | int err; | 267 | int err; |
266 | 268 | ||
267 | err = device_create_file(dev, &dev_attr_glitch_filter); | 269 | err = device_create_file(dev, &dev_attr_glitch_filter); |
268 | if (err) | 270 | if (err) |
269 | return err; | 271 | return err; |
270 | 272 | ||
271 | err = device_create_file(dev, &dev_attr_alarm_status); | 273 | err = device_create_file(dev, &dev_attr_trickle_charger); |
272 | if (err) | 274 | if (err) |
273 | goto error1; | 275 | goto error1; |
274 | 276 | ||
277 | if (priv->irq <= 0) | ||
278 | return err; | ||
279 | |||
275 | err = device_create_file(dev, &dev_attr_alarm_mode); | 280 | err = device_create_file(dev, &dev_attr_alarm_mode); |
276 | if (err) | 281 | if (err) |
277 | goto error2; | 282 | goto error2; |
278 | 283 | ||
279 | err = device_create_file(dev, &dev_attr_trickle_charger); | 284 | err = device_create_file(dev, &dev_attr_alarm_status); |
280 | if (!err) | 285 | if (!err) |
281 | return err; | 286 | return err; |
282 | 287 | ||
283 | device_remove_file(dev, &dev_attr_alarm_mode); | 288 | device_remove_file(dev, &dev_attr_alarm_mode); |
284 | 289 | ||
285 | error2: | 290 | error2: |
286 | device_remove_file(dev, &dev_attr_alarm_status); | 291 | device_remove_file(dev, &dev_attr_trickle_charger); |
287 | 292 | ||
288 | error1: | 293 | error1: |
289 | device_remove_file(dev, &dev_attr_glitch_filter); | 294 | device_remove_file(dev, &dev_attr_glitch_filter); |
@@ -293,10 +298,16 @@ error1: | |||
293 | 298 | ||
294 | static void ds1343_sysfs_unregister(struct device *dev) | 299 | static void ds1343_sysfs_unregister(struct device *dev) |
295 | { | 300 | { |
301 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
302 | |||
296 | device_remove_file(dev, &dev_attr_glitch_filter); | 303 | device_remove_file(dev, &dev_attr_glitch_filter); |
304 | device_remove_file(dev, &dev_attr_trickle_charger); | ||
305 | |||
306 | if (priv->irq <= 0) | ||
307 | return; | ||
308 | |||
297 | device_remove_file(dev, &dev_attr_alarm_status); | 309 | device_remove_file(dev, &dev_attr_alarm_status); |
298 | device_remove_file(dev, &dev_attr_alarm_mode); | 310 | device_remove_file(dev, &dev_attr_alarm_mode); |
299 | device_remove_file(dev, &dev_attr_trickle_charger); | ||
300 | } | 311 | } |
301 | 312 | ||
302 | static int ds1343_read_time(struct device *dev, struct rtc_time *dt) | 313 | static int ds1343_read_time(struct device *dev, struct rtc_time *dt) |
@@ -415,11 +426,10 @@ static int ds1343_update_alarm(struct device *dev) | |||
415 | static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 426 | static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
416 | { | 427 | { |
417 | struct ds1343_priv *priv = dev_get_drvdata(dev); | 428 | struct ds1343_priv *priv = dev_get_drvdata(dev); |
418 | struct spi_device *spi = priv->spi; | ||
419 | int res = 0; | 429 | int res = 0; |
420 | unsigned int stat; | 430 | unsigned int stat; |
421 | 431 | ||
422 | if (spi->irq <= 0) | 432 | if (priv->irq <= 0) |
423 | return -EINVAL; | 433 | return -EINVAL; |
424 | 434 | ||
425 | mutex_lock(&priv->mutex); | 435 | mutex_lock(&priv->mutex); |
@@ -450,10 +460,9 @@ out: | |||
450 | static int ds1343_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 460 | static int ds1343_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
451 | { | 461 | { |
452 | struct ds1343_priv *priv = dev_get_drvdata(dev); | 462 | struct ds1343_priv *priv = dev_get_drvdata(dev); |
453 | struct spi_device *spi = priv->spi; | ||
454 | int res = 0; | 463 | int res = 0; |
455 | 464 | ||
456 | if (spi->irq <= 0) | 465 | if (priv->irq <= 0) |
457 | return -EINVAL; | 466 | return -EINVAL; |
458 | 467 | ||
459 | mutex_lock(&priv->mutex); | 468 | mutex_lock(&priv->mutex); |
@@ -476,10 +485,9 @@ static int ds1343_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
476 | static int ds1343_alarm_irq_enable(struct device *dev, unsigned int enabled) | 485 | static int ds1343_alarm_irq_enable(struct device *dev, unsigned int enabled) |
477 | { | 486 | { |
478 | struct ds1343_priv *priv = dev_get_drvdata(dev); | 487 | struct ds1343_priv *priv = dev_get_drvdata(dev); |
479 | struct spi_device *spi = priv->spi; | ||
480 | int res = 0; | 488 | int res = 0; |
481 | 489 | ||
482 | if (spi->irq <= 0) | 490 | if (priv->irq <= 0) |
483 | return -EINVAL; | 491 | return -EINVAL; |
484 | 492 | ||
485 | mutex_lock(&priv->mutex); | 493 | mutex_lock(&priv->mutex); |
@@ -593,18 +601,20 @@ static int ds1343_probe(struct spi_device *spi) | |||
593 | return PTR_ERR(priv->rtc); | 601 | return PTR_ERR(priv->rtc); |
594 | } | 602 | } |
595 | 603 | ||
596 | if (spi->irq >= 0) { | 604 | priv->irq = spi->irq; |
605 | |||
606 | if (priv->irq >= 0) { | ||
597 | res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, | 607 | res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, |
598 | ds1343_thread, | 608 | ds1343_thread, |
599 | IRQF_NO_SUSPEND | IRQF_ONESHOT, | 609 | IRQF_NO_SUSPEND | IRQF_ONESHOT, |
600 | "ds1343", priv); | 610 | "ds1343", priv); |
601 | if (res) { | 611 | if (res) { |
612 | priv->irq = -1; | ||
602 | dev_err(&spi->dev, | 613 | dev_err(&spi->dev, |
603 | "unable to request irq for rtc ds1343\n"); | 614 | "unable to request irq for rtc ds1343\n"); |
604 | return res; | 615 | } else { |
616 | device_set_wakeup_capable(&spi->dev, 1); | ||
605 | } | 617 | } |
606 | |||
607 | device_set_wakeup_capable(&spi->dev, 1); | ||
608 | } | 618 | } |
609 | 619 | ||
610 | res = ds1343_sysfs_register(&spi->dev); | 620 | res = ds1343_sysfs_register(&spi->dev); |