qcacmn: MCL specific movement from cmn to cld of stats

Move the MCL specific files related to cp stats from
the cmn to cld folder.

Change-Id: I62076512b1b407342338d4612087edd3ba2296df
CRs-Fixed: 2552452
Tento commit je obsažen v:
gaurank kathpalia
2020-04-16 17:45:14 +05:30
odevzdal nshrivas
rodič dfaf7550a0
revize dcc847a925
9 změnil soubory, kde provedl 28 přidání a 4041 odebrání

Zobrazit soubor

@@ -1,535 +0,0 @@
/*
* Copyright (c) 2012-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_defs.h
*
* This file provide definition for structure/enums/defines related to control
* path stats componenet
*/
#ifndef __WLAN_CP_STATS_MC_DEFS_H__
#define __WLAN_CP_STATS_MC_DEFS_H__
#ifdef CONFIG_MCL
#include "wlan_cmn.h"
#include "qdf_event.h"
#define MAX_NUM_CHAINS 2
#define MAX_MIB_STATS 1
#define IS_MSB_SET(__num) ((__num) & BIT(31))
#define IS_LSB_SET(__num) ((__num) & BIT(0))
/**
* enum stats_req_type - enum indicating bit position of various stats type in
* request map
* @TYPE_CONNECTION_TX_POWER: tx power was requested
* @TYPE_STATION_STATS: station stats was requested
* @TYPE_PEER_STATS: peer stats was requested
* @TYPE_MIB_STATS: MIB stats was requested
*/
enum stats_req_type {
TYPE_CONNECTION_TX_POWER = 0,
TYPE_STATION_STATS,
TYPE_PEER_STATS,
TYPE_MIB_STATS,
TYPE_MAX,
};
/**
* enum tx_rate_info - tx rate flags
* @TX_RATE_LEGACY: Legacy rates
* @TX_RATE_HT20: HT20 rates
* @TX_RATE_HT40: HT40 rates
* @TX_RATE_SGI: Rate with Short guard interval
* @TX_RATE_LGI: Rate with Long guard interval
* @TX_RATE_VHT20: VHT 20 rates
* @TX_RATE_VHT40: VHT 40 rates
* @TX_RATE_VHT80: VHT 80 rates
* @TX_RATE_HE20: HE 20 rates
* @TX_RATE_HE40: HE 40 rates
* @TX_RATE_HE80: HE 80 rates
* @TX_RATE_HE160: HE 160 rates
* @TX_RATE_VHT160: VHT 160 rates
*/
enum tx_rate_info {
TX_RATE_LEGACY = 0x1,
TX_RATE_HT20 = 0x2,
TX_RATE_HT40 = 0x4,
TX_RATE_SGI = 0x8,
TX_RATE_LGI = 0x10,
TX_RATE_VHT20 = 0x20,
TX_RATE_VHT40 = 0x40,
TX_RATE_VHT80 = 0x80,
TX_RATE_HE20 = 0x100,
TX_RATE_HE40 = 0x200,
TX_RATE_HE80 = 0x400,
TX_RATE_HE160 = 0x800,
TX_RATE_VHT160 = 0x1000,
};
/**
* enum - txrate_gi
* @txrate_gi_0_8_US: guard interval 0.8 us
* @txrate_gi_0_4_US: guard interval 0.4 us for legacy
* @txrate_gi_1_6_US: guard interval 1.6 us
* @txrate_gi_3_2_US: guard interval 3.2 us
*/
enum txrate_gi {
TXRATE_GI_0_8_US = 0,
TXRATE_GI_0_4_US,
TXRATE_GI_1_6_US,
TXRATE_GI_3_2_US,
};
/**
* struct wake_lock_stats - wake lock stats structure
* @ucast_wake_up_count: Unicast wakeup count
* @bcast_wake_up_count: Broadcast wakeup count
* @ipv4_mcast_wake_up_count: ipv4 multicast wakeup count
* @ipv6_mcast_wake_up_count: ipv6 multicast wakeup count
* @ipv6_mcast_ra_stats: ipv6 multicast ra stats
* @ipv6_mcast_ns_stats: ipv6 multicast ns stats
* @ipv6_mcast_na_stats: ipv6 multicast na stats
* @icmpv4_count: ipv4 icmp packet count
* @icmpv6_count: ipv6 icmp packet count
* @rssi_breach_wake_up_count: rssi breach wakeup count
* @low_rssi_wake_up_count: low rssi wakeup count
* @gscan_wake_up_count: gscan wakeup count
* @pno_complete_wake_up_count: pno complete wakeup count
* @pno_match_wake_up_count: pno match wakeup count
* @oem_response_wake_up_count: oem response wakeup count
* @pwr_save_fail_detected: pwr save fail detected wakeup count
* @scan_11d 11d scan wakeup count
* @mgmt_assoc: association request management frame
* @mgmt_disassoc: disassociation management frame
* @mgmt_assoc_resp: association response management frame
* @mgmt_reassoc: reassociate request management frame
* @mgmt_reassoc_resp: reassociate response management frame
* @mgmt_auth: authentication managament frame
* @mgmt_deauth: deauthentication management frame
* @mgmt_action: action managament frame
*/
struct wake_lock_stats {
uint32_t ucast_wake_up_count;
uint32_t bcast_wake_up_count;
uint32_t ipv4_mcast_wake_up_count;
uint32_t ipv6_mcast_wake_up_count;
uint32_t ipv6_mcast_ra_stats;
uint32_t ipv6_mcast_ns_stats;
uint32_t ipv6_mcast_na_stats;
uint32_t icmpv4_count;
uint32_t icmpv6_count;
uint32_t rssi_breach_wake_up_count;
uint32_t low_rssi_wake_up_count;
uint32_t gscan_wake_up_count;
uint32_t pno_complete_wake_up_count;
uint32_t pno_match_wake_up_count;
uint32_t oem_response_wake_up_count;
uint32_t pwr_save_fail_detected;
uint32_t scan_11d;
uint32_t mgmt_assoc;
uint32_t mgmt_disassoc;
uint32_t mgmt_assoc_resp;
uint32_t mgmt_reassoc;
uint32_t mgmt_reassoc_resp;
uint32_t mgmt_auth;
uint32_t mgmt_deauth;
uint32_t mgmt_action;
};
struct stats_event;
/**
* struct request_info: details of each request
* @cookie: identifier for os_if request
* @u: unified data type for callback to process tx power/peer rssi/
* station stats/mib stats request when response comes.
* @vdev_id: vdev_id of request
* @pdev_id: pdev_id of request
* @peer_mac_addr: peer mac address
*/
struct request_info {
void *cookie;
union {
void (*get_tx_power_cb)(int tx_power, void *cookie);
void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie);
void (*get_station_stats_cb)(struct stats_event *ev,
void *cookie);
void (*get_mib_stats_cb)(struct stats_event *ev,
void *cookie);
} u;
uint32_t vdev_id;
uint32_t pdev_id;
uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE];
};
/**
* struct pending_stats_requests: details of pending requests
* @type_map: map indicating type of outstanding requests
* @req: array of info for outstanding request of each type
*/
struct pending_stats_requests {
uint32_t type_map;
struct request_info req[TYPE_MAX];
};
/**
* struct cca_stats - cca stats
* @congestion: the congestion percentage = (busy_time/total_time)*100
* for the interval from when the vdev was started to the current time
* (or the time at which the vdev was stopped).
*/
struct cca_stats {
uint32_t congestion;
};
/**
* struct psoc_mc_cp_stats: psoc specific stats
* @is_cp_stats_suspended: is cp stats suspended or not
* @pending: details of pending requests
* @wow_unspecified_wake_up_count: number of non-wow related wake ups
* @wow_stats: wake_lock stats for vdev
*/
struct psoc_mc_cp_stats {
bool is_cp_stats_suspended;
struct pending_stats_requests pending;
uint32_t wow_unspecified_wake_up_count;
struct wake_lock_stats wow_stats;
};
/**
* struct pdev_mc_cp_stats: pdev specific stats
* @max_pwr: max tx power for vdev
*/
struct pdev_mc_cp_stats {
int32_t max_pwr;
};
/**
* struct summary_stats - summary stats
* @snr: snr of vdev
* @rssi: rssi of vdev
* @retry_cnt: retry count
* @multiple_retry_cnt: multiple_retry_cnt
* @tx_frm_cnt: num of tx frames
* @rx_frm_cnt: num of rx frames
* @frm_dup_cnt: duplicate frame count
* @fail_cnt: fail count
* @rts_fail_cnt: rts fail count
* @ack_fail_cnt: ack fail count
* @rts_succ_cnt: rts success count
* @rx_discard_cnt: rx frames discarded
* @rx_error_cnt: rx frames with error
*/
struct summary_stats {
uint32_t snr;
int8_t rssi;
uint32_t retry_cnt[4];
uint32_t multiple_retry_cnt[4];
uint32_t tx_frm_cnt[4];
uint32_t rx_frm_cnt;
uint32_t frm_dup_cnt;
uint32_t fail_cnt[4];
uint32_t rts_fail_cnt;
uint32_t ack_fail_cnt;
uint32_t rts_succ_cnt;
uint32_t rx_discard_cnt;
uint32_t rx_error_cnt;
};
/**
* struct vdev_mc_cp_stats - vdev specific stats
* @cca: cca stats
* @tx_rate_flags: tx rate flags (enum tx_rate_info)
* @chain_rssi: chain rssi
* @vdev_summary_stats: vdev's summary stats
*/
struct vdev_mc_cp_stats {
struct cca_stats cca;
uint32_t tx_rate_flags;
int8_t chain_rssi[MAX_NUM_CHAINS];
struct summary_stats vdev_summary_stats;
};
/**
* struct peer_extd_stats - Peer extension statistics
* @peer_macaddr: peer MAC address
* @rx_duration: lower 32 bits of rx duration in microseconds
* @peer_tx_bytes: Total TX bytes (including dot11 header) sent to peer
* @peer_rx_bytes: Total RX bytes (including dot11 header) received from peer
* @last_tx_rate_code: last TX ratecode
* @last_tx_power: TX power used by peer - units are 0.5 dBm
* @rx_mc_bc_cnt: Total number of received multicast & broadcast data frames
* corresponding to this peer, 1 in the MSB of rx_mc_bc_cnt represents a
* valid data
*/
struct peer_extd_stats {
uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE];
uint32_t rx_duration;
uint32_t peer_tx_bytes;
uint32_t peer_rx_bytes;
uint32_t last_tx_rate_code;
int32_t last_tx_power;
uint32_t rx_mc_bc_cnt;
};
/**
* struct peer_mc_cp_stats - peer specific stats
* @tx_rate: tx rate
* @rx_rate: rx rate
* @peer_rssi: rssi
* @peer_macaddr: mac address
* @extd_stats: Pointer to peer extended stats
* @adv_stats: Pointer to peer adv (extd2) stats
*/
struct peer_mc_cp_stats {
uint32_t tx_rate;
uint32_t rx_rate;
int8_t peer_rssi;
uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE];
struct peer_extd_stats *extd_stats;
struct peer_adv_mc_cp_stats *adv_stats;
};
/**
* struct peer_adv_mc_cp_stats - peer specific adv stats
* @peer_macaddr: mac address
* @fcs_count: fcs count
* @rx_bytes: rx bytes
* @rx_count: rx count
*/
struct peer_adv_mc_cp_stats {
uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE];
uint32_t fcs_count;
uint32_t rx_count;
uint64_t rx_bytes;
};
#ifdef WLAN_FEATURE_MIB_STATS
/**
* struct dot11_counters - mib group containing attributes that are MAC counters
* @tx_frags: successfully transmitted fragments
* @group_tx_frames: transmitted group addressed frames
* @failed_cnt: MSDUs not transmitted successfully
* @rx_frags: fragments successfully received
* @group_rx_frames: group addressed frames received
* @fcs_error_cnt: FCS errors detected
* @tx_frames: frames successfully transmitted
*/
struct dot11_counters {
uint32_t tx_frags;
uint32_t group_tx_frames;
uint32_t failed_cnt;
uint32_t rx_frags;
uint32_t group_rx_frames;
uint32_t fcs_error_cnt;
uint32_t tx_frames;
};
/**
* struct dot11_mac_statistics - mib stats information on the operation of MAC
* @retry_cnt: retries done by mac for successful transmition
* @multi_retry_cnt: multiple retries done before successful transmition
* @frame_dup_cnt: duplicate no of frames
* @rts_success_cnt: number of CTS received (in response to RTS)
* @rts_fail_cnt: number of CTS not received (in response to RTS)
* @tx_ack_fail_cnt: number of ACK not received
*/
struct dot11_mac_statistics {
uint32_t retry_cnt;
uint32_t multi_retry_cnt;
uint32_t frame_dup_cnt;
uint32_t rts_success_cnt;
uint32_t rts_fail_cnt;
uint32_t tx_ack_fail_cnt;
};
/**
* dot11_qos_counters - qos mac counters
* @qos_tx_frag_cnt: transmitted QoS fragments
* @qos_failed_cnt: failed Qos fragments
* @qos_retry_cnt: Qos frames transmitted after retransmissions
* @qos_multi_retry_cnt: Qos frames transmitted after more than
* one retransmissions
* @qos_frame_dup_cnt: duplicate frames
* @qos_rts_success_cnt: number of CTS received (in response to RTS)
* @qos_rts_fail_cnt: number of CTS not received (in response to RTS)
* @tx_qos_ack_fail_cnt_up: number of ACK not received
* (in response to Qos frame)
* @qos_rx_frag_cnt: number of received MPDU of type Data
* @qos_tx_frame_cnt: number of transmitted MPDU of type Data
* @qos_discarded_frame_cnt: total Discarded MSDUs
* @qos_mpdu_rx_cnt: total received MPDU
* @qos_retries_rx_cnt: received MPDU with retry bit equal to 1
*/
struct dot11_qos_counters {
uint32_t qos_tx_frag_cnt;
uint32_t qos_failed_cnt;
uint32_t qos_retry_cnt;
uint32_t qos_multi_retry_cnt;
uint32_t qos_frame_dup_cnt;
uint32_t qos_rts_success_cnt;
uint32_t qos_rts_fail_cnt;
uint32_t tx_qos_ack_fail_cnt_up;
uint32_t qos_rx_frag_cnt;
uint32_t qos_tx_frame_cnt;
uint32_t qos_discarded_frame_cnt;
uint32_t qos_mpdu_rx_cnt;
uint32_t qos_retries_rx_cnt;
};
/**
* dot11_rsna_stats - mib rsn stats
* @rm_ccmp_replays: received robust management CCMP MPDUs discarded
* by the replay mechanism
* @tkip_icv_err: TKIP ICV errors encountered
* @tkip_replays: TKIP replay errors detected
* @ccmp_decrypt_err: MPDUs discarded by the CCMP decryption algorithm
* @ccmp_replays: received CCMP MPDUs discarded by the replay mechanism
* @cmac_icv_err: MPDUs discarded by the CMAC integrity check algorithm
* @cmac_replays: MPDUs discarded by the CMAC replay errors
*/
struct dot11_rsna_stats {
uint32_t rm_ccmp_replays;
uint32_t tkip_icv_err;
uint32_t tkip_replays;
uint32_t ccmp_decrypt_err;
uint32_t ccmp_replays;
uint32_t cmac_icv_err;
uint32_t cmac_replays;
};
/**
* dot11_counters_group3 - dot11 group3 stats
* @tx_ampdu_cnt: transmitted AMPDUs
* @tx_mpdus_in_ampdu_cnt: number of MPDUs in the A-MPDU in transmitted AMPDUs
* @tx_octets_in_ampdu_cnt: octets in the transmitted A-MPDUs
* @ampdu_rx_cnt: received A-MPDU
* @mpdu_in_rx_ampdu_cnt: MPDUs received in the A-MPDU
* @rx_octets_in_ampdu_cnt: octets in the received A-MPDU
* @rx_ampdu_deli_crc_err_cnt: number of MPDUs delimiter with CRC error
*/
struct dot11_counters_group3 {
uint32_t tx_ampdu_cnt;
uint32_t tx_mpdus_in_ampdu_cnt;
uint64_t tx_octets_in_ampdu_cnt;
uint32_t ampdu_rx_cnt;
uint32_t mpdu_in_rx_ampdu_cnt;
uint64_t rx_octets_in_ampdu_cnt;
uint32_t rx_ampdu_deli_crc_err_cnt;
};
/**
* mib_stats_metrics - mib stats counters
* @mib_counters: dot11Counters group
* @mib_mac_statistics: dot11MACStatistics group
* @mib_qos_counters: dot11QoSCounters group
* @mib_rsna_stats: dot11RSNAStats group
* @mib_counters_group3: dot11CountersGroup3 group
*/
struct mib_stats_metrics {
struct dot11_counters mib_counters;
struct dot11_mac_statistics mib_mac_statistics;
struct dot11_qos_counters mib_qos_counters;
struct dot11_rsna_stats mib_rsna_stats;
struct dot11_counters_group3 mib_counters_group3;
};
#endif
/**
* struct congestion_stats_event: congestion stats event param
* @vdev_id: vdev_id of the event
* @congestion: the congestion percentage
*/
struct congestion_stats_event {
uint8_t vdev_id;
uint32_t congestion;
};
/**
* struct summary_stats_event - summary_stats event param
* @vdev_id: vdev_id of the event
* @stats: summary stats
*/
struct summary_stats_event {
uint8_t vdev_id;
struct summary_stats stats;
};
/**
* struct chain_rssi_event - chain_rssi event param
* @vdev_id: vdev_id of the event
* @chain_rssi: chain_rssi
*/
struct chain_rssi_event {
uint8_t vdev_id;
int8_t chain_rssi[MAX_NUM_CHAINS];
};
/**
* struct stats_event - parameters populated by stats event
* @num_pdev_stats: num pdev stats
* @pdev_stats: if populated array indicating pdev stats (index = pdev_id)
* @num_peer_stats: num peer stats
* @peer_stats: if populated array indicating peer stats
* @peer_adv_stats: if populated, indicates peer adv (extd2) stats
* @num_peer_adv_stats: number of peer adv (extd2) stats
* @num_peer_extd_stats: Num peer extended stats
* @peer_extended_stats: Peer extended stats
* @cca_stats: if populated indicates congestion stats
* @num_summary_stats: number of summary stats
* @vdev_summary_stats: if populated indicates array of summary stats per vdev
* @num_mib_stats: number of mib stats
* @mib_stats: if populated indicates array of mib stats per vdev
* @num_chain_rssi_stats: number of chain rssi stats
* @vdev_chain_rssi: if populated indicates array of chain rssi per vdev
* @tx_rate: tx rate (kbps)
* @tx_rate_flags: tx rate flags, (enum tx_rate_info)
* @last_event: The LSB indicates if the event is the last event or not and the
* MSB indicates if this feature is supported by FW or not.
*/
struct stats_event {
uint32_t num_pdev_stats;
struct pdev_mc_cp_stats *pdev_stats;
uint32_t num_peer_stats;
struct peer_mc_cp_stats *peer_stats;
uint32_t num_peer_adv_stats;
struct peer_adv_mc_cp_stats *peer_adv_stats;
uint32_t num_peer_extd_stats;
struct peer_extd_stats *peer_extended_stats;
struct congestion_stats_event *cca_stats;
uint32_t num_summary_stats;
struct summary_stats_event *vdev_summary_stats;
#ifdef WLAN_FEATURE_MIB_STATS
uint32_t num_mib_stats;
struct mib_stats_metrics *mib_stats;
#endif
uint32_t num_chain_rssi_stats;
struct chain_rssi_event *vdev_chain_rssi;
uint32_t tx_rate;
uint32_t rx_rate;
enum tx_rate_info tx_rate_flags;
uint32_t last_event;
};
#endif /* CONFIG_MCL */
#endif /* __WLAN_CP_STATS_MC_DEFS_H__ */

Zobrazit soubor

@@ -1,65 +0,0 @@
/*
* Copyright (c) 2018 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_tgt_api.h
*
* This header file provide with API declarations to interface with Southbound
*/
#ifndef __WLAN_CP_STATS_MC_TGT_API_H__
#define __WLAN_CP_STATS_MC_TGT_API_H__
#ifdef QCA_SUPPORT_CP_STATS
#include "wlan_cp_stats_mc_defs.h"
/**
* tgt_mc_cp_stats_process_stats_event(): API to process stats event
* @psoc: pointer to psoc object
* @event: event parameters
*
* Return: status of operation
*/
QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
struct stats_event *event);
/**
* tgt_send_mc_cp_stats_req(): API to send stats request to lmac
* @psoc: pointer to psoc object
*
* Return: status of operation
*/
QDF_STATUS tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *req);
/**
* tgt_mc_cp_stats_inc_wake_lock_stats() : API to increment wake lock stats
* given the wake reason code
* @psoc: pointer to psoc object
* @reason: wake reason
* @stats: vdev wow stats to update
* @unspecified_wake_count: unspecified wake count to update
*
* Return : status of operation
*/
QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
uint32_t reason, struct wake_lock_stats *stats,
uint32_t *unspecified_wake_count);
#endif /* QCA_SUPPORT_CP_STATS */
#endif /* __WLAN_CP_STATS_MC_TGT_API_H__ */

Zobrazit soubor

@@ -1,289 +0,0 @@
/*
* Copyright (c) 2018-2020 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.h
*
* This header file maintain API declaration required for northbound interaction
*/
#ifndef __WLAN_CP_STATS_MC_UCFG_API_H__
#define __WLAN_CP_STATS_MC_UCFG_API_H__
#ifdef QCA_SUPPORT_CP_STATS
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_cp_stats_mc_defs.h>
struct psoc_cp_stats;
struct vdev_cp_stats;
/**
* ucfg_mc_cp_stats_get_psoc_wake_lock_stats() : API to get wake lock stats from
* psoc
* @psoc: pointer to psoc object
* @stats: stats object to populate
*
* Return : status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_get_psoc_wake_lock_stats(
struct wlan_objmgr_psoc *psoc,
struct wake_lock_stats *stats);
/**
* ucfg_mc_cp_stats_get_vdev_wake_lock_stats() : API to get wake lock stats from
* vdev
* @vdev: pointer to vdev object
* @stats: stats object to populate
*
* Return : status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_get_vdev_wake_lock_stats(
struct wlan_objmgr_vdev *vdev,
struct wake_lock_stats *stats);
/**
* ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol() : API to increment wake
* lock stats given the protocol of the packet that was received.
* @psoc: pointer to psoc object
* @vdev_id: vdev_id for which the packet was received
* @protocol: protocol of the packet that was received
*
* Return : status of operation
*/
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);
/**
* ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol() : API to increment wake
* lock stats given destnation of packet that was received.
* @psoc: pointer to psoc object
* @dest_mac: destinamtion mac address of packet that was received
*
* Return : status of operation
*/
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);
/**
* ucfg_mc_cp_stats_inc_wake_lock_stats() : API to increment wake lock stats
* given wake reason.
* @psoc: pointer to psoc object
* @vdev_id: vdev_id on with WOW was received
* @reason: reason of WOW
*
* Return : status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
uint32_t reason);
/**
* ucfg_mc_cp_stats_write_wow_stats() - Writes WOW stats to buffer
* @psoc: pointer to psoc object
* @buffer: The char buffer to write to
* @max_len: The maximum number of chars to write
* @ret: number of bytes written
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_write_wow_stats(
struct wlan_objmgr_psoc *psoc,
char *buffer, uint16_t max_len, int *ret);
/**
* ucfg_mc_cp_stats_send_tx_power_request() - API to send tx_power request to
* lmac
* @vdev: pointer to vdev object
* @type: request type
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev,
enum stats_req_type type,
struct request_info *info);
/**
* ucfg_mc_cp_stats_get_tx_power() - API to fetch tx_power
* @vdev: pointer to vdev object
* @dbm: pointer to tx power in dbm
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
int *dbm);
/**
* ucfg_mc_cp_stats_is_req_pending() - API to tell if given request is pending
* @psoc: pointer to psoc object
* @type: request type to check
*
* Return: true of request is pending, false otherwise
*/
bool ucfg_mc_cp_stats_is_req_pending(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type);
/**
* ucfg_mc_cp_stats_set_pending_req() - API to set pending request
* @psoc: pointer to psoc object
* @type: request to update
* @req: value to update
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *req);
/**
* ucfg_mc_cp_stats_reset_pending_req() - API to reset pending request
* @psoc: pointer to psoc object
* @type: request to update
* @last_req: last request
* @pending: pending request present
*
* The function is an atomic operation of "reset" and "get" last request.
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *last_req,
bool *pending);
/**
* ucfg_mc_cp_stats_get_pending_req() - API to get pending request
* @psoc: pointer to psoc object
* @type: request to update
* @info: buffer to populate
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_get_pending_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *info);
/**
* ucfg_mc_cp_stats_free_stats_resources() - API to free buffers within stats_event
* structure
* @ev: strcture whose buffer are to freed
*
* Return: none
*/
void ucfg_mc_cp_stats_free_stats_resources(struct stats_event *ev);
/**
* ucfg_mc_cp_stats_cca_stats_get() - API to fetch cca stats
* @vdev: pointer to vdev object
* @cca_stats: pointer to cca info
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_cca_stats_get(struct wlan_objmgr_vdev *vdev,
struct cca_stats *cca_stats);
/**
* ucfg_mc_cp_stats_set_rate_flags() - API to set rate flags
* @vdev: pointer to vdev object
* @flags: value to set (enum tx_rate_info)
*
* Return: status of operation
*/
QDF_STATUS ucfg_mc_cp_stats_set_rate_flags(struct wlan_objmgr_vdev *vdev,
enum tx_rate_info flags);
/**
* ucfg_mc_cp_stats_register_lost_link_info_cb() - API to register lost link
* info callback
* @psoc: pointer to psoc object
* @lost_link_cp_stats_info_cb: Lost link info callback to be registered
*
*/
void ucfg_mc_cp_stats_register_lost_link_info_cb(
struct wlan_objmgr_psoc *psoc,
void (*lost_link_cp_stats_info_cb)(void *stats_ev));
#ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
/**
* ucfg_mc_cp_stats_register_pmo_handler() - API to register pmo handler
*
* Return: none
*/
void ucfg_mc_cp_stats_register_pmo_handler(void);
#else
void static inline ucfg_mc_cp_stats_register_pmo_handler(void) { };
#endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
#else
void static inline ucfg_mc_cp_stats_register_pmo_handler(void) { };
static inline QDF_STATUS ucfg_mc_cp_stats_send_stats_request(
struct wlan_objmgr_vdev *vdev,
enum stats_req_type type,
struct request_info *info)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS ucfg_mc_cp_stats_set_rate_flags(
struct wlan_objmgr_vdev *vdev,
enum tx_rate_info flags)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS ucfg_mc_cp_stats_get_psoc_wake_lock_stats(
struct wlan_objmgr_psoc *psoc,
struct wake_lock_stats *stats)
{
return QDF_STATUS_SUCCESS;
}
static inline 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)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats(
struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
uint32_t reason)
{
return QDF_STATUS_SUCCESS;
}
static inline 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)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS ucfg_mc_cp_stats_get_vdev_wake_lock_stats(
struct wlan_objmgr_vdev *vdev,
struct wake_lock_stats *stats)
{
return QDF_STATUS_SUCCESS;
}
#endif /* QCA_SUPPORT_CP_STATS */
#endif /* __WLAN_CP_STATS_MC_UCFG_API_H__ */

Zobrazit soubor

@@ -1,953 +0,0 @@
/*
* Copyright (c) 2018-2020 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_tgt_api.c
*
* This file provide API definitions to update control plane statistics received
* from southbound interface
*/
#include "wlan_cp_stats_mc_defs.h"
#include "target_if_cp_stats.h"
#include "wlan_cp_stats_tgt_api.h"
#include "wlan_cp_stats_mc_tgt_api.h"
#include <wlan_cp_stats_mc_ucfg_api.h>
#include <wlan_cp_stats_utils_api.h>
#include "../../core/src/wlan_cp_stats_defs.h"
static bool tgt_mc_cp_stats_is_last_event(struct stats_event *ev,
enum stats_req_type stats_type)
{
bool is_last_event;
if (IS_MSB_SET(ev->last_event)) {
is_last_event = IS_LSB_SET(ev->last_event);
} else {
if (stats_type == TYPE_CONNECTION_TX_POWER)
is_last_event = true;
else
is_last_event = !!ev->peer_stats;
}
if (is_last_event)
cp_stats_debug("Last stats event");
return is_last_event;
}
void tgt_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
{
rx_ops->cp_stats_rx_ops.process_stats_event =
tgt_mc_cp_stats_process_stats_event;
}
static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev,
bool is_station_stats)
{
int32_t max_pwr;
uint8_t pdev_id;
QDF_STATUS status;
struct wlan_objmgr_pdev *pdev;
struct request_info last_req = {0};
struct wlan_objmgr_vdev *vdev = NULL;
struct pdev_mc_cp_stats *pdev_mc_stats;
struct pdev_cp_stats *pdev_cp_stats_priv;
bool pending = false;
if (!ev->pdev_stats)
return;
if (is_station_stats)
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS, &last_req);
else
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_CONNECTION_TX_POWER, &last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
goto end;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
goto end;
}
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
cp_stats_err("pdev is null");
goto end;
}
pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
if (pdev_id >= ev->num_pdev_stats) {
cp_stats_err("pdev_id: %d invalid", pdev_id);
goto end;
}
pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
if (!pdev_cp_stats_priv) {
cp_stats_err("pdev_cp_stats_priv is null");
goto end;
}
wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
max_pwr = pdev_mc_stats->max_pwr = ev->pdev_stats[pdev_id].max_pwr;
wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
if (is_station_stats)
goto end;
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_CONNECTION_TX_POWER)) {
ucfg_mc_cp_stats_reset_pending_req(psoc,
TYPE_CONNECTION_TX_POWER,
&last_req,
&pending);
if (last_req.u.get_tx_power_cb && pending)
last_req.u.get_tx_power_cb(max_pwr, last_req.cookie);
}
end:
if (vdev)
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void peer_rssi_iterator(struct wlan_objmgr_pdev *pdev,
void *peer, void *arg)
{
struct stats_event *ev;
struct peer_mc_cp_stats *peer_mc_stats;
struct peer_cp_stats *peer_cp_stats_priv;
struct peer_extd_stats *peer_extd_mc_stats;
if (WLAN_PEER_SELF == wlan_peer_get_peer_type(peer)) {
cp_stats_debug("ignore self peer: %pM",
wlan_peer_get_macaddr(peer));
return;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer cp stats object is null");
return;
}
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
ev = arg;
ev->peer_stats[ev->num_peer_stats] = *peer_mc_stats;
ev->num_peer_stats++;
peer_extd_mc_stats = peer_mc_stats->extd_stats;
ev->peer_extended_stats[ev->num_peer_extd_stats] = *peer_extd_mc_stats;
ev->num_peer_extd_stats++;
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
}
static void
tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc,
struct request_info *last_req)
{
uint8_t *mac_addr;
uint16_t peer_count;
struct stats_event ev = {0};
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_vdev *vdev;
struct wlan_objmgr_peer *peer = NULL;
struct peer_mc_cp_stats *peer_mc_stats;
struct peer_extd_stats *peer_mc_extd_stats;
struct peer_cp_stats *peer_cp_stats_priv;
void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie);
get_peer_rssi_cb = last_req->u.get_peer_rssi_cb;
if (!get_peer_rssi_cb) {
cp_stats_err("get_peer_rssi_cb is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req->vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
goto end;
}
mac_addr = last_req->peer_mac_addr;
if (QDF_IS_ADDR_BROADCAST(mac_addr)) {
pdev = wlan_vdev_get_pdev(vdev);
peer_count = wlan_pdev_get_peer_count(pdev);
ev.peer_stats = qdf_mem_malloc(sizeof(*ev.peer_stats) *
peer_count);
if (!ev.peer_stats)
goto end;
ev.peer_extended_stats =
qdf_mem_malloc(sizeof(*ev.peer_extended_stats) *
peer_count);
if (!ev.peer_extended_stats)
goto end;
wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_PEER_OP,
peer_rssi_iterator, &ev,
true, WLAN_CP_STATS_ID);
} else {
peer = wlan_objmgr_get_peer(psoc, last_req->pdev_id,
mac_addr, WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_err("peer[%pM] is null", mac_addr);
goto end;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer cp stats object is null");
goto end;
}
ev.peer_stats = qdf_mem_malloc(sizeof(*ev.peer_stats));
if (!ev.peer_stats)
goto end;
ev.num_peer_stats = 1;
ev.peer_extended_stats =
qdf_mem_malloc(sizeof(*ev.peer_extended_stats));
if (!ev.peer_extended_stats)
goto end;
ev.num_peer_extd_stats = 1;
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
*ev.peer_stats = *peer_mc_stats;
peer_mc_extd_stats = peer_mc_stats->extd_stats;
*ev.peer_extended_stats = *peer_mc_extd_stats;
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
}
end:
if (ev.peer_stats)
get_peer_rssi_cb(&ev, last_req->cookie);
ucfg_mc_cp_stats_free_stats_resources(&ev);
if (vdev)
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
if (peer)
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
}
static QDF_STATUS
tgt_mc_cp_stats_update_peer_adv_stats(struct wlan_objmgr_psoc *psoc,
struct peer_adv_mc_cp_stats
*peer_adv_stats, uint32_t size)
{
uint8_t *peer_mac_addr;
struct wlan_objmgr_peer *peer;
struct peer_mc_cp_stats *peer_mc_stats;
struct peer_adv_mc_cp_stats *peer_adv_mc_stats;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct peer_cp_stats *peer_cp_stats_priv;
if (!peer_adv_stats)
return QDF_STATUS_E_INVAL;
peer_mac_addr = peer_adv_stats->peer_macaddr;
peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_debug("peer is null");
return QDF_STATUS_E_EXISTS;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer_cp_stats_priv is null");
status = QDF_STATUS_E_EXISTS;
goto end;
}
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
peer_adv_mc_stats = peer_mc_stats->adv_stats;
qdf_mem_copy(peer_adv_mc_stats->peer_macaddr,
peer_adv_stats->peer_macaddr,
QDF_MAC_ADDR_SIZE);
if (peer_adv_stats->fcs_count)
peer_adv_mc_stats->fcs_count = peer_adv_stats->fcs_count;
if (peer_adv_stats->rx_bytes)
peer_adv_mc_stats->rx_bytes = peer_adv_stats->rx_bytes;
if (peer_adv_stats->rx_count)
peer_adv_mc_stats->rx_count = peer_adv_stats->rx_count;
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
end:
if (peer)
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
return status;
}
static QDF_STATUS
tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc *psoc,
struct peer_mc_cp_stats *peer_stats)
{
uint8_t *peer_mac_addr;
struct wlan_objmgr_peer *peer;
struct peer_mc_cp_stats *peer_mc_stats;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct peer_cp_stats *peer_cp_stats_priv;
if (!peer_stats)
return QDF_STATUS_E_INVAL;
peer_mac_addr = peer_stats->peer_macaddr;
peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_debug("peer is null");
return QDF_STATUS_E_EXISTS;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer_cp_stats_priv is null");
status = QDF_STATUS_E_EXISTS;
goto end;
}
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
qdf_mem_copy(peer_mc_stats->peer_macaddr,
peer_stats->peer_macaddr,
QDF_MAC_ADDR_SIZE);
if (peer_stats->tx_rate)
peer_mc_stats->tx_rate = peer_stats->tx_rate;
if (peer_stats->rx_rate)
peer_mc_stats->rx_rate = peer_stats->rx_rate;
if (peer_stats->peer_rssi)
peer_mc_stats->peer_rssi = peer_stats->peer_rssi;
cp_stats_nofl_debug("PEER STATS: peer_mac=%pM, tx_rate=%u, rx_rate=%u, peer_rssi=%d",
peer_mc_stats->peer_macaddr, peer_mc_stats->tx_rate,
peer_mc_stats->rx_rate, peer_mc_stats->peer_rssi);
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
end:
if (peer)
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
return status;
}
static QDF_STATUS
tgt_mc_cp_stats_update_peer_extd_stats(
struct wlan_objmgr_psoc *psoc,
struct peer_extd_stats *peer_extended_stats)
{
uint8_t *peer_mac_addr;
struct wlan_objmgr_peer *peer;
struct peer_mc_cp_stats *peer_mc_stats;
struct peer_extd_stats *peer_extd_mc_stats;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct peer_cp_stats *peer_cp_stats_priv;
if (!peer_extended_stats)
return QDF_STATUS_E_INVAL;
peer_mac_addr = peer_extended_stats->peer_macaddr;
peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_debug("peer is null");
return QDF_STATUS_E_EXISTS;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer_cp_stats_priv is null");
status = QDF_STATUS_E_EXISTS;
goto end;
}
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
peer_extd_mc_stats = peer_mc_stats->extd_stats;
if (!peer_extd_mc_stats) {
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
cp_stats_err("No peer_extd_mc_stats");
status = QDF_STATUS_E_INVAL;
goto end;
}
qdf_mem_copy(peer_extd_mc_stats->peer_macaddr,
peer_extended_stats->peer_macaddr,
QDF_MAC_ADDR_SIZE);
if (peer_extended_stats->rx_mc_bc_cnt)
peer_extd_mc_stats->rx_mc_bc_cnt =
peer_extended_stats->rx_mc_bc_cnt;
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
cp_stats_debug("peer_mac=%pM, rx_mc_bc_cnt=%u",
peer_extended_stats->peer_macaddr,
peer_extended_stats->rx_mc_bc_cnt);
end:
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
return status;
}
static void tgt_mc_cp_stats_extract_peer_extd_stats(
struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
uint32_t i, selected;
QDF_STATUS status;
struct request_info last_req = {0};
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_PEER_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
selected = ev->num_peer_extd_stats;
for (i = 0; i < ev->num_peer_extd_stats; i++) {
status = tgt_mc_cp_stats_update_peer_extd_stats(
psoc,
&ev->peer_extended_stats[i]);
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
!qdf_mem_cmp(ev->peer_extended_stats[i].peer_macaddr,
last_req.peer_mac_addr,
QDF_MAC_ADDR_SIZE)) {
/* mac is specified, but failed to update the peer */
if (QDF_IS_STATUS_ERROR(status))
return;
selected = i;
}
}
/* no matched peer */
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
selected == ev->num_peer_extd_stats) {
cp_stats_err("peer not found stats");
return;
}
}
static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev,
bool is_station_stats)
{
uint32_t i;
QDF_STATUS status;
struct request_info last_req = {0};
bool pending = false;
uint32_t selected;
if (is_station_stats)
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS,
&last_req);
else
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_PEER_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
if (!ev->peer_stats)
goto extd2_stats;
selected = ev->num_peer_stats;
for (i = 0; i < ev->num_peer_stats; i++) {
status = tgt_mc_cp_stats_update_peer_stats(psoc,
&ev->peer_stats[i]);
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
!qdf_mem_cmp(ev->peer_stats[i].peer_macaddr,
last_req.peer_mac_addr,
QDF_MAC_ADDR_SIZE)) {
/* mac is specified, but failed to update the peer */
if (QDF_IS_STATUS_ERROR(status))
return;
selected = i;
}
}
/* no matched peer */
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
selected == ev->num_peer_stats) {
cp_stats_err("peer not found for stats");
}
extd2_stats:
if (!ev->peer_adv_stats)
goto complete;
selected = ev->num_peer_adv_stats;
for (i = 0; i < ev->num_peer_adv_stats; i++) {
status = tgt_mc_cp_stats_update_peer_adv_stats(
psoc, &ev->peer_adv_stats[i],
ev->num_peer_adv_stats);
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
!qdf_mem_cmp(ev->peer_adv_stats[i].peer_macaddr,
last_req.peer_mac_addr,
QDF_MAC_ADDR_SIZE)) {
/* mac is specified, but failed to update the peer */
if (QDF_IS_STATUS_ERROR(status))
return;
selected = i;
}
}
/* no matched peer */
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
selected == ev->num_peer_adv_stats) {
cp_stats_debug("peer not found for extd stats");
return;
}
complete:
if (is_station_stats)
return;
tgt_mc_cp_stats_extract_peer_extd_stats(psoc, ev);
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_PEER_STATS)) {
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS,
&last_req, &pending);
if (pending && last_req.u.get_peer_rssi_cb)
tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req);
}
}
#ifdef WLAN_FEATURE_MIB_STATS
static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
QDF_STATUS status;
struct request_info last_req = {0};
bool pending = false;
if (!ev->mib_stats) {
cp_stats_debug("no mib stats");
return;
}
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_MIB_STATS, &last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) {
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS,
&last_req, &pending);
if (last_req.u.get_mib_stats_cb && pending)
last_req.u.get_mib_stats_cb(ev, last_req.cookie);
}
}
#else
static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
}
#endif
static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
struct wlan_objmgr_vdev *vdev;
struct vdev_mc_cp_stats *vdev_mc_stats;
struct vdev_cp_stats *vdev_cp_stats_priv;
if (!ev->cca_stats)
return;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
ev->cca_stats->vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
return;
}
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");
goto end;
}
wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
vdev_mc_stats->cca.congestion = ev->cca_stats->congestion;
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void tgt_mc_cp_stats_extract_vdev_summary_stats(
struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
uint8_t i;
QDF_STATUS status;
struct wlan_objmgr_peer *peer = NULL;
struct request_info last_req = {0};
struct wlan_objmgr_vdev *vdev;
struct peer_mc_cp_stats *peer_mc_stats;
struct vdev_mc_cp_stats *vdev_mc_stats;
struct peer_cp_stats *peer_cp_stats_priv;
struct vdev_cp_stats *vdev_cp_stats_priv;
if (!ev->vdev_summary_stats)
return;
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
for (i = 0; i < ev->num_summary_stats; i++) {
if (ev->vdev_summary_stats[i].vdev_id == last_req.vdev_id)
break;
}
if (i == ev->num_summary_stats) {
cp_stats_debug("vdev_id %d not found", last_req.vdev_id);
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
return;
}
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");
goto end;
}
wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
qdf_mem_copy(&vdev_mc_stats->vdev_summary_stats,
&ev->vdev_summary_stats[i].stats,
sizeof(vdev_mc_stats->vdev_summary_stats));
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
peer = wlan_objmgr_get_peer(psoc, last_req.pdev_id,
last_req.peer_mac_addr, WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_debug("peer is null %pM", last_req.peer_mac_addr);
goto end;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer cp stats object is null");
goto end;
}
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
peer_mc_stats->peer_rssi = ev->vdev_summary_stats[i].stats.rssi;
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
end:
if (peer)
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(
struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
uint8_t i, j;
QDF_STATUS status;
struct request_info last_req = {0};
struct wlan_objmgr_vdev *vdev;
struct vdev_mc_cp_stats *vdev_mc_stats;
struct vdev_cp_stats *vdev_cp_stats_priv;
if (!ev->vdev_chain_rssi)
return;
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
for (i = 0; i < ev->num_chain_rssi_stats; i++) {
if (ev->vdev_chain_rssi[i].vdev_id == last_req.vdev_id)
break;
}
if (i == ev->num_chain_rssi_stats) {
cp_stats_debug("vdev_id %d not found", last_req.vdev_id);
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
return;
}
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");
goto end;
}
wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
for (j = 0; j < MAX_NUM_CHAINS; j++) {
vdev_mc_stats->chain_rssi[j] =
ev->vdev_chain_rssi[i].chain_rssi[j];
}
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
struct request_info *last_req)
{
/* station_stats to be given to userspace thread */
struct stats_event info = {0};
struct wlan_objmgr_vdev *vdev;
struct wlan_objmgr_peer *peer;
struct peer_mc_cp_stats *peer_mc_stats;
struct vdev_mc_cp_stats *vdev_mc_stats;
struct peer_cp_stats *peer_cp_stats_priv;
struct vdev_cp_stats *vdev_cp_stats_priv;
void (*get_station_stats_cb)(struct stats_event *info, void *cookie);
get_station_stats_cb = last_req->u.get_station_stats_cb;
if (!get_station_stats_cb) {
cp_stats_err("callback is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req->vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev object is null");
return;
}
peer = wlan_objmgr_get_peer(psoc, last_req->pdev_id,
last_req->peer_mac_addr, WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_err("peer object is null");
goto end;
}
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");
goto end;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer cp stats object is null");
goto end;
}
info.num_summary_stats = 1;
info.vdev_summary_stats = qdf_mem_malloc(
sizeof(*info.vdev_summary_stats));
if (!info.vdev_summary_stats)
goto end;
info.num_chain_rssi_stats = 1;
info.vdev_chain_rssi = qdf_mem_malloc(sizeof(*info.vdev_chain_rssi));;
if (!info.vdev_chain_rssi)
goto end;
wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
info.vdev_summary_stats[0].vdev_id = last_req->vdev_id;
info.vdev_summary_stats[0].stats = vdev_mc_stats->vdev_summary_stats;
info.vdev_chain_rssi[0].vdev_id = last_req->vdev_id;
qdf_mem_copy(info.vdev_chain_rssi[0].chain_rssi,
vdev_mc_stats->chain_rssi,
sizeof(vdev_mc_stats->chain_rssi));
info.tx_rate_flags = vdev_mc_stats->tx_rate_flags;
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
info.peer_adv_stats = qdf_mem_malloc(sizeof(*info.peer_adv_stats));
if (!info.peer_adv_stats)
goto end;
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
/*
* The linkspeed returned by fw is in kbps so convert
* it in units of 100kbps which is expected by UMAC
*/
info.tx_rate = peer_mc_stats->tx_rate / 100;
info.rx_rate = peer_mc_stats->rx_rate / 100;
if (peer_mc_stats->adv_stats) {
info.num_peer_adv_stats = 1;
qdf_mem_copy(info.peer_adv_stats,
peer_mc_stats->adv_stats,
sizeof(peer_mc_stats->adv_stats));
}
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
end:
if (info.vdev_summary_stats && info.vdev_chain_rssi)
get_station_stats_cb(&info, last_req->cookie);
ucfg_mc_cp_stats_free_stats_resources(&info);
if (peer)
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void tgt_mc_cp_stats_extract_station_stats(
struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
QDF_STATUS status;
struct request_info last_req = {0};
bool pending = false;
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
tgt_mc_cp_stats_extract_tx_power(psoc, ev, true);
tgt_mc_cp_stats_extract_peer_stats(psoc, ev, true);
tgt_mc_cp_stats_extract_vdev_summary_stats(psoc, ev);
tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(psoc, ev);
/*
* PEER stats are the last stats sent for get_station statistics.
* reset type_map bit for station stats .
*/
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_STATION_STATS)) {
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS,
&last_req,
&pending);
if (pending && last_req.u.get_station_stats_cb)
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(
psoc, &last_req);
}
}
static void tgt_mc_cp_send_lost_link_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
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 && psoc_cp_stats_priv->legacy_stats_cb)
psoc_cp_stats_priv->legacy_stats_cb(ev);
}
QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONNECTION_TX_POWER))
tgt_mc_cp_stats_extract_tx_power(psoc, ev, false);
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS))
tgt_mc_cp_stats_extract_peer_stats(psoc, ev, false);
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_STATION_STATS))
tgt_mc_cp_stats_extract_station_stats(psoc, ev);
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_MIB_STATS))
tgt_mc_cp_stats_extract_mib_stats(psoc, ev);
tgt_mc_cp_stats_extract_cca_stats(psoc, ev);
tgt_mc_cp_send_lost_link_stats(psoc, ev);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
uint32_t reason,
struct wake_lock_stats *stats,
uint32_t *unspecified_wake_count)
{
struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
tx_ops = target_if_cp_stats_get_tx_ops(psoc);
if (!tx_ops)
return QDF_STATUS_E_NULL_VALUE;
tx_ops->inc_wake_lock_stats(reason, stats, unspecified_wake_count);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *req)
{
struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
tx_ops = target_if_cp_stats_get_tx_ops(psoc);
if (!tx_ops || !tx_ops->send_req_stats) {
cp_stats_err("could not get tx_ops");
return QDF_STATUS_E_NULL_VALUE;
}
return tx_ops->send_req_stats(psoc, type, req);
}

Zobrazit soubor

@@ -1,725 +0,0 @@
/*
* Copyright (c) 2018-2020 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"
#ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
#include <wlan_pmo_obj_mgmt_api.h>
#endif
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)
{
struct peer_mc_cp_stats *peer_mc_stats;
peer_mc_stats = qdf_mem_malloc(sizeof(struct peer_mc_cp_stats));
if (!peer_mc_stats)
return QDF_STATUS_E_NOMEM;
peer_mc_stats->adv_stats =
qdf_mem_malloc(sizeof(struct peer_adv_mc_cp_stats));
if (!peer_mc_stats->adv_stats) {
qdf_mem_free(peer_mc_stats);
peer_mc_stats = NULL;
return QDF_STATUS_E_NOMEM;
}
peer_mc_stats->extd_stats =
qdf_mem_malloc(sizeof(struct peer_extd_stats));
if (!peer_mc_stats->extd_stats) {
qdf_mem_free(peer_mc_stats->adv_stats);
peer_mc_stats->adv_stats = NULL;
qdf_mem_free(peer_mc_stats);
peer_mc_stats = NULL;
return QDF_STATUS_E_NOMEM;
}
peer_cs->peer_stats = peer_mc_stats;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS wlan_cp_stats_peer_cs_deinit(struct peer_cp_stats *peer_cs)
{
struct peer_mc_cp_stats *peer_mc_stats = peer_cs->peer_stats;
qdf_mem_free(peer_mc_stats->adv_stats);
peer_mc_stats->adv_stats = NULL;
qdf_mem_free(peer_mc_stats->extd_stats);
peer_mc_stats->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 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;
if (!psoc_mc_stats) {
cp_stats_err("psoc mc stats is null");
return QDF_STATUS_E_NULL_VALUE;
}
stats = &psoc_mc_stats->wow_stats;
switch (protocol) {
case QDF_PROTO_ICMP_REQ:
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_psoc_obj_unlock(psoc_cp_stats_priv);
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 psoc_cp_stats *psoc_cp_stats_priv;
struct psoc_mc_cp_stats *psoc_mc_stats;
struct wake_lock_stats *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;
if (!psoc_mc_stats) {
cp_stats_err("psoc mc stats is null");
return QDF_STATUS_E_NULL_VALUE;
}
stats = &psoc_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_psoc_obj_unlock(psoc_cp_stats_priv);
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 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;
}
wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
if (!psoc_mc_stats) {
cp_stats_err("psoc mc stats is null");
return QDF_STATUS_E_NULL_VALUE;
}
stats = &psoc_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_psoc_obj_unlock(psoc_cp_stats_priv);
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 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;
}
psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
if (!psoc_mc_stats) {
cp_stats_err("psoc mc stats is null");
return;
}
vdev_stats = &psoc_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;
}
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 wlan_objmgr_psoc *psoc;
struct psoc_cp_stats *psoc_cp_stats_priv;
struct psoc_mc_cp_stats *psoc_mc_stats;
wlan_vdev_obj_lock(vdev);
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
wlan_vdev_obj_unlock(vdev);
cp_stats_err("psoc NULL");
return QDF_STATUS_E_INVAL;
}
wlan_vdev_obj_unlock(vdev);
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;
if (!psoc_mc_stats) {
cp_stats_err("psoc mc stats is null");
return QDF_STATUS_E_NULL_VALUE;
}
qdf_mem_copy(stats, &psoc_mc_stats->wow_stats, sizeof(*stats));
wlan_cp_stats_psoc_obj_unlock(psoc_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;
if (psoc_mc_stats->is_cp_stats_suspended) {
cp_stats_debug("cp stats is suspended try again after resume");
wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
return QDF_STATUS_E_AGAIN;
}
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 request_info *last_req,
bool *pending)
{
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;
if (psoc_mc_stats->pending.type_map & (1 << type)) {
*last_req = psoc_mc_stats->pending.req[type];
*pending = true;
} else {
*pending = false;
}
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;
}
void ucfg_mc_cp_stats_register_lost_link_info_cb(
struct wlan_objmgr_psoc *psoc,
void (*lost_link_cp_stats_info_cb)(void *stats_ev))
{
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;
}
psoc_cp_stats_priv->legacy_stats_cb = lost_link_cp_stats_info_cb;
}
#ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
static QDF_STATUS
ucfg_mc_cp_stats_suspend_req_handler(struct wlan_objmgr_psoc *psoc)
{
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;
}
wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
psoc_mc_stats->is_cp_stats_suspended = true;
wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
ucfg_mc_cp_stats_resume_req_handler(struct wlan_objmgr_psoc *psoc)
{
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;
}
wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
psoc_mc_stats->is_cp_stats_suspended = false;
wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
ucfg_mc_cp_stats_resume_handler(struct wlan_objmgr_psoc *psoc,
void *arg)
{
return ucfg_mc_cp_stats_resume_req_handler(psoc);
}
static QDF_STATUS
ucfg_mc_cp_stats_suspend_handler(struct wlan_objmgr_psoc *psoc,
void *arg)
{
return ucfg_mc_cp_stats_suspend_req_handler(psoc);
}
void ucfg_mc_cp_stats_register_pmo_handler(void)
{
pmo_register_suspend_handler(WLAN_UMAC_COMP_CP_STATS,
ucfg_mc_cp_stats_suspend_handler, NULL);
pmo_register_resume_handler(WLAN_UMAC_COMP_CP_STATS,
ucfg_mc_cp_stats_resume_handler, NULL);
}
#endif