History

linux/dim: Move logic to dim.h

In preparation for supporting more implementations of the DIM algorithm, I'm moving what would become common logic to a common library. Downstream DIM implementations will use the common lib for their implementation.

Tal Gilboa committed 8 years ago

Commit 0e589831 parent cd6c84d3 files · +156 −146Browse files

Unified · Split

3 files
  1. MAINTAINERS +1 −0
  2. include/linux/dim.h +153 −0
  3. include/linux/net_dim.h +2 −146
MAINTAINERS+1−0
@@ -5589,6 +5589,7 @@ DYNAMIC INTERRUPT MODERATION · 5588 unmodified lines
55895589 M: Tal Gilboa <talgi@mellanox.com>
55905590 S: Maintained
55915591 F: include/linux/net_dim.h
5592+F: include/linux/dim.h
55925593
55935594 DZ DECSTATION DZ11 SERIAL DRIVER
55945595 M: "Maciej W. Rozycki" <macro@linux-mips.org>
include/linux/dim.h+153−0
@@ -0,0 +1,153 @@
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+
9+#define NET_DIM_NEVENTS 64
10+
11+/* more than 10% difference */
12+#define IS_SIGNIFICANT_DIFF(val, ref) \
13+ (((100UL * abs((val) - (ref))) / (ref)) > 10)
14+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \
15+& (BIT_ULL(bits) - 1))
16+
17+struct net_dim_cq_moder {
18+ u16 usec;
19+ u16 pkts;
20+ u8 cq_period_mode;
21+};
22+
23+struct net_dim_sample {
24+ ktime_t time;
25+ u32 pkt_ctr;
26+ u32 byte_ctr;
27+ u16 event_ctr;
28+};
29+
30+struct net_dim_stats {
31+ int ppms; /* packets per msec */
32+ int bpms; /* bytes per msec */
33+ int epms; /* events per msec */
34+};
35+
36+struct net_dim { /* Dynamic Interrupt Moderation */
37+ u8 state;
38+ struct net_dim_stats prev_stats;
39+ struct net_dim_sample start_sample;
40+ struct work_struct work;
41+ u8 profile_ix;
42+ u8 mode;
43+ u8 tune_state;
44+ u8 steps_right;
45+ u8 steps_left;
46+ u8 tired;
47+};
48+
49+enum {
50+ NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0,
51+ NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1,
52+ NET_DIM_CQ_PERIOD_NUM_MODES
53+};
54+
55+enum {
56+ NET_DIM_START_MEASURE,
57+ NET_DIM_MEASURE_IN_PROGRESS,
58+ NET_DIM_APPLY_NEW_PROFILE,
59+};
60+
61+enum {
62+ NET_DIM_PARKING_ON_TOP,
63+ NET_DIM_PARKING_TIRED,
64+ NET_DIM_GOING_RIGHT,
65+ NET_DIM_GOING_LEFT,
66+};
67+
68+enum {
69+ NET_DIM_STATS_WORSE,
70+ NET_DIM_STATS_SAME,
71+ NET_DIM_STATS_BETTER,
72+};
73+
74+enum {
75+ NET_DIM_STEPPED,
76+ NET_DIM_TOO_TIRED,
77+ NET_DIM_ON_EDGE,
78+};
79+
80+static inline bool net_dim_on_top(struct net_dim *net_dim)
81+{
82+ switch (net_dim->tune_state) {
83+ case NET_DIM_PARKING_ON_TOP:
84+ case NET_DIM_PARKING_TIRED:
85+ return true;
86+ case NET_DIM_GOING_RIGHT:
87+ return (net_dim->steps_left > 1) && (net_dim->steps_right == 1);
88+ default: /* NET_DIM_GOING_LEFT */
89+ return (net_dim->steps_right > 1) && (net_dim->steps_left == 1);
90+ }
91+}
92+
93+static inline void net_dim_turn(struct net_dim *net_dim)
94+{
95+ switch (net_dim->tune_state) {
96+ case NET_DIM_PARKING_ON_TOP:
97+ case NET_DIM_PARKING_TIRED:
98+ break;
99+ case NET_DIM_GOING_RIGHT:
100+ net_dim->tune_state = NET_DIM_GOING_LEFT;
101+ net_dim->steps_left = 0;
102+ break;
103+ case NET_DIM_GOING_LEFT:
104+ net_dim->tune_state = NET_DIM_GOING_RIGHT;
105+ net_dim->steps_right = 0;
106+ break;
107+ }
108+}
109+
110+static inline void net_dim_park_on_top(struct net_dim *net_dim)
111+{
112+ net_dim->steps_right = 0;
113+ net_dim->steps_left = 0;
114+ net_dim->tired = 0;
115+ net_dim->tune_state = NET_DIM_PARKING_ON_TOP;
116+}
117+
118+static inline void net_dim_park_tired(struct net_dim *net_dim)
119+{
120+ net_dim->steps_right = 0;
121+ net_dim->steps_left = 0;
122+ net_dim->tune_state = NET_DIM_PARKING_TIRED;
123+}
124+
125+static inline void
126+net_dim_sample(u16 event_ctr, u64 packets, u64 bytes, struct net_dim_sample *s)
127+{
128+ s->time = ktime_get();
129+ s->pkt_ctr = packets;
130+ s->byte_ctr = bytes;
131+ s->event_ctr = event_ctr;
132+}
133+
134+static inline void
135+net_dim_calc_stats(struct net_dim_sample *start, struct net_dim_sample *end,
136+ struct net_dim_stats *curr_stats)
137+{
138+ /* u32 holds up to 71 minutes, should be enough */
139+ u32 delta_us = ktime_us_delta(end->time, start->time);
140+ u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
141+ u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
142+ start->byte_ctr);
143+
144+ if (!delta_us)
145+ return;
146+
147+ curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
148+ curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
149+ curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC,
150+ delta_us);
151+}
152+
153+#endif /* DIM_H */
include/linux/net_dim.h+2−146
@@ -35,73 +35,10 @@ · 34 unmodified lines
3535 #define NET_DIM_H
3636
3737 #include <linux/module.h>
38−
39−struct net_dim_cq_moder {
40− u16 usec;
41− u16 pkts;
42− u8 cq_period_mode;
43−};
44−
45−struct net_dim_sample {
46− ktime_t time;
47− u32 pkt_ctr;
48− u32 byte_ctr;
49− u16 event_ctr;
50−};
51−
52−struct net_dim_stats {
53− int ppms; /* packets per msec */
54− int bpms; /* bytes per msec */
55− int epms; /* events per msec */
56−};
57−
58−struct net_dim { /* Adaptive Moderation */
59− u8 state;
60− struct net_dim_stats prev_stats;
61− struct net_dim_sample start_sample;
62− struct work_struct work;
63− u8 profile_ix;
64− u8 mode;
65− u8 tune_state;
66− u8 steps_right;
67− u8 steps_left;
68− u8 tired;
69−};
70−
71−enum {
72− NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0,
73− NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1,
74− NET_DIM_CQ_PERIOD_NUM_MODES
75−};
76−
77−/* Adaptive moderation logic */
78−enum {
79− NET_DIM_START_MEASURE,
80− NET_DIM_MEASURE_IN_PROGRESS,
81− NET_DIM_APPLY_NEW_PROFILE,
82−};
83−
84−enum {
85− NET_DIM_PARKING_ON_TOP,
86− NET_DIM_PARKING_TIRED,
87− NET_DIM_GOING_RIGHT,
88− NET_DIM_GOING_LEFT,
89−};
90−
91−enum {
92− NET_DIM_STATS_WORSE,
93− NET_DIM_STATS_SAME,
94− NET_DIM_STATS_BETTER,
95−};
96−
97−enum {
98− NET_DIM_STEPPED,
99− NET_DIM_TOO_TIRED,
100− NET_DIM_ON_EDGE,
101−};
38+#include <linux/dim.h>
10239
10340 #define NET_DIM_PARAMS_NUM_PROFILES 5
104−/* Adaptive moderation profiles */
41+/* Netdev dynamic interrupt moderation profiles */
10542 #define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
10643 #define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
10744 #define NET_DIM_DEF_PROFILE_CQE 1
@@ -188,36 +125,6 @@ net_dim_get_def_tx_moderation(u8 cq_period_mode) · 80 unmodified lines
188125 return net_dim_get_tx_moderation(cq_period_mode, profile_ix);
189126 }
190127
191−static inline bool net_dim_on_top(struct net_dim *dim)
192−{
193− switch (dim->tune_state) {
194− case NET_DIM_PARKING_ON_TOP:
195− case NET_DIM_PARKING_TIRED:
196− return true;
197− case NET_DIM_GOING_RIGHT:
198− return (dim->steps_left > 1) && (dim->steps_right == 1);
199− default: /* NET_DIM_GOING_LEFT */
200− return (dim->steps_right > 1) && (dim->steps_left == 1);
201− }
202−}
203−
204−static inline void net_dim_turn(struct net_dim *dim)
205−{
206− switch (dim->tune_state) {
207− case NET_DIM_PARKING_ON_TOP:
208− case NET_DIM_PARKING_TIRED:
209− break;
210− case NET_DIM_GOING_RIGHT:
211− dim->tune_state = NET_DIM_GOING_LEFT;
212− dim->steps_left = 0;
213− break;
214− case NET_DIM_GOING_LEFT:
215− dim->tune_state = NET_DIM_GOING_RIGHT;
216− dim->steps_right = 0;
217− break;
218− }
219−}
220−
221128 static inline int net_dim_step(struct net_dim *dim)
222129 {
223130 if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2))
@@ -245,21 +152,6 @@ static inline int net_dim_step(struct net_dim *dim) · 21 unmodified lines
245152 return NET_DIM_STEPPED;
246153 }
247154
248−static inline void net_dim_park_on_top(struct net_dim *dim)
249−{
250− dim->steps_right = 0;
251− dim->steps_left = 0;
252− dim->tired = 0;
253− dim->tune_state = NET_DIM_PARKING_ON_TOP;
254−}
255−
256−static inline void net_dim_park_tired(struct net_dim *dim)
257−{
258− dim->steps_right = 0;
259− dim->steps_left = 0;
260− dim->tune_state = NET_DIM_PARKING_TIRED;
261−}
262−
263155 static inline void net_dim_exit_parking(struct net_dim *dim)
264156 {
265157 dim->tune_state = dim->profile_ix ? NET_DIM_GOING_LEFT :
@@ -267,9 +159,6 @@ static inline void net_dim_exit_parking(struct net_dim *dim) · 1 unmodified line
267159 net_dim_step(dim);
268160 }
269161
270−#define IS_SIGNIFICANT_DIFF(val, ref) \
271− (((100UL * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
272−
273162 static inline int net_dim_stats_compare(struct net_dim_stats *curr,
274163 struct net_dim_stats *prev)
275164 {
@@ -351,39 +240,6 @@ static inline bool net_dim_decision(struct net_dim_stats *curr_stats, · 75 unmodified lines
351240 return dim->profile_ix != prev_ix;
352241 }
353242
354−static inline void net_dim_sample(u16 event_ctr,
355− u64 packets,
356− u64 bytes,
357− struct net_dim_sample *s)
358−{
359− s->time = ktime_get();
360− s->pkt_ctr = packets;
361− s->byte_ctr = bytes;
362− s->event_ctr = event_ctr;
363−}
364−
365−#define NET_DIM_NEVENTS 64
366−#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
367−
368−static inline void net_dim_calc_stats(struct net_dim_sample *start,
369− struct net_dim_sample *end,
370− struct net_dim_stats *curr_stats)
371−{
372− /* u32 holds up to 71 minutes, should be enough */
373− u32 delta_us = ktime_us_delta(end->time, start->time);
374− u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
375− u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
376− start->byte_ctr);
377−
378− if (!delta_us)
379− return;
380−
381− curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
382− curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
383− curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC,
384− delta_us);
385−}
386−
387243 static inline void net_dim(struct net_dim *dim,
388244 struct net_dim_sample end_sample)
389245 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t