| /* |
| * Copyright (c) 2018-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. |
| */ |
| |
| /** |
| * DOC: wlan_cp_stats_mc_ucfg_api.c |
| * |
| * This file provide API definitions required for northbound interaction |
| */ |
| |
| #include <wlan_objmgr_psoc_obj.h> |
| #include "wlan_cp_stats_mc_defs.h" |
| #include <wlan_cp_stats_mc_ucfg_api.h> |
| #include <wlan_cp_stats_mc_tgt_api.h> |
| #include <wlan_cp_stats_utils_api.h> |
| #include "../../core/src/wlan_cp_stats_defs.h" |
| #include "../../core/src/wlan_cp_stats_defs.h" |
| #include "../../core/src/wlan_cp_stats_cmn_api_i.h" |
| |
| QDF_STATUS wlan_cp_stats_psoc_cs_init(struct psoc_cp_stats *psoc_cs) |
| { |
| psoc_cs->obj_stats = qdf_mem_malloc(sizeof(struct psoc_mc_cp_stats)); |
| if (!psoc_cs->obj_stats) |
| return QDF_STATUS_E_NOMEM; |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_psoc_cs_deinit(struct psoc_cp_stats *psoc_cs) |
| { |
| qdf_mem_free(psoc_cs->obj_stats); |
| psoc_cs->obj_stats = NULL; |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_vdev_cs_init(struct vdev_cp_stats *vdev_cs) |
| { |
| vdev_cs->vdev_stats = qdf_mem_malloc(sizeof(struct vdev_mc_cp_stats)); |
| if (!vdev_cs->vdev_stats) |
| return QDF_STATUS_E_NOMEM; |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_vdev_cs_deinit(struct vdev_cp_stats *vdev_cs) |
| { |
| qdf_mem_free(vdev_cs->vdev_stats); |
| vdev_cs->vdev_stats = NULL; |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_pdev_cs_init(struct pdev_cp_stats *pdev_cs) |
| { |
| pdev_cs->pdev_stats = qdf_mem_malloc(sizeof(struct pdev_mc_cp_stats)); |
| if (!pdev_cs->pdev_stats) |
| return QDF_STATUS_E_NOMEM; |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_pdev_cs_deinit(struct pdev_cp_stats *pdev_cs) |
| { |
| qdf_mem_free(pdev_cs->pdev_stats); |
| pdev_cs->pdev_stats = NULL; |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_peer_cs_init(struct peer_cp_stats *peer_cs) |
| { |
| peer_cs->peer_stats = qdf_mem_malloc(sizeof(struct peer_mc_cp_stats)); |
| if (!peer_cs->peer_stats) |
| return QDF_STATUS_E_NOMEM; |
| |
| peer_cs->peer_adv_stats = qdf_mem_malloc(sizeof |
| (struct peer_adv_mc_cp_stats)); |
| if (!peer_cs->peer_adv_stats) { |
| qdf_mem_free(peer_cs->peer_stats); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| peer_cs->peer_extd_stats = |
| qdf_mem_malloc(sizeof(struct peer_extd_stats)); |
| if (!peer_cs->peer_extd_stats) { |
| qdf_mem_free(peer_cs->peer_stats); |
| peer_cs->peer_stats = NULL; |
| qdf_mem_free(peer_cs->peer_adv_stats); |
| peer_cs->peer_adv_stats = NULL; |
| return QDF_STATUS_E_NOMEM; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS wlan_cp_stats_peer_cs_deinit(struct peer_cp_stats *peer_cs) |
| { |
| qdf_mem_free(peer_cs->peer_adv_stats); |
| peer_cs->peer_adv_stats = NULL; |
| qdf_mem_free(peer_cs->peer_extd_stats); |
| peer_cs->peer_extd_stats = NULL; |
| qdf_mem_free(peer_cs->peer_stats); |
| peer_cs->peer_stats = NULL; |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol( |
| struct wlan_objmgr_psoc *psoc, |
| uint8_t vdev_id, |
| enum qdf_proto_subtype protocol) |
| { |
| struct wlan_objmgr_vdev *vdev; |
| struct wake_lock_stats *stats; |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| |
| vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, |
| WLAN_CP_STATS_ID); |
| if (!vdev) { |
| cp_stats_err("vdev numm for vdev_id: %d", vdev_id); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| stats = &vdev_mc_stats->wow_stats; |
| switch (protocol) { |
| case QDF_PROTO_ICMP_RES: |
| stats->icmpv4_count++; |
| break; |
| case QDF_PROTO_ICMPV6_REQ: |
| case QDF_PROTO_ICMPV6_RES: |
| case QDF_PROTO_ICMPV6_RS: |
| stats->icmpv6_count++; |
| break; |
| case QDF_PROTO_ICMPV6_RA: |
| stats->icmpv6_count++; |
| stats->ipv6_mcast_ra_stats++; |
| break; |
| case QDF_PROTO_ICMPV6_NS: |
| stats->icmpv6_count++; |
| stats->ipv6_mcast_ns_stats++; |
| break; |
| case QDF_PROTO_ICMPV6_NA: |
| stats->icmpv6_count++; |
| stats->ipv6_mcast_na_stats++; |
| break; |
| default: |
| break; |
| } |
| |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats_by_dst_addr( |
| struct wlan_objmgr_psoc *psoc, |
| uint8_t vdev_id, uint8_t *dest_mac) |
| { |
| struct wlan_objmgr_vdev *vdev; |
| struct wake_lock_stats *stats; |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| |
| vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, |
| WLAN_CP_STATS_ID); |
| if (!vdev) { |
| cp_stats_err("vdev numm for vdev_id: %d", vdev_id); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| stats = &vdev_mc_stats->wow_stats; |
| switch (*dest_mac) { |
| case QDF_BCAST_MAC_ADDR: |
| stats->bcast_wake_up_count++; |
| break; |
| case QDF_MCAST_IPV4_MAC_ADDR: |
| stats->ipv4_mcast_wake_up_count++; |
| break; |
| case QDF_MCAST_IPV6_MAC_ADDR: |
| stats->ipv6_mcast_wake_up_count++; |
| break; |
| default: |
| stats->ucast_wake_up_count++; |
| break; |
| } |
| |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc, |
| uint8_t vdev_id, |
| uint32_t reason) |
| { |
| struct wake_lock_stats *stats; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct wlan_objmgr_vdev *vdev = NULL; |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, |
| WLAN_CP_STATS_ID); |
| if (!vdev) { |
| cp_stats_err("vdev numm for vdev_id: %d", vdev_id); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| status = QDF_STATUS_E_NULL_VALUE; |
| goto release_vdev_ref; |
| } |
| |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| stats = &vdev_mc_stats->wow_stats; |
| status = tgt_mc_cp_stats_inc_wake_lock_stats(psoc, reason, stats, |
| &psoc_mc_stats->wow_unspecified_wake_up_count); |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| release_vdev_ref: |
| if (vdev) |
| wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); |
| |
| return status; |
| } |
| |
| /** |
| * vdev_iterator() - iterator function to collect wake_lock_stats from all vdev |
| * @psoc: pointer to psoc object |
| * @vdev: pointer to vdev object |
| * @arg: stats object pointer passed as arg |
| * |
| * Return - none |
| */ |
| static void vdev_iterator(struct wlan_objmgr_psoc *psoc, void *vdev, void *arg) |
| { |
| struct wake_lock_stats *vdev_stats; |
| struct wake_lock_stats *stats = arg; |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| return; |
| } |
| |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| vdev_stats = &vdev_mc_stats->wow_stats; |
| stats->ucast_wake_up_count += vdev_stats->ucast_wake_up_count; |
| stats->bcast_wake_up_count += vdev_stats->bcast_wake_up_count; |
| stats->ipv4_mcast_wake_up_count += vdev_stats->ipv4_mcast_wake_up_count; |
| stats->ipv6_mcast_wake_up_count += vdev_stats->ipv6_mcast_wake_up_count; |
| stats->ipv6_mcast_ra_stats += vdev_stats->ipv6_mcast_ra_stats; |
| stats->ipv6_mcast_ns_stats += vdev_stats->ipv6_mcast_ns_stats; |
| stats->ipv6_mcast_na_stats += vdev_stats->ipv6_mcast_na_stats; |
| stats->icmpv4_count += vdev_stats->icmpv4_count; |
| stats->icmpv6_count += vdev_stats->icmpv6_count; |
| stats->rssi_breach_wake_up_count += |
| vdev_stats->rssi_breach_wake_up_count; |
| stats->low_rssi_wake_up_count += vdev_stats->low_rssi_wake_up_count; |
| stats->gscan_wake_up_count += vdev_stats->gscan_wake_up_count; |
| stats->pno_complete_wake_up_count += |
| vdev_stats->pno_complete_wake_up_count; |
| stats->pno_match_wake_up_count += vdev_stats->pno_match_wake_up_count; |
| stats->oem_response_wake_up_count += |
| vdev_stats->oem_response_wake_up_count; |
| stats->pwr_save_fail_detected += vdev_stats->pwr_save_fail_detected; |
| stats->scan_11d += vdev_stats->scan_11d; |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_get_psoc_wake_lock_stats( |
| struct wlan_objmgr_psoc *psoc, |
| struct wake_lock_stats *stats) |
| { |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| /* iterate through all vdevs, and get wow stats from vdev_cs object */ |
| wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, vdev_iterator, |
| stats, true, WLAN_CP_STATS_ID); |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_get_vdev_wake_lock_stats( |
| struct wlan_objmgr_vdev *vdev, |
| struct wake_lock_stats *stats) |
| { |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| qdf_mem_copy(stats, &vdev_mc_stats->wow_stats, sizeof(*stats)); |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_write_wow_stats( |
| struct wlan_objmgr_psoc *psoc, |
| char *buffer, uint16_t max_len, int *ret) |
| { |
| QDF_STATUS status; |
| uint32_t unspecified_wake_count; |
| struct wake_lock_stats wow_stats = {0}; |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| /* get stats from psoc */ |
| status = ucfg_mc_cp_stats_get_psoc_wake_lock_stats(psoc, &wow_stats); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| cp_stats_err("Failed to get WoW stats"); |
| return status; |
| } |
| |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| unspecified_wake_count = psoc_mc_stats->wow_unspecified_wake_up_count; |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| *ret = qdf_scnprintf(buffer, max_len, |
| "WoW Wake Reasons\n" |
| "\tunspecified wake count: %u\n" |
| "\tunicast: %u\n" |
| "\tbroadcast: %u\n" |
| "\tIPv4 multicast: %u\n" |
| "\tIPv6 multicast: %u\n" |
| "\tIPv6 multicast RA: %u\n" |
| "\tIPv6 multicast NS: %u\n" |
| "\tIPv6 multicast NA: %u\n" |
| "\tICMPv4: %u\n" |
| "\tICMPv6: %u\n" |
| "\tRSSI Breach: %u\n" |
| "\tLow RSSI: %u\n" |
| "\tG-Scan: %u\n" |
| "\tPNO Complete: %u\n" |
| "\tPNO Match: %u\n" |
| "\tOEM rsp wake_count: %u\n" |
| "\twake count due to pwr_save_fail_detected: %u\n" |
| "\twake count due to 11d scan: %u\n", |
| unspecified_wake_count, |
| wow_stats.ucast_wake_up_count, |
| wow_stats.bcast_wake_up_count, |
| wow_stats.ipv4_mcast_wake_up_count, |
| wow_stats.ipv6_mcast_wake_up_count, |
| wow_stats.ipv6_mcast_ra_stats, |
| wow_stats.ipv6_mcast_ns_stats, |
| wow_stats.ipv6_mcast_na_stats, |
| wow_stats.icmpv4_count, |
| wow_stats.icmpv6_count, |
| wow_stats.rssi_breach_wake_up_count, |
| wow_stats.low_rssi_wake_up_count, |
| wow_stats.gscan_wake_up_count, |
| wow_stats.pno_complete_wake_up_count, |
| wow_stats.pno_match_wake_up_count, |
| wow_stats.oem_response_wake_up_count, |
| wow_stats.pwr_save_fail_detected, |
| wow_stats.scan_11d); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev, |
| enum stats_req_type type, |
| struct request_info *info) |
| { |
| QDF_STATUS status; |
| |
| status = ucfg_mc_cp_stats_set_pending_req(wlan_vdev_get_psoc(vdev), |
| type, info); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| cp_stats_err("ucfg_mc_cp_stats_set_pending_req pdev failed: %d", |
| status); |
| return status; |
| } |
| |
| return tgt_send_mc_cp_stats_req(wlan_vdev_get_psoc(vdev), type, info); |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, |
| int *dbm) |
| { |
| struct wlan_objmgr_pdev *pdev; |
| struct pdev_mc_cp_stats *pdev_mc_stats; |
| struct pdev_cp_stats *pdev_cp_stats_priv; |
| |
| pdev = wlan_vdev_get_pdev(vdev); |
| pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev); |
| if (!pdev_cp_stats_priv) { |
| cp_stats_err("pdev cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv); |
| pdev_mc_stats = pdev_cp_stats_priv->pdev_stats; |
| *dbm = pdev_mc_stats->max_pwr; |
| wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| bool ucfg_mc_cp_stats_is_req_pending(struct wlan_objmgr_psoc *psoc, |
| enum stats_req_type type) |
| { |
| uint32_t pending_req_map; |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return false; |
| } |
| |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| pending_req_map = psoc_mc_stats->pending.type_map; |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| return (pending_req_map & (1 << type)); |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc, |
| enum stats_req_type type, |
| struct request_info *req) |
| { |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| if (type >= TYPE_MAX) { |
| cp_stats_err("Invalid type index: %d", type); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| psoc_mc_stats->pending.type_map |= (1 << type); |
| psoc_mc_stats->pending.req[type] = *req; |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, |
| enum stats_req_type type) |
| { |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| if (type >= TYPE_MAX) { |
| cp_stats_err("Invalid type index: %d", type); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| psoc_mc_stats->pending.type_map &= ~(1 << type); |
| qdf_mem_zero(&psoc_mc_stats->pending.req[type], |
| sizeof(psoc_mc_stats->pending.req[type])); |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_get_pending_req(struct wlan_objmgr_psoc *psoc, |
| enum stats_req_type type, |
| struct request_info *info) |
| { |
| struct psoc_mc_cp_stats *psoc_mc_stats; |
| struct psoc_cp_stats *psoc_cp_stats_priv; |
| |
| psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); |
| if (!psoc_cp_stats_priv) { |
| cp_stats_err("psoc cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| if (type >= TYPE_MAX) { |
| cp_stats_err("Invalid type index: %d", type); |
| return QDF_STATUS_E_INVAL; |
| } |
| wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); |
| psoc_mc_stats = psoc_cp_stats_priv->obj_stats; |
| *info = psoc_mc_stats->pending.req[type]; |
| wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| void ucfg_mc_cp_stats_free_stats_resources(struct stats_event *ev) |
| { |
| if (!ev) |
| return; |
| |
| qdf_mem_free(ev->pdev_stats); |
| qdf_mem_free(ev->peer_adv_stats); |
| qdf_mem_free(ev->peer_stats); |
| qdf_mem_free(ev->cca_stats); |
| qdf_mem_free(ev->vdev_summary_stats); |
| qdf_mem_free(ev->vdev_chain_rssi); |
| qdf_mem_free(ev->peer_extended_stats); |
| qdf_mem_zero(ev, sizeof(*ev)); |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_cca_stats_get(struct wlan_objmgr_vdev *vdev, |
| struct cca_stats *cca_stats) |
| { |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| cca_stats->congestion = vdev_mc_stats->cca.congestion; |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS ucfg_mc_cp_stats_set_rate_flags(struct wlan_objmgr_vdev *vdev, |
| uint32_t flags) |
| { |
| struct vdev_mc_cp_stats *vdev_mc_stats; |
| struct vdev_cp_stats *vdev_cp_stats_priv; |
| |
| vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); |
| if (!vdev_cp_stats_priv) { |
| cp_stats_err("vdev cp stats object is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); |
| vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; |
| vdev_mc_stats->tx_rate_flags = flags; |
| wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); |
| |
| return QDF_STATUS_SUCCESS; |
| } |