forked from microsoft/WSL2-Linux-Kernel
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
linux/dim: Implement RDMA adaptive moderation (DIM)
RDMA DIM implements a different algorithm from net DIM and is based on completions which is how we can implement interrupt moderation in RDMA. The algorithm optimizes for number of completions and ratio between completions and events. In order to avoid long latencies, the implementation performs fast reduction of moderation level when the traffic changes. Signed-off-by: Yamin Friedman <yaminf@mellanox.com> Reviewed-by: Max Gurtovoy <maxg@mellanox.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
- Loading branch information
1 parent
2ef38e3
commit f491545
Showing
3 changed files
with
146 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB | ||
/* | ||
* Copyright (c) 2019, Mellanox Technologies inc. All rights reserved. | ||
*/ | ||
|
||
#include <linux/dim.h> | ||
|
||
static int rdma_dim_step(struct dim *dim) | ||
{ | ||
if (dim->tune_state == DIM_GOING_RIGHT) { | ||
if (dim->profile_ix == (RDMA_DIM_PARAMS_NUM_PROFILES - 1)) | ||
return DIM_ON_EDGE; | ||
dim->profile_ix++; | ||
dim->steps_right++; | ||
} | ||
if (dim->tune_state == DIM_GOING_LEFT) { | ||
if (dim->profile_ix == 0) | ||
return DIM_ON_EDGE; | ||
dim->profile_ix--; | ||
dim->steps_left++; | ||
} | ||
|
||
return DIM_STEPPED; | ||
} | ||
|
||
static int rdma_dim_stats_compare(struct dim_stats *curr, | ||
struct dim_stats *prev) | ||
{ | ||
/* first stat */ | ||
if (!prev->cpms) | ||
return DIM_STATS_SAME; | ||
|
||
if (IS_SIGNIFICANT_DIFF(curr->cpms, prev->cpms)) | ||
return (curr->cpms > prev->cpms) ? DIM_STATS_BETTER : | ||
DIM_STATS_WORSE; | ||
|
||
if (IS_SIGNIFICANT_DIFF(curr->cpe_ratio, prev->cpe_ratio)) | ||
return (curr->cpe_ratio > prev->cpe_ratio) ? DIM_STATS_BETTER : | ||
DIM_STATS_WORSE; | ||
|
||
return DIM_STATS_SAME; | ||
} | ||
|
||
static bool rdma_dim_decision(struct dim_stats *curr_stats, struct dim *dim) | ||
{ | ||
int prev_ix = dim->profile_ix; | ||
u8 state = dim->tune_state; | ||
int stats_res; | ||
int step_res; | ||
|
||
if (state != DIM_PARKING_ON_TOP && state != DIM_PARKING_TIRED) { | ||
stats_res = rdma_dim_stats_compare(curr_stats, | ||
&dim->prev_stats); | ||
|
||
switch (stats_res) { | ||
case DIM_STATS_SAME: | ||
if (curr_stats->cpe_ratio <= 50 * prev_ix) | ||
dim->profile_ix = 0; | ||
break; | ||
case DIM_STATS_WORSE: | ||
dim_turn(dim); | ||
/* fall through */ | ||
case DIM_STATS_BETTER: | ||
step_res = rdma_dim_step(dim); | ||
if (step_res == DIM_ON_EDGE) | ||
dim_turn(dim); | ||
break; | ||
} | ||
} | ||
|
||
dim->prev_stats = *curr_stats; | ||
|
||
return dim->profile_ix != prev_ix; | ||
} | ||
|
||
void rdma_dim(struct dim *dim, u64 completions) | ||
{ | ||
struct dim_sample *curr_sample = &dim->measuring_sample; | ||
struct dim_stats curr_stats; | ||
u32 nevents; | ||
|
||
dim_update_sample_with_comps(curr_sample->event_ctr + 1, 0, 0, | ||
curr_sample->comp_ctr + completions, | ||
&dim->measuring_sample); | ||
|
||
switch (dim->state) { | ||
case DIM_MEASURE_IN_PROGRESS: | ||
nevents = curr_sample->event_ctr - dim->start_sample.event_ctr; | ||
if (nevents < DIM_NEVENTS) | ||
break; | ||
dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats); | ||
if (rdma_dim_decision(&curr_stats, dim)) { | ||
dim->state = DIM_APPLY_NEW_PROFILE; | ||
schedule_work(&dim->work); | ||
break; | ||
} | ||
/* fall through */ | ||
case DIM_START_MEASURE: | ||
dim->state = DIM_MEASURE_IN_PROGRESS; | ||
dim_update_sample_with_comps(curr_sample->event_ctr, 0, 0, | ||
curr_sample->comp_ctr, | ||
&dim->start_sample); | ||
break; | ||
case DIM_APPLY_NEW_PROFILE: | ||
break; | ||
} | ||
} | ||
EXPORT_SYMBOL(rdma_dim); |