110 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB2/*3 * Copyright (c) 2019, Mellanox Technologies inc. All rights reserved.4 */5 6#include <linux/dim.h>7 8static int rdma_dim_step(struct dim *dim)9{10 if (dim->tune_state == DIM_GOING_RIGHT) {11 if (dim->profile_ix == (RDMA_DIM_PARAMS_NUM_PROFILES - 1))12 return DIM_ON_EDGE;13 dim->profile_ix++;14 dim->steps_right++;15 }16 if (dim->tune_state == DIM_GOING_LEFT) {17 if (dim->profile_ix == 0)18 return DIM_ON_EDGE;19 dim->profile_ix--;20 dim->steps_left++;21 }22 23 return DIM_STEPPED;24}25 26static int rdma_dim_stats_compare(struct dim_stats *curr,27 struct dim_stats *prev)28{29 /* first stat */30 if (!prev->cpms)31 return DIM_STATS_SAME;32 33 if (IS_SIGNIFICANT_DIFF(curr->cpms, prev->cpms))34 return (curr->cpms > prev->cpms) ? DIM_STATS_BETTER :35 DIM_STATS_WORSE;36 37 if (IS_SIGNIFICANT_DIFF(curr->cpe_ratio, prev->cpe_ratio))38 return (curr->cpe_ratio > prev->cpe_ratio) ? DIM_STATS_BETTER :39 DIM_STATS_WORSE;40 41 return DIM_STATS_SAME;42}43 44static bool rdma_dim_decision(struct dim_stats *curr_stats, struct dim *dim)45{46 int prev_ix = dim->profile_ix;47 u8 state = dim->tune_state;48 int stats_res;49 int step_res;50 51 if (state != DIM_PARKING_ON_TOP && state != DIM_PARKING_TIRED) {52 stats_res = rdma_dim_stats_compare(curr_stats,53 &dim->prev_stats);54 55 switch (stats_res) {56 case DIM_STATS_SAME:57 if (curr_stats->cpe_ratio <= 50 * prev_ix)58 dim->profile_ix = 0;59 break;60 case DIM_STATS_WORSE:61 dim_turn(dim);62 fallthrough;63 case DIM_STATS_BETTER:64 step_res = rdma_dim_step(dim);65 if (step_res == DIM_ON_EDGE)66 dim_turn(dim);67 break;68 }69 }70 71 dim->prev_stats = *curr_stats;72 73 return dim->profile_ix != prev_ix;74}75 76void rdma_dim(struct dim *dim, u64 completions)77{78 struct dim_sample *curr_sample = &dim->measuring_sample;79 struct dim_stats curr_stats;80 u32 nevents;81 82 dim_update_sample_with_comps(curr_sample->event_ctr + 1, 0, 0,83 curr_sample->comp_ctr + completions,84 &dim->measuring_sample);85 86 switch (dim->state) {87 case DIM_MEASURE_IN_PROGRESS:88 nevents = curr_sample->event_ctr - dim->start_sample.event_ctr;89 if (nevents < DIM_NEVENTS)90 break;91 if (!dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats))92 break;93 if (rdma_dim_decision(&curr_stats, dim)) {94 dim->state = DIM_APPLY_NEW_PROFILE;95 schedule_work(&dim->work);96 break;97 }98 fallthrough;99 case DIM_START_MEASURE:100 dim->state = DIM_MEASURE_IN_PROGRESS;101 dim_update_sample_with_comps(curr_sample->event_ctr, 0, 0,102 curr_sample->comp_ctr,103 &dim->start_sample);104 break;105 case DIM_APPLY_NEW_PROFILE:106 break;107 }108}109EXPORT_SYMBOL(rdma_dim);110