Merge tag 'pm-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
[linux-2.6-block.git] / kernel / time / alarmtimer.c
index 93b382d9701cd4658a9d203e6ff5be020b91a213..451f9d05ccfec5397eee2784fb92e695d2e9c86e 100644 (file)
@@ -432,7 +432,7 @@ int alarm_cancel(struct alarm *alarm)
                int ret = alarm_try_to_cancel(alarm);
                if (ret >= 0)
                        return ret;
-               cpu_relax();
+               hrtimer_cancel_wait_running(&alarm->timer);
        }
 }
 EXPORT_SYMBOL_GPL(alarm_cancel);
@@ -605,6 +605,19 @@ static int alarm_timer_try_to_cancel(struct k_itimer *timr)
        return alarm_try_to_cancel(&timr->it.alarm.alarmtimer);
 }
 
+/**
+ * alarm_timer_wait_running - Posix timer callback to wait for a timer
+ * @timr:      Pointer to the posixtimer data struct
+ *
+ * Called from the core code when timer cancel detected that the callback
+ * is running. @timr is unlocked and rcu read lock is held to prevent it
+ * from being freed.
+ */
+static void alarm_timer_wait_running(struct k_itimer *timr)
+{
+       hrtimer_cancel_wait_running(&timr->it.alarm.alarmtimer.timer);
+}
+
 /**
  * alarm_timer_arm - Posix timer callback to arm a timer
  * @timr:      Pointer to the posixtimer data struct
@@ -672,7 +685,7 @@ static int alarm_timer_create(struct k_itimer *new_timer)
        enum  alarmtimer_type type;
 
        if (!alarmtimer_get_rtcdev())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        if (!capable(CAP_WAKE_ALARM))
                return -EPERM;
@@ -790,7 +803,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
        int ret = 0;
 
        if (!alarmtimer_get_rtcdev())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        if (flags & ~TIMER_ABSTIME)
                return -EINVAL;
@@ -834,6 +847,7 @@ const struct k_clock alarm_clock = {
        .timer_forward          = alarm_timer_forward,
        .timer_remaining        = alarm_timer_remaining,
        .timer_try_to_cancel    = alarm_timer_try_to_cancel,
+       .timer_wait_running     = alarm_timer_wait_running,
        .nsleep                 = alarm_timer_nsleep,
 };
 #endif /* CONFIG_POSIX_TIMERS */