From aa156c8aee22a24865bf94d0c4a5f604f687fa7d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 14 Oct 2016 10:15:35 -0300 Subject: rtc: asm9260: fix module autoload If the driver is built as a module, autoload won't work because the module alias information is not filled so user-space can't match the registered device with the corresponding module. Export the module alias information using the MODULE_DEVICE_TABLE() macro. Before this patch: $ modinfo drivers/rtc/rtc-asm9260.ko | grep alias $ After this patch: $ modinfo drivers/rtc/rtc-asm9260.ko | grep alias alias: of:N*T*Calphascale,asm9260-rtcC* alias: of:N*T*Calphascale,asm9260-rtc Signed-off-by: Javier Martinez Canillas Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-asm9260.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index 18a93d3e3f93..d36534965635 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -327,6 +327,7 @@ static const struct of_device_id asm9260_dt_ids[] = { { .compatible = "alphascale,asm9260-rtc", }, {} }; +MODULE_DEVICE_TABLE(of, asm9260_dt_ids); static struct platform_driver asm9260_rtc_driver = { .probe = asm9260_rtc_probe, -- cgit v1.2.3 From a3a0673b9db6fad2a3f7874c34e4b5cbc5fa01c6 Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Tue, 18 Oct 2016 16:39:54 +0200 Subject: rtc: cmos: remove all __exit_p annotations I got the following stack trace under qemu: [ 7.575243] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 [ 7.596098] IP: [] cmos_set_alarm+0x38/0x280 [ 7.615699] PGD 3ccbe067 [ 7.615923] PUD 3daf2067 [ 7.635156] PMD 0 [ 7.654358] Oops: 0000 [#1] SMP [ 7.673869] Modules linked in: [ 7.693235] CPU: 0 PID: 1701 Comm: hwclock Tainted: G W 4.9.0-rc1+ #24 [ 7.712455] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014 [ 7.753569] task: ffff88003d88dc40 task.stack: ffffc90000224000 [ 7.773743] RIP: 0010:[] [] cmos_set_alarm+0x38/0x280 [ 7.794893] RSP: 0018:ffffc90000227c10 EFLAGS: 00010296 [ 7.815890] RAX: 000000000000001d RBX: ffffc90000227d28 RCX: ffffffff8182be78 [ 7.836057] RDX: 0000000000000001 RSI: 0000000000000202 RDI: 0000000000000202 [ 7.856612] RBP: ffffc90000227c48 R08: 0000000000000000 R09: 0000000000000001 [ 7.877561] R10: 00000000000001c0 R11: 00000000000001c0 R12: 0000000000000000 [ 7.897072] R13: ffff88003d96f400 R14: ffff88003dac6410 R15: ffff88003dac6420 [ 7.917403] FS: 00007f77f42d9700(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000 [ 7.938293] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 7.958364] CR2: 0000000000000010 CR3: 000000003ccbb000 CR4: 00000000000006f0 [ 7.978028] Stack: [ 7.997120] ffff88003dac6000 ffff88003dac6410 0000000058049d01 ffffc90000227d28 [ 8.016993] ffff88003dac6000 ffff88003dac6410 ffff88003dac6420 ffffc90000227c98 [ 8.039505] ffffffff814f225d 0000001800227c98 000000090000002a 0000000900000011 [ 8.059985] Call Trace: [ 8.080110] [] __rtc_set_alarm+0x8d/0xa0 [ 8.099421] [] rtc_timer_enqueue+0x119/0x190 [ 8.119925] [] rtc_update_irq_enable+0xbe/0x100 [ 8.140583] [] rtc_dev_ioctl+0x3c0/0x480 [ 8.161162] [] ? user_path_at_empty+0x3a/0x50 [ 8.182717] [] do_vfs_ioctl+0x96/0x5c0 [ 8.204624] [] ? vfs_stat+0x16/0x20 [ 8.225994] [] ? SyS_newstat+0x15/0x30 [ 8.247043] [] SyS_ioctl+0x47/0x80 [ 8.267191] [] entry_SYSCALL_64_fastpath+0x1a/0xa9 [ 8.288719] Code: 6a 81 48 89 e5 41 57 41 56 41 55 49 89 fd 41 54 53 48 89 f3 48 c7 c6 20 c4 78 81 48 83 ec 10 e8 8f 00 ef ff 4d 8b a5 a0 00 00 00 <41> 8b 44 24 10 85 c0 0f 8e 2b 02 00 00 4c 89 ef 31 c0 b9 53 01 [ 8.335233] RIP [] cmos_set_alarm+0x38/0x280 [ 8.357096] RSP [ 8.379051] CR2: 0000000000000010 [ 8.401736] ---[ end trace 5cbcd83a1f225ed3 ]--- This occur only when CONFIG_DEBUG_TEST_DRIVER_REMOVE is enabled and CONFIG_RTC_DRV_CMOS builtin. When cmos_set_alarm() is called dev is NULL and so trigger the deref via cmos->irq The problem comes from that the device is removed but no remove function are called due to _exit_p(). This patch remove all _exit_p() annotation. Signed-off-by: Corentin Labbe Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index dd3d59806ffa..6f0e12e66296 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -776,7 +776,7 @@ static void cmos_do_shutdown(int rtc_irq) spin_unlock_irq(&rtc_lock); } -static void __exit cmos_do_remove(struct device *dev) +static void cmos_do_remove(struct device *dev) { struct cmos_rtc *cmos = dev_get_drvdata(dev); struct resource *ports; @@ -1129,7 +1129,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) pnp_irq(pnp, 0)); } -static void __exit cmos_pnp_remove(struct pnp_dev *pnp) +static void cmos_pnp_remove(struct pnp_dev *pnp) { cmos_do_remove(&pnp->dev); } @@ -1161,7 +1161,7 @@ static struct pnp_driver cmos_pnp_driver = { .name = (char *) driver_name, .id_table = rtc_ids, .probe = cmos_pnp_probe, - .remove = __exit_p(cmos_pnp_remove), + .remove = cmos_pnp_remove, .shutdown = cmos_pnp_shutdown, /* flag ensures resume() gets called, and stops syslog spam */ @@ -1238,7 +1238,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) return cmos_do_probe(&pdev->dev, resource, irq); } -static int __exit cmos_platform_remove(struct platform_device *pdev) +static int cmos_platform_remove(struct platform_device *pdev) { cmos_do_remove(&pdev->dev); return 0; @@ -1263,7 +1263,7 @@ static void cmos_platform_shutdown(struct platform_device *pdev) MODULE_ALIAS("platform:rtc_cmos"); static struct platform_driver cmos_platform_driver = { - .remove = __exit_p(cmos_platform_remove), + .remove = cmos_platform_remove, .shutdown = cmos_platform_shutdown, .driver = { .name = driver_name, -- cgit v1.2.3 From 368e21aebe9535c1643b272aaa9819298a6bc3e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 19 Oct 2016 21:02:04 +0300 Subject: rtc: cmos: Don't enable interrupts in the middle of the interrupt handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using spin_lock_irq()/spin_unlock_irq() from within the interrupt handler is a no-no. Let's save/restore the flags to avoid turning on interrupts prematurely. We hit this in a bunch of our CI systems, but for whatever reason I wasn't able to reproduce on my own machine, so this fix is just based on the backtrace. [ 202.634918] WARNING: CPU: 0 PID: 0 at kernel/locking/lockdep.c:2729 trace_hardirqs_on_caller+0x113/0x1b0 [ 202.634919] DEBUG_LOCKS_WARN_ON(current->hardirq_context) [ 202.634929] Modules linked in: snd_hda_intel i915 x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel lpc_ich snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec_hdmi snd_hda_codec snd_hwdep i2c_designware_platform i2c_designware_core snd_hda_core mei_me mei snd_pcm r8169 mii sdhci_acpi sdhci mmc_core i2c_hid [last unloaded: i915] [ 202.634930] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G U 4.9.0-rc1-CI-CI_DRM_1734+ #1 [ 202.634931] Hardware name: GIGABYTE M4HM87P-00/M4HM87P-00, BIOS F6 12/10/2014 [ 202.634933] ffff88011ea03d68 ffffffff8142dce5 ffff88011ea03db8 0000000000000000 [ 202.634934] ffff88011ea03da8 ffffffff8107e496 00000aa900000002 ffffffff81e249a0 [ 202.634935] ffffffff81815637 ffffffff82e7c280 0000000000000000 0000000000000004 [ 202.634936] Call Trace: [ 202.634939] [ 202.634939] [] dump_stack+0x67/0x92 [ 202.634941] [] __warn+0xc6/0xe0 [ 202.634944] [] ? _raw_spin_unlock_irq+0x27/0x50 [ 202.634945] [] warn_slowpath_fmt+0x4a/0x50 [ 202.634946] [] trace_hardirqs_on_caller+0x113/0x1b0 [ 202.634948] [] trace_hardirqs_on+0xd/0x10 [ 202.634949] [] _raw_spin_unlock_irq+0x27/0x50 [ 202.634951] [] rtc_handler+0x32/0xa0 [ 202.634954] [] acpi_ev_fixed_event_detect+0xd4/0xfb [ 202.634956] [] acpi_ev_sci_xrupt_handler+0xf/0x2d [ 202.634957] [] acpi_irq+0x11/0x2c [ 202.634960] [] __handle_irq_event_percpu+0x58/0x370 [ 202.634961] [] handle_irq_event_percpu+0x1e/0x50 [ 202.634962] [] handle_irq_event+0x34/0x60 [ 202.634963] [] handle_fasteoi_irq+0xa6/0x170 [ 202.634966] [] handle_irq+0x15/0x20 [ 202.634967] [] do_IRQ+0x68/0x130 [ 202.634968] [] common_interrupt+0x89/0x89 [ 202.634970] [ 202.634970] [] ? mwait_idle+0x93/0x210 [ 202.634971] [] ? mwait_idle+0x8a/0x210 [ 202.634972] [] arch_cpu_idle+0xa/0x10 [ 202.634973] [] default_idle_call+0x1e/0x30 [ 202.634974] [] cpu_startup_entry+0x17c/0x1f0 [ 202.634976] [] rest_init+0x127/0x130 [ 202.634978] [] start_kernel+0x3f6/0x403 [ 202.634980] [] x86_64_start_reservations+0x2a/0x2c [ 202.634981] [] x86_64_start_kernel+0x173/0x186 [ 202.634982] ---[ end trace 293c99618fa08d34 ]--- Cc: Gabriele Mazzotta Cc: Alexandre Belloni Fixes: 983bf1256edb ("rtc: cmos: Clear ACPI-driven alarms upon resume") Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 6f0e12e66296..7030d7cd3861 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -996,8 +996,9 @@ static u32 rtc_handler(void *context) struct cmos_rtc *cmos = dev_get_drvdata(dev); unsigned char rtc_control = 0; unsigned char rtc_intr; + unsigned long flags; - spin_lock_irq(&rtc_lock); + spin_lock_irqsave(&rtc_lock, flags); if (cmos_rtc.suspend_ctrl) rtc_control = CMOS_READ(RTC_CONTROL); if (rtc_control & RTC_AIE) { @@ -1006,7 +1007,7 @@ static u32 rtc_handler(void *context) rtc_intr = CMOS_READ(RTC_INTR_FLAGS); rtc_update_irq(cmos->rtc, 1, rtc_intr); } - spin_unlock_irq(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); pm_wakeup_event(dev, 0); acpi_clear_event(ACPI_EVENT_RTC); -- cgit v1.2.3 From 3984903a2e3906d3def220e688040ce93368200a Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 27 Oct 2016 11:27:25 +0530 Subject: rtc: omap: Fix selecting external osc RTC can be clocked from an external 32KHz oscillator, or from the Peripheral PLL. The RTC has an internal oscillator buffer to support direct operation with a crystal. ---------------------------------------- | Device --------- | | | | | | | RTCSS | | | --------- | | | OSC |<------| RTC | | | | |------>| OSC |--- | | | | -------- | | | | | ----|clk | | | -------- | | | | | | PRCM |--- | | | | -------- -------- | ---------------------------------------- The RTC functional clock is sourced by default from the clock derived from the Peripheral PLL. In order to select source as external osc clk the following changes needs to be done: - Enable the RTC OSC (RTC_OSC_REG[4]OSC32K_GZ = 0) - Enable the clock mux(RTC_OSC_REG[6]K32CLK_EN = 1) - Select the external clock source (RTC_OSC_REG[3]32KCLK_SEL = 1) Fixes: 399cf0f63f6f2 ("rtc: omap: Add external clock enabling support") Signed-off-by: Keerthy Signed-off-by: Lokesh Vutla Signed-off-by: Dave Gerlach Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index b04ea9b5ae67..dddaa60871b9 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -113,6 +113,7 @@ /* OMAP_RTC_OSC_REG bit fields: */ #define OMAP_RTC_OSC_32KCLK_EN BIT(6) #define OMAP_RTC_OSC_SEL_32KCLK_SRC BIT(3) +#define OMAP_RTC_OSC_OSC32K_GZ_DISABLE BIT(4) /* OMAP_RTC_IRQWAKEEN bit fields: */ #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1) @@ -786,8 +787,9 @@ static int omap_rtc_probe(struct platform_device *pdev) */ if (rtc->has_ext_clk) { reg = rtc_read(rtc, OMAP_RTC_OSC_REG); - rtc_write(rtc, OMAP_RTC_OSC_REG, - reg | OMAP_RTC_OSC_SEL_32KCLK_SRC); + reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE; + reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC; + rtc_writel(rtc, OMAP_RTC_OSC_REG, reg); } rtc->type->lock(rtc); -- cgit v1.2.3 From efce21fc43e00a76aee7b0a1eda73730ed2d5d3a Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 27 Oct 2016 11:27:26 +0530 Subject: rtc: omap: prevent disabling of clock/module during suspend If RTC is running from an internal clock source, the RTC module can't be disabled; otherwise it stops ticking completely. Current suspend handler implementation disables the clock/module unconditionally, instead fix this by disabling the clock only if we are running on external clock source, which is not affected by suspend. The prevention of disabling the clock must be done via implementing the runtime_pm handlers for the device, and returning an error code from the runtime suspend handler; otherwise OMAP core PM will disable the clocks for the driver. Signed-off-by: Tero Kristo Signed-off-by: Keerthy Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index dddaa60871b9..51e52446eacb 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -147,6 +147,7 @@ struct omap_rtc { u8 interrupts_reg; bool is_pmic_controller; bool has_ext_clk; + bool is_suspending; const struct omap_rtc_device_type *type; struct pinctrl_dev *pctldev; }; @@ -900,8 +901,7 @@ static int omap_rtc_suspend(struct device *dev) rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); rtc->type->lock(rtc); - /* Disable the clock/module */ - pm_runtime_put_sync(dev); + rtc->is_suspending = true; return 0; } @@ -910,9 +910,6 @@ static int omap_rtc_resume(struct device *dev) { struct omap_rtc *rtc = dev_get_drvdata(dev); - /* Enable the clock/module so that we can access the registers */ - pm_runtime_get_sync(dev); - rtc->type->unlock(rtc); if (device_may_wakeup(dev)) disable_irq_wake(rtc->irq_alarm); @@ -920,11 +917,34 @@ static int omap_rtc_resume(struct device *dev) rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg); rtc->type->lock(rtc); + rtc->is_suspending = false; + return 0; } #endif -static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume); +#ifdef CONFIG_PM +static int omap_rtc_runtime_suspend(struct device *dev) +{ + struct omap_rtc *rtc = dev_get_drvdata(dev); + + if (rtc->is_suspending && !rtc->has_ext_clk) + return -EBUSY; + + return 0; +} + +static int omap_rtc_runtime_resume(struct device *dev) +{ + return 0; +} +#endif + +static const struct dev_pm_ops omap_rtc_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap_rtc_suspend, omap_rtc_resume) + SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend, + omap_rtc_runtime_resume, NULL) +}; static void omap_rtc_shutdown(struct platform_device *pdev) { -- cgit v1.2.3