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

drivers/rtc/rtc-s5m.c: re-add support for devices without irq specified

The rtc-s5m driver used to support devices without irq specified in the
past. Re-add this support.

The patch fixes boot for Insignal's Exynos4412 based Origen board.

Error messages before the patch:

...
Unable to handle kernel NULL pointer dereference at virtual address 00000094
pgd = c0004000
[00000094] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT SMP ARM
Modules linked in:
CPU: 1 PID: 1 Comm: swapper/0 Not tainted 3.16.0-next-20140804-00008-ga59480f-dirty #701
task: ea80f000 ti: ea882000 task.ti: ea882000
PC is at regmap_irq_get_virq+0x0/0x28
LR is at s5m_rtc_probe+0xdc/0x310
pc : [<c02574fc>] lr : [<c02de75c>] psr: 80000153
sp : ea883e48 ip : 00000000 fp : 00000000
r10: 0000000c r9 : c05de7ac r8 : eaabc600
r7 : eaa6b4d0 r6 : c0439e8c r5 : eaabc610 r4 : eab30e50
r3 : 00000000 r2 : 00000000 r1 : 0000000c r0 : 00000000
Flags: Nzcv IRQs on FIQs off Mode SVC_32 ISA ARM Segment kernel
Control: 10c5387d Table: 4000404a DAC: 00000015
Process swapper/0 (pid: 1, stack limit = 0xea882240)
Backtrace:
regmap_irq_get_virq
s5m_rtc_probe
platform_drv_probe
driver_probe_device
__driver_attach
bus_for_each_dev
bus_add_driver
driver_register
do_one_initcall
kernel_init_freeable
kernel_init
---[ end trace a954d7f019122700 ]---
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
...

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Bartlomiej Zolnierkiewicz and committed by
Linus Torvalds
b7d5b9a9 bfcfd44c

+14 -7
+14 -7
drivers/rtc/rtc-s5m.c
··· 717 717 info->device_type = s5m87xx->device_type; 718 718 info->wtsr_smpl = s5m87xx->wtsr_smpl; 719 719 720 - info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); 721 - if (info->irq <= 0) { 722 - ret = -EINVAL; 723 - dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", 720 + if (s5m87xx->irq_data) { 721 + info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); 722 + if (info->irq <= 0) { 723 + ret = -EINVAL; 724 + dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", 724 725 alarm_irq); 725 - goto err; 726 + goto err; 727 + } 726 728 } 727 729 728 730 platform_set_drvdata(pdev, info); ··· 744 742 if (IS_ERR(info->rtc_dev)) { 745 743 ret = PTR_ERR(info->rtc_dev); 746 744 goto err; 745 + } 746 + 747 + if (!info->irq) { 748 + dev_info(&pdev->dev, "Alarm IRQ not available\n"); 749 + return 0; 747 750 } 748 751 749 752 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, ··· 809 802 struct s5m_rtc_info *info = dev_get_drvdata(dev); 810 803 int ret = 0; 811 804 812 - if (device_may_wakeup(dev)) 805 + if (info->irq && device_may_wakeup(dev)) 813 806 ret = disable_irq_wake(info->irq); 814 807 815 808 return ret; ··· 820 813 struct s5m_rtc_info *info = dev_get_drvdata(dev); 821 814 int ret = 0; 822 815 823 - if (device_may_wakeup(dev)) 816 + if (info->irq && device_may_wakeup(dev)) 824 817 ret = enable_irq_wake(info->irq); 825 818 826 819 return ret;