diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-09-22 18:32:50 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-09-22 18:35:06 +1000 |
| commit | b0a3a811634aa7422f8a92196db47a06a70bda16 (patch) | |
| tree | 15f8b05b9a0e99e87fecb6751a0a9ef59589c28c /include/net/codel_impl.h | |
| parent | 014ee7742bed896f1aee13ecdee5fe8c7826c0a1 (diff) | |
| parent | 93f51579e7df248780214094418f205253383cc5 (diff) | |
Backmerge tag 'v7.3-rc4' into drm-next
Linux 7.3-rc4
Requested by Philipp Stanner for
2ab510e63197360945f915dd5631a77c63ac6b27 would be needed as a groundlayer
for further patches that extend the locking in drm_sched
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include/net/codel_impl.h')
| -rw-r--r-- | include/net/codel_impl.h | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/include/net/codel_impl.h b/include/net/codel_impl.h index 2c1f0ec309e9..8f26132d45b7 100644 --- a/include/net/codel_impl.h +++ b/include/net/codel_impl.h @@ -93,12 +93,17 @@ static void codel_Newton_step(struct codel_vars *vars) * CoDel control_law is t + interval/sqrt(count) * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid * both sqrt() and divide operation. + * + * Clamp the increment to at least 1 tick: a very small interval (or a + * large count) can truncate it to zero, stalling the dropping loop. */ static codel_time_t codel_control_law(codel_time_t t, codel_time_t interval, u32 rec_inv_sqrt) { - return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); + return t + max_t(u32, 1, + reciprocal_scale(interval, + rec_inv_sqrt << REC_INV_SQRT_SHIFT)); } static bool codel_should_drop(const struct sk_buff *skb, @@ -154,6 +159,7 @@ static struct sk_buff *codel_dequeue(void *ctx, codel_skb_dequeue_t dequeue_func) { struct sk_buff *skb = dequeue_func(vars, ctx); + unsigned int drops = 0; codel_time_t now; bool drop; @@ -180,6 +186,14 @@ static struct sk_buff *codel_dequeue(void *ctx, */ while (vars->dropping && codel_time_after_eq(now, vars->drop_next)) { + if (++drops > CODEL_MAX_DROPS_PER_DEQUEUE) { + /* fell far behind the schedule */ + WRITE_ONCE(vars->drop_next, + codel_control_law(now, + params->interval, + vars->rec_inv_sqrt)); + break; + } /* dont care of possible wrap * since there is no more divide. */ |
