From 0e58983de0d89f6ee75daab1b0ea918cfcf6ddbf Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Sun, 4 Nov 2018 19:07:02 +0200 Subject: 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. Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/net_dim.h | 148 +--------------------------------------------- 2 files changed, 155 insertions(+), 146 deletions(-) create mode 100644 include/linux/dim.h (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h new file mode 100644 index 000000000000..67d7ca40f3dd --- /dev/null +++ b/include/linux/dim.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef DIM_H +#define DIM_H + +#include + +#define NET_DIM_NEVENTS 64 + +/* more than 10% difference */ +#define IS_SIGNIFICANT_DIFF(val, ref) \ + (((100UL * abs((val) - (ref))) / (ref)) > 10) +#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \ +& (BIT_ULL(bits) - 1)) + +struct net_dim_cq_moder { + u16 usec; + u16 pkts; + u8 cq_period_mode; +}; + +struct net_dim_sample { + ktime_t time; + u32 pkt_ctr; + u32 byte_ctr; + u16 event_ctr; +}; + +struct net_dim_stats { + int ppms; /* packets per msec */ + int bpms; /* bytes per msec */ + int epms; /* events per msec */ +}; + +struct net_dim { /* Dynamic Interrupt Moderation */ + u8 state; + struct net_dim_stats prev_stats; + struct net_dim_sample start_sample; + struct work_struct work; + u8 profile_ix; + u8 mode; + u8 tune_state; + u8 steps_right; + u8 steps_left; + u8 tired; +}; + +enum { + NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, + NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, + NET_DIM_CQ_PERIOD_NUM_MODES +}; + +enum { + NET_DIM_START_MEASURE, + NET_DIM_MEASURE_IN_PROGRESS, + NET_DIM_APPLY_NEW_PROFILE, +}; + +enum { + NET_DIM_PARKING_ON_TOP, + NET_DIM_PARKING_TIRED, + NET_DIM_GOING_RIGHT, + NET_DIM_GOING_LEFT, +}; + +enum { + NET_DIM_STATS_WORSE, + NET_DIM_STATS_SAME, + NET_DIM_STATS_BETTER, +}; + +enum { + NET_DIM_STEPPED, + NET_DIM_TOO_TIRED, + NET_DIM_ON_EDGE, +}; + +static inline bool net_dim_on_top(struct net_dim *net_dim) +{ + switch (net_dim->tune_state) { + case NET_DIM_PARKING_ON_TOP: + case NET_DIM_PARKING_TIRED: + return true; + case NET_DIM_GOING_RIGHT: + return (net_dim->steps_left > 1) && (net_dim->steps_right == 1); + default: /* NET_DIM_GOING_LEFT */ + return (net_dim->steps_right > 1) && (net_dim->steps_left == 1); + } +} + +static inline void net_dim_turn(struct net_dim *net_dim) +{ + switch (net_dim->tune_state) { + case NET_DIM_PARKING_ON_TOP: + case NET_DIM_PARKING_TIRED: + break; + case NET_DIM_GOING_RIGHT: + net_dim->tune_state = NET_DIM_GOING_LEFT; + net_dim->steps_left = 0; + break; + case NET_DIM_GOING_LEFT: + net_dim->tune_state = NET_DIM_GOING_RIGHT; + net_dim->steps_right = 0; + break; + } +} + +static inline void net_dim_park_on_top(struct net_dim *net_dim) +{ + net_dim->steps_right = 0; + net_dim->steps_left = 0; + net_dim->tired = 0; + net_dim->tune_state = NET_DIM_PARKING_ON_TOP; +} + +static inline void net_dim_park_tired(struct net_dim *net_dim) +{ + net_dim->steps_right = 0; + net_dim->steps_left = 0; + net_dim->tune_state = NET_DIM_PARKING_TIRED; +} + +static inline void +net_dim_sample(u16 event_ctr, u64 packets, u64 bytes, struct net_dim_sample *s) +{ + s->time = ktime_get(); + s->pkt_ctr = packets; + s->byte_ctr = bytes; + s->event_ctr = event_ctr; +} + +static inline void +net_dim_calc_stats(struct net_dim_sample *start, struct net_dim_sample *end, + struct net_dim_stats *curr_stats) +{ + /* u32 holds up to 71 minutes, should be enough */ + u32 delta_us = ktime_us_delta(end->time, start->time); + u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); + u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, + start->byte_ctr); + + if (!delta_us) + return; + + curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); + curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); + curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC, + delta_us); +} + +#endif /* DIM_H */ diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h index fd458389f7d1..373cda74b167 100644 --- a/include/linux/net_dim.h +++ b/include/linux/net_dim.h @@ -35,73 +35,10 @@ #define NET_DIM_H #include - -struct net_dim_cq_moder { - u16 usec; - u16 pkts; - u8 cq_period_mode; -}; - -struct net_dim_sample { - ktime_t time; - u32 pkt_ctr; - u32 byte_ctr; - u16 event_ctr; -}; - -struct net_dim_stats { - int ppms; /* packets per msec */ - int bpms; /* bytes per msec */ - int epms; /* events per msec */ -}; - -struct net_dim { /* Adaptive Moderation */ - u8 state; - struct net_dim_stats prev_stats; - struct net_dim_sample start_sample; - struct work_struct work; - u8 profile_ix; - u8 mode; - u8 tune_state; - u8 steps_right; - u8 steps_left; - u8 tired; -}; - -enum { - NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, - NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, - NET_DIM_CQ_PERIOD_NUM_MODES -}; - -/* Adaptive moderation logic */ -enum { - NET_DIM_START_MEASURE, - NET_DIM_MEASURE_IN_PROGRESS, - NET_DIM_APPLY_NEW_PROFILE, -}; - -enum { - NET_DIM_PARKING_ON_TOP, - NET_DIM_PARKING_TIRED, - NET_DIM_GOING_RIGHT, - NET_DIM_GOING_LEFT, -}; - -enum { - NET_DIM_STATS_WORSE, - NET_DIM_STATS_SAME, - NET_DIM_STATS_BETTER, -}; - -enum { - NET_DIM_STEPPED, - NET_DIM_TOO_TIRED, - NET_DIM_ON_EDGE, -}; +#include #define NET_DIM_PARAMS_NUM_PROFILES 5 -/* Adaptive moderation profiles */ +/* Netdev dynamic interrupt moderation profiles */ #define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256 #define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128 #define NET_DIM_DEF_PROFILE_CQE 1 @@ -188,36 +125,6 @@ net_dim_get_def_tx_moderation(u8 cq_period_mode) return net_dim_get_tx_moderation(cq_period_mode, profile_ix); } -static inline bool net_dim_on_top(struct net_dim *dim) -{ - switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: - return true; - case NET_DIM_GOING_RIGHT: - return (dim->steps_left > 1) && (dim->steps_right == 1); - default: /* NET_DIM_GOING_LEFT */ - return (dim->steps_right > 1) && (dim->steps_left == 1); - } -} - -static inline void net_dim_turn(struct net_dim *dim) -{ - switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: - break; - case NET_DIM_GOING_RIGHT: - dim->tune_state = NET_DIM_GOING_LEFT; - dim->steps_left = 0; - break; - case NET_DIM_GOING_LEFT: - dim->tune_state = NET_DIM_GOING_RIGHT; - dim->steps_right = 0; - break; - } -} - static inline int net_dim_step(struct net_dim *dim) { if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2)) @@ -245,21 +152,6 @@ static inline int net_dim_step(struct net_dim *dim) return NET_DIM_STEPPED; } -static inline void net_dim_park_on_top(struct net_dim *dim) -{ - dim->steps_right = 0; - dim->steps_left = 0; - dim->tired = 0; - dim->tune_state = NET_DIM_PARKING_ON_TOP; -} - -static inline void net_dim_park_tired(struct net_dim *dim) -{ - dim->steps_right = 0; - dim->steps_left = 0; - dim->tune_state = NET_DIM_PARKING_TIRED; -} - static inline void net_dim_exit_parking(struct net_dim *dim) { 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) net_dim_step(dim); } -#define IS_SIGNIFICANT_DIFF(val, ref) \ - (((100UL * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */ - static inline int net_dim_stats_compare(struct net_dim_stats *curr, struct net_dim_stats *prev) { @@ -351,39 +240,6 @@ static inline bool net_dim_decision(struct net_dim_stats *curr_stats, return dim->profile_ix != prev_ix; } -static inline void net_dim_sample(u16 event_ctr, - u64 packets, - u64 bytes, - struct net_dim_sample *s) -{ - s->time = ktime_get(); - s->pkt_ctr = packets; - s->byte_ctr = bytes; - s->event_ctr = event_ctr; -} - -#define NET_DIM_NEVENTS 64 -#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1)) - -static inline void net_dim_calc_stats(struct net_dim_sample *start, - struct net_dim_sample *end, - struct net_dim_stats *curr_stats) -{ - /* u32 holds up to 71 minutes, should be enough */ - u32 delta_us = ktime_us_delta(end->time, start->time); - u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); - u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, - start->byte_ctr); - - if (!delta_us) - return; - - curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); - curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); - curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC, - delta_us); -} - static inline void net_dim(struct net_dim *dim, struct net_dim_sample end_sample) { -- cgit v1.2.3 From 449986ea92412727e8c553eaa5c8d3ed884253c4 Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Mon, 5 Nov 2018 11:57:10 +0200 Subject: linux/dim: Remove "net" prefix from internal DIM members Only renaming functions and structs which aren't used by an external code. Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 86 ++++++++++++++++++++++++------------------------ include/linux/net_dim.h | 87 ++++++++++++++++++++++++------------------------- 2 files changed, 86 insertions(+), 87 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h index 67d7ca40f3dd..6ee991681d62 100644 --- a/include/linux/dim.h +++ b/include/linux/dim.h @@ -6,7 +6,7 @@ #include -#define NET_DIM_NEVENTS 64 +#define DIM_NEVENTS 64 /* more than 10% difference */ #define IS_SIGNIFICANT_DIFF(val, ref) \ @@ -27,7 +27,7 @@ struct net_dim_sample { u16 event_ctr; }; -struct net_dim_stats { +struct dim_stats { int ppms; /* packets per msec */ int bpms; /* bytes per msec */ int epms; /* events per msec */ @@ -35,7 +35,7 @@ struct net_dim_stats { struct net_dim { /* Dynamic Interrupt Moderation */ u8 state; - struct net_dim_stats prev_stats; + struct dim_stats prev_stats; struct net_dim_sample start_sample; struct work_struct work; u8 profile_ix; @@ -59,67 +59,67 @@ enum { }; enum { - NET_DIM_PARKING_ON_TOP, - NET_DIM_PARKING_TIRED, - NET_DIM_GOING_RIGHT, - NET_DIM_GOING_LEFT, + DIM_PARKING_ON_TOP, + DIM_PARKING_TIRED, + DIM_GOING_RIGHT, + DIM_GOING_LEFT, }; enum { - NET_DIM_STATS_WORSE, - NET_DIM_STATS_SAME, - NET_DIM_STATS_BETTER, + DIM_STATS_WORSE, + DIM_STATS_SAME, + DIM_STATS_BETTER, }; enum { - NET_DIM_STEPPED, - NET_DIM_TOO_TIRED, - NET_DIM_ON_EDGE, + DIM_STEPPED, + DIM_TOO_TIRED, + DIM_ON_EDGE, }; -static inline bool net_dim_on_top(struct net_dim *net_dim) +static inline bool dim_on_top(struct net_dim *dim) { - switch (net_dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: + switch (dim->tune_state) { + case DIM_PARKING_ON_TOP: + case DIM_PARKING_TIRED: return true; - case NET_DIM_GOING_RIGHT: - return (net_dim->steps_left > 1) && (net_dim->steps_right == 1); - default: /* NET_DIM_GOING_LEFT */ - return (net_dim->steps_right > 1) && (net_dim->steps_left == 1); + case DIM_GOING_RIGHT: + return (dim->steps_left > 1) && (dim->steps_right == 1); + default: /* DIM_GOING_LEFT */ + return (dim->steps_right > 1) && (dim->steps_left == 1); } } -static inline void net_dim_turn(struct net_dim *net_dim) +static inline void dim_turn(struct net_dim *dim) { - switch (net_dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: + switch (dim->tune_state) { + case DIM_PARKING_ON_TOP: + case DIM_PARKING_TIRED: break; - case NET_DIM_GOING_RIGHT: - net_dim->tune_state = NET_DIM_GOING_LEFT; - net_dim->steps_left = 0; + case DIM_GOING_RIGHT: + dim->tune_state = DIM_GOING_LEFT; + dim->steps_left = 0; break; - case NET_DIM_GOING_LEFT: - net_dim->tune_state = NET_DIM_GOING_RIGHT; - net_dim->steps_right = 0; + case DIM_GOING_LEFT: + dim->tune_state = DIM_GOING_RIGHT; + dim->steps_right = 0; break; } } -static inline void net_dim_park_on_top(struct net_dim *net_dim) +static inline void dim_park_on_top(struct net_dim *dim) { - net_dim->steps_right = 0; - net_dim->steps_left = 0; - net_dim->tired = 0; - net_dim->tune_state = NET_DIM_PARKING_ON_TOP; + dim->steps_right = 0; + dim->steps_left = 0; + dim->tired = 0; + dim->tune_state = DIM_PARKING_ON_TOP; } -static inline void net_dim_park_tired(struct net_dim *net_dim) +static inline void dim_park_tired(struct net_dim *dim) { - net_dim->steps_right = 0; - net_dim->steps_left = 0; - net_dim->tune_state = NET_DIM_PARKING_TIRED; + dim->steps_right = 0; + dim->steps_left = 0; + dim->tune_state = DIM_PARKING_TIRED; } static inline void @@ -132,8 +132,8 @@ net_dim_sample(u16 event_ctr, u64 packets, u64 bytes, struct net_dim_sample *s) } static inline void -net_dim_calc_stats(struct net_dim_sample *start, struct net_dim_sample *end, - struct net_dim_stats *curr_stats) +dim_calc_stats(struct net_dim_sample *start, struct net_dim_sample *end, + struct dim_stats *curr_stats) { /* u32 holds up to 71 minutes, should be enough */ u32 delta_us = ktime_us_delta(end->time, start->time); @@ -146,7 +146,7 @@ net_dim_calc_stats(struct net_dim_sample *start, struct net_dim_sample *end, curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); - curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC, + curr_stats->epms = DIV_ROUND_UP(DIM_NEVENTS * USEC_PER_MSEC, delta_us); } diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h index 373cda74b167..f89fa4fdfb46 100644 --- a/include/linux/net_dim.h +++ b/include/linux/net_dim.h @@ -128,67 +128,67 @@ net_dim_get_def_tx_moderation(u8 cq_period_mode) static inline int net_dim_step(struct net_dim *dim) { if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2)) - return NET_DIM_TOO_TIRED; + return DIM_TOO_TIRED; switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: + case DIM_PARKING_ON_TOP: + case DIM_PARKING_TIRED: break; - case NET_DIM_GOING_RIGHT: + case DIM_GOING_RIGHT: if (dim->profile_ix == (NET_DIM_PARAMS_NUM_PROFILES - 1)) - return NET_DIM_ON_EDGE; + return DIM_ON_EDGE; dim->profile_ix++; dim->steps_right++; break; - case NET_DIM_GOING_LEFT: + case DIM_GOING_LEFT: if (dim->profile_ix == 0) - return NET_DIM_ON_EDGE; + return DIM_ON_EDGE; dim->profile_ix--; dim->steps_left++; break; } dim->tired++; - return NET_DIM_STEPPED; + return DIM_STEPPED; } static inline void net_dim_exit_parking(struct net_dim *dim) { - dim->tune_state = dim->profile_ix ? NET_DIM_GOING_LEFT : - NET_DIM_GOING_RIGHT; + dim->tune_state = dim->profile_ix ? DIM_GOING_LEFT : + DIM_GOING_RIGHT; net_dim_step(dim); } -static inline int net_dim_stats_compare(struct net_dim_stats *curr, - struct net_dim_stats *prev) +static inline int net_dim_stats_compare(struct dim_stats *curr, + struct dim_stats *prev) { if (!prev->bpms) - return curr->bpms ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_SAME; + return curr->bpms ? DIM_STATS_BETTER : + DIM_STATS_SAME; if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms)) - return (curr->bpms > prev->bpms) ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_WORSE; + return (curr->bpms > prev->bpms) ? DIM_STATS_BETTER : + DIM_STATS_WORSE; if (!prev->ppms) - return curr->ppms ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_SAME; + return curr->ppms ? DIM_STATS_BETTER : + DIM_STATS_SAME; if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms)) - return (curr->ppms > prev->ppms) ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_WORSE; + return (curr->ppms > prev->ppms) ? DIM_STATS_BETTER : + DIM_STATS_WORSE; if (!prev->epms) - return NET_DIM_STATS_SAME; + return DIM_STATS_SAME; if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms)) - return (curr->epms < prev->epms) ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_WORSE; + return (curr->epms < prev->epms) ? DIM_STATS_BETTER : + DIM_STATS_WORSE; - return NET_DIM_STATS_SAME; + return DIM_STATS_SAME; } -static inline bool net_dim_decision(struct net_dim_stats *curr_stats, +static inline bool net_dim_decision(struct dim_stats *curr_stats, struct net_dim *dim) { int prev_state = dim->tune_state; @@ -197,44 +197,44 @@ static inline bool net_dim_decision(struct net_dim_stats *curr_stats, int step_res; switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: + case DIM_PARKING_ON_TOP: stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats); - if (stats_res != NET_DIM_STATS_SAME) + if (stats_res != DIM_STATS_SAME) net_dim_exit_parking(dim); break; - case NET_DIM_PARKING_TIRED: + case DIM_PARKING_TIRED: dim->tired--; if (!dim->tired) net_dim_exit_parking(dim); break; - case NET_DIM_GOING_RIGHT: - case NET_DIM_GOING_LEFT: + case DIM_GOING_RIGHT: + case DIM_GOING_LEFT: stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats); - if (stats_res != NET_DIM_STATS_BETTER) - net_dim_turn(dim); + if (stats_res != DIM_STATS_BETTER) + dim_turn(dim); - if (net_dim_on_top(dim)) { - net_dim_park_on_top(dim); + if (dim_on_top(dim)) { + dim_park_on_top(dim); break; } step_res = net_dim_step(dim); switch (step_res) { - case NET_DIM_ON_EDGE: - net_dim_park_on_top(dim); + case DIM_ON_EDGE: + dim_park_on_top(dim); break; - case NET_DIM_TOO_TIRED: - net_dim_park_tired(dim); + case DIM_TOO_TIRED: + dim_park_tired(dim); break; } break; } - if ((prev_state != NET_DIM_PARKING_ON_TOP) || - (dim->tune_state != NET_DIM_PARKING_ON_TOP)) + if (prev_state != DIM_PARKING_ON_TOP || + dim->tune_state != DIM_PARKING_ON_TOP) dim->prev_stats = *curr_stats; return dim->profile_ix != prev_ix; @@ -243,7 +243,7 @@ static inline bool net_dim_decision(struct net_dim_stats *curr_stats, static inline void net_dim(struct net_dim *dim, struct net_dim_sample end_sample) { - struct net_dim_stats curr_stats; + struct dim_stats curr_stats; u16 nevents; switch (dim->state) { @@ -251,10 +251,9 @@ static inline void net_dim(struct net_dim *dim, nevents = BIT_GAP(BITS_PER_TYPE(u16), end_sample.event_ctr, dim->start_sample.event_ctr); - if (nevents < NET_DIM_NEVENTS) + if (nevents < DIM_NEVENTS) break; - net_dim_calc_stats(&dim->start_sample, &end_sample, - &curr_stats); + dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats); if (net_dim_decision(&curr_stats, dim)) { dim->state = NET_DIM_APPLY_NEW_PROFILE; schedule_work(&dim->work); -- cgit v1.2.3 From c002bd529d719858d4cc233431c88c9efa844053 Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Mon, 5 Nov 2018 12:07:52 +0200 Subject: linux/dim: Rename externally exposed macros Renamed macros in use by external drivers. Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 12 ++++++------ include/linux/net_dim.h | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h index 6ee991681d62..989dbbdf9d45 100644 --- a/include/linux/dim.h +++ b/include/linux/dim.h @@ -47,15 +47,15 @@ struct net_dim { /* Dynamic Interrupt Moderation */ }; enum { - NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, - NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, - NET_DIM_CQ_PERIOD_NUM_MODES + DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, + DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, + DIM_CQ_PERIOD_NUM_MODES }; enum { - NET_DIM_START_MEASURE, - NET_DIM_MEASURE_IN_PROGRESS, - NET_DIM_APPLY_NEW_PROFILE, + DIM_START_MEASURE, + DIM_MEASURE_IN_PROGRESS, + DIM_APPLY_NEW_PROFILE, }; enum { diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h index f89fa4fdfb46..e0c97f824dd0 100644 --- a/include/linux/net_dim.h +++ b/include/linux/net_dim.h @@ -78,13 +78,13 @@ } static const struct net_dim_cq_moder -rx_profile[NET_DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { +rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { NET_DIM_RX_EQE_PROFILES, NET_DIM_RX_CQE_PROFILES, }; static const struct net_dim_cq_moder -tx_profile[NET_DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { +tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { NET_DIM_TX_EQE_PROFILES, NET_DIM_TX_CQE_PROFILES, }; @@ -101,7 +101,7 @@ net_dim_get_rx_moderation(u8 cq_period_mode, int ix) static inline struct net_dim_cq_moder net_dim_get_def_rx_moderation(u8 cq_period_mode) { - u8 profile_ix = cq_period_mode == NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE ? + u8 profile_ix = cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE ? NET_DIM_DEF_PROFILE_CQE : NET_DIM_DEF_PROFILE_EQE; return net_dim_get_rx_moderation(cq_period_mode, profile_ix); @@ -119,7 +119,7 @@ net_dim_get_tx_moderation(u8 cq_period_mode, int ix) static inline struct net_dim_cq_moder net_dim_get_def_tx_moderation(u8 cq_period_mode) { - u8 profile_ix = cq_period_mode == NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE ? + u8 profile_ix = cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE ? NET_DIM_DEF_PROFILE_CQE : NET_DIM_DEF_PROFILE_EQE; return net_dim_get_tx_moderation(cq_period_mode, profile_ix); @@ -247,7 +247,7 @@ static inline void net_dim(struct net_dim *dim, u16 nevents; switch (dim->state) { - case NET_DIM_MEASURE_IN_PROGRESS: + case DIM_MEASURE_IN_PROGRESS: nevents = BIT_GAP(BITS_PER_TYPE(u16), end_sample.event_ctr, dim->start_sample.event_ctr); @@ -255,17 +255,17 @@ static inline void net_dim(struct net_dim *dim, break; dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats); if (net_dim_decision(&curr_stats, dim)) { - dim->state = NET_DIM_APPLY_NEW_PROFILE; + dim->state = DIM_APPLY_NEW_PROFILE; schedule_work(&dim->work); break; } /* fall through */ - case NET_DIM_START_MEASURE: + case DIM_START_MEASURE: net_dim_sample(end_sample.event_ctr, end_sample.pkt_ctr, end_sample.byte_ctr, &dim->start_sample); - dim->state = NET_DIM_MEASURE_IN_PROGRESS; + dim->state = DIM_MEASURE_IN_PROGRESS; break; - case NET_DIM_APPLY_NEW_PROFILE: + case DIM_APPLY_NEW_PROFILE: break; } } -- cgit v1.2.3 From e5b6ab02d7aa4118c9a36491633812dcc442acbe Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Mon, 14 Jan 2019 15:32:49 +0200 Subject: linux/dim: Rename net_dim_sample() to net_dim_update_sample() In order to avoid confusion between the function and the similarly named struct. In preparation for removing the 'net' prefix from dim members. Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 3 ++- include/linux/net_dim.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h index 989dbbdf9d45..f0f20ed25497 100644 --- a/include/linux/dim.h +++ b/include/linux/dim.h @@ -123,7 +123,8 @@ static inline void dim_park_tired(struct net_dim *dim) } static inline void -net_dim_sample(u16 event_ctr, u64 packets, u64 bytes, struct net_dim_sample *s) +net_dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, + struct net_dim_sample *s) { s->time = ktime_get(); s->pkt_ctr = packets; diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h index e0c97f824dd0..d4b40adc7fa1 100644 --- a/include/linux/net_dim.h +++ b/include/linux/net_dim.h @@ -261,8 +261,8 @@ static inline void net_dim(struct net_dim *dim, } /* fall through */ case DIM_START_MEASURE: - net_dim_sample(end_sample.event_ctr, end_sample.pkt_ctr, end_sample.byte_ctr, - &dim->start_sample); + net_dim_update_sample(end_sample.event_ctr, end_sample.pkt_ctr, + end_sample.byte_ctr, &dim->start_sample); dim->state = DIM_MEASURE_IN_PROGRESS; break; case DIM_APPLY_NEW_PROFILE: -- cgit v1.2.3 From 8960b38932bee8db0bc9c4d8c135f21df6cdd297 Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Thu, 31 Jan 2019 16:44:48 +0200 Subject: linux/dim: Rename externally used net_dim members Removed 'net' prefix from functions and structs used by external drivers. Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 21 ++++++++++----------- include/linux/net_dim.h | 30 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h index f0f20ed25497..60e5074a7cc0 100644 --- a/include/linux/dim.h +++ b/include/linux/dim.h @@ -14,13 +14,13 @@ #define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \ & (BIT_ULL(bits) - 1)) -struct net_dim_cq_moder { +struct dim_cq_moder { u16 usec; u16 pkts; u8 cq_period_mode; }; -struct net_dim_sample { +struct dim_sample { ktime_t time; u32 pkt_ctr; u32 byte_ctr; @@ -33,10 +33,10 @@ struct dim_stats { int epms; /* events per msec */ }; -struct net_dim { /* Dynamic Interrupt Moderation */ +struct dim { /* Dynamic Interrupt Moderation */ u8 state; struct dim_stats prev_stats; - struct net_dim_sample start_sample; + struct dim_sample start_sample; struct work_struct work; u8 profile_ix; u8 mode; @@ -77,7 +77,7 @@ enum { DIM_ON_EDGE, }; -static inline bool dim_on_top(struct net_dim *dim) +static inline bool dim_on_top(struct dim *dim) { switch (dim->tune_state) { case DIM_PARKING_ON_TOP: @@ -90,7 +90,7 @@ static inline bool dim_on_top(struct net_dim *dim) } } -static inline void dim_turn(struct net_dim *dim) +static inline void dim_turn(struct dim *dim) { switch (dim->tune_state) { case DIM_PARKING_ON_TOP: @@ -107,7 +107,7 @@ static inline void dim_turn(struct net_dim *dim) } } -static inline void dim_park_on_top(struct net_dim *dim) +static inline void dim_park_on_top(struct dim *dim) { dim->steps_right = 0; dim->steps_left = 0; @@ -115,7 +115,7 @@ static inline void dim_park_on_top(struct net_dim *dim) dim->tune_state = DIM_PARKING_ON_TOP; } -static inline void dim_park_tired(struct net_dim *dim) +static inline void dim_park_tired(struct dim *dim) { dim->steps_right = 0; dim->steps_left = 0; @@ -123,8 +123,7 @@ static inline void dim_park_tired(struct net_dim *dim) } static inline void -net_dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, - struct net_dim_sample *s) +dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s) { s->time = ktime_get(); s->pkt_ctr = packets; @@ -133,7 +132,7 @@ net_dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, } static inline void -dim_calc_stats(struct net_dim_sample *start, struct net_dim_sample *end, +dim_calc_stats(struct dim_sample *start, struct dim_sample *end, struct dim_stats *curr_stats) { /* u32 holds up to 71 minutes, should be enough */ diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h index d4b40adc7fa1..4e009ec193ef 100644 --- a/include/linux/net_dim.h +++ b/include/linux/net_dim.h @@ -77,28 +77,28 @@ {64, 32} \ } -static const struct net_dim_cq_moder +static const struct dim_cq_moder rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { NET_DIM_RX_EQE_PROFILES, NET_DIM_RX_CQE_PROFILES, }; -static const struct net_dim_cq_moder +static const struct dim_cq_moder tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { NET_DIM_TX_EQE_PROFILES, NET_DIM_TX_CQE_PROFILES, }; -static inline struct net_dim_cq_moder +static inline struct dim_cq_moder net_dim_get_rx_moderation(u8 cq_period_mode, int ix) { - struct net_dim_cq_moder cq_moder = rx_profile[cq_period_mode][ix]; + struct dim_cq_moder cq_moder = rx_profile[cq_period_mode][ix]; cq_moder.cq_period_mode = cq_period_mode; return cq_moder; } -static inline struct net_dim_cq_moder +static inline struct dim_cq_moder net_dim_get_def_rx_moderation(u8 cq_period_mode) { u8 profile_ix = cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE ? @@ -107,16 +107,16 @@ net_dim_get_def_rx_moderation(u8 cq_period_mode) return net_dim_get_rx_moderation(cq_period_mode, profile_ix); } -static inline struct net_dim_cq_moder +static inline struct dim_cq_moder net_dim_get_tx_moderation(u8 cq_period_mode, int ix) { - struct net_dim_cq_moder cq_moder = tx_profile[cq_period_mode][ix]; + struct dim_cq_moder cq_moder = tx_profile[cq_period_mode][ix]; cq_moder.cq_period_mode = cq_period_mode; return cq_moder; } -static inline struct net_dim_cq_moder +static inline struct dim_cq_moder net_dim_get_def_tx_moderation(u8 cq_period_mode) { u8 profile_ix = cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE ? @@ -125,7 +125,7 @@ net_dim_get_def_tx_moderation(u8 cq_period_mode) return net_dim_get_tx_moderation(cq_period_mode, profile_ix); } -static inline int net_dim_step(struct net_dim *dim) +static inline int net_dim_step(struct dim *dim) { if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2)) return DIM_TOO_TIRED; @@ -152,7 +152,7 @@ static inline int net_dim_step(struct net_dim *dim) return DIM_STEPPED; } -static inline void net_dim_exit_parking(struct net_dim *dim) +static inline void net_dim_exit_parking(struct dim *dim) { dim->tune_state = dim->profile_ix ? DIM_GOING_LEFT : DIM_GOING_RIGHT; @@ -189,7 +189,7 @@ static inline int net_dim_stats_compare(struct dim_stats *curr, } static inline bool net_dim_decision(struct dim_stats *curr_stats, - struct net_dim *dim) + struct dim *dim) { int prev_state = dim->tune_state; int prev_ix = dim->profile_ix; @@ -240,8 +240,8 @@ static inline bool net_dim_decision(struct dim_stats *curr_stats, return dim->profile_ix != prev_ix; } -static inline void net_dim(struct net_dim *dim, - struct net_dim_sample end_sample) +static inline void net_dim(struct dim *dim, + struct dim_sample end_sample) { struct dim_stats curr_stats; u16 nevents; @@ -261,8 +261,8 @@ static inline void net_dim(struct net_dim *dim, } /* fall through */ case DIM_START_MEASURE: - net_dim_update_sample(end_sample.event_ctr, end_sample.pkt_ctr, - end_sample.byte_ctr, &dim->start_sample); + dim_update_sample(end_sample.event_ctr, end_sample.pkt_ctr, + end_sample.byte_ctr, &dim->start_sample); dim->state = DIM_MEASURE_IN_PROGRESS; break; case DIM_APPLY_NEW_PROFILE: -- cgit v1.2.3 From 4f75da3666c0c572967729a2401ac650be5581b6 Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Thu, 10 Jan 2019 17:33:17 +0200 Subject: linux/dim: Move implementation to .c files Moved all logic from dim.h and net_dim.h to dim.c and net_dim.c. This is both more structurally appealing and would allow to only expose externally used functions. Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 319 ++++++++++++++++++++++++++++++++++++++---------- include/linux/net_dim.h | 273 ----------------------------------------- 2 files changed, 255 insertions(+), 337 deletions(-) delete mode 100644 include/linux/net_dim.h (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h index 60e5074a7cc0..f48ede3e0322 100644 --- a/include/linux/dim.h +++ b/include/linux/dim.h @@ -6,20 +6,49 @@ #include +/** + * Number of events between DIM iterations. + * Causes a moderation of the algorithm run. + */ #define DIM_NEVENTS 64 -/* more than 10% difference */ +/** + * Is a difference between values justifies taking an action. + * We consider 10% difference as significant. + */ #define IS_SIGNIFICANT_DIFF(val, ref) \ (((100UL * abs((val) - (ref))) / (ref)) > 10) + +/** + * Calculate the gap between two values. + * Take wrap-around and variable size into consideration. + */ #define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \ -& (BIT_ULL(bits) - 1)) + & (BIT_ULL(bits) - 1)) +/** + * Structure for CQ moderation values. + * Used for communications between DIM and its consumer. + * + * @usec: CQ timer suggestion (by DIM) + * @pkts: CQ packet counter suggestion (by DIM) + * @cq_period_mode: CQ priod count mode (from CQE/EQE) + */ struct dim_cq_moder { u16 usec; u16 pkts; u8 cq_period_mode; }; +/** + * Structure for DIM sample data. + * Used for communications between DIM and its consumer. + * + * @time: Sample timestamp + * @pkt_ctr: Number of packets + * @byte_ctr: Number of bytes + * @event_ctr: Number of events + */ struct dim_sample { ktime_t time; u32 pkt_ctr; @@ -27,13 +56,36 @@ struct dim_sample { u16 event_ctr; }; +/** + * Structure for DIM stats. + * Used for holding current measured rates. + * + * @ppms: Packets per msec + * @bpms: Bytes per msec + * @epms: Events per msec + */ struct dim_stats { - int ppms; /* packets per msec */ - int bpms; /* bytes per msec */ - int epms; /* events per msec */ + int ppms; + int bpms; + int epms; }; -struct dim { /* Dynamic Interrupt Moderation */ +/** + * Main structure for dynamic interrupt moderation (DIM). + * Used for holding all information about a specific DIM instance. + * + * @state: Algorithm state (see below) + * @prev_stats: Measured rates from previous iteration (for comparison) + * @start_sample: Sampled data at start of current iteration + * @work: Work to perform on action required + * @profile_ix: Current moderation profile + * @mode: CQ period count mode + * @tune_state: Algorithm tuning state (see below) + * @steps_right: Number of steps taken towards higher moderation + * @steps_left: Number of steps taken towards lower moderation + * @tired: Parking depth counter + */ +struct dim { u8 state; struct dim_stats prev_stats; struct dim_sample start_sample; @@ -46,18 +98,49 @@ struct dim { /* Dynamic Interrupt Moderation */ u8 tired; }; +/** + * enum dim_cq_period_mode + * + * These are the modes for CQ period count. + * + * @DIM_CQ_PERIOD_MODE_START_FROM_EQE: Start counting from EQE + * @DIM_CQ_PERIOD_MODE_START_FROM_CQE: Start counting from CQE (implies timer reset) + * @DIM_CQ_PERIOD_NUM_MODES: Number of modes + */ enum { DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, DIM_CQ_PERIOD_NUM_MODES }; +/** + * enum dim_state + * + * These are the DIM algorithm states. + * These will determine if the algorithm is in a valid state to start an iteration. + * + * @DIM_START_MEASURE: This is the first iteration (also after applying a new profile) + * @DIM_MEASURE_IN_PROGRESS: Algorithm is already in progress - check if + * need to perform an action + * @DIM_APPLY_NEW_PROFILE: DIM consumer is currently applying a profile - no need to measure + */ enum { DIM_START_MEASURE, DIM_MEASURE_IN_PROGRESS, DIM_APPLY_NEW_PROFILE, }; +/** + * enum dim_tune_state + * + * These are the DIM algorithm tune states. + * These will determine which action the algorithm should perform. + * + * @DIM_PARKING_ON_TOP: Algorithm found a local top point - exit on significant difference + * @DIM_PARKING_TIRED: Algorithm found a deep top point - don't exit if tired > 0 + * @DIM_GOING_RIGHT: Algorithm is currently trying higher moderation levels + * @DIM_GOING_LEFT: Algorithm is currently trying lower moderation levels + */ enum { DIM_PARKING_ON_TOP, DIM_PARKING_TIRED, @@ -65,63 +148,95 @@ enum { DIM_GOING_LEFT, }; +/** + * enum dim_stats_state + * + * These are the DIM algorithm statistics states. + * These will determine the verdict of current iteration. + * + * @DIM_STATS_WORSE: Current iteration shows worse performance than before + * @DIM_STATS_WORSE: Current iteration shows same performance than before + * @DIM_STATS_WORSE: Current iteration shows better performance than before + */ enum { DIM_STATS_WORSE, DIM_STATS_SAME, DIM_STATS_BETTER, }; +/** + * enum dim_step_result + * + * These are the DIM algorithm step results. + * These describe the result of a step. + * + * @DIM_STEPPED: Performed a regular step + * @DIM_TOO_TIRED: Same kind of step was done multiple times - should go to + * tired parking + * @DIM_ON_EDGE: Stepped to the most left/right profile + */ enum { DIM_STEPPED, DIM_TOO_TIRED, DIM_ON_EDGE, }; -static inline bool dim_on_top(struct dim *dim) -{ - switch (dim->tune_state) { - case DIM_PARKING_ON_TOP: - case DIM_PARKING_TIRED: - return true; - case DIM_GOING_RIGHT: - return (dim->steps_left > 1) && (dim->steps_right == 1); - default: /* DIM_GOING_LEFT */ - return (dim->steps_right > 1) && (dim->steps_left == 1); - } -} +/** + * dim_on_top - check if current state is a good place to stop (top location) + * @dim: DIM context + * + * Check if current profile is a good place to park at. + * This will result in reducing the DIM checks frequency as we assume we + * shouldn't probably change profiles, unless traffic pattern wasn't changed. + */ +bool dim_on_top(struct dim *dim); -static inline void dim_turn(struct dim *dim) -{ - switch (dim->tune_state) { - case DIM_PARKING_ON_TOP: - case DIM_PARKING_TIRED: - break; - case DIM_GOING_RIGHT: - dim->tune_state = DIM_GOING_LEFT; - dim->steps_left = 0; - break; - case DIM_GOING_LEFT: - dim->tune_state = DIM_GOING_RIGHT; - dim->steps_right = 0; - break; - } -} +/** + * dim_turn - change profile alterning direction + * @dim: DIM context + * + * Go left if we were going right and vice-versa. + * Do nothing if currently parking. + */ +void dim_turn(struct dim *dim); -static inline void dim_park_on_top(struct dim *dim) -{ - dim->steps_right = 0; - dim->steps_left = 0; - dim->tired = 0; - dim->tune_state = DIM_PARKING_ON_TOP; -} +/** + * dim_park_on_top - enter a parking state on a top location + * @dim: DIM context + * + * Enter parking state. + * Clear all movement history. + */ +void dim_park_on_top(struct dim *dim); -static inline void dim_park_tired(struct dim *dim) -{ - dim->steps_right = 0; - dim->steps_left = 0; - dim->tune_state = DIM_PARKING_TIRED; -} +/** + * dim_park_tired - enter a tired parking state + * @dim: DIM context + * + * Enter parking state. + * Clear all movement history and cause DIM checks frequency to reduce. + */ +void dim_park_tired(struct dim *dim); + +/** + * dim_calc_stats - calculate the difference between two samples + * @start: start sample + * @end: end sample + * @curr_stats: delta between samples + * + * Calculate the delta between two samples (in data rates). + * Takes into consideration counter wrap-around. + */ +void dim_calc_stats(struct dim_sample *start, struct dim_sample *end, + struct dim_stats *curr_stats); +/** + * dim_update_sample - set a sample's fields with give values + * @event_ctr: number of events to set + * @packets: number of packets to set + * @bytes: number of bytes to set + * @s: DIM sample + */ static inline void dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s) { @@ -131,23 +246,99 @@ dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s) s->event_ctr = event_ctr; } -static inline void -dim_calc_stats(struct dim_sample *start, struct dim_sample *end, - struct dim_stats *curr_stats) -{ - /* u32 holds up to 71 minutes, should be enough */ - u32 delta_us = ktime_us_delta(end->time, start->time); - u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); - u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, - start->byte_ctr); - - if (!delta_us) - return; - - curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); - curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); - curr_stats->epms = DIV_ROUND_UP(DIM_NEVENTS * USEC_PER_MSEC, - delta_us); +/* Net DIM */ + +/* + * Net DIM profiles: + * There are different set of profiles for each CQ period mode. + * There are different set of profiles for RX/TX CQs. + * Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES + */ +#define NET_DIM_PARAMS_NUM_PROFILES 5 +#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256 +#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128 +#define NET_DIM_DEF_PROFILE_CQE 1 +#define NET_DIM_DEF_PROFILE_EQE 1 + +#define NET_DIM_RX_EQE_PROFILES { \ + {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ } +#define NET_DIM_RX_CQE_PROFILES { \ + {2, 256}, \ + {8, 128}, \ + {16, 64}, \ + {32, 64}, \ + {64, 64} \ +} + +#define NET_DIM_TX_EQE_PROFILES { \ + {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ + {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \ +} + +#define NET_DIM_TX_CQE_PROFILES { \ + {5, 128}, \ + {8, 64}, \ + {16, 32}, \ + {32, 32}, \ + {64, 32} \ +} + +static const struct dim_cq_moder +rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { + NET_DIM_RX_EQE_PROFILES, + NET_DIM_RX_CQE_PROFILES, +}; + +static const struct dim_cq_moder +tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { + NET_DIM_TX_EQE_PROFILES, + NET_DIM_TX_CQE_PROFILES, +}; + +/** + * net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile + * @cq_period_mode: CQ period mode + * @ix: Profile index + */ +struct dim_cq_moder net_dim_get_rx_moderation(u8 cq_period_mode, int ix); + +/** + * net_dim_get_def_rx_moderation - provide the default RX moderation + * @cq_period_mode: CQ period mode + */ +struct dim_cq_moder net_dim_get_def_rx_moderation(u8 cq_period_mode); + +/** + * net_dim_get_tx_moderation - provide a CQ moderation object for the given TX profile + * @cq_period_mode: CQ period mode + * @ix: Profile index + */ +struct dim_cq_moder net_dim_get_tx_moderation(u8 cq_period_mode, int ix); + +/** + * net_dim_get_def_tx_moderation - provide the default TX moderation + * @cq_period_mode: CQ period mode + */ +struct dim_cq_moder net_dim_get_def_tx_moderation(u8 cq_period_mode); + +/** + * net_dim - main DIM algorithm entry point + * @dim: DIM instance information + * @end_sample: Current data measurement + * + * Called by the consumer. + * This is the main logic of the algorithm, where data is processed in order to decide on next + * required action. + */ +void net_dim(struct dim *dim, struct dim_sample end_sample); + #endif /* DIM_H */ diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h deleted file mode 100644 index 4e009ec193ef..000000000000 --- a/include/linux/net_dim.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2016, Mellanox Technologies. All rights reserved. - * Copyright (c) 2017-2018, Broadcom Limited. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef NET_DIM_H -#define NET_DIM_H - -#include -#include - -#define NET_DIM_PARAMS_NUM_PROFILES 5 -/* Netdev dynamic interrupt moderation profiles */ -#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256 -#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128 -#define NET_DIM_DEF_PROFILE_CQE 1 -#define NET_DIM_DEF_PROFILE_EQE 1 - -/* All profiles sizes must be NET_PARAMS_DIM_NUM_PROFILES */ -#define NET_DIM_RX_EQE_PROFILES { \ - {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ -} - -#define NET_DIM_RX_CQE_PROFILES { \ - {2, 256}, \ - {8, 128}, \ - {16, 64}, \ - {32, 64}, \ - {64, 64} \ -} - -#define NET_DIM_TX_EQE_PROFILES { \ - {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \ -} - -#define NET_DIM_TX_CQE_PROFILES { \ - {5, 128}, \ - {8, 64}, \ - {16, 32}, \ - {32, 32}, \ - {64, 32} \ -} - -static const struct dim_cq_moder -rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { - NET_DIM_RX_EQE_PROFILES, - NET_DIM_RX_CQE_PROFILES, -}; - -static const struct dim_cq_moder -tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { - NET_DIM_TX_EQE_PROFILES, - NET_DIM_TX_CQE_PROFILES, -}; - -static inline struct dim_cq_moder -net_dim_get_rx_moderation(u8 cq_period_mode, int ix) -{ - struct dim_cq_moder cq_moder = rx_profile[cq_period_mode][ix]; - - cq_moder.cq_period_mode = cq_period_mode; - return cq_moder; -} - -static inline struct dim_cq_moder -net_dim_get_def_rx_moderation(u8 cq_period_mode) -{ - u8 profile_ix = cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE ? - NET_DIM_DEF_PROFILE_CQE : NET_DIM_DEF_PROFILE_EQE; - - return net_dim_get_rx_moderation(cq_period_mode, profile_ix); -} - -static inline struct dim_cq_moder -net_dim_get_tx_moderation(u8 cq_period_mode, int ix) -{ - struct dim_cq_moder cq_moder = tx_profile[cq_period_mode][ix]; - - cq_moder.cq_period_mode = cq_period_mode; - return cq_moder; -} - -static inline struct dim_cq_moder -net_dim_get_def_tx_moderation(u8 cq_period_mode) -{ - u8 profile_ix = cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE ? - NET_DIM_DEF_PROFILE_CQE : NET_DIM_DEF_PROFILE_EQE; - - return net_dim_get_tx_moderation(cq_period_mode, profile_ix); -} - -static inline int net_dim_step(struct dim *dim) -{ - if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2)) - return DIM_TOO_TIRED; - - switch (dim->tune_state) { - case DIM_PARKING_ON_TOP: - case DIM_PARKING_TIRED: - break; - case DIM_GOING_RIGHT: - if (dim->profile_ix == (NET_DIM_PARAMS_NUM_PROFILES - 1)) - return DIM_ON_EDGE; - dim->profile_ix++; - dim->steps_right++; - break; - case DIM_GOING_LEFT: - if (dim->profile_ix == 0) - return DIM_ON_EDGE; - dim->profile_ix--; - dim->steps_left++; - break; - } - - dim->tired++; - return DIM_STEPPED; -} - -static inline void net_dim_exit_parking(struct dim *dim) -{ - dim->tune_state = dim->profile_ix ? DIM_GOING_LEFT : - DIM_GOING_RIGHT; - net_dim_step(dim); -} - -static inline int net_dim_stats_compare(struct dim_stats *curr, - struct dim_stats *prev) -{ - if (!prev->bpms) - return curr->bpms ? DIM_STATS_BETTER : - DIM_STATS_SAME; - - if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms)) - return (curr->bpms > prev->bpms) ? DIM_STATS_BETTER : - DIM_STATS_WORSE; - - if (!prev->ppms) - return curr->ppms ? DIM_STATS_BETTER : - DIM_STATS_SAME; - - if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms)) - return (curr->ppms > prev->ppms) ? DIM_STATS_BETTER : - DIM_STATS_WORSE; - - if (!prev->epms) - return DIM_STATS_SAME; - - if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms)) - return (curr->epms < prev->epms) ? DIM_STATS_BETTER : - DIM_STATS_WORSE; - - return DIM_STATS_SAME; -} - -static inline bool net_dim_decision(struct dim_stats *curr_stats, - struct dim *dim) -{ - int prev_state = dim->tune_state; - int prev_ix = dim->profile_ix; - int stats_res; - int step_res; - - switch (dim->tune_state) { - case DIM_PARKING_ON_TOP: - stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats); - if (stats_res != DIM_STATS_SAME) - net_dim_exit_parking(dim); - break; - - case DIM_PARKING_TIRED: - dim->tired--; - if (!dim->tired) - net_dim_exit_parking(dim); - break; - - case DIM_GOING_RIGHT: - case DIM_GOING_LEFT: - stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats); - if (stats_res != DIM_STATS_BETTER) - dim_turn(dim); - - if (dim_on_top(dim)) { - dim_park_on_top(dim); - break; - } - - step_res = net_dim_step(dim); - switch (step_res) { - case DIM_ON_EDGE: - dim_park_on_top(dim); - break; - case DIM_TOO_TIRED: - dim_park_tired(dim); - break; - } - - break; - } - - if (prev_state != DIM_PARKING_ON_TOP || - dim->tune_state != DIM_PARKING_ON_TOP) - dim->prev_stats = *curr_stats; - - return dim->profile_ix != prev_ix; -} - -static inline void net_dim(struct dim *dim, - struct dim_sample end_sample) -{ - struct dim_stats curr_stats; - u16 nevents; - - switch (dim->state) { - case DIM_MEASURE_IN_PROGRESS: - nevents = BIT_GAP(BITS_PER_TYPE(u16), - end_sample.event_ctr, - dim->start_sample.event_ctr); - if (nevents < DIM_NEVENTS) - break; - dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats); - if (net_dim_decision(&curr_stats, dim)) { - dim->state = DIM_APPLY_NEW_PROFILE; - schedule_work(&dim->work); - break; - } - /* fall through */ - case DIM_START_MEASURE: - dim_update_sample(end_sample.event_ctr, end_sample.pkt_ctr, - end_sample.byte_ctr, &dim->start_sample); - dim->state = DIM_MEASURE_IN_PROGRESS; - break; - case DIM_APPLY_NEW_PROFILE: - break; - } -} - -#endif /* NET_DIM_H */ -- cgit v1.2.3 From 398c2b05bbee21cc172dfff017c0351d4d14e04c Mon Sep 17 00:00:00 2001 From: Yamin Friedman Date: Thu, 22 Nov 2018 09:51:17 +0200 Subject: linux/dim: Add completions count to dim_sample Added a measurement of completions per/msec to allow for completion based dim algorithms. In order to use dynamic interrupt moderation with RDMA we need to have a different measurment than packets per second. This change is meant to prepare for adding a new DIM method. All drivers that use net_dim and thus do not need a completion count will have the completions set to 0. Signed-off-by: Yamin Friedman Reviewed-by: Max Gurtovoy Signed-off-by: Saeed Mahameed --- include/linux/dim.h | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dim.h b/include/linux/dim.h index f48ede3e0322..aa9bdd47a648 100644 --- a/include/linux/dim.h +++ b/include/linux/dim.h @@ -37,6 +37,7 @@ struct dim_cq_moder { u16 usec; u16 pkts; + u16 comps; u8 cq_period_mode; }; @@ -54,6 +55,7 @@ struct dim_sample { u32 pkt_ctr; u32 byte_ctr; u16 event_ctr; + u32 comp_ctr; }; /** @@ -65,9 +67,11 @@ struct dim_sample { * @epms: Events per msec */ struct dim_stats { - int ppms; - int bpms; - int epms; + int ppms; /* packets per msec */ + int bpms; /* bytes per msec */ + int epms; /* events per msec */ + int cpms; /* completions per msec */ + int cpe_ratio; /* ratio of completions to events */ }; /** @@ -89,6 +93,7 @@ struct dim { u8 state; struct dim_stats prev_stats; struct dim_sample start_sample; + struct dim_sample measuring_sample; struct work_struct work; u8 profile_ix; u8 mode; @@ -246,6 +251,23 @@ dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s) s->event_ctr = event_ctr; } +/** + * dim_update_sample_with_comps - set a sample's fields with given + * values including the completion parameter + * @event_ctr: number of events to set + * @packets: number of packets to set + * @bytes: number of bytes to set + * @comps: number of completions to set + * @s: DIM sample + */ +static inline void +dim_update_sample_with_comps(u16 event_ctr, u64 packets, u64 bytes, u64 comps, + struct dim_sample *s) +{ + dim_update_sample(event_ctr, packets, bytes, s); + s->comp_ctr = comps; +} + /* Net DIM */ /* -- cgit v1.2.3