mirror of https://github.com/torvalds/linux.git
Currently the sh_cmt clocksource timer is disabled or enabled
unconditionally on clocksource suspend resp. resume, even if a
better clocksource is present (e.g. arch_sys_counter) and the
sh_cmt clocksource is not enabled.
As sh_cmt is a syscore device when its timer is enabled, this
may lead to a genpd.prepared_count imbalance in the presence of
PM Domains, which may cause a lock-up during reboot after s2ram.
During suspend:
- pm_genpd_prepare() is called for all non-syscore devices (incl.
sh_cmt), increasing genpd.prepared_count for each device,
- clocksource.suspend() is called for all clocksource devices,
- sh_cmt_clocksource_suspend() calls sh_cmt_stop(), which is a no-op
as the clocksource was not enabled.
During resume:
- clocksource.resume() is called for all clocksource devices,
- sh_cmt_clocksource_resume() calls sh_cmt_start(), which enables the
clocksource timer, and turns sh_cmt into a syscore device,
- pm_genpd_complete() is called for all non-syscore devices (excl.
sh_cmt now!), decreasing genpd.prepared_count for each device but
sh_cmt.
Now genpd.prepared_count of the PM Domain containing sh_cmt is
still 1 instead of zero. On subsequent suspend/resume cycles,
sh_cmt is still a syscore device, hence it's skipped for
pm_genpd_{prepare,complete}(), keeping the imbalance of
genpd.prepared_count at 1.
During reboot:
- platform_drv_shutdown() is called for any platform device that has
a driver with a .shutdown() method (only rcar-dmac on R-Car Gen2),
- platform_drv_shutdown() calls dev_pm_domain_detach(), which
calls genpd_dev_pm_detach(),
- genpd_dev_pm_detach() keeps calling pm_genpd_remove_device() until
it doesn't return -EAGAIN[*],
- If the device is part of the same PM Domain as sh_cmt,
pm_genpd_remove_device() always fails with -EAGAIN due to
genpd.prepared_count > 0.
- Infinite loop in genpd_dev_pm_detach()[*].
[*] Commit
|
||
|---|---|---|
| .. | ||
| Kconfig | ||
| Makefile | ||
| acpi_pm.c | ||
| arm_arch_timer.c | ||
| arm_global_timer.c | ||
| armv7m_systick.c | ||
| asm9260_timer.c | ||
| bcm2835_timer.c | ||
| bcm_kona_timer.c | ||
| cadence_ttc_timer.c | ||
| clksrc-dbx500-prcmu.c | ||
| clksrc-of.c | ||
| clps711x-timer.c | ||
| cs5535-clockevt.c | ||
| dummy_timer.c | ||
| dw_apb_timer.c | ||
| dw_apb_timer_of.c | ||
| em_sti.c | ||
| exynos_mct.c | ||
| fsl_ftm_timer.c | ||
| h8300_timer8.c | ||
| h8300_timer16.c | ||
| h8300_tpu.c | ||
| i8253.c | ||
| meson6_timer.c | ||
| metag_generic.c | ||
| mips-gic-timer.c | ||
| mmio.c | ||
| moxart_timer.c | ||
| mtk_timer.c | ||
| mxs_timer.c | ||
| nomadik-mtu.c | ||
| pxa_timer.c | ||
| qcom-timer.c | ||
| rockchip_timer.c | ||
| samsung_pwm_timer.c | ||
| scx200_hrt.c | ||
| sh_cmt.c | ||
| sh_mtu2.c | ||
| sh_tmu.c | ||
| sun4i_timer.c | ||
| tcb_clksrc.c | ||
| tegra20_timer.c | ||
| time-armada-370-xp.c | ||
| time-efm32.c | ||
| time-lpc32xx.c | ||
| time-orion.c | ||
| timer-atlas7.c | ||
| timer-atmel-pit.c | ||
| timer-atmel-st.c | ||
| timer-digicolor.c | ||
| timer-imx-gpt.c | ||
| timer-integrator-ap.c | ||
| timer-keystone.c | ||
| timer-prima2.c | ||
| timer-sp.h | ||
| timer-sp804.c | ||
| timer-stm32.c | ||
| timer-sun5i.c | ||
| timer-u300.c | ||
| versatile.c | ||
| vf_pit_timer.c | ||
| vt8500_timer.c | ||
| zevio-timer.c | ||