Skip to content

Commit c79108b

Browse files
bebarinoKAGA-KOKO
authored andcommitted
alarmtimer: Make alarmtimer platform device child of RTC device
The alarmtimer_suspend() function will fail if an RTC device is on a bus such as SPI or i2c and that RTC device registers and probes after alarmtimer_init() registers and probes the 'alarmtimer' platform device. This is because system wide suspend suspends devices in the reverse order of their probe. When alarmtimer_suspend() attempts to program the RTC for a wakeup it will try to program an RTC device on a bus that has already been suspended. Move the alarmtimer device registration to happen when the RTC which is used for wakeup is registered. Register the 'alarmtimer' platform device as a child of the RTC device too, so that it can be guaranteed that the RTC device won't be suspended when alarmtimer_suspend() is called. Reported-by: Douglas Anderson <[email protected]> Signed-off-by: Stephen Boyd <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Douglas Anderson <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 6b088ce commit c79108b

File tree

1 file changed

+9
-11
lines changed

1 file changed

+9
-11
lines changed

kernel/time/alarmtimer.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static int alarmtimer_rtc_add_device(struct device *dev,
8989
unsigned long flags;
9090
struct rtc_device *rtc = to_rtc_device(dev);
9191
struct wakeup_source *__ws;
92+
struct platform_device *pdev;
9293
int ret = 0;
9394

9495
if (rtcdev)
@@ -100,9 +101,11 @@ static int alarmtimer_rtc_add_device(struct device *dev,
100101
return -1;
101102

102103
__ws = wakeup_source_register(dev, "alarmtimer");
104+
pdev = platform_device_register_data(dev, "alarmtimer",
105+
PLATFORM_DEVID_AUTO, NULL, 0);
103106

104107
spin_lock_irqsave(&rtcdev_lock, flags);
105-
if (!rtcdev) {
108+
if (__ws && !IS_ERR(pdev) && !rtcdev) {
106109
if (!try_module_get(rtc->owner)) {
107110
ret = -1;
108111
goto unlock;
@@ -113,10 +116,14 @@ static int alarmtimer_rtc_add_device(struct device *dev,
113116
get_device(dev);
114117
ws = __ws;
115118
__ws = NULL;
119+
pdev = NULL;
120+
} else {
121+
ret = -1;
116122
}
117123
unlock:
118124
spin_unlock_irqrestore(&rtcdev_lock, flags);
119125

126+
platform_device_unregister(pdev);
120127
wakeup_source_unregister(__ws);
121128

122129
return ret;
@@ -903,8 +910,7 @@ static void get_boottime_timespec(struct timespec64 *tp)
903910
*/
904911
static int __init alarmtimer_init(void)
905912
{
906-
struct platform_device *pdev;
907-
int error = 0;
913+
int error;
908914
int i;
909915

910916
alarmtimer_rtc_timer_init();
@@ -929,15 +935,7 @@ static int __init alarmtimer_init(void)
929935
if (error)
930936
goto out_if;
931937

932-
pdev = platform_device_register_simple("alarmtimer", -1, NULL, 0);
933-
if (IS_ERR(pdev)) {
934-
error = PTR_ERR(pdev);
935-
goto out_drv;
936-
}
937938
return 0;
938-
939-
out_drv:
940-
platform_driver_unregister(&alarmtimer_driver);
941939
out_if:
942940
alarmtimer_rtc_interface_remove();
943941
return error;

0 commit comments

Comments
 (0)