]>
Commit | Line | Data |
---|---|---|
0e58983d TG |
1 | /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ |
2 | /* Copyright (c) 2019 Mellanox Technologies. */ | |
3 | ||
4 | #ifndef DIM_H | |
5 | #define DIM_H | |
6 | ||
7 | #include <linux/module.h> | |
8 | ||
4f75da36 TG |
9 | /** |
10 | * Number of events between DIM iterations. | |
11 | * Causes a moderation of the algorithm run. | |
12 | */ | |
449986ea | 13 | #define DIM_NEVENTS 64 |
0e58983d | 14 | |
4f75da36 TG |
15 | /** |
16 | * Is a difference between values justifies taking an action. | |
17 | * We consider 10% difference as significant. | |
18 | */ | |
0e58983d TG |
19 | #define IS_SIGNIFICANT_DIFF(val, ref) \ |
20 | (((100UL * abs((val) - (ref))) / (ref)) > 10) | |
4f75da36 TG |
21 | |
22 | /** | |
23 | * Calculate the gap between two values. | |
24 | * Take wrap-around and variable size into consideration. | |
25 | */ | |
0e58983d | 26 | #define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \ |
4f75da36 | 27 | & (BIT_ULL(bits) - 1)) |
0e58983d | 28 | |
4f75da36 TG |
29 | /** |
30 | * Structure for CQ moderation values. | |
31 | * Used for communications between DIM and its consumer. | |
32 | * | |
33 | * @usec: CQ timer suggestion (by DIM) | |
34 | * @pkts: CQ packet counter suggestion (by DIM) | |
35 | * @cq_period_mode: CQ priod count mode (from CQE/EQE) | |
36 | */ | |
8960b389 | 37 | struct dim_cq_moder { |
0e58983d TG |
38 | u16 usec; |
39 | u16 pkts; | |
40 | u8 cq_period_mode; | |
41 | }; | |
42 | ||
4f75da36 TG |
43 | /** |
44 | * Structure for DIM sample data. | |
45 | * Used for communications between DIM and its consumer. | |
46 | * | |
47 | * @time: Sample timestamp | |
48 | * @pkt_ctr: Number of packets | |
49 | * @byte_ctr: Number of bytes | |
50 | * @event_ctr: Number of events | |
51 | */ | |
8960b389 | 52 | struct dim_sample { |
0e58983d TG |
53 | ktime_t time; |
54 | u32 pkt_ctr; | |
55 | u32 byte_ctr; | |
56 | u16 event_ctr; | |
57 | }; | |
58 | ||
4f75da36 TG |
59 | /** |
60 | * Structure for DIM stats. | |
61 | * Used for holding current measured rates. | |
62 | * | |
63 | * @ppms: Packets per msec | |
64 | * @bpms: Bytes per msec | |
65 | * @epms: Events per msec | |
66 | */ | |
449986ea | 67 | struct dim_stats { |
4f75da36 TG |
68 | int ppms; |
69 | int bpms; | |
70 | int epms; | |
0e58983d TG |
71 | }; |
72 | ||
4f75da36 TG |
73 | /** |
74 | * Main structure for dynamic interrupt moderation (DIM). | |
75 | * Used for holding all information about a specific DIM instance. | |
76 | * | |
77 | * @state: Algorithm state (see below) | |
78 | * @prev_stats: Measured rates from previous iteration (for comparison) | |
79 | * @start_sample: Sampled data at start of current iteration | |
80 | * @work: Work to perform on action required | |
81 | * @profile_ix: Current moderation profile | |
82 | * @mode: CQ period count mode | |
83 | * @tune_state: Algorithm tuning state (see below) | |
84 | * @steps_right: Number of steps taken towards higher moderation | |
85 | * @steps_left: Number of steps taken towards lower moderation | |
86 | * @tired: Parking depth counter | |
87 | */ | |
88 | struct dim { | |
0e58983d | 89 | u8 state; |
449986ea | 90 | struct dim_stats prev_stats; |
8960b389 | 91 | struct dim_sample start_sample; |
0e58983d TG |
92 | struct work_struct work; |
93 | u8 profile_ix; | |
94 | u8 mode; | |
95 | u8 tune_state; | |
96 | u8 steps_right; | |
97 | u8 steps_left; | |
98 | u8 tired; | |
99 | }; | |
100 | ||
4f75da36 TG |
101 | /** |
102 | * enum dim_cq_period_mode | |
103 | * | |
104 | * These are the modes for CQ period count. | |
105 | * | |
106 | * @DIM_CQ_PERIOD_MODE_START_FROM_EQE: Start counting from EQE | |
107 | * @DIM_CQ_PERIOD_MODE_START_FROM_CQE: Start counting from CQE (implies timer reset) | |
108 | * @DIM_CQ_PERIOD_NUM_MODES: Number of modes | |
109 | */ | |
0e58983d | 110 | enum { |
c002bd52 TG |
111 | DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, |
112 | DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, | |
113 | DIM_CQ_PERIOD_NUM_MODES | |
0e58983d TG |
114 | }; |
115 | ||
4f75da36 TG |
116 | /** |
117 | * enum dim_state | |
118 | * | |
119 | * These are the DIM algorithm states. | |
120 | * These will determine if the algorithm is in a valid state to start an iteration. | |
121 | * | |
122 | * @DIM_START_MEASURE: This is the first iteration (also after applying a new profile) | |
123 | * @DIM_MEASURE_IN_PROGRESS: Algorithm is already in progress - check if | |
124 | * need to perform an action | |
125 | * @DIM_APPLY_NEW_PROFILE: DIM consumer is currently applying a profile - no need to measure | |
126 | */ | |
0e58983d | 127 | enum { |
c002bd52 TG |
128 | DIM_START_MEASURE, |
129 | DIM_MEASURE_IN_PROGRESS, | |
130 | DIM_APPLY_NEW_PROFILE, | |
0e58983d TG |
131 | }; |
132 | ||
4f75da36 TG |
133 | /** |
134 | * enum dim_tune_state | |
135 | * | |
136 | * These are the DIM algorithm tune states. | |
137 | * These will determine which action the algorithm should perform. | |
138 | * | |
139 | * @DIM_PARKING_ON_TOP: Algorithm found a local top point - exit on significant difference | |
140 | * @DIM_PARKING_TIRED: Algorithm found a deep top point - don't exit if tired > 0 | |
141 | * @DIM_GOING_RIGHT: Algorithm is currently trying higher moderation levels | |
142 | * @DIM_GOING_LEFT: Algorithm is currently trying lower moderation levels | |
143 | */ | |
0e58983d | 144 | enum { |
449986ea TG |
145 | DIM_PARKING_ON_TOP, |
146 | DIM_PARKING_TIRED, | |
147 | DIM_GOING_RIGHT, | |
148 | DIM_GOING_LEFT, | |
0e58983d TG |
149 | }; |
150 | ||
4f75da36 TG |
151 | /** |
152 | * enum dim_stats_state | |
153 | * | |
154 | * These are the DIM algorithm statistics states. | |
155 | * These will determine the verdict of current iteration. | |
156 | * | |
157 | * @DIM_STATS_WORSE: Current iteration shows worse performance than before | |
158 | * @DIM_STATS_WORSE: Current iteration shows same performance than before | |
159 | * @DIM_STATS_WORSE: Current iteration shows better performance than before | |
160 | */ | |
0e58983d | 161 | enum { |
449986ea TG |
162 | DIM_STATS_WORSE, |
163 | DIM_STATS_SAME, | |
164 | DIM_STATS_BETTER, | |
0e58983d TG |
165 | }; |
166 | ||
4f75da36 TG |
167 | /** |
168 | * enum dim_step_result | |
169 | * | |
170 | * These are the DIM algorithm step results. | |
171 | * These describe the result of a step. | |
172 | * | |
173 | * @DIM_STEPPED: Performed a regular step | |
174 | * @DIM_TOO_TIRED: Same kind of step was done multiple times - should go to | |
175 | * tired parking | |
176 | * @DIM_ON_EDGE: Stepped to the most left/right profile | |
177 | */ | |
0e58983d | 178 | enum { |
449986ea TG |
179 | DIM_STEPPED, |
180 | DIM_TOO_TIRED, | |
181 | DIM_ON_EDGE, | |
0e58983d TG |
182 | }; |
183 | ||
4f75da36 TG |
184 | /** |
185 | * dim_on_top - check if current state is a good place to stop (top location) | |
186 | * @dim: DIM context | |
187 | * | |
188 | * Check if current profile is a good place to park at. | |
189 | * This will result in reducing the DIM checks frequency as we assume we | |
190 | * shouldn't probably change profiles, unless traffic pattern wasn't changed. | |
191 | */ | |
192 | bool dim_on_top(struct dim *dim); | |
0e58983d | 193 | |
4f75da36 TG |
194 | /** |
195 | * dim_turn - change profile alterning direction | |
196 | * @dim: DIM context | |
197 | * | |
198 | * Go left if we were going right and vice-versa. | |
199 | * Do nothing if currently parking. | |
200 | */ | |
201 | void dim_turn(struct dim *dim); | |
0e58983d | 202 | |
4f75da36 TG |
203 | /** |
204 | * dim_park_on_top - enter a parking state on a top location | |
205 | * @dim: DIM context | |
206 | * | |
207 | * Enter parking state. | |
208 | * Clear all movement history. | |
209 | */ | |
210 | void dim_park_on_top(struct dim *dim); | |
0e58983d | 211 | |
4f75da36 TG |
212 | /** |
213 | * dim_park_tired - enter a tired parking state | |
214 | * @dim: DIM context | |
215 | * | |
216 | * Enter parking state. | |
217 | * Clear all movement history and cause DIM checks frequency to reduce. | |
218 | */ | |
219 | void dim_park_tired(struct dim *dim); | |
220 | ||
221 | /** | |
222 | * dim_calc_stats - calculate the difference between two samples | |
223 | * @start: start sample | |
224 | * @end: end sample | |
225 | * @curr_stats: delta between samples | |
226 | * | |
227 | * Calculate the delta between two samples (in data rates). | |
228 | * Takes into consideration counter wrap-around. | |
229 | */ | |
230 | void dim_calc_stats(struct dim_sample *start, struct dim_sample *end, | |
231 | struct dim_stats *curr_stats); | |
0e58983d | 232 | |
4f75da36 TG |
233 | /** |
234 | * dim_update_sample - set a sample's fields with give values | |
235 | * @event_ctr: number of events to set | |
236 | * @packets: number of packets to set | |
237 | * @bytes: number of bytes to set | |
238 | * @s: DIM sample | |
239 | */ | |
0e58983d | 240 | static inline void |
8960b389 | 241 | dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s) |
0e58983d TG |
242 | { |
243 | s->time = ktime_get(); | |
244 | s->pkt_ctr = packets; | |
245 | s->byte_ctr = bytes; | |
246 | s->event_ctr = event_ctr; | |
247 | } | |
248 | ||
4f75da36 TG |
249 | /* Net DIM */ |
250 | ||
251 | /* | |
252 | * Net DIM profiles: | |
253 | * There are different set of profiles for each CQ period mode. | |
254 | * There are different set of profiles for RX/TX CQs. | |
255 | * Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES | |
256 | */ | |
257 | #define NET_DIM_PARAMS_NUM_PROFILES 5 | |
258 | #define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256 | |
259 | #define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128 | |
260 | #define NET_DIM_DEF_PROFILE_CQE 1 | |
261 | #define NET_DIM_DEF_PROFILE_EQE 1 | |
262 | ||
263 | #define NET_DIM_RX_EQE_PROFILES { \ | |
264 | {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
265 | {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
266 | {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
267 | {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
268 | {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
0e58983d TG |
269 | } |
270 | ||
4f75da36 TG |
271 | #define NET_DIM_RX_CQE_PROFILES { \ |
272 | {2, 256}, \ | |
273 | {8, 128}, \ | |
274 | {16, 64}, \ | |
275 | {32, 64}, \ | |
276 | {64, 64} \ | |
277 | } | |
278 | ||
279 | #define NET_DIM_TX_EQE_PROFILES { \ | |
280 | {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
281 | {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
282 | {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
283 | {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ | |
284 | {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \ | |
285 | } | |
286 | ||
287 | #define NET_DIM_TX_CQE_PROFILES { \ | |
288 | {5, 128}, \ | |
289 | {8, 64}, \ | |
290 | {16, 32}, \ | |
291 | {32, 32}, \ | |
292 | {64, 32} \ | |
293 | } | |
294 | ||
295 | static const struct dim_cq_moder | |
296 | rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { | |
297 | NET_DIM_RX_EQE_PROFILES, | |
298 | NET_DIM_RX_CQE_PROFILES, | |
299 | }; | |
300 | ||
301 | static const struct dim_cq_moder | |
302 | tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { | |
303 | NET_DIM_TX_EQE_PROFILES, | |
304 | NET_DIM_TX_CQE_PROFILES, | |
305 | }; | |
306 | ||
307 | /** | |
308 | * net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile | |
309 | * @cq_period_mode: CQ period mode | |
310 | * @ix: Profile index | |
311 | */ | |
312 | struct dim_cq_moder net_dim_get_rx_moderation(u8 cq_period_mode, int ix); | |
313 | ||
314 | /** | |
315 | * net_dim_get_def_rx_moderation - provide the default RX moderation | |
316 | * @cq_period_mode: CQ period mode | |
317 | */ | |
318 | struct dim_cq_moder net_dim_get_def_rx_moderation(u8 cq_period_mode); | |
319 | ||
320 | /** | |
321 | * net_dim_get_tx_moderation - provide a CQ moderation object for the given TX profile | |
322 | * @cq_period_mode: CQ period mode | |
323 | * @ix: Profile index | |
324 | */ | |
325 | struct dim_cq_moder net_dim_get_tx_moderation(u8 cq_period_mode, int ix); | |
326 | ||
327 | /** | |
328 | * net_dim_get_def_tx_moderation - provide the default TX moderation | |
329 | * @cq_period_mode: CQ period mode | |
330 | */ | |
331 | struct dim_cq_moder net_dim_get_def_tx_moderation(u8 cq_period_mode); | |
332 | ||
333 | /** | |
334 | * net_dim - main DIM algorithm entry point | |
335 | * @dim: DIM instance information | |
336 | * @end_sample: Current data measurement | |
337 | * | |
338 | * Called by the consumer. | |
339 | * This is the main logic of the algorithm, where data is processed in order to decide on next | |
340 | * required action. | |
341 | */ | |
342 | void net_dim(struct dim *dim, struct dim_sample end_sample); | |
343 | ||
0e58983d | 344 | #endif /* DIM_H */ |