do_usleep_range(min, max);
}
EXPORT_SYMBOL(usleep_range);
+
+#ifdef CONFIG_ARCH_RK29
+static void do_nsleep(unsigned int nsecs, struct hrtimer_sleeper *sleeper,
+ int sigs)
+{
+ enum hrtimer_mode mode = HRTIMER_MODE_REL;
+ int state = sigs ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+
+ /*
+ * This is really just a reworked and simplified version
+ * of do_nanosleep().
+ */
+ hrtimer_init(&sleeper->timer, CLOCK_MONOTONIC, mode);
+ sleeper->timer._expires = ktime_set(0, nsecs);
+ hrtimer_init_sleeper(sleeper, current);
+
+ do {
+ set_current_state(state);
+ hrtimer_start(&sleeper->timer, sleeper->timer._expires, mode);
+ if (sleeper->task)
+ schedule();
+ hrtimer_cancel(&sleeper->timer);
+ mode = HRTIMER_MODE_ABS;
+ } while (sleeper->task && !(sigs && signal_pending(current)));
+}
+
+/**
+ * msleep - sleep safely even with waitqueue interruptions
+ * @msecs: Time in milliseconds to sleep for
+ */
+void hr_msleep(unsigned int msecs)
+{
+ struct hrtimer_sleeper sleeper;
+
+ do_nsleep(msecs * NSEC_PER_MSEC, &sleeper, 0);
+}
+
+EXPORT_SYMBOL(hr_msleep);
+
+/**
+ * msleep_interruptible - sleep waiting for signals
+ * @msecs: Time in milliseconds to sleep for
+ */
+unsigned long hr_msleep_interruptible(unsigned int msecs)
+{
+ struct hrtimer_sleeper sleeper;
+ ktime_t left;
+
+ do_nsleep(msecs * NSEC_PER_MSEC, &sleeper, 1);
+
+ if (!sleeper.task)
+ return 0;
+ left = ktime_sub(sleeper.timer._expires,
+ sleeper.timer.base->get_time());
+ return max(((long) ktime_to_ns(left))/(long)NSEC_PER_MSEC, 1L);
+}
+
+EXPORT_SYMBOL(hr_msleep_interruptible);
+#endif /* CONFIG_ARCH_RK29 */