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