1 /*
2  * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "dp_cal_client_api.h"
21 #include "qdf_module.h"
22 
23 /* dp_cal_client_attach - function to attach cal client timer
24  * @cal_client_ctx: cal client timer context
25  * @pdev: pdev handle
26  * @osdev: device pointer
27  * @dp_iterate_peer_list : function pointer to iterate and update peer stats
28  *
29  * return: void
30  */
dp_cal_client_attach(struct cdp_cal_client ** cal_client_ctx,struct cdp_pdev * pdev,qdf_device_t osdev,void (* dp_iterate_peer_list)(struct cdp_pdev *))31 void dp_cal_client_attach(struct cdp_cal_client **cal_client_ctx,
32 			  struct cdp_pdev *pdev,
33 			  qdf_device_t osdev,
34 			  void (*dp_iterate_peer_list)(struct cdp_pdev *))
35 {
36 	struct cal_client *cal_cl;
37 
38 	*cal_client_ctx = qdf_mem_malloc(sizeof(struct cal_client));
39 
40 	if (!(*cal_client_ctx))
41 		return;
42 
43 	cal_cl = (struct cal_client *)(*cal_client_ctx);
44 	cal_cl->iterate_update_peer_list = dp_iterate_peer_list;
45 	cal_cl->pdev_hdl = pdev;
46 
47 	qdf_timer_init(osdev, &cal_cl->cal_client_timer,
48 		       dp_cal_client_stats_timer_fn, *cal_client_ctx,
49 		       QDF_TIMER_TYPE_WAKE_APPS);
50 }
51 
52 qdf_export_symbol(dp_cal_client_attach);
53 
54 /* dp_cal_client_detach - detach cal client timer
55  * @cal_client_ctx: cal client timer context
56  *
57  * return: void
58  */
dp_cal_client_detach(struct cdp_cal_client ** cal_client_ctx)59 void dp_cal_client_detach(struct cdp_cal_client **cal_client_ctx)
60 {
61 	struct cal_client *cal_cl;
62 
63 	if (*cal_client_ctx) {
64 		cal_cl = (struct cal_client *)*cal_client_ctx;
65 
66 		qdf_timer_stop(&cal_cl->cal_client_timer);
67 		qdf_timer_free(&cal_cl->cal_client_timer);
68 		qdf_mem_free(cal_cl);
69 		*cal_client_ctx = NULL;
70 	}
71 }
72 
73 qdf_export_symbol(dp_cal_client_detach);
74 
75 /* dp_cal_client_timer_start- api to start cal client timer
76  * @ctx: cal client timer ctx
77  *
78  * return: void
79  */
dp_cal_client_timer_start(void * ctx)80 void dp_cal_client_timer_start(void *ctx)
81 {
82 	struct cal_client *cal_cl;
83 
84 	if (ctx) {
85 		cal_cl  = (struct cal_client *)ctx;
86 		qdf_timer_start(&cal_cl->cal_client_timer, DP_CAL_CLIENT_TIME);
87 	}
88 }
89 
90 qdf_export_symbol(dp_cal_client_timer_start);
91 
92 /* dp_cal_client_timer_stop- api to stop cal client timer
93  * @ctx: cal client timer ctx
94  *
95  * return: void
96  */
dp_cal_client_timer_stop(void * ctx)97 void dp_cal_client_timer_stop(void *ctx)
98 {
99 	struct cal_client *cal_cl;
100 
101 	if (ctx) {
102 		cal_cl = (struct cal_client *)ctx;
103 		qdf_timer_sync_cancel(&cal_cl->cal_client_timer);
104 		qdf_timer_stop(&cal_cl->cal_client_timer);
105 	}
106 }
107 
108 qdf_export_symbol(dp_cal_client_timer_stop);
109 
110 /* dp_cal_client_stats_timer_fn- function called on timer interval
111  * @ctx: cal client timer ctx
112  *
113  * return: void
114  */
dp_cal_client_stats_timer_fn(void * ctx)115 void dp_cal_client_stats_timer_fn(void *ctx)
116 {
117 	struct cal_client *cal_cl = (struct cal_client *)ctx;
118 
119 	if (!cal_cl)
120 		return;
121 
122 	cal_cl->iterate_update_peer_list(cal_cl->pdev_hdl);
123 	qdf_timer_mod(&cal_cl->cal_client_timer, DP_CAL_CLIENT_TIME);
124 }
125 
126 qdf_export_symbol(dp_cal_client_stats_timer_fn);
127 
128 /*dp_cal_client_update_peer_stats - update peer stats in peer
129  * @peer_stats: cdp peer stats pointer
130  *
131  * return: void
132  */
dp_cal_client_update_peer_stats(struct cdp_peer_stats * peer_stats)133 void dp_cal_client_update_peer_stats(struct cdp_peer_stats *peer_stats)
134 {
135 	uint32_t temp_rx_bytes = peer_stats->rx.to_stack.bytes;
136 	uint32_t temp_rx_data = peer_stats->rx.to_stack.num;
137 	uint32_t temp_tx_bytes = peer_stats->tx.tx_success.bytes;
138 	uint32_t temp_tx_data = peer_stats->tx.tx_success.num;
139 	uint32_t temp_tx_ucast_pkts = peer_stats->tx.ucast.num;
140 
141 	peer_stats->rx.rx_byte_rate = temp_rx_bytes -
142 					peer_stats->rx.rx_bytes_success_last;
143 	peer_stats->rx.rx_data_rate  = temp_rx_data -
144 					peer_stats->rx.rx_data_success_last;
145 	peer_stats->tx.tx_byte_rate = temp_tx_bytes -
146 					peer_stats->tx.tx_bytes_success_last;
147 	peer_stats->tx.tx_data_rate  = temp_tx_data -
148 					peer_stats->tx.tx_data_success_last;
149 	peer_stats->tx.tx_data_ucast_rate = temp_tx_ucast_pkts -
150 					peer_stats->tx.tx_data_ucast_last;
151 
152 	/* Check tx and rx packets in last one second, and increment
153 	 * inactive time for peer
154 	 */
155 	if (peer_stats->tx.tx_data_rate || peer_stats->rx.rx_data_rate)
156 		peer_stats->tx.inactive_time = 0;
157 	else
158 		peer_stats->tx.inactive_time++;
159 
160 	peer_stats->rx.rx_bytes_success_last = temp_rx_bytes;
161 	peer_stats->rx.rx_data_success_last = temp_rx_data;
162 	peer_stats->tx.tx_bytes_success_last = temp_tx_bytes;
163 	peer_stats->tx.tx_data_success_last = temp_tx_data;
164 	peer_stats->tx.tx_data_ucast_last = temp_tx_ucast_pkts;
165 
166 	if (peer_stats->tx.tx_data_ucast_rate) {
167 		if (peer_stats->tx.tx_data_ucast_rate >
168 				peer_stats->tx.tx_data_rate)
169 			peer_stats->tx.last_per =
170 				((peer_stats->tx.tx_data_ucast_rate -
171 					peer_stats->tx.tx_data_rate) * 100) /
172 				peer_stats->tx.tx_data_ucast_rate;
173 		else
174 			peer_stats->tx.last_per = 0;
175 	}
176 
177 }
178 
179 qdf_export_symbol(dp_cal_client_update_peer_stats);
180 
dp_cal_client_update_peer_stats_wifi3(struct cdp_calibr_stats_intf * peer_stats_intf,struct cdp_calibr_stats * peer_calibr_stats)181 void dp_cal_client_update_peer_stats_wifi3(struct cdp_calibr_stats_intf *peer_stats_intf,
182 					   struct cdp_calibr_stats *peer_calibr_stats)
183 {
184 	uint32_t temp_rx_bytes = peer_stats_intf->to_stack.bytes;
185 	uint32_t temp_rx_data = peer_stats_intf->to_stack.num;
186 	uint32_t temp_tx_bytes = peer_stats_intf->tx_success.bytes;
187 	uint32_t temp_tx_data = peer_stats_intf->tx_success.num;
188 	uint32_t temp_tx_ucast_pkts = peer_stats_intf->tx_ucast.num;
189 
190 	peer_calibr_stats->rx.rx_byte_rate = temp_rx_bytes -
191 				peer_calibr_stats->rx.rx_bytes_success_last;
192 	peer_calibr_stats->rx.rx_data_rate  = temp_rx_data -
193 				peer_calibr_stats->rx.rx_data_success_last;
194 	peer_calibr_stats->tx.tx_byte_rate = temp_tx_bytes -
195 				peer_calibr_stats->tx.tx_bytes_success_last;
196 	peer_calibr_stats->tx.tx_data_rate  = temp_tx_data -
197 				peer_calibr_stats->tx.tx_data_success_last;
198 	peer_calibr_stats->tx.tx_data_ucast_rate = temp_tx_ucast_pkts -
199 				peer_calibr_stats->tx.tx_data_ucast_last;
200 
201 	/* Check tx and rx packets in last one second, and increment
202 	 * inactive time for peer
203 	 */
204 	if (peer_calibr_stats->tx.tx_data_rate || peer_calibr_stats->rx.rx_data_rate)
205 		peer_calibr_stats->tx.inactive_time = 0;
206 	else
207 		peer_calibr_stats->tx.inactive_time++;
208 
209 	peer_calibr_stats->rx.rx_bytes_success_last = temp_rx_bytes;
210 	peer_calibr_stats->rx.rx_data_success_last = temp_rx_data;
211 	peer_calibr_stats->tx.tx_bytes_success_last = temp_tx_bytes;
212 	peer_calibr_stats->tx.tx_data_success_last = temp_tx_data;
213 	peer_calibr_stats->tx.tx_data_ucast_last = temp_tx_ucast_pkts;
214 
215 	if (peer_calibr_stats->tx.tx_data_ucast_rate) {
216 		if (peer_calibr_stats->tx.tx_data_ucast_rate >
217 				peer_calibr_stats->tx.tx_data_rate)
218 			peer_calibr_stats->tx.last_per =
219 				((peer_calibr_stats->tx.tx_data_ucast_rate -
220 					peer_calibr_stats->tx.tx_data_rate) * 100) /
221 				peer_calibr_stats->tx.tx_data_ucast_rate;
222 		else
223 			peer_calibr_stats->tx.last_per = 0;
224 	}
225 }
226 
227 qdf_export_symbol(dp_cal_client_update_peer_stats_wifi3);
228