1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2019, Mellanox Technologies inc. All rights reserved.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/dim.h>
7*4882a593Smuzhiyun
dim_on_top(struct dim * dim)8*4882a593Smuzhiyun bool dim_on_top(struct dim *dim)
9*4882a593Smuzhiyun {
10*4882a593Smuzhiyun switch (dim->tune_state) {
11*4882a593Smuzhiyun case DIM_PARKING_ON_TOP:
12*4882a593Smuzhiyun case DIM_PARKING_TIRED:
13*4882a593Smuzhiyun return true;
14*4882a593Smuzhiyun case DIM_GOING_RIGHT:
15*4882a593Smuzhiyun return (dim->steps_left > 1) && (dim->steps_right == 1);
16*4882a593Smuzhiyun default: /* DIM_GOING_LEFT */
17*4882a593Smuzhiyun return (dim->steps_right > 1) && (dim->steps_left == 1);
18*4882a593Smuzhiyun }
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun EXPORT_SYMBOL(dim_on_top);
21*4882a593Smuzhiyun
dim_turn(struct dim * dim)22*4882a593Smuzhiyun void dim_turn(struct dim *dim)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun switch (dim->tune_state) {
25*4882a593Smuzhiyun case DIM_PARKING_ON_TOP:
26*4882a593Smuzhiyun case DIM_PARKING_TIRED:
27*4882a593Smuzhiyun break;
28*4882a593Smuzhiyun case DIM_GOING_RIGHT:
29*4882a593Smuzhiyun dim->tune_state = DIM_GOING_LEFT;
30*4882a593Smuzhiyun dim->steps_left = 0;
31*4882a593Smuzhiyun break;
32*4882a593Smuzhiyun case DIM_GOING_LEFT:
33*4882a593Smuzhiyun dim->tune_state = DIM_GOING_RIGHT;
34*4882a593Smuzhiyun dim->steps_right = 0;
35*4882a593Smuzhiyun break;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun EXPORT_SYMBOL(dim_turn);
39*4882a593Smuzhiyun
dim_park_on_top(struct dim * dim)40*4882a593Smuzhiyun void dim_park_on_top(struct dim *dim)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun dim->steps_right = 0;
43*4882a593Smuzhiyun dim->steps_left = 0;
44*4882a593Smuzhiyun dim->tired = 0;
45*4882a593Smuzhiyun dim->tune_state = DIM_PARKING_ON_TOP;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun EXPORT_SYMBOL(dim_park_on_top);
48*4882a593Smuzhiyun
dim_park_tired(struct dim * dim)49*4882a593Smuzhiyun void dim_park_tired(struct dim *dim)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun dim->steps_right = 0;
52*4882a593Smuzhiyun dim->steps_left = 0;
53*4882a593Smuzhiyun dim->tune_state = DIM_PARKING_TIRED;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun EXPORT_SYMBOL(dim_park_tired);
56*4882a593Smuzhiyun
dim_calc_stats(struct dim_sample * start,struct dim_sample * end,struct dim_stats * curr_stats)57*4882a593Smuzhiyun void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
58*4882a593Smuzhiyun struct dim_stats *curr_stats)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun /* u32 holds up to 71 minutes, should be enough */
61*4882a593Smuzhiyun u32 delta_us = ktime_us_delta(end->time, start->time);
62*4882a593Smuzhiyun u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
63*4882a593Smuzhiyun u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
64*4882a593Smuzhiyun start->byte_ctr);
65*4882a593Smuzhiyun u32 ncomps = BIT_GAP(BITS_PER_TYPE(u32), end->comp_ctr,
66*4882a593Smuzhiyun start->comp_ctr);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun if (!delta_us)
69*4882a593Smuzhiyun return;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
72*4882a593Smuzhiyun curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
73*4882a593Smuzhiyun curr_stats->epms = DIV_ROUND_UP(DIM_NEVENTS * USEC_PER_MSEC,
74*4882a593Smuzhiyun delta_us);
75*4882a593Smuzhiyun curr_stats->cpms = DIV_ROUND_UP(ncomps * USEC_PER_MSEC, delta_us);
76*4882a593Smuzhiyun if (curr_stats->epms != 0)
77*4882a593Smuzhiyun curr_stats->cpe_ratio = DIV_ROUND_DOWN_ULL(
78*4882a593Smuzhiyun curr_stats->cpms * 100, curr_stats->epms);
79*4882a593Smuzhiyun else
80*4882a593Smuzhiyun curr_stats->cpe_ratio = 0;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun EXPORT_SYMBOL(dim_calc_stats);
84