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