diff --git a/umac/cp_stats/core/src/wlan_cp_stats_ol_api.c b/umac/cp_stats/core/src/wlan_cp_stats_ol_api.c index 049592e3d15e..d0a7a5b53852 100644 --- a/umac/cp_stats/core/src/wlan_cp_stats_ol_api.c +++ b/umac/cp_stats/core/src/wlan_cp_stats_ol_api.c @@ -32,6 +32,7 @@ #include "wlan_cp_stats_ic_ucfg_handler.h" #include +#include QDF_STATUS wlan_cp_stats_psoc_obj_init_ol(struct psoc_cp_stats *psoc_cs) { @@ -111,21 +112,49 @@ QDF_STATUS wlan_cp_stats_close_ol(struct wlan_objmgr_psoc *psoc) QDF_STATUS wlan_cp_stats_enable_ol(struct wlan_objmgr_psoc *psoc) { + struct wlan_lmac_if_cp_stats_tx_ops *tx_ops; + if (!psoc) { - cp_stats_err("PSOC is null!\n"); + cp_stats_err("PSOC is null!"); return QDF_STATUS_E_INVAL; } + tx_ops = target_if_cp_stats_get_tx_ops(psoc); + if (!tx_ops) { + cp_stats_err("tx_ops is null!"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!tx_ops->cp_stats_attach) { + cp_stats_err("cp_stats_attach function ptr is null!"); + return QDF_STATUS_E_NULL_VALUE; + } + + tx_ops->cp_stats_attach(psoc); return QDF_STATUS_SUCCESS; } QDF_STATUS wlan_cp_stats_disable_ol(struct wlan_objmgr_psoc *psoc) { + struct wlan_lmac_if_cp_stats_tx_ops *tx_ops; + if (!psoc) { - cp_stats_err("PSOC is null!\n"); + cp_stats_err("PSOC is null!"); return QDF_STATUS_E_INVAL; } + tx_ops = target_if_cp_stats_get_tx_ops(psoc); + if (!tx_ops) { + cp_stats_err("tx_ops is null!"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!tx_ops->cp_stats_detach) { + cp_stats_err("cp_stats_detach function ptr is null!"); + return QDF_STATUS_E_NULL_VALUE; + } + + tx_ops->cp_stats_detach(psoc); return QDF_STATUS_SUCCESS; } diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h index 049948dfa46f..9c21101f834c 100644 --- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h +++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h @@ -35,6 +35,23 @@ #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" + +/** + * 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 + */ +enum stats_req_type { + TYPE_CONNECTION_TX_POWER = 0, + TYPE_STATION_STATS, + TYPE_MAX, +}; + /** * struct wake_lock_stats - wake lock stats structure * @ucast_wake_up_count: Unicast wakeup count @@ -76,13 +93,51 @@ struct wake_lock_stats { }; /** - * struct psoc_mc_cp_stats - psoc specific stats + * struct request_info: details of each request + * @cookie: identifier for os_if request + * @callback: callback to process os_if 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); + } u; + uint32_t vdev_id; + uint32_t pdev_id; + uint8_t peer_mac_addr[WLAN_MACADDR_LEN]; +}; + +/** + * 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 psoc_mc_cp_stats: psoc specific stats + * @pending: details of pending requests * @wow_unspecified_wake_up_count: number of non-wow related wake ups */ struct psoc_mc_cp_stats { + struct pending_stats_requests pending; uint32_t wow_unspecified_wake_up_count; }; +/** + * 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 vdev_mc_cp_stats - vdev specific stats * @wow_stats: wake_lock stats for vdev @@ -91,4 +146,15 @@ struct vdev_mc_cp_stats { struct wake_lock_stats wow_stats; }; +/** + * struct stats_event - parameters populated by stats event + * @num_pdev_stats: number of pdev stats + * @pdev_stats: array of per pdev stats (index = pdev_id) + */ +struct stats_event { + uint32_t num_pdev_stats; + struct pdev_mc_cp_stats *pdev_stats; +}; + +#endif /* CONFIG_MCL */ #endif /* __WLAN_CP_STATS_MC_DEFS_H__ */ diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h index 0cf29ec7a7c0..5ee653bfb4bc 100644 --- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h +++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h @@ -25,6 +25,27 @@ #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 @@ -42,4 +63,3 @@ QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc, #endif /* QCA_SUPPORT_CP_STATS */ #endif /* __WLAN_CP_STATS_MC_TGT_API_H__ */ - diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h index 950ea778ac5c..75d694e9c8a9 100644 --- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h +++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h @@ -110,5 +110,71 @@ 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 + * + * Return - status of operation + */ +QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, + enum stats_req_type type); + +/** + * 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); + #endif /* QCA_SUPPORT_CP_STATS */ #endif /* __WLAN_CP_STATS_UCFG_API_H__ */ diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 24ebfc4ec96f..4fe11d74b1be 100644 --- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -23,13 +23,97 @@ * from southbound interface */ -#include "target_if_cp_stats.h" #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 "../../core/src/wlan_cp_stats_defs.h" +#include #include +#include "../../core/src/wlan_cp_stats_defs.h" +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; + + if (!ev->pdev_stats) { + cp_stats_err("no 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 (last_req.u.get_tx_power_cb) + last_req.u.get_tx_power_cb(max_pwr, last_req.cookie); + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_CONNECTION_TX_POWER); + +end: + if (vdev) + wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); + qdf_mem_free(ev->pdev_stats); + ev->pdev_stats = NULL; +} + +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); + + + return QDF_STATUS_SUCCESS; +} QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc, uint32_t reason, @@ -46,3 +130,18 @@ QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc, 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) { + cp_stats_err("could not get tx_ops"); + return QDF_STATUS_E_NULL_VALUE; + } + + return tx_ops->send_req_stats(psoc, type, req); +} diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index c979592eefd8..07e30070f9c2 100644 --- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -23,9 +23,11 @@ */ #include -#include +#include "wlan_cp_stats_mc_defs.h" #include #include +#include +#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" @@ -66,11 +68,18 @@ QDF_STATUS wlan_cp_stats_vdev_cs_deinit(struct vdev_cp_stats *vdev_cs) 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) { + cp_stats_err("malloc failed"); + 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; } @@ -397,3 +406,128 @@ QDF_STATUS ucfg_mc_cp_stats_write_wow_stats( 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; + } + + 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; + } + + 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; + } + + 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; +} diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index ac564fc21f31..b60bf973e9cd 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -28,6 +28,7 @@ #endif #include "wlan_mgmt_txrx_utils_api.h" #include "wlan_scan_public_structs.h" + #ifdef WLAN_ATF_ENABLE #include "wlan_atf_utils_defs.h" #endif @@ -90,6 +91,9 @@ struct wlan_lmac_if_cp_stats_tx_ops { void (*inc_wake_lock_stats)(uint32_t reason, struct wake_lock_stats *stats, uint32_t *unspecified_wake_count); + QDF_STATUS (*send_req_stats)(struct wlan_objmgr_psoc *psoc, + enum stats_req_type type, + struct request_info *req); #endif }; @@ -100,6 +104,10 @@ struct wlan_lmac_if_cp_stats_tx_ops { */ struct wlan_lmac_if_cp_stats_rx_ops { QDF_STATUS (*cp_stats_rx_event_handler)(struct wlan_objmgr_vdev *vdev); +#ifdef CONFIG_MCL + QDF_STATUS (*process_stats_event)(struct wlan_objmgr_psoc *psoc, + struct stats_event *ev); +#endif }; #endif diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index 22ca795fe66e..4ed28cde6997 100644 --- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c @@ -65,6 +65,7 @@ #ifdef QCA_SUPPORT_CP_STATS #include +#include #endif /* QCA_SUPPORT_CP_STATS */ /* Function pointer for OL/WMA specific UMAC tx_ops @@ -86,13 +87,14 @@ qdf_export_symbol(wlan_lmac_if_umac_tx_ops_register); static void wlan_lmac_if_cp_stats_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) { + target_if_cp_stats_register_rx_ops(rx_ops); } #else static void wlan_lmac_if_cp_stats_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) { } -#endif +#endif /* QCA_SUPPORT_CP_STATS */ #ifdef WLAN_ATF_ENABLE /**