Commit b522ff02 authored by Stephen Boyd's avatar Stephen Boyd Committed by Greg Kroah-Hartman

alarmtimer: Unregister wakeup source when module get fails

commit 6b6d188a upstream.

The alarmtimer_rtc_add_device() function creates a wakeup source and then
tries to grab a module reference. If that fails the function returns early
with an error code, but fails to remove the wakeup source.

Cleanup this exit path so there is no dangling wakeup source, which is
named 'alarmtime' left allocated which will conflict with another RTC
device that may be registered later.

Fixes: 51218298 ("alarmtimer: Ensure RTC module is not unloaded")
Signed-off-by: default avatarStephen Boyd <swboyd@chromium.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20200109155910.907-2-swboyd@chromium.orgSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 70435409
...@@ -91,6 +91,7 @@ static int alarmtimer_rtc_add_device(struct device *dev, ...@@ -91,6 +91,7 @@ static int alarmtimer_rtc_add_device(struct device *dev,
unsigned long flags; unsigned long flags;
struct rtc_device *rtc = to_rtc_device(dev); struct rtc_device *rtc = to_rtc_device(dev);
struct wakeup_source *__ws; struct wakeup_source *__ws;
int ret = 0;
if (rtcdev) if (rtcdev)
return -EBUSY; return -EBUSY;
...@@ -105,8 +106,8 @@ static int alarmtimer_rtc_add_device(struct device *dev, ...@@ -105,8 +106,8 @@ static int alarmtimer_rtc_add_device(struct device *dev,
spin_lock_irqsave(&rtcdev_lock, flags); spin_lock_irqsave(&rtcdev_lock, flags);
if (!rtcdev) { if (!rtcdev) {
if (!try_module_get(rtc->owner)) { if (!try_module_get(rtc->owner)) {
spin_unlock_irqrestore(&rtcdev_lock, flags); ret = -1;
return -1; goto unlock;
} }
rtcdev = rtc; rtcdev = rtc;
...@@ -115,11 +116,12 @@ static int alarmtimer_rtc_add_device(struct device *dev, ...@@ -115,11 +116,12 @@ static int alarmtimer_rtc_add_device(struct device *dev,
ws = __ws; ws = __ws;
__ws = NULL; __ws = NULL;
} }
unlock:
spin_unlock_irqrestore(&rtcdev_lock, flags); spin_unlock_irqrestore(&rtcdev_lock, flags);
wakeup_source_unregister(__ws); wakeup_source_unregister(__ws);
return 0; return ret;
} }
static inline void alarmtimer_rtc_timer_init(void) static inline void alarmtimer_rtc_timer_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment