| /* |
| * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| #include "dp_cal_client_api.h" |
| #include "qdf_module.h" |
| |
| /* dp_cal_client_attach - function to attach cal client timer |
| * @cal_client_ctx: cal client timer context |
| * @pdev: pdev handle |
| * @osdev: device pointer |
| * @dp_iterate_peer_list : function pointer to iterate and update peer stats |
| * |
| * return: void |
| */ |
| void 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 *)) |
| { |
| struct cal_client *cal_cl; |
| |
| *cal_client_ctx = qdf_mem_malloc(sizeof(struct cal_client)); |
| |
| if (!(*cal_client_ctx)) |
| return; |
| |
| cal_cl = (struct cal_client *)(*cal_client_ctx); |
| cal_cl->iterate_update_peer_list = dp_iterate_peer_list; |
| cal_cl->pdev_hdl = pdev; |
| |
| qdf_timer_init(osdev, &cal_cl->cal_client_timer, |
| dp_cal_client_stats_timer_fn, *cal_client_ctx, |
| QDF_TIMER_TYPE_WAKE_APPS); |
| } |
| |
| qdf_export_symbol(dp_cal_client_attach); |
| |
| /* dp_cal_client_detach - detach cal client timer |
| * @cal_client_ctx: cal client timer context |
| * |
| * return: void |
| */ |
| void dp_cal_client_detach(struct cdp_cal_client **cal_client_ctx) |
| { |
| struct cal_client *cal_cl; |
| |
| if (*cal_client_ctx) { |
| cal_cl = (struct cal_client *)*cal_client_ctx; |
| |
| qdf_timer_stop(&cal_cl->cal_client_timer); |
| qdf_timer_free(&cal_cl->cal_client_timer); |
| qdf_mem_free(cal_cl); |
| *cal_client_ctx = NULL; |
| } |
| } |
| |
| qdf_export_symbol(dp_cal_client_detach); |
| |
| /* dp_cal_client_timer_start- api to start cal client timer |
| * @ctx: cal client timer ctx |
| * |
| * return: void |
| */ |
| void dp_cal_client_timer_start(void *ctx) |
| { |
| struct cal_client *cal_cl; |
| |
| if (ctx) { |
| cal_cl = (struct cal_client *)ctx; |
| qdf_timer_start(&cal_cl->cal_client_timer, DP_CAL_CLIENT_TIME); |
| } |
| } |
| |
| qdf_export_symbol(dp_cal_client_timer_start); |
| |
| /* dp_cal_client_timer_stop- api to stop cal client timer |
| * @ctx: cal client timer ctx |
| * |
| * return: void |
| */ |
| void dp_cal_client_timer_stop(void *ctx) |
| { |
| struct cal_client *cal_cl; |
| |
| if (ctx) { |
| cal_cl = (struct cal_client *)ctx; |
| qdf_timer_sync_cancel(&cal_cl->cal_client_timer); |
| qdf_timer_stop(&cal_cl->cal_client_timer); |
| } |
| } |
| |
| qdf_export_symbol(dp_cal_client_timer_stop); |
| |
| /* dp_cal_client_stats_timer_fn- function called on timer interval |
| * @ctx: cal client timer ctx |
| * |
| * return: void |
| */ |
| void dp_cal_client_stats_timer_fn(void *ctx) |
| { |
| struct cal_client *cal_cl = (struct cal_client *)ctx; |
| |
| if (!cal_cl) |
| return; |
| |
| cal_cl->iterate_update_peer_list(cal_cl->pdev_hdl); |
| qdf_timer_mod(&cal_cl->cal_client_timer, DP_CAL_CLIENT_TIME); |
| } |
| |
| qdf_export_symbol(dp_cal_client_stats_timer_fn); |
| |
| /*dp_cal_client_update_peer_stats - update peer stats in peer |
| * @peer_stats: cdp peer stats pointer |
| * |
| * return: void |
| */ |
| void dp_cal_client_update_peer_stats(struct cdp_peer_stats *peer_stats) |
| { |
| uint32_t temp_rx_bytes = peer_stats->rx.to_stack.bytes; |
| uint32_t temp_rx_data = peer_stats->rx.to_stack.num; |
| uint32_t temp_tx_bytes = peer_stats->tx.tx_success.bytes; |
| uint32_t temp_tx_data = peer_stats->tx.tx_success.num; |
| uint32_t temp_tx_ucast_pkts = peer_stats->tx.ucast.num; |
| |
| peer_stats->rx.rx_byte_rate = temp_rx_bytes - |
| peer_stats->rx.rx_bytes_success_last; |
| peer_stats->rx.rx_data_rate = temp_rx_data - |
| peer_stats->rx.rx_data_success_last; |
| peer_stats->tx.tx_byte_rate = temp_tx_bytes - |
| peer_stats->tx.tx_bytes_success_last; |
| peer_stats->tx.tx_data_rate = temp_tx_data - |
| peer_stats->tx.tx_data_success_last; |
| peer_stats->tx.tx_data_ucast_rate = temp_tx_ucast_pkts - |
| peer_stats->tx.tx_data_ucast_last; |
| |
| /* Check tx and rx packets in last one second, and increment |
| * inactive time for peer |
| */ |
| if (peer_stats->tx.tx_data_rate || peer_stats->rx.rx_data_rate) |
| peer_stats->tx.inactive_time = 0; |
| else |
| peer_stats->tx.inactive_time++; |
| |
| peer_stats->rx.rx_bytes_success_last = temp_rx_bytes; |
| peer_stats->rx.rx_data_success_last = temp_rx_data; |
| peer_stats->tx.tx_bytes_success_last = temp_tx_bytes; |
| peer_stats->tx.tx_data_success_last = temp_tx_data; |
| peer_stats->tx.tx_data_ucast_last = temp_tx_ucast_pkts; |
| |
| if (peer_stats->tx.tx_data_ucast_rate) { |
| if (peer_stats->tx.tx_data_ucast_rate > |
| peer_stats->tx.tx_data_rate) |
| peer_stats->tx.last_per = |
| ((peer_stats->tx.tx_data_ucast_rate - |
| peer_stats->tx.tx_data_rate) * 100) / |
| peer_stats->tx.tx_data_ucast_rate; |
| else |
| peer_stats->tx.last_per = 0; |
| } |
| |
| } |
| |
| qdf_export_symbol(dp_cal_client_update_peer_stats); |
| |