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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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