1 // SPDX-License-Identifier: GPL-2.0
3 * Dynamic byte queue limits. See include/linux/dynamic_queue_limits.h
5 * Copyright (c) 2011, Tom Herbert <therbert@google.com>
7 #include <linux/types.h>
8 #include <linux/kernel.h>
9 #include <linux/jiffies.h>
10 #include <linux/dynamic_queue_limits.h>
11 #include <linux/compiler.h>
12 #include <linux/export.h>
13 #include <trace/events/napi.h>
15 #define POSDIFF(A, B) ((int)((A) - (B)) > 0 ? (A) - (B) : 0)
16 #define AFTER_EQ(A, B) ((int)((A) - (B)) >= 0)
18 static void dql_check_stall(struct dql
*dql
, unsigned short stall_thrs
)
26 /* Check for a potential stall */
27 if (time_after_eq(now
, dql
->last_reap
+ stall_thrs
)) {
28 unsigned long hist_head
, t
, start
, end
;
30 /* We are trying to detect a period of at least @stall_thrs
31 * jiffies without any Tx completions, but during first half
32 * of which some Tx was posted.
35 hist_head
= READ_ONCE(dql
->history_head
);
36 /* pairs with smp_wmb() in dql_queued() */
39 /* Get the previous entry in the ring buffer, which is the
42 start
= (hist_head
- DQL_HIST_LEN
+ 1) * BITS_PER_LONG
;
44 /* Advance start to continue from the last reap time */
45 if (time_before(start
, dql
->last_reap
+ 1))
46 start
= dql
->last_reap
+ 1;
48 /* Newest sample we should have already seen a completion for */
49 end
= hist_head
* BITS_PER_LONG
+ (BITS_PER_LONG
- 1);
51 /* Shrink the search space to [start, (now - start_thrs/2)] if
52 * `end` is beyond the stall zone
54 if (time_before(now
, end
+ stall_thrs
/ 2))
55 end
= now
- stall_thrs
/ 2;
57 /* Search for the queued time in [t, end] */
58 for (t
= start
; time_before_eq(t
, end
); t
++)
59 if (test_bit(t
% (DQL_HIST_LEN
* BITS_PER_LONG
),
63 /* Variable t contains the time of the queue */
64 if (!time_before_eq(t
, end
))
67 /* The ring buffer was modified in the meantime, retry */
68 if (hist_head
!= READ_ONCE(dql
->history_head
))
72 dql
->stall_max
= max_t(unsigned short, dql
->stall_max
, now
- t
);
74 trace_dql_stall_detected(dql
->stall_thrs
, now
- t
,
75 dql
->last_reap
, dql
->history_head
,
82 /* Records completed count and recalculates the queue limit */
83 void dql_completed(struct dql
*dql
, unsigned int count
)
85 unsigned int inprogress
, prev_inprogress
, limit
;
86 unsigned int ovlimit
, completed
, num_queued
;
87 unsigned short stall_thrs
;
88 bool all_prev_completed
;
90 num_queued
= READ_ONCE(dql
->num_queued
);
91 /* Read stall_thrs in advance since it belongs to the same (first)
92 * cache line as ->num_queued. This way, dql_check_stall() does not
93 * need to touch the first cache line again later, reducing the window
94 * of possible false sharing.
96 stall_thrs
= READ_ONCE(dql
->stall_thrs
);
98 /* Can't complete more than what's in queue */
99 BUG_ON(count
> num_queued
- dql
->num_completed
);
101 completed
= dql
->num_completed
+ count
;
103 ovlimit
= POSDIFF(num_queued
- dql
->num_completed
, limit
);
104 inprogress
= num_queued
- completed
;
105 prev_inprogress
= dql
->prev_num_queued
- dql
->num_completed
;
106 all_prev_completed
= AFTER_EQ(completed
, dql
->prev_num_queued
);
108 if ((ovlimit
&& !inprogress
) ||
109 (dql
->prev_ovlimit
&& all_prev_completed
)) {
111 * Queue considered starved if:
112 * - The queue was over-limit in the last interval,
113 * and there is no more data in the queue.
115 * - The queue was over-limit in the previous interval and
116 * when enqueuing it was possible that all queued data
117 * had been consumed. This covers the case when queue
118 * may have becomes starved between completion processing
119 * running and next time enqueue was scheduled.
121 * When queue is starved increase the limit by the amount
122 * of bytes both sent and completed in the last interval,
123 * plus any previous over-limit.
125 limit
+= POSDIFF(completed
, dql
->prev_num_queued
) +
127 dql
->slack_start_time
= jiffies
;
128 dql
->lowest_slack
= UINT_MAX
;
129 } else if (inprogress
&& prev_inprogress
&& !all_prev_completed
) {
131 * Queue was not starved, check if the limit can be decreased.
132 * A decrease is only considered if the queue has been busy in
133 * the whole interval (the check above).
135 * If there is slack, the amount of excess data queued above
136 * the amount needed to prevent starvation, the queue limit
137 * can be decreased. To avoid hysteresis we consider the
138 * minimum amount of slack found over several iterations of the
139 * completion routine.
141 unsigned int slack
, slack_last_objs
;
144 * Slack is the maximum of
145 * - The queue limit plus previous over-limit minus twice
146 * the number of objects completed. Note that two times
147 * number of completed bytes is a basis for an upper bound
149 * - Portion of objects in the last queuing operation that
150 * was not part of non-zero previous over-limit. That is
151 * "round down" by non-overlimit portion of the last
152 * queueing operation.
154 slack
= POSDIFF(limit
+ dql
->prev_ovlimit
,
155 2 * (completed
- dql
->num_completed
));
156 slack_last_objs
= dql
->prev_ovlimit
?
157 POSDIFF(dql
->prev_last_obj_cnt
, dql
->prev_ovlimit
) : 0;
159 slack
= max(slack
, slack_last_objs
);
161 if (slack
< dql
->lowest_slack
)
162 dql
->lowest_slack
= slack
;
164 if (time_after(jiffies
,
165 dql
->slack_start_time
+ dql
->slack_hold_time
)) {
166 limit
= POSDIFF(limit
, dql
->lowest_slack
);
167 dql
->slack_start_time
= jiffies
;
168 dql
->lowest_slack
= UINT_MAX
;
172 /* Enforce bounds on limit */
173 limit
= clamp(limit
, dql
->min_limit
, dql
->max_limit
);
175 if (limit
!= dql
->limit
) {
180 dql
->adj_limit
= limit
+ completed
;
181 dql
->prev_ovlimit
= ovlimit
;
182 dql
->prev_last_obj_cnt
= READ_ONCE(dql
->last_obj_cnt
);
183 dql
->num_completed
= completed
;
184 dql
->prev_num_queued
= num_queued
;
186 dql_check_stall(dql
, stall_thrs
);
188 EXPORT_SYMBOL(dql_completed
);
190 void dql_reset(struct dql
*dql
)
192 /* Reset all dynamic values */
195 dql
->num_completed
= 0;
196 dql
->last_obj_cnt
= 0;
197 dql
->prev_num_queued
= 0;
198 dql
->prev_last_obj_cnt
= 0;
199 dql
->prev_ovlimit
= 0;
200 dql
->lowest_slack
= UINT_MAX
;
201 dql
->slack_start_time
= jiffies
;
203 dql
->last_reap
= jiffies
;
204 dql
->history_head
= jiffies
/ BITS_PER_LONG
;
205 memset(dql
->history
, 0, sizeof(dql
->history
));
207 EXPORT_SYMBOL(dql_reset
);
209 void dql_init(struct dql
*dql
, unsigned int hold_time
)
211 dql
->max_limit
= DQL_MAX_LIMIT
;
213 dql
->slack_hold_time
= hold_time
;
217 EXPORT_SYMBOL(dql_init
);