Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drivers/rtc/rtc-s3c.c: allow multiple open / allow no-ioctl-open'ed rtc to have irq.

The previous rtc-s3c had two issues related with its IRQ.

1. Users cannot open rtc multiple times because an open operation
calls request_irq on the same IRQ. (e.g., two user processes wants to
open and read RTC time from rtc-s3c at the same time)

2. If alarm is set and no one has the rtc opened with filesystem
(either the alarm is set by kernel/boot-loader or user set an alarm and
closed rtc dev file), the pending bit is not cleared and no further
interrupt is invoked. When the alarm is used by the system itself such
as a resume from suspend-to-RAM or other Low-power modes/idle, this is
a critical issue.

This patch mitigates these issues by calling request_irq at probe and
free_irq at remove.

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

MyungJoo Ham and committed by
Linus Torvalds
62d17601 4e8896cd

+25 -42
+25 -42
drivers/rtc/rtc-s3c.c
··· 319 319 return 0; 320 320 } 321 321 322 - static int s3c_rtc_open(struct device *dev) 323 - { 324 - struct platform_device *pdev = to_platform_device(dev); 325 - struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 326 - int ret; 327 - 328 - ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, 329 - IRQF_DISABLED, "s3c2410-rtc alarm", rtc_dev); 330 - 331 - if (ret) { 332 - dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); 333 - return ret; 334 - } 335 - 336 - ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, 337 - IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev); 338 - 339 - if (ret) { 340 - dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); 341 - goto tick_err; 342 - } 343 - 344 - return ret; 345 - 346 - tick_err: 347 - free_irq(s3c_rtc_alarmno, rtc_dev); 348 - return ret; 349 - } 350 - 351 - static void s3c_rtc_release(struct device *dev) 352 - { 353 - struct platform_device *pdev = to_platform_device(dev); 354 - struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 355 - 356 - /* do not clear AIE here, it may be needed for wake */ 357 - 358 - free_irq(s3c_rtc_alarmno, rtc_dev); 359 - free_irq(s3c_rtc_tickno, rtc_dev); 360 - } 361 - 362 322 static const struct rtc_class_ops s3c_rtcops = { 363 - .open = s3c_rtc_open, 364 - .release = s3c_rtc_release, 365 323 .read_time = s3c_rtc_gettime, 366 324 .set_time = s3c_rtc_settime, 367 325 .read_alarm = s3c_rtc_getalarm, ··· 382 424 static int __devexit s3c_rtc_remove(struct platform_device *dev) 383 425 { 384 426 struct rtc_device *rtc = platform_get_drvdata(dev); 427 + 428 + free_irq(s3c_rtc_alarmno, rtc); 429 + free_irq(s3c_rtc_tickno, rtc); 385 430 386 431 platform_set_drvdata(dev, NULL); 387 432 rtc_device_unregister(rtc); ··· 509 548 510 549 s3c_rtc_setfreq(&pdev->dev, 1); 511 550 551 + ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, 552 + IRQF_DISABLED, "s3c2410-rtc alarm", rtc); 553 + if (ret) { 554 + dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); 555 + goto err_alarm_irq; 556 + } 557 + 558 + ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, 559 + IRQF_DISABLED, "s3c2410-rtc tick", rtc); 560 + if (ret) { 561 + dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); 562 + free_irq(s3c_rtc_alarmno, rtc); 563 + goto err_tick_irq; 564 + } 565 + 512 566 clk_disable(rtc_clk); 513 567 514 568 return 0; 569 + 570 + err_tick_irq: 571 + free_irq(s3c_rtc_alarmno, rtc); 572 + 573 + err_alarm_irq: 574 + platform_set_drvdata(pdev, NULL); 575 + rtc_device_unregister(rtc); 515 576 516 577 err_nortc: 517 578 s3c_rtc_enable(pdev, 0);