xref: /openbmc/linux/include/linux/dim.h (revision 162bd18e)
10e58983dSTal Gilboa /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
20e58983dSTal Gilboa /* Copyright (c) 2019 Mellanox Technologies. */
30e58983dSTal Gilboa 
40e58983dSTal Gilboa #ifndef DIM_H
50e58983dSTal Gilboa #define DIM_H
60e58983dSTal Gilboa 
7690a6ca7SRandy Dunlap #include <linux/bits.h>
8690a6ca7SRandy Dunlap #include <linux/kernel.h>
90e58983dSTal Gilboa #include <linux/module.h>
10690a6ca7SRandy Dunlap #include <linux/types.h>
11690a6ca7SRandy Dunlap #include <linux/workqueue.h>
120e58983dSTal Gilboa 
13690a6ca7SRandy Dunlap /*
144f75da36STal Gilboa  * Number of events between DIM iterations.
154f75da36STal Gilboa  * Causes a moderation of the algorithm run.
164f75da36STal Gilboa  */
17449986eaSTal Gilboa #define DIM_NEVENTS 64
180e58983dSTal Gilboa 
19690a6ca7SRandy Dunlap /*
204f75da36STal Gilboa  * Is a difference between values justifies taking an action.
214f75da36STal Gilboa  * We consider 10% difference as significant.
224f75da36STal Gilboa  */
230e58983dSTal Gilboa #define IS_SIGNIFICANT_DIFF(val, ref) \
240fe3dbbeSTao Liu 	((ref) && (((100UL * abs((val) - (ref))) / (ref)) > 10))
254f75da36STal Gilboa 
26690a6ca7SRandy Dunlap /*
274f75da36STal Gilboa  * Calculate the gap between two values.
284f75da36STal Gilboa  * Take wrap-around and variable size into consideration.
294f75da36STal Gilboa  */
300e58983dSTal Gilboa #define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \
310e58983dSTal Gilboa 		& (BIT_ULL(bits) - 1))
320e58983dSTal Gilboa 
334f75da36STal Gilboa /**
34690a6ca7SRandy Dunlap  * struct dim_cq_moder - Structure for CQ moderation values.
354f75da36STal Gilboa  * Used for communications between DIM and its consumer.
364f75da36STal Gilboa  *
374f75da36STal Gilboa  * @usec: CQ timer suggestion (by DIM)
384f75da36STal Gilboa  * @pkts: CQ packet counter suggestion (by DIM)
39690a6ca7SRandy Dunlap  * @comps: Completion counter
40690a6ca7SRandy Dunlap  * @cq_period_mode: CQ period count mode (from CQE/EQE)
414f75da36STal Gilboa  */
428960b389STal Gilboa struct dim_cq_moder {
430e58983dSTal Gilboa 	u16 usec;
440e58983dSTal Gilboa 	u16 pkts;
45398c2b05SYamin Friedman 	u16 comps;
460e58983dSTal Gilboa 	u8 cq_period_mode;
470e58983dSTal Gilboa };
480e58983dSTal Gilboa 
494f75da36STal Gilboa /**
50690a6ca7SRandy Dunlap  * struct dim_sample - Structure for DIM sample data.
514f75da36STal Gilboa  * Used for communications between DIM and its consumer.
524f75da36STal Gilboa  *
534f75da36STal Gilboa  * @time: Sample timestamp
544f75da36STal Gilboa  * @pkt_ctr: Number of packets
554f75da36STal Gilboa  * @byte_ctr: Number of bytes
564f75da36STal Gilboa  * @event_ctr: Number of events
57690a6ca7SRandy Dunlap  * @comp_ctr: Current completion counter
584f75da36STal Gilboa  */
598960b389STal Gilboa struct dim_sample {
600e58983dSTal Gilboa 	ktime_t time;
610e58983dSTal Gilboa 	u32 pkt_ctr;
620e58983dSTal Gilboa 	u32 byte_ctr;
630e58983dSTal Gilboa 	u16 event_ctr;
64398c2b05SYamin Friedman 	u32 comp_ctr;
650e58983dSTal Gilboa };
660e58983dSTal Gilboa 
674f75da36STal Gilboa /**
68690a6ca7SRandy Dunlap  * struct dim_stats - Structure for DIM stats.
694f75da36STal Gilboa  * Used for holding current measured rates.
704f75da36STal Gilboa  *
714f75da36STal Gilboa  * @ppms: Packets per msec
724f75da36STal Gilboa  * @bpms: Bytes per msec
734f75da36STal Gilboa  * @epms: Events per msec
74690a6ca7SRandy Dunlap  * @cpms: Completions per msec
75690a6ca7SRandy Dunlap  * @cpe_ratio: Ratio of completions to events
764f75da36STal Gilboa  */
77449986eaSTal Gilboa struct dim_stats {
78398c2b05SYamin Friedman 	int ppms; /* packets per msec */
79398c2b05SYamin Friedman 	int bpms; /* bytes per msec */
80398c2b05SYamin Friedman 	int epms; /* events per msec */
81398c2b05SYamin Friedman 	int cpms; /* completions per msec */
82398c2b05SYamin Friedman 	int cpe_ratio; /* ratio of completions to events */
830e58983dSTal Gilboa };
840e58983dSTal Gilboa 
854f75da36STal Gilboa /**
86690a6ca7SRandy Dunlap  * struct dim - Main structure for dynamic interrupt moderation (DIM).
874f75da36STal Gilboa  * Used for holding all information about a specific DIM instance.
884f75da36STal Gilboa  *
894f75da36STal Gilboa  * @state: Algorithm state (see below)
904f75da36STal Gilboa  * @prev_stats: Measured rates from previous iteration (for comparison)
914f75da36STal Gilboa  * @start_sample: Sampled data at start of current iteration
92690a6ca7SRandy Dunlap  * @measuring_sample: A &dim_sample that is used to update the current events
934f75da36STal Gilboa  * @work: Work to perform on action required
94f4915455SYamin Friedman  * @priv: A pointer to the struct that points to dim
954f75da36STal Gilboa  * @profile_ix: Current moderation profile
964f75da36STal Gilboa  * @mode: CQ period count mode
974f75da36STal Gilboa  * @tune_state: Algorithm tuning state (see below)
984f75da36STal Gilboa  * @steps_right: Number of steps taken towards higher moderation
994f75da36STal Gilboa  * @steps_left: Number of steps taken towards lower moderation
1004f75da36STal Gilboa  * @tired: Parking depth counter
1014f75da36STal Gilboa  */
1024f75da36STal Gilboa struct dim {
1030e58983dSTal Gilboa 	u8 state;
104449986eaSTal Gilboa 	struct dim_stats prev_stats;
1058960b389STal Gilboa 	struct dim_sample start_sample;
106398c2b05SYamin Friedman 	struct dim_sample measuring_sample;
1070e58983dSTal Gilboa 	struct work_struct work;
108f4915455SYamin Friedman 	void *priv;
1090e58983dSTal Gilboa 	u8 profile_ix;
1100e58983dSTal Gilboa 	u8 mode;
1110e58983dSTal Gilboa 	u8 tune_state;
1120e58983dSTal Gilboa 	u8 steps_right;
1130e58983dSTal Gilboa 	u8 steps_left;
1140e58983dSTal Gilboa 	u8 tired;
1150e58983dSTal Gilboa };
1160e58983dSTal Gilboa 
1174f75da36STal Gilboa /**
118690a6ca7SRandy Dunlap  * enum dim_cq_period_mode - Modes for CQ period count
1194f75da36STal Gilboa  *
1204f75da36STal Gilboa  * @DIM_CQ_PERIOD_MODE_START_FROM_EQE: Start counting from EQE
1214f75da36STal Gilboa  * @DIM_CQ_PERIOD_MODE_START_FROM_CQE: Start counting from CQE (implies timer reset)
1224f75da36STal Gilboa  * @DIM_CQ_PERIOD_NUM_MODES: Number of modes
1234f75da36STal Gilboa  */
124690a6ca7SRandy Dunlap enum dim_cq_period_mode {
125c002bd52STal Gilboa 	DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0,
126c002bd52STal Gilboa 	DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1,
127c002bd52STal Gilboa 	DIM_CQ_PERIOD_NUM_MODES
1280e58983dSTal Gilboa };
1290e58983dSTal Gilboa 
1304f75da36STal Gilboa /**
131690a6ca7SRandy Dunlap  * enum dim_state - DIM algorithm states
1324f75da36STal Gilboa  *
1334f75da36STal Gilboa  * These will determine if the algorithm is in a valid state to start an iteration.
1344f75da36STal Gilboa  *
1354f75da36STal Gilboa  * @DIM_START_MEASURE: This is the first iteration (also after applying a new profile)
1364f75da36STal Gilboa  * @DIM_MEASURE_IN_PROGRESS: Algorithm is already in progress - check if
1374f75da36STal Gilboa  * need to perform an action
1384f75da36STal Gilboa  * @DIM_APPLY_NEW_PROFILE: DIM consumer is currently applying a profile - no need to measure
1394f75da36STal Gilboa  */
140690a6ca7SRandy Dunlap enum dim_state {
141c002bd52STal Gilboa 	DIM_START_MEASURE,
142c002bd52STal Gilboa 	DIM_MEASURE_IN_PROGRESS,
143c002bd52STal Gilboa 	DIM_APPLY_NEW_PROFILE,
1440e58983dSTal Gilboa };
1450e58983dSTal Gilboa 
1464f75da36STal Gilboa /**
147690a6ca7SRandy Dunlap  * enum dim_tune_state - DIM algorithm tune states
1484f75da36STal Gilboa  *
1494f75da36STal Gilboa  * These will determine which action the algorithm should perform.
1504f75da36STal Gilboa  *
1514f75da36STal Gilboa  * @DIM_PARKING_ON_TOP: Algorithm found a local top point - exit on significant difference
1524f75da36STal Gilboa  * @DIM_PARKING_TIRED: Algorithm found a deep top point - don't exit if tired > 0
1534f75da36STal Gilboa  * @DIM_GOING_RIGHT: Algorithm is currently trying higher moderation levels
1544f75da36STal Gilboa  * @DIM_GOING_LEFT: Algorithm is currently trying lower moderation levels
1554f75da36STal Gilboa  */
156690a6ca7SRandy Dunlap enum dim_tune_state {
157449986eaSTal Gilboa 	DIM_PARKING_ON_TOP,
158449986eaSTal Gilboa 	DIM_PARKING_TIRED,
159449986eaSTal Gilboa 	DIM_GOING_RIGHT,
160449986eaSTal Gilboa 	DIM_GOING_LEFT,
1610e58983dSTal Gilboa };
1620e58983dSTal Gilboa 
1634f75da36STal Gilboa /**
164690a6ca7SRandy Dunlap  * enum dim_stats_state - DIM algorithm statistics states
1654f75da36STal Gilboa  *
1664f75da36STal Gilboa  * These will determine the verdict of current iteration.
1674f75da36STal Gilboa  *
1684f75da36STal Gilboa  * @DIM_STATS_WORSE: Current iteration shows worse performance than before
169690a6ca7SRandy Dunlap  * @DIM_STATS_SAME:  Current iteration shows same performance than before
170690a6ca7SRandy Dunlap  * @DIM_STATS_BETTER: Current iteration shows better performance than before
1714f75da36STal Gilboa  */
172690a6ca7SRandy Dunlap enum dim_stats_state {
173449986eaSTal Gilboa 	DIM_STATS_WORSE,
174449986eaSTal Gilboa 	DIM_STATS_SAME,
175449986eaSTal Gilboa 	DIM_STATS_BETTER,
1760e58983dSTal Gilboa };
1770e58983dSTal Gilboa 
1784f75da36STal Gilboa /**
179690a6ca7SRandy Dunlap  * enum dim_step_result - DIM algorithm step results
1804f75da36STal Gilboa  *
1814f75da36STal Gilboa  * These describe the result of a step.
1824f75da36STal Gilboa  *
1834f75da36STal Gilboa  * @DIM_STEPPED: Performed a regular step
1844f75da36STal Gilboa  * @DIM_TOO_TIRED: Same kind of step was done multiple times - should go to
1854f75da36STal Gilboa  * tired parking
1864f75da36STal Gilboa  * @DIM_ON_EDGE: Stepped to the most left/right profile
1874f75da36STal Gilboa  */
188690a6ca7SRandy Dunlap enum dim_step_result {
189449986eaSTal Gilboa 	DIM_STEPPED,
190449986eaSTal Gilboa 	DIM_TOO_TIRED,
191449986eaSTal Gilboa 	DIM_ON_EDGE,
1920e58983dSTal Gilboa };
1930e58983dSTal Gilboa 
1944f75da36STal Gilboa /**
1954f75da36STal Gilboa  *	dim_on_top - check if current state is a good place to stop (top location)
1964f75da36STal Gilboa  *	@dim: DIM context
1974f75da36STal Gilboa  *
1984f75da36STal Gilboa  * Check if current profile is a good place to park at.
1994f75da36STal Gilboa  * This will result in reducing the DIM checks frequency as we assume we
2004f75da36STal Gilboa  * shouldn't probably change profiles, unless traffic pattern wasn't changed.
2014f75da36STal Gilboa  */
2024f75da36STal Gilboa bool dim_on_top(struct dim *dim);
2030e58983dSTal Gilboa 
2044f75da36STal Gilboa /**
205690a6ca7SRandy Dunlap  *	dim_turn - change profile altering direction
2064f75da36STal Gilboa  *	@dim: DIM context
2074f75da36STal Gilboa  *
2084f75da36STal Gilboa  * Go left if we were going right and vice-versa.
2094f75da36STal Gilboa  * Do nothing if currently parking.
2104f75da36STal Gilboa  */
2114f75da36STal Gilboa void dim_turn(struct dim *dim);
2120e58983dSTal Gilboa 
2134f75da36STal Gilboa /**
2144f75da36STal Gilboa  *	dim_park_on_top - enter a parking state on a top location
2154f75da36STal Gilboa  *	@dim: DIM context
2164f75da36STal Gilboa  *
2174f75da36STal Gilboa  * Enter parking state.
2184f75da36STal Gilboa  * Clear all movement history.
2194f75da36STal Gilboa  */
2204f75da36STal Gilboa void dim_park_on_top(struct dim *dim);
2210e58983dSTal Gilboa 
2224f75da36STal Gilboa /**
2234f75da36STal Gilboa  *	dim_park_tired - enter a tired parking state
2244f75da36STal Gilboa  *	@dim: DIM context
2254f75da36STal Gilboa  *
2264f75da36STal Gilboa  * Enter parking state.
2274f75da36STal Gilboa  * Clear all movement history and cause DIM checks frequency to reduce.
2284f75da36STal Gilboa  */
2294f75da36STal Gilboa void dim_park_tired(struct dim *dim);
2300e58983dSTal Gilboa 
2314f75da36STal Gilboa /**
2324f75da36STal Gilboa  *	dim_calc_stats - calculate the difference between two samples
2334f75da36STal Gilboa  *	@start: start sample
2344f75da36STal Gilboa  *	@end: end sample
2354f75da36STal Gilboa  *	@curr_stats: delta between samples
2364f75da36STal Gilboa  *
2374f75da36STal Gilboa  * Calculate the delta between two samples (in data rates).
2384f75da36STal Gilboa  * Takes into consideration counter wrap-around.
239*162bd18eSRoy Novich  * Returned boolean indicates whether curr_stats are reliable.
2404f75da36STal Gilboa  */
241*162bd18eSRoy Novich bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
2424f75da36STal Gilboa 		    struct dim_stats *curr_stats);
2434f75da36STal Gilboa 
2444f75da36STal Gilboa /**
245690a6ca7SRandy Dunlap  *	dim_update_sample - set a sample's fields with given values
2464f75da36STal Gilboa  *	@event_ctr: number of events to set
2474f75da36STal Gilboa  *	@packets: number of packets to set
2484f75da36STal Gilboa  *	@bytes: number of bytes to set
2494f75da36STal Gilboa  *	@s: DIM sample
2504f75da36STal Gilboa  */
2510e58983dSTal Gilboa static inline void
dim_update_sample(u16 event_ctr,u64 packets,u64 bytes,struct dim_sample * s)2528960b389STal Gilboa dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s)
2530e58983dSTal Gilboa {
2540e58983dSTal Gilboa 	s->time	     = ktime_get();
2550e58983dSTal Gilboa 	s->pkt_ctr   = packets;
2560e58983dSTal Gilboa 	s->byte_ctr  = bytes;
2570e58983dSTal Gilboa 	s->event_ctr = event_ctr;
2580e58983dSTal Gilboa }
2590e58983dSTal Gilboa 
260398c2b05SYamin Friedman /**
261398c2b05SYamin Friedman  *	dim_update_sample_with_comps - set a sample's fields with given
262398c2b05SYamin Friedman  *	values including the completion parameter
263398c2b05SYamin Friedman  *	@event_ctr: number of events to set
264398c2b05SYamin Friedman  *	@packets: number of packets to set
265398c2b05SYamin Friedman  *	@bytes: number of bytes to set
266398c2b05SYamin Friedman  *	@comps: number of completions to set
267398c2b05SYamin Friedman  *	@s: DIM sample
268398c2b05SYamin Friedman  */
269398c2b05SYamin Friedman static inline void
dim_update_sample_with_comps(u16 event_ctr,u64 packets,u64 bytes,u64 comps,struct dim_sample * s)270398c2b05SYamin Friedman dim_update_sample_with_comps(u16 event_ctr, u64 packets, u64 bytes, u64 comps,
271398c2b05SYamin Friedman 			     struct dim_sample *s)
272398c2b05SYamin Friedman {
273398c2b05SYamin Friedman 	dim_update_sample(event_ctr, packets, bytes, s);
274398c2b05SYamin Friedman 	s->comp_ctr = comps;
275398c2b05SYamin Friedman }
276398c2b05SYamin Friedman 
2774f75da36STal Gilboa /* Net DIM */
2780e58983dSTal Gilboa 
2794f75da36STal Gilboa /**
2804f75da36STal Gilboa  *	net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile
2814f75da36STal Gilboa  *	@cq_period_mode: CQ period mode
2824f75da36STal Gilboa  *	@ix: Profile index
2834f75da36STal Gilboa  */
2844f75da36STal Gilboa struct dim_cq_moder net_dim_get_rx_moderation(u8 cq_period_mode, int ix);
2854f75da36STal Gilboa 
2864f75da36STal Gilboa /**
2874f75da36STal Gilboa  *	net_dim_get_def_rx_moderation - provide the default RX moderation
2884f75da36STal Gilboa  *	@cq_period_mode: CQ period mode
2894f75da36STal Gilboa  */
2904f75da36STal Gilboa struct dim_cq_moder net_dim_get_def_rx_moderation(u8 cq_period_mode);
2914f75da36STal Gilboa 
2924f75da36STal Gilboa /**
2934f75da36STal Gilboa  *	net_dim_get_tx_moderation - provide a CQ moderation object for the given TX profile
2944f75da36STal Gilboa  *	@cq_period_mode: CQ period mode
2954f75da36STal Gilboa  *	@ix: Profile index
2964f75da36STal Gilboa  */
2974f75da36STal Gilboa struct dim_cq_moder net_dim_get_tx_moderation(u8 cq_period_mode, int ix);
2984f75da36STal Gilboa 
2994f75da36STal Gilboa /**
3004f75da36STal Gilboa  *	net_dim_get_def_tx_moderation - provide the default TX moderation
3014f75da36STal Gilboa  *	@cq_period_mode: CQ period mode
3024f75da36STal Gilboa  */
3034f75da36STal Gilboa struct dim_cq_moder net_dim_get_def_tx_moderation(u8 cq_period_mode);
3044f75da36STal Gilboa 
3054f75da36STal Gilboa /**
3064f75da36STal Gilboa  *	net_dim - main DIM algorithm entry point
3074f75da36STal Gilboa  *	@dim: DIM instance information
3084f75da36STal Gilboa  *	@end_sample: Current data measurement
3094f75da36STal Gilboa  *
3104f75da36STal Gilboa  * Called by the consumer.
311690a6ca7SRandy Dunlap  * This is the main logic of the algorithm, where data is processed in order
312690a6ca7SRandy Dunlap  * to decide on next required action.
3134f75da36STal Gilboa  */
3144f75da36STal Gilboa void net_dim(struct dim *dim, struct dim_sample end_sample);
3154f75da36STal Gilboa 
316f4915455SYamin Friedman /* RDMA DIM */
317f4915455SYamin Friedman 
318f4915455SYamin Friedman /*
319f4915455SYamin Friedman  * RDMA DIM profile:
320f4915455SYamin Friedman  * profile size must be of RDMA_DIM_PARAMS_NUM_PROFILES.
321f4915455SYamin Friedman  */
322f4915455SYamin Friedman #define RDMA_DIM_PARAMS_NUM_PROFILES 9
323f4915455SYamin Friedman #define RDMA_DIM_START_PROFILE 0
324f4915455SYamin Friedman 
325f4915455SYamin Friedman /**
326f4915455SYamin Friedman  * rdma_dim - Runs the adaptive moderation.
327f4915455SYamin Friedman  * @dim: The moderation struct.
328f4915455SYamin Friedman  * @completions: The number of completions collected in this round.
329f4915455SYamin Friedman  *
330f4915455SYamin Friedman  * Each call to rdma_dim takes the latest amount of completions that
331f4915455SYamin Friedman  * have been collected and counts them as a new event.
332f4915455SYamin Friedman  * Once enough events have been collected the algorithm decides a new
333f4915455SYamin Friedman  * moderation level.
334f4915455SYamin Friedman  */
335f4915455SYamin Friedman void rdma_dim(struct dim *dim, u64 completions);
336f4915455SYamin Friedman 
3370e58983dSTal Gilboa #endif /* DIM_H */
338