* [PATCH v3 00/16] timers: Cleanup delay/sleep related mess
@ 2024-10-14 8:22 Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 01/16] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
` (16 more replies)
0 siblings, 17 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Andrew Morton, damon, linux-mm, SeongJae Park,
Arnd Bergmann, linux-arch, Heiner Kallweit, David S. Miller,
Andy Whitcroft, Joe Perches, Dwaipayan Ray, Liam Girdwood,
Mark Brown, Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media, Sebastian Andrzej Siewior
Hi,
a question about which sleeping function should be used in acpi_os_sleep()
started a discussion and examination about the existing documentation and
implementation of functions which insert a sleep/delay.
The result of the discussion was, that the documentation is outdated and
the implemented fsleep() reflects the outdated documentation but doesn't
help to reflect reality which in turns leads to the queue which covers the
following things:
- Split out all timeout and sleep related functions from hrtimer.c and timer.c
into a separate file
- Update function descriptions of sleep related functions
- Change fsleep() to reflect reality
- Rework all comments or users which obviously rely on the outdated
documentation as they reference "Documentation/timers/timers-howto.rst"
- Update the outdated documentation and move it into a file with a self
explaining file name (as there are no more references)
- Remove checkpatch checks which also rely on the outdated documentation
The queue is available here:
git://git.kernel.org/pub/scm/linux/kernel/git/anna-maria/linux-devel.git timers/misc
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
Changes in v3:
- Add review remarks
- Split checkpatch patch: 1. Remove links to outdated documentation,
2. Remove checks in checkpatch which rely on outdated documentation
- Link to v2: https://lore.kernel.org/r/20240911-devel-anna-maria-b4-timers-flseep-v2-0-b0d3f33ccfe0@linutronix.de
Changes in v2:
- change udelay() and ndelay() as suggested by Thomas
- Update some formatting in the new sleep_timeout.c file
- minor typo changes and other small review remarks
Thanks,
Anna-Maria
---
Anna-Maria Behnsen (16):
MAINTAINERS: Add missing file include/linux/delay.h
timers: Move *sleep*() and timeout functions into a separate file
timers: Update schedule_[hr]timeout*() related function descriptions
timers: Rename usleep_idle_range() to usleep_range_idle()
timers: Update function descriptions of sleep/delay related functions
delay: Rework udelay and ndelay
timers: Adjust flseep() to reflect reality
mm/damon/core: Use generic upper bound recommondation for usleep_range()
timers: Add a warning to usleep_range_state() for wrong order of arguments
checkpatch: Remove links to outdated documentation
regulator: core: Use fsleep() to get best sleep mechanism
iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
powerpc/rtas: Use fsleep() to minimize additional sleep duration
media: anysee: Fix and remove outdated comment
timers/Documentation: Cleanup delay/sleep documentation
checkpatch: Remove broken sleep/delay related checks
Documentation/dev-tools/checkpatch.rst | 6 -
Documentation/timers/delay_sleep_functions.rst | 121 ++++++++
Documentation/timers/index.rst | 2 +-
Documentation/timers/timers-howto.rst | 115 --------
MAINTAINERS | 2 +
arch/powerpc/kernel/rtas.c | 21 +-
drivers/media/usb/dvb-usb-v2/anysee.c | 17 +-
drivers/regulator/core.c | 47 +--
include/asm-generic/delay.h | 96 +++++--
include/linux/delay.h | 79 ++++--
include/linux/iopoll.h | 52 ++--
include/linux/phy.h | 9 +-
include/linux/regmap.h | 38 +--
kernel/time/Makefile | 2 +-
kernel/time/hrtimer.c | 120 --------
kernel/time/sleep_timeout.c | 377 +++++++++++++++++++++++++
kernel/time/timer.c | 192 -------------
mm/damon/core.c | 5 +-
scripts/checkpatch.pl | 38 ---
sound/soc/sof/ops.h | 8 +-
20 files changed, 704 insertions(+), 643 deletions(-)
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v3 01/16] MAINTAINERS: Add missing file include/linux/delay.h
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 02/16] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
` (15 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda
include/linux/delay.h is not covered by MAINTAINERS file. Add it to the
"HIGH-RESOLUTION TIMERS, TIMER WHEEL, CLOCKEVENTS" section.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
---
v2: New (splitted as requested by Frederic)
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 7ad507f49324..91c3e79c69cd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10165,6 +10165,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
F: Documentation/timers/
F: include/linux/clockchips.h
+F: include/linux/delay.h
F: include/linux/hrtimer.h
F: include/linux/timer.h
F: kernel/time/clockevents.c
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 02/16] timers: Move *sleep*() and timeout functions into a separate file
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 01/16] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 03/16] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
` (14 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda
All schedule_timeout() and *sleep*() related functions are interfaces on
top of timer list timers and hrtimers to add a sleep to the code. As they
are built on top of the timer list timers and hrtimers, the [hr]timer
interfaces are already used except when queuing the timer in
schedule_timeout(). But there exists the appropriate interface add_timer()
which does the same job with an extra check for an already pending timer.
Split all those functions as they are into a separate file and use
add_timer() instead of __mod_timer() in schedule_timeout().
While at it fix minor formatting issues and a multi line printk function
call in schedule_timeout().
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
---
v2:
- Drop adding delay.h to MAINTAINERS file
- Some more minor formatting fixups
---
MAINTAINERS | 1 +
kernel/time/Makefile | 2 +-
kernel/time/hrtimer.c | 120 -----------------
kernel/time/sleep_timeout.c | 317 ++++++++++++++++++++++++++++++++++++++++++++
kernel/time/timer.c | 192 ---------------------------
5 files changed, 319 insertions(+), 313 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 91c3e79c69cd..4b067e68911b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10170,6 +10170,7 @@ F: include/linux/hrtimer.h
F: include/linux/timer.h
F: kernel/time/clockevents.c
F: kernel/time/hrtimer.c
+F: kernel/time/sleep_timeout.c
F: kernel/time/timer.c
F: kernel/time/timer_list.c
F: kernel/time/timer_migration.*
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 4af2a264a160..fe0ae82124fe 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y += time.o timer.o hrtimer.o
+obj-y += time.o timer.o hrtimer.o sleep_timeout.o
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
obj-y += timeconv.o timecounter.o alarmtimer.o
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index cddcd08ea827..04f7d8a392c3 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -2242,123 +2242,3 @@ void __init hrtimers_init(void)
hrtimers_prepare_cpu(smp_processor_id());
open_softirq(HRTIMER_SOFTIRQ, hrtimer_run_softirq);
}
-
-/**
- * schedule_hrtimeout_range_clock - sleep until timeout
- * @expires: timeout value (ktime_t)
- * @delta: slack in expires timeout (ktime_t)
- * @mode: timer mode
- * @clock_id: timer clock to be used
- */
-int __sched
-schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
- const enum hrtimer_mode mode, clockid_t clock_id)
-{
- struct hrtimer_sleeper t;
-
- /*
- * Optimize when a zero timeout value is given. It does not
- * matter whether this is an absolute or a relative time.
- */
- if (expires && *expires == 0) {
- __set_current_state(TASK_RUNNING);
- return 0;
- }
-
- /*
- * A NULL parameter means "infinite"
- */
- if (!expires) {
- schedule();
- return -EINTR;
- }
-
- hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
- hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
- hrtimer_sleeper_start_expires(&t, mode);
-
- if (likely(t.task))
- schedule();
-
- hrtimer_cancel(&t.timer);
- destroy_hrtimer_on_stack(&t.timer);
-
- __set_current_state(TASK_RUNNING);
-
- return !t.task ? 0 : -EINTR;
-}
-EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock);
-
-/**
- * schedule_hrtimeout_range - sleep until timeout
- * @expires: timeout value (ktime_t)
- * @delta: slack in expires timeout (ktime_t)
- * @mode: timer mode
- *
- * Make the current task sleep until the given expiry time has
- * elapsed. The routine will return immediately unless
- * the current task state has been set (see set_current_state()).
- *
- * The @delta argument gives the kernel the freedom to schedule the
- * actual wakeup to a time that is both power and performance friendly
- * for regular (non RT/DL) tasks.
- * The kernel give the normal best effort behavior for "@expires+@delta",
- * but may decide to fire the timer earlier, but no earlier than @expires.
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- *
- * Returns 0 when the timer has expired. If the task was woken before the
- * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
- * by an explicit wakeup, it returns -EINTR.
- */
-int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
- const enum hrtimer_mode mode)
-{
- return schedule_hrtimeout_range_clock(expires, delta, mode,
- CLOCK_MONOTONIC);
-}
-EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
-
-/**
- * schedule_hrtimeout - sleep until timeout
- * @expires: timeout value (ktime_t)
- * @mode: timer mode
- *
- * Make the current task sleep until the given expiry time has
- * elapsed. The routine will return immediately unless
- * the current task state has been set (see set_current_state()).
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- *
- * Returns 0 when the timer has expired. If the task was woken before the
- * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
- * by an explicit wakeup, it returns -EINTR.
- */
-int __sched schedule_hrtimeout(ktime_t *expires,
- const enum hrtimer_mode mode)
-{
- return schedule_hrtimeout_range(expires, 0, mode);
-}
-EXPORT_SYMBOL_GPL(schedule_hrtimeout);
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
new file mode 100644
index 000000000000..78b2e7e30b1e
--- /dev/null
+++ b/kernel/time/sleep_timeout.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kernel internal schedule timeout and sleeping functions
+ */
+
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/sched/signal.h>
+#include <linux/sched/debug.h>
+
+#include "tick-internal.h"
+
+/*
+ * Since schedule_timeout()'s timer is defined on the stack, it must store
+ * the target task on the stack as well.
+ */
+struct process_timer {
+ struct timer_list timer;
+ struct task_struct *task;
+};
+
+static void process_timeout(struct timer_list *t)
+{
+ struct process_timer *timeout = from_timer(timeout, t, timer);
+
+ wake_up_process(timeout->task);
+}
+
+/**
+ * schedule_timeout - sleep until timeout
+ * @timeout: timeout value in jiffies
+ *
+ * Make the current task sleep until @timeout jiffies have elapsed.
+ * The function behavior depends on the current task state
+ * (see also set_current_state() description):
+ *
+ * %TASK_RUNNING - the scheduler is called, but the task does not sleep
+ * at all. That happens because sched_submit_work() does nothing for
+ * tasks in %TASK_RUNNING state.
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task or the current task is explicitly woken
+ * up.
+ *
+ * The current task state is guaranteed to be %TASK_RUNNING when this
+ * routine returns.
+ *
+ * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule
+ * the CPU away without a bound on the timeout. In this case the return
+ * value will be %MAX_SCHEDULE_TIMEOUT.
+ *
+ * Returns: 0 when the timer has expired otherwise the remaining time in
+ * jiffies will be returned. In all cases the return value is guaranteed
+ * to be non-negative.
+ */
+signed long __sched schedule_timeout(signed long timeout)
+{
+ struct process_timer timer;
+ unsigned long expire;
+
+ switch (timeout) {
+ case MAX_SCHEDULE_TIMEOUT:
+ /*
+ * These two special cases are useful to be comfortable
+ * in the caller. Nothing more. We could take
+ * MAX_SCHEDULE_TIMEOUT from one of the negative value
+ * but I' d like to return a valid offset (>=0) to allow
+ * the caller to do everything it want with the retval.
+ */
+ schedule();
+ goto out;
+ default:
+ /*
+ * Another bit of PARANOID. Note that the retval will be
+ * 0 since no piece of kernel is supposed to do a check
+ * for a negative retval of schedule_timeout() (since it
+ * should never happens anyway). You just have the printk()
+ * that will tell you if something is gone wrong and where.
+ */
+ if (timeout < 0) {
+ pr_err("%s: wrong timeout value %lx\n", __func__, timeout);
+ dump_stack();
+ __set_current_state(TASK_RUNNING);
+ goto out;
+ }
+ }
+
+ expire = timeout + jiffies;
+
+ timer.task = current;
+ timer_setup_on_stack(&timer.timer, process_timeout, 0);
+ timer.timer.expires = expire;
+ add_timer(&timer.timer);
+ schedule();
+ del_timer_sync(&timer.timer);
+
+ /* Remove the timer from the object tracker */
+ destroy_timer_on_stack(&timer.timer);
+
+ timeout = expire - jiffies;
+
+ out:
+ return timeout < 0 ? 0 : timeout;
+}
+EXPORT_SYMBOL(schedule_timeout);
+
+/*
+ * We can use __set_current_state() here because schedule_timeout() calls
+ * schedule() unconditionally.
+ */
+signed long __sched schedule_timeout_interruptible(signed long timeout)
+{
+ __set_current_state(TASK_INTERRUPTIBLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_interruptible);
+
+signed long __sched schedule_timeout_killable(signed long timeout)
+{
+ __set_current_state(TASK_KILLABLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_killable);
+
+signed long __sched schedule_timeout_uninterruptible(signed long timeout)
+{
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_uninterruptible);
+
+/*
+ * Like schedule_timeout_uninterruptible(), except this task will not contribute
+ * to load average.
+ */
+signed long __sched schedule_timeout_idle(signed long timeout)
+{
+ __set_current_state(TASK_IDLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_idle);
+
+/**
+ * schedule_hrtimeout_range_clock - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @delta: slack in expires timeout (ktime_t)
+ * @mode: timer mode
+ * @clock_id: timer clock to be used
+ */
+int __sched schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
+ const enum hrtimer_mode mode, clockid_t clock_id)
+{
+ struct hrtimer_sleeper t;
+
+ /*
+ * Optimize when a zero timeout value is given. It does not
+ * matter whether this is an absolute or a relative time.
+ */
+ if (expires && *expires == 0) {
+ __set_current_state(TASK_RUNNING);
+ return 0;
+ }
+
+ /*
+ * A NULL parameter means "infinite"
+ */
+ if (!expires) {
+ schedule();
+ return -EINTR;
+ }
+
+ hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
+ hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
+ hrtimer_sleeper_start_expires(&t, mode);
+
+ if (likely(t.task))
+ schedule();
+
+ hrtimer_cancel(&t.timer);
+ destroy_hrtimer_on_stack(&t.timer);
+
+ __set_current_state(TASK_RUNNING);
+
+ return !t.task ? 0 : -EINTR;
+}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock);
+
+/**
+ * schedule_hrtimeout_range - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @delta: slack in expires timeout (ktime_t)
+ * @mode: timer mode
+ *
+ * Make the current task sleep until the given expiry time has
+ * elapsed. The routine will return immediately unless
+ * the current task state has been set (see set_current_state()).
+ *
+ * The @delta argument gives the kernel the freedom to schedule the
+ * actual wakeup to a time that is both power and performance friendly
+ * for regular (non RT/DL) tasks.
+ * The kernel give the normal best effort behavior for "@expires+@delta",
+ * but may decide to fire the timer earlier, but no earlier than @expires.
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task or the current task is explicitly woken
+ * up.
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ *
+ * Returns: 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
+ */
+int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
+ const enum hrtimer_mode mode)
+{
+ return schedule_hrtimeout_range_clock(expires, delta, mode,
+ CLOCK_MONOTONIC);
+}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
+
+/**
+ * schedule_hrtimeout - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @mode: timer mode
+ *
+ * Make the current task sleep until the given expiry time has
+ * elapsed. The routine will return immediately unless
+ * the current task state has been set (see set_current_state()).
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task or the current task is explicitly woken
+ * up.
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ *
+ * Returns: 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
+ */
+int __sched schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode)
+{
+ return schedule_hrtimeout_range(expires, 0, mode);
+}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout);
+
+/**
+ * msleep - sleep safely even with waitqueue interruptions
+ * @msecs: Time in milliseconds to sleep for
+ */
+void msleep(unsigned int msecs)
+{
+ unsigned long timeout = msecs_to_jiffies(msecs);
+
+ while (timeout)
+ timeout = schedule_timeout_uninterruptible(timeout);
+}
+EXPORT_SYMBOL(msleep);
+
+/**
+ * msleep_interruptible - sleep waiting for signals
+ * @msecs: Time in milliseconds to sleep for
+ */
+unsigned long msleep_interruptible(unsigned int msecs)
+{
+ unsigned long timeout = msecs_to_jiffies(msecs);
+
+ while (timeout && !signal_pending(current))
+ timeout = schedule_timeout_interruptible(timeout);
+ return jiffies_to_msecs(timeout);
+}
+EXPORT_SYMBOL(msleep_interruptible);
+
+/**
+ * usleep_range_state - Sleep for an approximate time in a given state
+ * @min: Minimum time in usecs to sleep
+ * @max: Maximum time in usecs to sleep
+ * @state: State of the current task that will be while sleeping
+ *
+ * In non-atomic context where the exact wakeup time is flexible, use
+ * usleep_range_state() instead of udelay(). The sleep improves responsiveness
+ * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces
+ * power usage by allowing hrtimers to take advantage of an already-
+ * scheduled interrupt instead of scheduling a new one just for this sleep.
+ */
+void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned int state)
+{
+ ktime_t exp = ktime_add_us(ktime_get(), min);
+ u64 delta = (u64)(max - min) * NSEC_PER_USEC;
+
+ for (;;) {
+ __set_current_state(state);
+ /* Do not return before the requested sleep time has elapsed */
+ if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS))
+ break;
+ }
+}
+EXPORT_SYMBOL(usleep_range_state);
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 0fc9d066a7be..02355b275bab 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -37,7 +37,6 @@
#include <linux/tick.h>
#include <linux/kallsyms.h>
#include <linux/irq_work.h>
-#include <linux/sched/signal.h>
#include <linux/sched/sysctl.h>
#include <linux/sched/nohz.h>
#include <linux/sched/debug.h>
@@ -2526,141 +2525,6 @@ void update_process_times(int user_tick)
run_posix_cpu_timers();
}
-/*
- * Since schedule_timeout()'s timer is defined on the stack, it must store
- * the target task on the stack as well.
- */
-struct process_timer {
- struct timer_list timer;
- struct task_struct *task;
-};
-
-static void process_timeout(struct timer_list *t)
-{
- struct process_timer *timeout = from_timer(timeout, t, timer);
-
- wake_up_process(timeout->task);
-}
-
-/**
- * schedule_timeout - sleep until timeout
- * @timeout: timeout value in jiffies
- *
- * Make the current task sleep until @timeout jiffies have elapsed.
- * The function behavior depends on the current task state
- * (see also set_current_state() description):
- *
- * %TASK_RUNNING - the scheduler is called, but the task does not sleep
- * at all. That happens because sched_submit_work() does nothing for
- * tasks in %TASK_RUNNING state.
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be %TASK_RUNNING when this
- * routine returns.
- *
- * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule
- * the CPU away without a bound on the timeout. In this case the return
- * value will be %MAX_SCHEDULE_TIMEOUT.
- *
- * Returns 0 when the timer has expired otherwise the remaining time in
- * jiffies will be returned. In all cases the return value is guaranteed
- * to be non-negative.
- */
-signed long __sched schedule_timeout(signed long timeout)
-{
- struct process_timer timer;
- unsigned long expire;
-
- switch (timeout)
- {
- case MAX_SCHEDULE_TIMEOUT:
- /*
- * These two special cases are useful to be comfortable
- * in the caller. Nothing more. We could take
- * MAX_SCHEDULE_TIMEOUT from one of the negative value
- * but I' d like to return a valid offset (>=0) to allow
- * the caller to do everything it want with the retval.
- */
- schedule();
- goto out;
- default:
- /*
- * Another bit of PARANOID. Note that the retval will be
- * 0 since no piece of kernel is supposed to do a check
- * for a negative retval of schedule_timeout() (since it
- * should never happens anyway). You just have the printk()
- * that will tell you if something is gone wrong and where.
- */
- if (timeout < 0) {
- printk(KERN_ERR "schedule_timeout: wrong timeout "
- "value %lx\n", timeout);
- dump_stack();
- __set_current_state(TASK_RUNNING);
- goto out;
- }
- }
-
- expire = timeout + jiffies;
-
- timer.task = current;
- timer_setup_on_stack(&timer.timer, process_timeout, 0);
- __mod_timer(&timer.timer, expire, MOD_TIMER_NOTPENDING);
- schedule();
- del_timer_sync(&timer.timer);
-
- /* Remove the timer from the object tracker */
- destroy_timer_on_stack(&timer.timer);
-
- timeout = expire - jiffies;
-
- out:
- return timeout < 0 ? 0 : timeout;
-}
-EXPORT_SYMBOL(schedule_timeout);
-
-/*
- * We can use __set_current_state() here because schedule_timeout() calls
- * schedule() unconditionally.
- */
-signed long __sched schedule_timeout_interruptible(signed long timeout)
-{
- __set_current_state(TASK_INTERRUPTIBLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_interruptible);
-
-signed long __sched schedule_timeout_killable(signed long timeout)
-{
- __set_current_state(TASK_KILLABLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_killable);
-
-signed long __sched schedule_timeout_uninterruptible(signed long timeout)
-{
- __set_current_state(TASK_UNINTERRUPTIBLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_uninterruptible);
-
-/*
- * Like schedule_timeout_uninterruptible(), except this task will not contribute
- * to load average.
- */
-signed long __sched schedule_timeout_idle(signed long timeout)
-{
- __set_current_state(TASK_IDLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_idle);
-
#ifdef CONFIG_HOTPLUG_CPU
static void migrate_timer_list(struct timer_base *new_base, struct hlist_head *head)
{
@@ -2757,59 +2621,3 @@ void __init init_timers(void)
posix_cputimers_init_work();
open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
}
-
-/**
- * msleep - sleep safely even with waitqueue interruptions
- * @msecs: Time in milliseconds to sleep for
- */
-void msleep(unsigned int msecs)
-{
- unsigned long timeout = msecs_to_jiffies(msecs);
-
- while (timeout)
- timeout = schedule_timeout_uninterruptible(timeout);
-}
-
-EXPORT_SYMBOL(msleep);
-
-/**
- * msleep_interruptible - sleep waiting for signals
- * @msecs: Time in milliseconds to sleep for
- */
-unsigned long msleep_interruptible(unsigned int msecs)
-{
- unsigned long timeout = msecs_to_jiffies(msecs);
-
- while (timeout && !signal_pending(current))
- timeout = schedule_timeout_interruptible(timeout);
- return jiffies_to_msecs(timeout);
-}
-
-EXPORT_SYMBOL(msleep_interruptible);
-
-/**
- * usleep_range_state - Sleep for an approximate time in a given state
- * @min: Minimum time in usecs to sleep
- * @max: Maximum time in usecs to sleep
- * @state: State of the current task that will be while sleeping
- *
- * In non-atomic context where the exact wakeup time is flexible, use
- * usleep_range_state() instead of udelay(). The sleep improves responsiveness
- * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces
- * power usage by allowing hrtimers to take advantage of an already-
- * scheduled interrupt instead of scheduling a new one just for this sleep.
- */
-void __sched usleep_range_state(unsigned long min, unsigned long max,
- unsigned int state)
-{
- ktime_t exp = ktime_add_us(ktime_get(), min);
- u64 delta = (u64)(max - min) * NSEC_PER_USEC;
-
- for (;;) {
- __set_current_state(state);
- /* Do not return before the requested sleep time has elapsed */
- if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS))
- break;
- }
-}
-EXPORT_SYMBOL(usleep_range_state);
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 03/16] timers: Update schedule_[hr]timeout*() related function descriptions
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 01/16] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 02/16] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 04/16] timers: Rename usleep_idle_range() to usleep_range_idle() Anna-Maria Behnsen
` (13 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda
schedule_timeout*() functions do not have proper kernel-doc formatted
function descriptions. schedule_hrtimeout() and schedule_hrtimeout_range()
have a almost identical description.
Add missing function descriptions. Remove copy of function description and
add a pointer to the existing description instead.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
---
v2: New in v2
---
kernel/time/sleep_timeout.c | 66 ++++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 25 deletions(-)
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
index 78b2e7e30b1e..560d17c30aa5 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -110,8 +110,17 @@ signed long __sched schedule_timeout(signed long timeout)
EXPORT_SYMBOL(schedule_timeout);
/*
- * We can use __set_current_state() here because schedule_timeout() calls
- * schedule() unconditionally.
+ * __set_current_state() can be used in schedule_timeout_*() functions, because
+ * schedule_timeout() calls schedule() unconditionally.
+ */
+
+/**
+ * schedule_timeout_interruptible - sleep until timeout (interruptible)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_INTERRUPTIBLE before starting the timeout.
*/
signed long __sched schedule_timeout_interruptible(signed long timeout)
{
@@ -120,6 +129,14 @@ signed long __sched schedule_timeout_interruptible(signed long timeout)
}
EXPORT_SYMBOL(schedule_timeout_interruptible);
+/**
+ * schedule_timeout_killable - sleep until timeout (killable)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_KILLABLE before starting the timeout.
+ */
signed long __sched schedule_timeout_killable(signed long timeout)
{
__set_current_state(TASK_KILLABLE);
@@ -127,6 +144,14 @@ signed long __sched schedule_timeout_killable(signed long timeout)
}
EXPORT_SYMBOL(schedule_timeout_killable);
+/**
+ * schedule_timeout_uninterruptible - sleep until timeout (uninterruptible)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_UNINTERRUPTIBLE before starting the timeout.
+ */
signed long __sched schedule_timeout_uninterruptible(signed long timeout)
{
__set_current_state(TASK_UNINTERRUPTIBLE);
@@ -134,9 +159,15 @@ signed long __sched schedule_timeout_uninterruptible(signed long timeout)
}
EXPORT_SYMBOL(schedule_timeout_uninterruptible);
-/*
- * Like schedule_timeout_uninterruptible(), except this task will not contribute
- * to load average.
+/**
+ * schedule_timeout_idle - sleep until timeout (idle)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_IDLE before starting the timeout. It is similar to
+ * schedule_timeout_uninterruptible(), except this task will not contribute to
+ * load average.
*/
signed long __sched schedule_timeout_idle(signed long timeout)
{
@@ -151,6 +182,9 @@ EXPORT_SYMBOL(schedule_timeout_idle);
* @delta: slack in expires timeout (ktime_t)
* @mode: timer mode
* @clock_id: timer clock to be used
+ *
+ * Details are explained in schedule_hrtimeout_range() function description as
+ * this function is commonly used.
*/
int __sched schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode, clockid_t clock_id)
@@ -236,26 +270,8 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
* @expires: timeout value (ktime_t)
* @mode: timer mode
*
- * Make the current task sleep until the given expiry time has
- * elapsed. The routine will return immediately unless
- * the current task state has been set (see set_current_state()).
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- *
- * Returns: 0 when the timer has expired. If the task was woken before the
- * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
- * by an explicit wakeup, it returns -EINTR.
+ * See schedule_hrtimeout_range() for details. @delta argument of
+ * schedule_hrtimeout_range() is set to 0 and has therefore no impact.
*/
int __sched schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode)
{
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 04/16] timers: Rename usleep_idle_range() to usleep_range_idle()
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (2 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 03/16] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 05/16] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
` (12 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Andrew Morton, damon, linux-mm, SeongJae Park
usleep_idle_range() is a variant of usleep_range(). Both are using
usleep_range_state() as a base. To be able to find all the related
functions in one go, rename it usleep_idle_range() to usleep_range_idle().
No functional change.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: damon@lists.linux.dev
Cc: linux-mm@kvack.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Reviewed-by: SeongJae Park <sj@kernel.org>
---
v2: Fix typos in commit message
---
include/linux/delay.h | 2 +-
mm/damon/core.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/delay.h b/include/linux/delay.h
index ff9cda975e30..2bc586aa2068 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -68,7 +68,7 @@ static inline void usleep_range(unsigned long min, unsigned long max)
usleep_range_state(min, max, TASK_UNINTERRUPTIBLE);
}
-static inline void usleep_idle_range(unsigned long min, unsigned long max)
+static inline void usleep_range_idle(unsigned long min, unsigned long max)
{
usleep_range_state(min, max, TASK_IDLE);
}
diff --git a/mm/damon/core.c b/mm/damon/core.c
index a83f3b736d51..c725c78b43f0 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1896,7 +1896,7 @@ static void kdamond_usleep(unsigned long usecs)
if (usecs > 20 * USEC_PER_MSEC)
schedule_timeout_idle(usecs_to_jiffies(usecs));
else
- usleep_idle_range(usecs, usecs + 1);
+ usleep_range_idle(usecs, usecs + 1);
}
/* Returns negative error code if it's not activated but should return */
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 05/16] timers: Update function descriptions of sleep/delay related functions
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (3 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 04/16] timers: Rename usleep_idle_range() to usleep_range_idle() Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 06/16] delay: Rework udelay and ndelay Anna-Maria Behnsen
` (11 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Arnd Bergmann, linux-arch
A lot of commonly used functions for inserting a sleep or delay lack a
proper function description. Add function descriptions to all of them to
have important information in a central place close to the code.
No functional change.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
v3:
- Rephrase msleep function description to make it clear
v2:
- Fix typos
- Fix proper usage of kernel-doc return formatting
---
include/asm-generic/delay.h | 41 +++++++++++++++++++++++++++++++----
include/linux/delay.h | 48 ++++++++++++++++++++++++++++++----------
kernel/time/sleep_timeout.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 120 insertions(+), 22 deletions(-)
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index e448ac61430c..a8cee41cc51b 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -12,11 +12,39 @@ extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
/*
- * The weird n/20000 thing suppresses a "comparison is always false due to
- * limited range of data type" warning with non-const 8-bit arguments.
+ * Implementation details:
+ *
+ * * The weird n/20000 thing suppresses a "comparison is always false due to
+ * limited range of data type" warning with non-const 8-bit arguments.
+ * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
+ * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
*/
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
+/**
+ * udelay - Inserting a delay based on microseconds with busy waiting
+ * @usec: requested delay in microseconds
+ *
+ * When delaying in an atomic context ndelay(), udelay() and mdelay() are the
+ * only valid variants of delaying/sleeping to go with.
+ *
+ * When inserting delays in non atomic context which are shorter than the time
+ * which is required to queue e.g. an hrtimer and to enter then the scheduler,
+ * it is also valuable to use udelay(). But it is not simple to specify a
+ * generic threshold for this which will fit for all systems. An approximation
+ * is a threshold for all delays up to 10 microseconds.
+ *
+ * When having a delay which is larger than the architecture specific
+ * %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
+ * risk is given.
+ *
+ * Please note that ndelay(), udelay() and mdelay() may return early for several
+ * reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
+ *
+ * #. computed loops_per_jiffy too low (due to the time taken to execute the
+ * timer interrupt.)
+ * #. cache behaviour affecting the time it takes to execute the loop function.
+ * #. CPU clock rate changes.
+ */
#define udelay(n) \
({ \
if (__builtin_constant_p(n)) { \
@@ -29,7 +57,12 @@ extern void __delay(unsigned long loops);
} \
})
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
+/**
+ * ndelay - Inserting a delay based on nanoseconds with busy waiting
+ * @nsec: requested delay in nanoseconds
+ *
+ * See udelay() for basic information about ndelay() and it's variants.
+ */
#define ndelay(n) \
({ \
if (__builtin_constant_p(n)) { \
diff --git a/include/linux/delay.h b/include/linux/delay.h
index 2bc586aa2068..2de509e4adce 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -6,17 +6,7 @@
* Copyright (C) 1993 Linus Torvalds
*
* Delay routines, using a pre-computed "loops_per_jiffy" value.
- *
- * Please note that ndelay(), udelay() and mdelay() may return early for
- * several reasons:
- * 1. computed loops_per_jiffy too low (due to the time taken to
- * execute the timer interrupt.)
- * 2. cache behaviour affecting the time it takes to execute the
- * loop function.
- * 3. CPU clock rate changes.
- *
- * Please see this thread:
- * https://lists.openwall.net/linux-kernel/2011/01/09/56
+ * Sleep routines using timer list timers or hrtimers.
*/
#include <linux/math.h>
@@ -35,12 +25,21 @@ extern unsigned long loops_per_jiffy;
* The 2nd mdelay() definition ensures GCC will optimize away the
* while loop for the common cases where n <= MAX_UDELAY_MS -- Paul G.
*/
-
#ifndef MAX_UDELAY_MS
#define MAX_UDELAY_MS 5
#endif
#ifndef mdelay
+/**
+ * mdelay - Inserting a delay based on milliseconds with busy waiting
+ * @n: requested delay in milliseconds
+ *
+ * See udelay() for basic information about mdelay() and it's variants.
+ *
+ * Please double check, whether mdelay() is the right way to go or whether a
+ * refactoring of the code is the better variant to be able to use msleep()
+ * instead.
+ */
#define mdelay(n) (\
(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
@@ -63,16 +62,41 @@ unsigned long msleep_interruptible(unsigned int msecs);
void usleep_range_state(unsigned long min, unsigned long max,
unsigned int state);
+/**
+ * usleep_range - Sleep for an approximate time
+ * @min: Minimum time in microseconds to sleep
+ * @max: Maximum time in microseconds to sleep
+ *
+ * For basic information please refere to usleep_range_state().
+ *
+ * The task will be in the state TASK_UNINTERRUPTIBLE during the sleep.
+ */
static inline void usleep_range(unsigned long min, unsigned long max)
{
usleep_range_state(min, max, TASK_UNINTERRUPTIBLE);
}
+/**
+ * usleep_range_idle - Sleep for an approximate time with idle time accounting
+ * @min: Minimum time in microseconds to sleep
+ * @max: Maximum time in microseconds to sleep
+ *
+ * For basic information please refere to usleep_range_state().
+ *
+ * The sleeping task has the state TASK_IDLE during the sleep to prevent
+ * contribution to the load avarage.
+ */
static inline void usleep_range_idle(unsigned long min, unsigned long max)
{
usleep_range_state(min, max, TASK_IDLE);
}
+/**
+ * ssleep - wrapper for seconds around msleep
+ * @seconds: Requested sleep duration in seconds
+ *
+ * Please refere to msleep() for detailed information.
+ */
static inline void ssleep(unsigned int seconds)
{
msleep(seconds * 1000);
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
index 560d17c30aa5..f3f246e4c8d1 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
/**
* msleep - sleep safely even with waitqueue interruptions
- * @msecs: Time in milliseconds to sleep for
+ * @msecs: Requested sleep duration in milliseconds
+ *
+ * msleep() uses jiffy based timeouts for the sleep duration. Because of the
+ * design of the timer wheel, the maximum additional percentage delay (slack) is
+ * 12.5%. This is only valid for timers which will end up in level 1 or a higher
+ * level of the timer wheel. For explanation of those 12.5% please check the
+ * detailed description about the basics of the timer wheel.
+ *
+ * The slack of timers which will end up in level 0 depends on sleep duration
+ * (msecs) and HZ configuration and can be calculated in the following way (with
+ * the timer wheel design restriction that the slack is not less than 12.5%):
+ *
+ * ``slack = MSECS_PER_TICK / msecs``
+ *
+ * When the allowed slack of the callsite is known, the calculation could be
+ * turned around to find the minimal allowed sleep duration to meet the
+ * constraints. For example:
+ *
+ * * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
+ * all sleep durations greater or equal 4ms will meet the constraints.
+ * * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
+ * all sleep durations greater or equal 8ms will meet the constraints.
+ * * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
+ * all sleep durations greater or equal 16ms will meet the constraints.
+ * * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
+ * all sleep durations greater or equal 32ms will meet the constraints.
+ *
+ * See also the signal aware variant msleep_interruptible().
*/
void msleep(unsigned int msecs)
{
@@ -294,7 +321,15 @@ EXPORT_SYMBOL(msleep);
/**
* msleep_interruptible - sleep waiting for signals
- * @msecs: Time in milliseconds to sleep for
+ * @msecs: Requested sleep duration in milliseconds
+ *
+ * See msleep() for some basic information.
+ *
+ * The difference between msleep() and msleep_interruptible() is that the sleep
+ * could be interrupted by a signal delivery and then returns early.
+ *
+ * Returns: The remaining time of the sleep duration transformed to msecs (see
+ * schedule_timeout() for details).
*/
unsigned long msleep_interruptible(unsigned int msecs)
{
@@ -312,11 +347,17 @@ EXPORT_SYMBOL(msleep_interruptible);
* @max: Maximum time in usecs to sleep
* @state: State of the current task that will be while sleeping
*
+ * usleep_range_state() sleeps at least for the minimum specified time but not
+ * longer than the maximum specified amount of time. The range might reduce
+ * power usage by allowing hrtimers to coalesce an already scheduled interrupt
+ * with this hrtimer. In the worst case, an interrupt is scheduled for the upper
+ * bound.
+ *
+ * The sleeping task is set to the specified state before starting the sleep.
+ *
* In non-atomic context where the exact wakeup time is flexible, use
- * usleep_range_state() instead of udelay(). The sleep improves responsiveness
- * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces
- * power usage by allowing hrtimers to take advantage of an already-
- * scheduled interrupt instead of scheduling a new one just for this sleep.
+ * usleep_range() or its variants instead of udelay(). The sleep improves
+ * responsiveness by avoiding the CPU-hogging busy-wait of udelay().
*/
void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned int state)
{
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 06/16] delay: Rework udelay and ndelay
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (4 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 05/16] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 07/16] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
` (10 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda
udelay() as well as ndelay() are defines and no functions and are using
constants to be able to transform a sleep time into loops and to prevent
too long udelays/ndelays. There was a compiler error with non-const 8 bit
arguments which was fixed by commit a87e553fabe8 ("asm-generic: delay.h fix
udelay and ndelay for 8 bit args"). When using a function, the non-const 8
bit argument is type casted and the problem would be gone.
Transform udelay() and ndelay() into proper functions, remove the no longer
and confusing division, add defines for the magic values and add some
explanations as well.
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
v3: Fix build error for i386 (missing linux/math.h include).
v2: New in v2 (as suggested by Thomas)
---
include/asm-generic/delay.h | 65 ++++++++++++++++++++++++++-------------------
1 file changed, 37 insertions(+), 28 deletions(-)
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index a8cee41cc51b..76cf237b6e4c 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -2,6 +2,9 @@
#ifndef __ASM_GENERIC_DELAY_H
#define __ASM_GENERIC_DELAY_H
+#include <linux/math.h>
+#include <vdso/time64.h>
+
/* Undefined functions to get compile-time errors */
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
@@ -12,13 +15,18 @@ extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
/*
- * Implementation details:
- *
- * * The weird n/20000 thing suppresses a "comparison is always false due to
- * limited range of data type" warning with non-const 8-bit arguments.
- * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
- * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
+ * The microseconds/nanosecond delay multiplicators are used to convert a
+ * constant microseconds/nanoseconds value to a value which can be used by the
+ * architectures specific implementation to transform it into loops.
+ */
+#define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, USEC_PER_SEC))
+#define NDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, NSEC_PER_SEC))
+
+/*
+ * The maximum constant udelay/ndelay value picked out of thin air to prevent
+ * too long constant udelays/ndelays.
*/
+#define DELAY_CONST_MAX 20000
/**
* udelay - Inserting a delay based on microseconds with busy waiting
@@ -45,17 +53,17 @@ extern void __delay(unsigned long loops);
* #. cache behaviour affecting the time it takes to execute the loop function.
* #. CPU clock rate changes.
*/
-#define udelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / 20000 >= 1) \
- __bad_udelay(); \
- else \
- __const_udelay((n) * 0x10c7ul); \
- } else { \
- __udelay(n); \
- } \
- })
+static __always_inline void udelay(unsigned long usec)
+{
+ if (__builtin_constant_p(usec)) {
+ if (usec >= DELAY_CONST_MAX)
+ __bad_udelay();
+ else
+ __const_udelay(usec * UDELAY_CONST_MULT);
+ } else {
+ __udelay(usec);
+ }
+}
/**
* ndelay - Inserting a delay based on nanoseconds with busy waiting
@@ -63,16 +71,17 @@ extern void __delay(unsigned long loops);
*
* See udelay() for basic information about ndelay() and it's variants.
*/
-#define ndelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / 20000 >= 1) \
- __bad_ndelay(); \
- else \
- __const_udelay((n) * 5ul); \
- } else { \
- __ndelay(n); \
- } \
- })
+static __always_inline void ndelay(unsigned long nsec)
+{
+ if (__builtin_constant_p(nsec)) {
+ if (nsec >= DELAY_CONST_MAX)
+ __bad_udelay();
+ else
+ __const_udelay(nsec * NDELAY_CONST_MULT);
+ } else {
+ __udelay(nsec);
+ }
+}
+#define ndelay(x) ndelay(x)
#endif /* __ASM_GENERIC_DELAY_H */
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 07/16] timers: Adjust flseep() to reflect reality
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (5 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 06/16] delay: Rework udelay and ndelay Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 08/16] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
` (9 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Heiner Kallweit, David S. Miller
fsleep() simply implements the recommendations of the outdated
documentation in "Documentation/timers/timers-howto.rst". This should be a
user friendly interface to choose always the best timeout function
approach:
- udelay() for very short sleep durations shorter than 10 microseconds
- usleep_range() for sleep durations until 20 milliseconds
- msleep() for the others
The actual implementation has several problems:
- It does not take into account that HZ resolution also has an impact on
granularity of jiffies and has also an impact on the granularity of the
buckets of timer wheel levels. This means that accuracy for the timeout
does not have an upper limit. When executing fsleep(20000) on a HZ=100
system, the possible additional slack will be 50% as the granularity of
the buckets in the lowest level is 10 milliseconds.
- The upper limit of usleep_range() is twice the requested timeout. When no
other interrupts occur in this range, the maximum value is used. This
means that the requested sleep length has then an additional delay of
100%.
Change the thresholds for the decisions in fsleep() to make sure the
maximum slack which is added to the sleep duration is 25%.
Note: Outdated documentation will be updated in a followup patch.
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
include/linux/delay.h | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/include/linux/delay.h b/include/linux/delay.h
index 2de509e4adce..89866bab100d 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -11,6 +11,7 @@
#include <linux/math.h>
#include <linux/sched.h>
+#include <linux/jiffies.h>
extern unsigned long loops_per_jiffy;
@@ -102,15 +103,35 @@ static inline void ssleep(unsigned int seconds)
msleep(seconds * 1000);
}
-/* see Documentation/timers/timers-howto.rst for the thresholds */
+static const unsigned int max_slack_shift = 2;
+#define USLEEP_RANGE_UPPER_BOUND ((TICK_NSEC << max_slack_shift) / NSEC_PER_USEC)
+
+/**
+ * fsleep - flexible sleep which autoselects the best mechanism
+ * @usecs: requested sleep duration in microseconds
+ *
+ * flseep() selects the best mechanism that will provide maximum 25% slack
+ * to the requested sleep duration. Therefore it uses:
+ *
+ * * udelay() loop for sleep durations <= 10 microseconds to avoid hrtimer
+ * overhead for really short sleep durations.
+ * * usleep_range() for sleep durations which would lead with the usage of
+ * msleep() to a slack larger than 25%. This depends on the granularity of
+ * jiffies.
+ * * msleep() for all other sleep durations.
+ *
+ * Note: When %CONFIG_HIGH_RES_TIMERS is not set, all sleeps are processed with
+ * the granularity of jiffies and the slack might exceed 25% especially for
+ * short sleep durations.
+ */
static inline void fsleep(unsigned long usecs)
{
if (usecs <= 10)
udelay(usecs);
- else if (usecs <= 20000)
- usleep_range(usecs, 2 * usecs);
+ else if (usecs < USLEEP_RANGE_UPPER_BOUND)
+ usleep_range(usecs, usecs + (usecs >> max_slack_shift));
else
- msleep(DIV_ROUND_UP(usecs, 1000));
+ msleep(DIV_ROUND_UP(usecs, USEC_PER_MSEC));
}
#endif /* defined(_LINUX_DELAY_H) */
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 08/16] mm/damon/core: Use generic upper bound recommondation for usleep_range()
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (6 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 07/16] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 09/16] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
` (8 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, SeongJae Park, Andrew Morton, damon, linux-mm
The upper bound for usleep_range_idle() was taken from the outdated
documentation. As a recommondation for the upper bound of usleep_range()
depends on HZ configuration it is not possible to hard code it.
Use the define "USLEEP_RANGE_UPPER_BOUND" instead.
Cc: SeongJae Park <sj@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: damon@lists.linux.dev
Cc: linux-mm@kvack.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: SeongJae Park <sj@kernel.org>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
mm/damon/core.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index c725c78b43f0..79efd8089d6c 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1892,8 +1892,7 @@ static unsigned long damos_wmark_wait_us(struct damos *scheme)
static void kdamond_usleep(unsigned long usecs)
{
- /* See Documentation/timers/timers-howto.rst for the thresholds */
- if (usecs > 20 * USEC_PER_MSEC)
+ if (usecs >= USLEEP_RANGE_UPPER_BOUND)
schedule_timeout_idle(usecs_to_jiffies(usecs));
else
usleep_range_idle(usecs, usecs + 1);
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 09/16] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (7 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 08/16] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-15 13:54 ` Frederic Weisbecker
2024-10-14 8:22 ` [PATCH v3 10/16] checkpatch: Remove links to outdated documentation Anna-Maria Behnsen
` (7 subsequent siblings)
16 siblings, 1 reply; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda
There is a warning in checkpatch script that triggers, when min and max
arguments of usleep_range_state() are in reverse order. This check does
only cover callsites which uses constants. Add this check into the code as
a WARN_ON_ONCE() to also cover callsites not using constants and fix the
miss usage by resetting the delta to 0.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v3: Drop removal of checkpatch check, fix delta value
---
kernel/time/sleep_timeout.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
index f3f246e4c8d1..3054e5232d20 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -364,6 +364,9 @@ void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned i
ktime_t exp = ktime_add_us(ktime_get(), min);
u64 delta = (u64)(max - min) * NSEC_PER_USEC;
+ if (WARN_ON_ONCE(max < min))
+ delta = 0;
+
for (;;) {
__set_current_state(state);
/* Do not return before the requested sleep time has elapsed */
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 10/16] checkpatch: Remove links to outdated documentation
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (8 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 09/16] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-15 14:08 ` Frederic Weisbecker
2024-10-14 8:22 ` [PATCH v3 11/16] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
` (6 subsequent siblings)
16 siblings, 1 reply; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Andy Whitcroft, Joe Perches, Dwaipayan Ray
checkpatch.pl checks for several things related to sleep and delay
functions. In all warnings the outdated documentation is referenced. Also
in checkpatch kernel documentation the outdated documentation is
referenced.
Replace the links to the outdated documentation with links to the function
description.
Note: Update of the outdated checkpatch checks is done in a second step.
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v3: new in v3, replace only the links to the outdated documentation
---
Documentation/dev-tools/checkpatch.rst | 2 --
scripts/checkpatch.pl | 10 +++++-----
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
index a9fac978a525..abb3ff682076 100644
--- a/Documentation/dev-tools/checkpatch.rst
+++ b/Documentation/dev-tools/checkpatch.rst
@@ -470,8 +470,6 @@ API usage
usleep_range() should be preferred over udelay(). The proper way of
using usleep_range() is mentioned in the kernel docs.
- See: https://www.kernel.org/doc/html/latest/timers/timers-howto.html#delays-information-on-the-various-kernel-delay-sleep-mechanisms
-
Comments
--------
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4427572b2477..98790fe5115d 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6597,11 +6597,11 @@ sub process {
# ignore udelay's < 10, however
if (! ($delay < 10) ) {
CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
+ "usleep_range is preferred over udelay; see function description of usleep_range() and udelay().\n" . $herecurr);
}
if ($delay > 2000) {
WARN("LONG_UDELAY",
- "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
+ "long udelay - prefer mdelay; see function description of mdelay().\n" . $herecurr);
}
}
@@ -6609,7 +6609,7 @@ sub process {
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
+ "msleep < 20ms can sleep for up to 20ms; see function description of msleep().\n" . $herecurr);
}
}
@@ -7077,11 +7077,11 @@ sub process {
my $max = $7;
if ($min eq $max) {
WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
+ "usleep_range should not use min == max args; see function description of usleep_range().\n" . "$here\n$stat\n");
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
$min > $max) {
WARN("USLEEP_RANGE",
- "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
+ "usleep_range args reversed, use min then max; see function description of usleep_range().\n" . "$here\n$stat\n");
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 11/16] regulator: core: Use fsleep() to get best sleep mechanism
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (9 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 10/16] checkpatch: Remove links to outdated documentation Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 12/16] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
` (5 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Liam Girdwood, Mark Brown
_regulator_delay_helper() implements the recommondation of the outdated
documentation which sleep mechanism should be used. There is already a
function in place which does everything and also maps to reality called
fsleep().
Use fsleep() directly.
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
v2: Use fsleep() directly
---
drivers/regulator/core.c | 47 ++++-------------------------------------------
1 file changed, 4 insertions(+), 43 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 1179766811f5..2605f6e76ea4 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2642,45 +2642,6 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
return 0;
}
-/**
- * _regulator_delay_helper - a delay helper function
- * @delay: time to delay in microseconds
- *
- * Delay for the requested amount of time as per the guidelines in:
- *
- * Documentation/timers/timers-howto.rst
- *
- * The assumption here is that these regulator operations will never used in
- * atomic context and therefore sleeping functions can be used.
- */
-static void _regulator_delay_helper(unsigned int delay)
-{
- unsigned int ms = delay / 1000;
- unsigned int us = delay % 1000;
-
- if (ms > 0) {
- /*
- * For small enough values, handle super-millisecond
- * delays in the usleep_range() call below.
- */
- if (ms < 20)
- us += ms * 1000;
- else
- msleep(ms);
- }
-
- /*
- * Give the scheduler some room to coalesce with any other
- * wakeup sources. For delays shorter than 10 us, don't even
- * bother setting up high-resolution timers and just busy-
- * loop.
- */
- if (us >= 10)
- usleep_range(us, us + 100);
- else
- udelay(us);
-}
-
/**
* _regulator_check_status_enabled - check if regulator status can be
* interpreted as "regulator is enabled"
@@ -2733,7 +2694,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
s64 remaining = ktime_us_delta(end, ktime_get_boottime());
if (remaining > 0)
- _regulator_delay_helper(remaining);
+ fsleep(remaining);
}
if (rdev->ena_pin) {
@@ -2767,7 +2728,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
int time_remaining = delay;
while (time_remaining > 0) {
- _regulator_delay_helper(rdev->desc->poll_enabled_time);
+ fsleep(rdev->desc->poll_enabled_time);
if (rdev->desc->ops->get_status) {
ret = _regulator_check_status_enabled(rdev);
@@ -2786,7 +2747,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
return -ETIMEDOUT;
}
} else {
- _regulator_delay_helper(delay);
+ fsleep(delay);
}
trace_regulator_enable_complete(rdev_get_name(rdev));
@@ -3730,7 +3691,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
/* Insert any necessary delays */
- _regulator_delay_helper(delay);
+ fsleep(delay);
if (best_val >= 0) {
unsigned long data = best_val;
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 12/16] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (10 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 11/16] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 13/16] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
` (4 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Heiner Kallweit, Jaroslav Kysela, Takashi Iwai,
netdev, linux-sound
Function descriptions in iopoll.h, regmap.h, phy.h and sound/soc/sof/ops.h
copied all the same outdated documentation about sleep/delay function
limitations. In those comments, the generic (and still outdated) timer
documentation file is referenced.
As proper function descriptions for used delay and sleep functions are in
place, simply update the descriptions to reference to them. While at it fix
missing colon after "Returns" in function description and move return value
description to the end of the function description.
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: netdev@vger.kernel.org
Cc: linux-sound@vger.kernel.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch> # for phy.h
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
v2: Add cleanup of usage of 'Returns' in function description
---
include/linux/iopoll.h | 52 +++++++++++++++++++++++++-------------------------
include/linux/phy.h | 9 +++++----
include/linux/regmap.h | 38 ++++++++++++++++++------------------
sound/soc/sof/ops.h | 8 ++++----
4 files changed, 54 insertions(+), 53 deletions(-)
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index 19a7b00baff4..91324c331a4b 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -19,19 +19,19 @@
* @op: accessor function (takes @args as its arguments)
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
* @sleep_before_read: if it is true, sleep @sleep_us before read.
* @args: arguments for @op poll
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @args is stored in @val. Must not
- * be called from atomic context if sleep_us or timeout_us are used.
- *
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @args is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
*/
#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
sleep_before_read, args...) \
@@ -64,22 +64,22 @@
* @op: accessor function (takes @args as its arguments)
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops). Should
- * be less than ~10us since udelay is used (see
- * Documentation/timers/timers-howto.rst).
+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Please
+ * read udelay() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
* @delay_before_read: if it is true, delay @delay_us before read.
* @args: arguments for @op poll
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @args is stored in @val.
- *
* This macro does not rely on timekeeping. Hence it is safe to call even when
* timekeeping is suspended, at the expense of an underestimation of wall clock
* time, which is rather minimal with a non-zero delay_us.
*
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @args is stored in @val.
*/
#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \
delay_before_read, args...) \
@@ -119,17 +119,17 @@
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @addr is stored in @val. Must not
- * be called from atomic context if sleep_us or timeout_us are used.
- *
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
*/
#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
@@ -140,16 +140,16 @@
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops). Should
- * be less than ~10us since udelay is used (see
- * Documentation/timers/timers-howto.rst).
+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Please
+ * read udelay() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @addr is stored in @val.
- *
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val.
*/
#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, false, addr)
diff --git a/include/linux/phy.h b/include/linux/phy.h
index a98bc91a0cde..504766d4b2d5 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1378,12 +1378,13 @@ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
* @regnum: The register on the MMD to read
* @val: Variable to read the register into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
* @sleep_before_read: if it is true, sleep @sleep_us before read.
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @args is stored in @val. Must not
* be called from atomic context if sleep_us or timeout_us are used.
*/
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index f9ccad32fc5c..75f162b60ba1 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -106,17 +106,17 @@ struct reg_sequence {
* @addr: Address to poll
* @val: Unsigned integer variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
+ * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
* error return value in case of a error read. In the two former cases,
* the last read value at @addr is stored in @val. Must not be called
* from atomic context if sleep_us or timeout_us are used.
- *
- * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
*/
#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \
({ \
@@ -133,20 +133,20 @@ struct reg_sequence {
* @addr: Address to poll
* @val: Unsigned integer variable to read the value into
* @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops).
- * Should be less than ~10us since udelay is used
- * (see Documentation/timers/timers-howto.rst).
+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Please
+ * read udelay() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
- * error return value in case of a error read. In the two former cases,
- * the last read value at @addr is stored in @val.
- *
* This is modelled after the readx_poll_timeout_atomic macros in linux/iopoll.h.
*
* Note: In general regmap cannot be used in atomic context. If you want to use
* this macro then first setup your regmap for atomic use (flat or no cache
* and MMIO regmap).
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
+ * error return value in case of a error read. In the two former cases,
+ * the last read value at @addr is stored in @val.
*/
#define regmap_read_poll_timeout_atomic(map, addr, val, cond, delay_us, timeout_us) \
({ \
@@ -177,17 +177,17 @@ struct reg_sequence {
* @field: Regmap field to read from
* @val: Unsigned integer variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read
+ * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read
* error return value in case of a error read. In the two former cases,
* the last read value at @addr is stored in @val. Must not be called
* from atomic context if sleep_us or timeout_us are used.
- *
- * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
*/
#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \
({ \
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 2584621c3b2d..d73644e85b6e 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -597,12 +597,12 @@ snd_sof_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type)
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @addr is stored in @val. Must not
* be called from atomic context if sleep_us or timeout_us are used.
*
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 13/16] powerpc/rtas: Use fsleep() to minimize additional sleep duration
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (11 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 12/16] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 14/16] media: anysee: Fix and remove outdated comment Anna-Maria Behnsen
` (3 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Michael Ellerman, Nathan Lynch, linuxppc-dev
When commit 38f7b7067dae ("powerpc/rtas: rtas_busy_delay() improvements")
was introduced, documentation about proper usage of sleep related functions
was outdated.
The commit message references the usage of a HZ=100 system. When using a
20ms sleep duration on such a system and therefore using msleep(), the
possible additional slack will be +10ms.
When the system is configured with HZ=100 the granularity of a jiffy and of
a bucket of the lowest timer wheel level is 10ms. To make sure a timer will
not expire early (when queueing of the timer races with an concurrent
update of jiffies), timers are always queued into the next bucket. This is
the reason for the maximal possible slack of 10ms.
fsleep() limits the maximal possible slack to 25% by making threshold
between usleep_range() and msleep() HZ dependent. As soon as the accuracy
of msleep() is sufficient, the less expensive timer list timer based
sleeping function is used instead of the more expensive hrtimer based
usleep_range() function. The udelay() will not be used in this specific
usecase as the lowest sleep length is larger than 1 millisecond.
Use fsleep() directly instead of using an own heuristic for the best
sleeping mechanism to use.
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
v2: fix typos
---
arch/powerpc/kernel/rtas.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index f7e86e09c49f..d31c9799cab2 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1390,21 +1390,14 @@ bool __ref rtas_busy_delay(int status)
*/
ms = clamp(ms, 1U, 1000U);
/*
- * The delay hint is an order-of-magnitude suggestion, not
- * a minimum. It is fine, possibly even advantageous, for
- * us to pause for less time than hinted. For small values,
- * use usleep_range() to ensure we don't sleep much longer
- * than actually needed.
- *
- * See Documentation/timers/timers-howto.rst for
- * explanation of the threshold used here. In effect we use
- * usleep_range() for 9900 and 9901, msleep() for
- * 9902-9905.
+ * The delay hint is an order-of-magnitude suggestion, not a
+ * minimum. It is fine, possibly even advantageous, for us to
+ * pause for less time than hinted. To make sure pause time will
+ * not be way longer than requested independent of HZ
+ * configuration, use fsleep(). See fsleep() for details of
+ * used sleeping functions.
*/
- if (ms <= 20)
- usleep_range(ms * 100, ms * 1000);
- else
- msleep(ms);
+ fsleep(ms * 1000);
break;
case RTAS_BUSY:
ret = true;
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 14/16] media: anysee: Fix and remove outdated comment
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (12 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 13/16] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-15 14:11 ` Frederic Weisbecker
2024-10-14 8:22 ` [PATCH v3 15/16] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
` (2 subsequent siblings)
16 siblings, 1 reply; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Mauro Carvalho Chehab, linux-media,
Sebastian Andrzej Siewior
anysee driver was transformed to use usbv2 years ago. The comments in
anysee_ctrl_msg() still are referencing the old interfaces where msleep()
was used. The v2 interfaces also changed over the years and with commit
1162c7b383a6 ("[media] dvb_usb_v2: refactor dvb_usbv2_generic_rw()") the
usage of msleep() was gone anyway.
Remove FIXME comment and update also comment before call to
dvb_usbv2_generic_rw_locked().
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: linux-media@vger.kernel.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
v3: Remove FIXME comment completely
---
drivers/media/usb/dvb-usb-v2/anysee.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index 8699846eb416..bea12cdc85e8 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -46,24 +46,15 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d,
dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, state->buf);
- /* We need receive one message more after dvb_usb_generic_rw due
- to weird transaction flow, which is 1 x send + 2 x receive. */
+ /*
+ * We need receive one message more after dvb_usbv2_generic_rw_locked()
+ * due to weird transaction flow, which is 1 x send + 2 x receive.
+ */
ret = dvb_usbv2_generic_rw_locked(d, state->buf, sizeof(state->buf),
state->buf, sizeof(state->buf));
if (ret)
goto error_unlock;
- /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
- * (EPIPE, Broken pipe). Function supports currently msleep() as a
- * parameter but I would not like to use it, since according to
- * Documentation/timers/timers-howto.rst it should not be used such
- * short, under < 20ms, sleeps. Repeating failed message would be
- * better choice as not to add unwanted delays...
- * Fixing that correctly is one of those or both;
- * 1) use repeat if possible
- * 2) add suitable delay
- */
-
/* get answer, retry few times if error returned */
for (i = 0; i < 3; i++) {
/* receive 2nd answer */
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 15/16] timers/Documentation: Cleanup delay/sleep documentation
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (13 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 14/16] media: anysee: Fix and remove outdated comment Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
2024-10-14 16:22 ` (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Mark Brown
16 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda
The documentation which tries to give advices how to properly inserting
delays or sleeps is outdated. The file name is 'timers-howto.rst' which
might be misleading as it is only about delay and sleep mechanisms and not
how to use timers.
Update the documentation by integrating the important parts from the
related function descriptions and move it all into a self explaining file
with the name "delay_sleep_functions.rst".
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
---
Documentation/timers/delay_sleep_functions.rst | 121 +++++++++++++++++++++++++
Documentation/timers/index.rst | 2 +-
Documentation/timers/timers-howto.rst | 115 -----------------------
3 files changed, 122 insertions(+), 116 deletions(-)
diff --git a/Documentation/timers/delay_sleep_functions.rst b/Documentation/timers/delay_sleep_functions.rst
new file mode 100644
index 000000000000..49d603a3f113
--- /dev/null
+++ b/Documentation/timers/delay_sleep_functions.rst
@@ -0,0 +1,121 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Delay and sleep mechanisms
+==========================
+
+This document seeks to answer the common question: "What is the
+RightWay (TM) to insert a delay?"
+
+This question is most often faced by driver writers who have to
+deal with hardware delays and who may not be the most intimately
+familiar with the inner workings of the Linux Kernel.
+
+The following table gives a rough overview about the existing function
+'families' and their limitations. This overview table does not replace the
+reading of the function description before usage!
+
+.. list-table::
+ :widths: 20 20 20 20 20
+ :header-rows: 2
+
+ * -
+ - `*delay()`
+ - `usleep_range*()`
+ - `*sleep()`
+ - `fsleep()`
+ * -
+ - busy-wait loop
+ - hrtimers based
+ - timer list timers based
+ - combines the others
+ * - Usage in atomic Context
+ - yes
+ - no
+ - no
+ - no
+ * - precise on "short intervals"
+ - yes
+ - yes
+ - depends
+ - yes
+ * - precise on "long intervals"
+ - Do not use!
+ - yes
+ - max 12.5% slack
+ - yes
+ * - interruptible variant
+ - no
+ - yes
+ - yes
+ - no
+
+A generic advice for non atomic contexts could be:
+
+#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
+ others)
+#. Use `*sleep()` whenever possible
+#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
+#. Use `*delay()` for very, very short delays
+
+Find some more detailed information about the function 'families' in the next
+sections.
+
+`*delay()` family of functions
+------------------------------
+
+These functions use the jiffy estimation of clock speed and will busy wait for
+enough loop cycles to achieve the desired delay. udelay() is the basic
+implementation and ndelay() as well as mdelay() are variants.
+
+These functions are mainly used to add a delay in atomic context. Please make
+sure to ask yourself before adding a delay in atomic context: Is this really
+required?
+
+.. kernel-doc:: include/asm-generic/delay.h
+ :identifiers: udelay ndelay
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: mdelay
+
+
+`usleep_range*()` and `*sleep()` family of functions
+----------------------------------------------------
+
+These functions use hrtimers or timer list timers to provide the requested
+sleeping duration. In order to decide which function is the right one to use,
+take some basic information into account:
+
+#. hrtimers are more expensive as they are using an rb-tree (instead of hashing)
+#. hrtimers are more expensive when the requested sleeping duration is the first
+ timer which means real hardware has to be programmed
+#. timer list timers always provide some sort of slack as they are jiffy based
+
+The generic advice is repeated here:
+
+#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
+ others)
+#. Use `*sleep()` whenever possible
+#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
+
+First check fsleep() function description and to learn more about accuracy,
+please check msleep() function description.
+
+
+`usleep_range*()`
+~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: usleep_range usleep_range_idle
+
+.. kernel-doc:: kernel/time/sleep_timeout.c
+ :identifiers: usleep_range_state
+
+
+`*sleep()`
+~~~~~~~~~~
+
+.. kernel-doc:: kernel/time/sleep_timeout.c
+ :identifiers: msleep msleep_interruptible
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: ssleep fsleep
diff --git a/Documentation/timers/index.rst b/Documentation/timers/index.rst
index 983f91f8f023..4e88116e4dcf 100644
--- a/Documentation/timers/index.rst
+++ b/Documentation/timers/index.rst
@@ -12,7 +12,7 @@ Timers
hrtimers
no_hz
timekeeping
- timers-howto
+ delay_sleep_functions
.. only:: subproject and html
diff --git a/Documentation/timers/timers-howto.rst b/Documentation/timers/timers-howto.rst
deleted file mode 100644
index ef7a4652ccc9..000000000000
--- a/Documentation/timers/timers-howto.rst
+++ /dev/null
@@ -1,115 +0,0 @@
-===================================================================
-delays - Information on the various kernel delay / sleep mechanisms
-===================================================================
-
-This document seeks to answer the common question: "What is the
-RightWay (TM) to insert a delay?"
-
-This question is most often faced by driver writers who have to
-deal with hardware delays and who may not be the most intimately
-familiar with the inner workings of the Linux Kernel.
-
-
-Inserting Delays
-----------------
-
-The first, and most important, question you need to ask is "Is my
-code in an atomic context?" This should be followed closely by "Does
-it really need to delay in atomic context?" If so...
-
-ATOMIC CONTEXT:
- You must use the `*delay` family of functions. These
- functions use the jiffy estimation of clock speed
- and will busy wait for enough loop cycles to achieve
- the desired delay:
-
- ndelay(unsigned long nsecs)
- udelay(unsigned long usecs)
- mdelay(unsigned long msecs)
-
- udelay is the generally preferred API; ndelay-level
- precision may not actually exist on many non-PC devices.
-
- mdelay is macro wrapper around udelay, to account for
- possible overflow when passing large arguments to udelay.
- In general, use of mdelay is discouraged and code should
- be refactored to allow for the use of msleep.
-
-NON-ATOMIC CONTEXT:
- You should use the `*sleep[_range]` family of functions.
- There are a few more options here, while any of them may
- work correctly, using the "right" sleep function will
- help the scheduler, power management, and just make your
- driver better :)
-
- -- Backed by busy-wait loop:
-
- udelay(unsigned long usecs)
-
- -- Backed by hrtimers:
-
- usleep_range(unsigned long min, unsigned long max)
-
- -- Backed by jiffies / legacy_timers
-
- msleep(unsigned long msecs)
- msleep_interruptible(unsigned long msecs)
-
- Unlike the `*delay` family, the underlying mechanism
- driving each of these calls varies, thus there are
- quirks you should be aware of.
-
-
- SLEEPING FOR "A FEW" USECS ( < ~10us? ):
- * Use udelay
-
- - Why not usleep?
- On slower systems, (embedded, OR perhaps a speed-
- stepped PC!) the overhead of setting up the hrtimers
- for usleep *may* not be worth it. Such an evaluation
- will obviously depend on your specific situation, but
- it is something to be aware of.
-
- SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
- * Use usleep_range
-
- - Why not msleep for (1ms - 20ms)?
- Explained originally here:
- https://lore.kernel.org/r/15327.1186166232@lwn.net
-
- msleep(1~20) may not do what the caller intends, and
- will often sleep longer (~20 ms actual sleep for any
- value given in the 1~20ms range). In many cases this
- is not the desired behavior.
-
- - Why is there no "usleep" / What is a good range?
- Since usleep_range is built on top of hrtimers, the
- wakeup will be very precise (ish), thus a simple
- usleep function would likely introduce a large number
- of undesired interrupts.
-
- With the introduction of a range, the scheduler is
- free to coalesce your wakeup with any other wakeup
- that may have happened for other reasons, or at the
- worst case, fire an interrupt for your upper bound.
-
- The larger a range you supply, the greater a chance
- that you will not trigger an interrupt; this should
- be balanced with what is an acceptable upper bound on
- delay / performance for your specific code path. Exact
- tolerances here are very situation specific, thus it
- is left to the caller to determine a reasonable range.
-
- SLEEPING FOR LARGER MSECS ( 10ms+ )
- * Use msleep or possibly msleep_interruptible
-
- - What's the difference?
- msleep sets the current task to TASK_UNINTERRUPTIBLE
- whereas msleep_interruptible sets the current task to
- TASK_INTERRUPTIBLE before scheduling the sleep. In
- short, the difference is whether the sleep can be ended
- early by a signal. In general, just use msleep unless
- you know you have a need for the interruptible variant.
-
- FLEXIBLE SLEEPING (any delay, uninterruptible)
- * Use fsleep
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (14 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 15/16] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
@ 2024-10-14 8:22 ` Anna-Maria Behnsen
2024-10-15 14:22 ` Frederic Weisbecker
2024-10-16 10:05 ` [PATCH v4] " Anna-Maria Behnsen
2024-10-14 16:22 ` (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Mark Brown
16 siblings, 2 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-14 8:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Andy Whitcroft, Joe Perches, Dwaipayan Ray
checkpatch.pl checks for several things related to sleep and delay
functions. In all warnings the outdated documentation is referenced. All
broken parts are listed one by one in the following with an explanation why
this check is broken. For a basic background of those functions please also
refere to the updated function descriptions of udelay(), nsleep_range() and
msleep().
Be aware: The change is done with a perl knowledge of the level "I'm able
to spell perl".
The following checks are broken:
- Check: (! ($delay < 10) )
Message: "usleep_range is preferred over udelay;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: When it is an atomic context, udelay() is
mandatory.
- Check: ($min eq $max)
Message: "usleep_range should not use min == max args;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: When the requested accuracy for the sleep
duration requires it, it is also valid to use
min == max.
- Check: ($delay > 2000)
Message: "long udelay - prefer mdelay;
see arch/arm/include/asm/delay.h\n"
Why is the check broken: The threshold when to start using mdelay() to
prevent an overflow depends on
MAX_UDELAY_MS. This value is architecture
dependent. The used value for the check and
reference is arm specific. Generic would be 5ms,
but this would "break" arm, loongarch and mips
and also the arm value might "break" mips and
loongarch in some configurations.
- Check: ($1 < 20)
Message: "msleep < 20ms can sleep for up to 20ms;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: msleep(1) might sleep up to 20ms but only on a
HZ=100 system. On a HZ=1000 system this will be
2ms. This means, the threshold cannot be hard
coded as it depends on HZ (jiffy granularity and
timer wheel bucket/level granularity) and also
on the required accuracy of the callsite. See
msleep() and also the USLEEP_RANGE_UPPER_BOUND
value.
Remove all broken checks. Update checkpatch documentation accordingly.
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v3: Move it to the end of the queue and adapt it to the new patch which
removes the link to the outdated documentation before.
v2: Rephrase commit message
---
Documentation/dev-tools/checkpatch.rst | 4 ----
scripts/checkpatch.pl | 38 ----------------------------------
2 files changed, 42 deletions(-)
diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
index abb3ff682076..f5c27be9e673 100644
--- a/Documentation/dev-tools/checkpatch.rst
+++ b/Documentation/dev-tools/checkpatch.rst
@@ -466,10 +466,6 @@ API usage
**UAPI_INCLUDE**
No #include statements in include/uapi should use a uapi/ path.
- **USLEEP_RANGE**
- usleep_range() should be preferred over udelay(). The proper way of
- using usleep_range() is mentioned in the kernel docs.
-
Comments
--------
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 98790fe5115d..34d4b5beda29 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6591,28 +6591,6 @@ sub process {
}
}
-# prefer usleep_range over udelay
- if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
- my $delay = $1;
- # ignore udelay's < 10, however
- if (! ($delay < 10) ) {
- CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see function description of usleep_range() and udelay().\n" . $herecurr);
- }
- if ($delay > 2000) {
- WARN("LONG_UDELAY",
- "long udelay - prefer mdelay; see function description of mdelay().\n" . $herecurr);
- }
- }
-
-# warn about unexpectedly long msleep's
- if ($line =~ /\bmsleep\s*\((\d+)\);/) {
- if ($1 < 20) {
- WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see function description of msleep().\n" . $herecurr);
- }
- }
-
# check for comparisons of jiffies
if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
WARN("JIFFIES_COMPARISON",
@@ -7069,22 +7047,6 @@ sub process {
}
}
-# check usleep_range arguments
- if ($perl_version_ok &&
- defined $stat &&
- $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
- my $min = $1;
- my $max = $7;
- if ($min eq $max) {
- WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see function description of usleep_range().\n" . "$here\n$stat\n");
- } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
- $min > $max) {
- WARN("USLEEP_RANGE",
- "usleep_range args reversed, use min then max; see function description of usleep_range().\n" . "$here\n$stat\n");
- }
- }
-
# check for naked sscanf
if ($perl_version_ok &&
defined $stat &&
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (15 preceding siblings ...)
2024-10-14 8:22 ` [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
@ 2024-10-14 16:22 ` Mark Brown
2024-10-18 8:06 ` Anna-Maria Behnsen
16 siblings, 1 reply; 28+ messages in thread
From: Mark Brown @ 2024-10-14 16:22 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
Anna-Maria Behnsen
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Miguel Ojeda,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, netdev, linux-sound, Michael Ellerman, Nathan Lynch,
linuxppc-dev, Mauro Carvalho Chehab, linux-media,
Sebastian Andrzej Siewior
On Mon, 14 Oct 2024 10:22:17 +0200, Anna-Maria Behnsen wrote:
> a question about which sleeping function should be used in acpi_os_sleep()
> started a discussion and examination about the existing documentation and
> implementation of functions which insert a sleep/delay.
>
> The result of the discussion was, that the documentation is outdated and
> the implemented fsleep() reflects the outdated documentation but doesn't
> help to reflect reality which in turns leads to the queue which covers the
> following things:
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
Thanks!
[11/16] regulator: core: Use fsleep() to get best sleep mechanism
commit: f20669fbcf99d0e15e94fb50929bb1c41618e197
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 09/16] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-10-14 8:22 ` [PATCH v3 09/16] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
@ 2024-10-15 13:54 ` Frederic Weisbecker
0 siblings, 0 replies; 28+ messages in thread
From: Frederic Weisbecker @ 2024-10-15 13:54 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, rust-for-linux, Alice Ryhl, FUJITA Tomonori,
Andrew Lunn, Miguel Ojeda
Le Mon, Oct 14, 2024 at 10:22:26AM +0200, Anna-Maria Behnsen a écrit :
> There is a warning in checkpatch script that triggers, when min and max
> arguments of usleep_range_state() are in reverse order. This check does
> only cover callsites which uses constants. Add this check into the code as
> a WARN_ON_ONCE() to also cover callsites not using constants and fix the
> miss usage by resetting the delta to 0.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 10/16] checkpatch: Remove links to outdated documentation
2024-10-14 8:22 ` [PATCH v3 10/16] checkpatch: Remove links to outdated documentation Anna-Maria Behnsen
@ 2024-10-15 14:08 ` Frederic Weisbecker
0 siblings, 0 replies; 28+ messages in thread
From: Frederic Weisbecker @ 2024-10-15 14:08 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, rust-for-linux, Alice Ryhl, FUJITA Tomonori,
Andrew Lunn, Miguel Ojeda, Andy Whitcroft, Joe Perches,
Dwaipayan Ray
Le Mon, Oct 14, 2024 at 10:22:27AM +0200, Anna-Maria Behnsen a écrit :
> checkpatch.pl checks for several things related to sleep and delay
> functions. In all warnings the outdated documentation is referenced. Also
> in checkpatch kernel documentation the outdated documentation is
> referenced.
>
> Replace the links to the outdated documentation with links to the function
> description.
>
> Note: Update of the outdated checkpatch checks is done in a second step.
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 14/16] media: anysee: Fix and remove outdated comment
2024-10-14 8:22 ` [PATCH v3 14/16] media: anysee: Fix and remove outdated comment Anna-Maria Behnsen
@ 2024-10-15 14:11 ` Frederic Weisbecker
0 siblings, 0 replies; 28+ messages in thread
From: Frederic Weisbecker @ 2024-10-15 14:11 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, rust-for-linux, Alice Ryhl, FUJITA Tomonori,
Andrew Lunn, Miguel Ojeda, Mauro Carvalho Chehab, linux-media,
Sebastian Andrzej Siewior
Le Mon, Oct 14, 2024 at 10:22:31AM +0200, Anna-Maria Behnsen a écrit :
> anysee driver was transformed to use usbv2 years ago. The comments in
> anysee_ctrl_msg() still are referencing the old interfaces where msleep()
> was used. The v2 interfaces also changed over the years and with commit
> 1162c7b383a6 ("[media] dvb_usb_v2: refactor dvb_usbv2_generic_rw()") the
> usage of msleep() was gone anyway.
>
> Remove FIXME comment and update also comment before call to
> dvb_usbv2_generic_rw_locked().
>
> Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> Cc: linux-media@vger.kernel.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks
2024-10-14 8:22 ` [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
@ 2024-10-15 14:22 ` Frederic Weisbecker
2024-10-16 9:55 ` Anna-Maria Behnsen
2024-10-16 10:05 ` [PATCH v4] " Anna-Maria Behnsen
1 sibling, 1 reply; 28+ messages in thread
From: Frederic Weisbecker @ 2024-10-15 14:22 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, rust-for-linux, Alice Ryhl, FUJITA Tomonori,
Andrew Lunn, Miguel Ojeda, Andy Whitcroft, Joe Perches,
Dwaipayan Ray
Le Mon, Oct 14, 2024 at 10:22:33AM +0200, Anna-Maria Behnsen a écrit :
> checkpatch.pl checks for several things related to sleep and delay
> functions. In all warnings the outdated documentation is referenced. All
> broken parts are listed one by one in the following with an explanation why
> this check is broken. For a basic background of those functions please also
> refere to the updated function descriptions of udelay(), nsleep_range() and
> msleep().
>
> Be aware: The change is done with a perl knowledge of the level "I'm able
> to spell perl".
>
> The following checks are broken:
>
> - Check: (! ($delay < 10) )
> Message: "usleep_range is preferred over udelay;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When it is an atomic context, udelay() is
> mandatory.
>
> - Check: ($min eq $max)
> Message: "usleep_range should not use min == max args;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When the requested accuracy for the sleep
> duration requires it, it is also valid to use
> min == max.
>
> - Check: ($delay > 2000)
> Message: "long udelay - prefer mdelay;
> see arch/arm/include/asm/delay.h\n"
> Why is the check broken: The threshold when to start using mdelay() to
> prevent an overflow depends on
> MAX_UDELAY_MS. This value is architecture
> dependent. The used value for the check and
> reference is arm specific. Generic would be 5ms,
> but this would "break" arm, loongarch and mips
> and also the arm value might "break" mips and
> loongarch in some configurations.
>
> - Check: ($1 < 20)
> Message: "msleep < 20ms can sleep for up to 20ms;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: msleep(1) might sleep up to 20ms but only on a
> HZ=100 system. On a HZ=1000 system this will be
> 2ms. This means, the threshold cannot be hard
> coded as it depends on HZ (jiffy granularity and
> timer wheel bucket/level granularity) and also
> on the required accuracy of the callsite. See
> msleep() and also the USLEEP_RANGE_UPPER_BOUND
> value.
>
> Remove all broken checks. Update checkpatch documentation accordingly.
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> v3: Move it to the end of the queue and adapt it to the new patch which
> removes the link to the outdated documentation before.
> v2: Rephrase commit message
> ---
> Documentation/dev-tools/checkpatch.rst | 4 ----
> scripts/checkpatch.pl | 38 ----------------------------------
> 2 files changed, 42 deletions(-)
>
> diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
> index abb3ff682076..f5c27be9e673 100644
> --- a/Documentation/dev-tools/checkpatch.rst
> +++ b/Documentation/dev-tools/checkpatch.rst
> @@ -466,10 +466,6 @@ API usage
> **UAPI_INCLUDE**
> No #include statements in include/uapi should use a uapi/ path.
>
> - **USLEEP_RANGE**
> - usleep_range() should be preferred over udelay(). The proper way of
> - using usleep_range() is mentioned in the kernel docs.
> -
>
> Comments
> --------
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index 98790fe5115d..34d4b5beda29 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -6591,28 +6591,6 @@ sub process {
> }
> }
>
> -# prefer usleep_range over udelay
> - if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
> - my $delay = $1;
> - # ignore udelay's < 10, however
> - if (! ($delay < 10) ) {
> - CHK("USLEEP_RANGE",
> - "usleep_range is preferred over udelay; see function description of usleep_range() and udelay().\n" . $herecurr);
> - }
> - if ($delay > 2000) {
> - WARN("LONG_UDELAY",
> - "long udelay - prefer mdelay; see function description of mdelay().\n" . $herecurr);
> - }
> - }
> -
> -# warn about unexpectedly long msleep's
> - if ($line =~ /\bmsleep\s*\((\d+)\);/) {
> - if ($1 < 20) {
> - WARN("MSLEEP",
> - "msleep < 20ms can sleep for up to 20ms; see function description of msleep().\n" . $herecurr);
> - }
> - }
> -
> # check for comparisons of jiffies
> if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
> WARN("JIFFIES_COMPARISON",
> @@ -7069,22 +7047,6 @@ sub process {
> }
> }
>
> -# check usleep_range arguments
> - if ($perl_version_ok &&
> - defined $stat &&
> - $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
> - my $min = $1;
> - my $max = $7;
> - if ($min eq $max) {
> - WARN("USLEEP_RANGE",
> - "usleep_range should not use min == max args; see function description of usleep_range().\n" . "$here\n$stat\n");
> - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
> - $min > $max) {
> - WARN("USLEEP_RANGE",
> - "usleep_range args reversed, use min then max; see function description of usleep_range().\n" . "$here\n$stat\n");
Why not keep the min > max static check?
Thanks.
> - }
> - }
> -
> # check for naked sscanf
> if ($perl_version_ok &&
> defined $stat &&
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks
2024-10-15 14:22 ` Frederic Weisbecker
@ 2024-10-16 9:55 ` Anna-Maria Behnsen
0 siblings, 0 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-16 9:55 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, rust-for-linux, Alice Ryhl, FUJITA Tomonori,
Andrew Lunn, Miguel Ojeda, Andy Whitcroft, Joe Perches,
Dwaipayan Ray
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Mon, Oct 14, 2024 at 10:22:33AM +0200, Anna-Maria Behnsen a écrit :
>> checkpatch.pl checks for several things related to sleep and delay
>> functions. In all warnings the outdated documentation is referenced. All
>> broken parts are listed one by one in the following with an explanation why
>> this check is broken. For a basic background of those functions please also
>> refere to the updated function descriptions of udelay(), nsleep_range() and
>> msleep().
>>
>> Be aware: The change is done with a perl knowledge of the level "I'm able
>> to spell perl".
>>
>> The following checks are broken:
>>
>> - Check: (! ($delay < 10) )
>> Message: "usleep_range is preferred over udelay;
>> see Documentation/timers/timers-howto.rst\n"
>> Why is the check broken: When it is an atomic context, udelay() is
>> mandatory.
>>
>> - Check: ($min eq $max)
>> Message: "usleep_range should not use min == max args;
>> see Documentation/timers/timers-howto.rst\n"
>> Why is the check broken: When the requested accuracy for the sleep
>> duration requires it, it is also valid to use
>> min == max.
>>
>> - Check: ($delay > 2000)
>> Message: "long udelay - prefer mdelay;
>> see arch/arm/include/asm/delay.h\n"
>> Why is the check broken: The threshold when to start using mdelay() to
>> prevent an overflow depends on
>> MAX_UDELAY_MS. This value is architecture
>> dependent. The used value for the check and
>> reference is arm specific. Generic would be 5ms,
>> but this would "break" arm, loongarch and mips
>> and also the arm value might "break" mips and
>> loongarch in some configurations.
>>
>> - Check: ($1 < 20)
>> Message: "msleep < 20ms can sleep for up to 20ms;
>> see Documentation/timers/timers-howto.rst\n"
>> Why is the check broken: msleep(1) might sleep up to 20ms but only on a
>> HZ=100 system. On a HZ=1000 system this will be
>> 2ms. This means, the threshold cannot be hard
>> coded as it depends on HZ (jiffy granularity and
>> timer wheel bucket/level granularity) and also
>> on the required accuracy of the callsite. See
>> msleep() and also the USLEEP_RANGE_UPPER_BOUND
>> value.
>>
>> Remove all broken checks. Update checkpatch documentation accordingly.
>>
>> Cc: Andy Whitcroft <apw@canonical.com>
>> Cc: Joe Perches <joe@perches.com>
>> Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>> ---
>> v3: Move it to the end of the queue and adapt it to the new patch which
>> removes the link to the outdated documentation before.
>> v2: Rephrase commit message
>> ---
>> Documentation/dev-tools/checkpatch.rst | 4 ----
>> scripts/checkpatch.pl | 38 ----------------------------------
>> 2 files changed, 42 deletions(-)
>>
>> diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
>> index abb3ff682076..f5c27be9e673 100644
>> --- a/Documentation/dev-tools/checkpatch.rst
>> +++ b/Documentation/dev-tools/checkpatch.rst
>> @@ -466,10 +466,6 @@ API usage
>> **UAPI_INCLUDE**
>> No #include statements in include/uapi should use a uapi/ path.
>>
>> - **USLEEP_RANGE**
>> - usleep_range() should be preferred over udelay(). The proper way of
>> - using usleep_range() is mentioned in the kernel docs.
>> -
>>
>> Comments
>> --------
>> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
>> index 98790fe5115d..34d4b5beda29 100755
>> --- a/scripts/checkpatch.pl
>> +++ b/scripts/checkpatch.pl
>> @@ -6591,28 +6591,6 @@ sub process {
>> }
>> }
>>
>> -# prefer usleep_range over udelay
>> - if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
>> - my $delay = $1;
>> - # ignore udelay's < 10, however
>> - if (! ($delay < 10) ) {
>> - CHK("USLEEP_RANGE",
>> - "usleep_range is preferred over udelay; see function description of usleep_range() and udelay().\n" . $herecurr);
>> - }
>> - if ($delay > 2000) {
>> - WARN("LONG_UDELAY",
>> - "long udelay - prefer mdelay; see function description of mdelay().\n" . $herecurr);
>> - }
>> - }
>> -
>> -# warn about unexpectedly long msleep's
>> - if ($line =~ /\bmsleep\s*\((\d+)\);/) {
>> - if ($1 < 20) {
>> - WARN("MSLEEP",
>> - "msleep < 20ms can sleep for up to 20ms; see function description of msleep().\n" . $herecurr);
>> - }
>> - }
>> -
>> # check for comparisons of jiffies
>> if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
>> WARN("JIFFIES_COMPARISON",
>> @@ -7069,22 +7047,6 @@ sub process {
>> }
>> }
>>
>> -# check usleep_range arguments
>> - if ($perl_version_ok &&
>> - defined $stat &&
>> - $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
>> - my $min = $1;
>> - my $max = $7;
>> - if ($min eq $max) {
>> - WARN("USLEEP_RANGE",
>> - "usleep_range should not use min == max args; see function description of usleep_range().\n" . "$here\n$stat\n");
>> - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
>> - $min > $max) {
>> - WARN("USLEEP_RANGE",
>> - "usleep_range args reversed, use min then max; see function description of usleep_range().\n" . "$here\n$stat\n");
>
> Why not keep the min > max static check?
I removed it accidentially... It was my plan to keep the min > max
static check.
I'll send a v4 for this patch.
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v4] checkpatch: Remove broken sleep/delay related checks
2024-10-14 8:22 ` [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
2024-10-15 14:22 ` Frederic Weisbecker
@ 2024-10-16 10:05 ` Anna-Maria Behnsen
2024-10-18 12:31 ` Frederic Weisbecker
1 sibling, 1 reply; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-16 10:05 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J . Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Anna-Maria Behnsen,
Miguel Ojeda, Andy Whitcroft, Joe Perches, Dwaipayan Ray
checkpatch.pl checks for several things related to sleep and delay
functions. In all warnings the outdated documentation is referenced. All
broken parts are listed one by one in the following with an explanation why
this check is broken. For a basic background of those functions please also
refere to the updated function descriptions of udelay(), nsleep_range() and
msleep().
Be aware: The change is done with a perl knowledge of the level "I'm able
to spell perl".
The following checks are broken:
- Check: (! ($delay < 10) )
Message: "usleep_range is preferred over udelay;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: When it is an atomic context, udelay() is
mandatory.
- Check: ($min eq $max)
Message: "usleep_range should not use min == max args;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: When the requested accuracy for the sleep
duration requires it, it is also valid to use
min == max.
- Check: ($delay > 2000)
Message: "long udelay - prefer mdelay;
see arch/arm/include/asm/delay.h\n"
Why is the check broken: The threshold when to start using mdelay() to
prevent an overflow depends on
MAX_UDELAY_MS. This value is architecture
dependent. The used value for the check and
reference is arm specific. Generic would be 5ms,
but this would "break" arm, loongarch and mips
and also the arm value might "break" mips and
loongarch in some configurations.
- Check: ($1 < 20)
Message: "msleep < 20ms can sleep for up to 20ms;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: msleep(1) might sleep up to 20ms but only on a
HZ=100 system. On a HZ=1000 system this will be
2ms. This means, the threshold cannot be hard
coded as it depends on HZ (jiffy granularity and
timer wheel bucket/level granularity) and also
on the required accuracy of the callsite. See
msleep() and also the USLEEP_RANGE_UPPER_BOUND
value.
Remove all broken checks. Update checkpatch documentation accordingly.
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
Documentation/dev-tools/checkpatch.rst | 3 +--
scripts/checkpatch.pl | 27 +-------------------------
2 files changed, 2 insertions(+), 28 deletions(-)
diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
index abb3ff682076..d29ead254353 100644
--- a/Documentation/dev-tools/checkpatch.rst
+++ b/Documentation/dev-tools/checkpatch.rst
@@ -467,8 +467,7 @@ API usage
No #include statements in include/uapi should use a uapi/ path.
**USLEEP_RANGE**
- usleep_range() should be preferred over udelay(). The proper way of
- using usleep_range() is mentioned in the kernel docs.
+ The proper way of using usleep_range() is mentioned in the kernel docs.
Comments
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 98790fe5115d..2d7cf7d4fc5b 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6591,28 +6591,6 @@ sub process {
}
}
-# prefer usleep_range over udelay
- if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
- my $delay = $1;
- # ignore udelay's < 10, however
- if (! ($delay < 10) ) {
- CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see function description of usleep_range() and udelay().\n" . $herecurr);
- }
- if ($delay > 2000) {
- WARN("LONG_UDELAY",
- "long udelay - prefer mdelay; see function description of mdelay().\n" . $herecurr);
- }
- }
-
-# warn about unexpectedly long msleep's
- if ($line =~ /\bmsleep\s*\((\d+)\);/) {
- if ($1 < 20) {
- WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see function description of msleep().\n" . $herecurr);
- }
- }
-
# check for comparisons of jiffies
if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
WARN("JIFFIES_COMPARISON",
@@ -7075,10 +7053,7 @@ sub process {
$stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
my $min = $1;
my $max = $7;
- if ($min eq $max) {
- WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see function description of usleep_range().\n" . "$here\n$stat\n");
- } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
+ if ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
$min > $max) {
WARN("USLEEP_RANGE",
"usleep_range args reversed, use min then max; see function description of usleep_range().\n" . "$here\n$stat\n");
--
2.39.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess
2024-10-14 16:22 ` (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Mark Brown
@ 2024-10-18 8:06 ` Anna-Maria Behnsen
2024-10-18 18:57 ` Mark Brown
2024-10-18 18:58 ` Mark Brown
0 siblings, 2 replies; 28+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-18 8:06 UTC (permalink / raw)
To: Mark Brown, Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Miguel Ojeda,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, netdev, linux-sound, Michael Ellerman, Nathan Lynch,
linuxppc-dev, Mauro Carvalho Chehab, linux-media,
Sebastian Andrzej Siewior
Hi Mark,
Mark Brown <broonie@kernel.org> writes:
> On Mon, 14 Oct 2024 10:22:17 +0200, Anna-Maria Behnsen wrote:
>> a question about which sleeping function should be used in acpi_os_sleep()
>> started a discussion and examination about the existing documentation and
>> implementation of functions which insert a sleep/delay.
>>
>> The result of the discussion was, that the documentation is outdated and
>> the implemented fsleep() reflects the outdated documentation but doesn't
>> help to reflect reality which in turns leads to the queue which covers the
>> following things:
>>
>> [...]
>
> Applied to
>
> https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
>
Would it be ok for you, if the patch is routed through tip tree? kernel
test robot triggers a warning for htmldoc that there is a reference to
the no longer existing file 'timer-howto.rst':
https://lore.kernel.org/r/202410161059.a0f6IBwj-lkp@intel.com
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v4] checkpatch: Remove broken sleep/delay related checks
2024-10-16 10:05 ` [PATCH v4] " Anna-Maria Behnsen
@ 2024-10-18 12:31 ` Frederic Weisbecker
0 siblings, 0 replies; 28+ messages in thread
From: Frederic Weisbecker @ 2024-10-18 12:31 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J . Wysocki, rust-for-linux, Alice Ryhl, FUJITA Tomonori,
Andrew Lunn, Miguel Ojeda, Andy Whitcroft, Joe Perches,
Dwaipayan Ray
Le Wed, Oct 16, 2024 at 12:05:31PM +0200, Anna-Maria Behnsen a écrit :
> checkpatch.pl checks for several things related to sleep and delay
> functions. In all warnings the outdated documentation is referenced. All
> broken parts are listed one by one in the following with an explanation why
> this check is broken. For a basic background of those functions please also
> refere to the updated function descriptions of udelay(), nsleep_range() and
> msleep().
>
> Be aware: The change is done with a perl knowledge of the level "I'm able
> to spell perl".
>
> The following checks are broken:
>
> - Check: (! ($delay < 10) )
> Message: "usleep_range is preferred over udelay;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When it is an atomic context, udelay() is
> mandatory.
>
> - Check: ($min eq $max)
> Message: "usleep_range should not use min == max args;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When the requested accuracy for the sleep
> duration requires it, it is also valid to use
> min == max.
>
> - Check: ($delay > 2000)
> Message: "long udelay - prefer mdelay;
> see arch/arm/include/asm/delay.h\n"
> Why is the check broken: The threshold when to start using mdelay() to
> prevent an overflow depends on
> MAX_UDELAY_MS. This value is architecture
> dependent. The used value for the check and
> reference is arm specific. Generic would be 5ms,
> but this would "break" arm, loongarch and mips
> and also the arm value might "break" mips and
> loongarch in some configurations.
>
> - Check: ($1 < 20)
> Message: "msleep < 20ms can sleep for up to 20ms;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: msleep(1) might sleep up to 20ms but only on a
> HZ=100 system. On a HZ=1000 system this will be
> 2ms. This means, the threshold cannot be hard
> coded as it depends on HZ (jiffy granularity and
> timer wheel bucket/level granularity) and also
> on the required accuracy of the callsite. See
> msleep() and also the USLEEP_RANGE_UPPER_BOUND
> value.
>
> Remove all broken checks. Update checkpatch documentation accordingly.
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess
2024-10-18 8:06 ` Anna-Maria Behnsen
@ 2024-10-18 18:57 ` Mark Brown
2024-10-18 18:58 ` Mark Brown
1 sibling, 0 replies; 28+ messages in thread
From: Mark Brown @ 2024-10-18 18:57 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Miguel Ojeda,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, netdev, linux-sound, Michael Ellerman, Nathan Lynch,
linuxppc-dev, Mauro Carvalho Chehab, linux-media,
Sebastian Andrzej Siewior
[-- Attachment #1: Type: text/plain, Size: 421 bytes --]
On Fri, Oct 18, 2024 at 10:06:33AM +0200, Anna-Maria Behnsen wrote:
> Would it be ok for you, if the patch is routed through tip tree? kernel
> test robot triggers a warning for htmldoc that there is a reference to
> the no longer existing file 'timer-howto.rst':
> https://lore.kernel.org/r/202410161059.a0f6IBwj-lkp@intel.com
It should be fine, worst case we just get a duplicate patch which
doesn't super matter.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess
2024-10-18 8:06 ` Anna-Maria Behnsen
2024-10-18 18:57 ` Mark Brown
@ 2024-10-18 18:58 ` Mark Brown
1 sibling, 0 replies; 28+ messages in thread
From: Mark Brown @ 2024-10-18 18:58 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, rust-for-linux,
Alice Ryhl, FUJITA Tomonori, Andrew Lunn, Miguel Ojeda,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, netdev, linux-sound, Michael Ellerman, Nathan Lynch,
linuxppc-dev, Mauro Carvalho Chehab, linux-media,
Sebastian Andrzej Siewior
[-- Attachment #1: Type: text/plain, Size: 397 bytes --]
On Fri, Oct 18, 2024 at 10:06:33AM +0200, Anna-Maria Behnsen wrote:
> Would it be ok for you, if the patch is routed through tip tree? kernel
> test robot triggers a warning for htmldoc that there is a reference to
> the no longer existing file 'timer-howto.rst':
> https://lore.kernel.org/r/202410161059.a0f6IBwj-lkp@intel.com
Oh, and for that:
Reviewed-by: Mark Brown <broonie@kernel.org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2024-10-18 18:58 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-14 8:22 [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 01/16] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 02/16] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 03/16] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 04/16] timers: Rename usleep_idle_range() to usleep_range_idle() Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 05/16] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 06/16] delay: Rework udelay and ndelay Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 07/16] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 08/16] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 09/16] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
2024-10-15 13:54 ` Frederic Weisbecker
2024-10-14 8:22 ` [PATCH v3 10/16] checkpatch: Remove links to outdated documentation Anna-Maria Behnsen
2024-10-15 14:08 ` Frederic Weisbecker
2024-10-14 8:22 ` [PATCH v3 11/16] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 12/16] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 13/16] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 14/16] media: anysee: Fix and remove outdated comment Anna-Maria Behnsen
2024-10-15 14:11 ` Frederic Weisbecker
2024-10-14 8:22 ` [PATCH v3 15/16] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
2024-10-14 8:22 ` [PATCH v3 16/16] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
2024-10-15 14:22 ` Frederic Weisbecker
2024-10-16 9:55 ` Anna-Maria Behnsen
2024-10-16 10:05 ` [PATCH v4] " Anna-Maria Behnsen
2024-10-18 12:31 ` Frederic Weisbecker
2024-10-14 16:22 ` (subset) [PATCH v3 00/16] timers: Cleanup delay/sleep related mess Mark Brown
2024-10-18 8:06 ` Anna-Maria Behnsen
2024-10-18 18:57 ` Mark Brown
2024-10-18 18:58 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).