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