From 299269828a56fa55f0129e2ddcbe7779036ed86a Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 6 Apr 2018 10:57:20 -0700 Subject: [PATCH] qcacmn: Add target_if/wmi implementation of get_tx_power Add changes to support get tx power from within cp_stats component. Change-Id: I89ac372bd31a8aa5a76938dc4ea4cfe05d6c7cf1 CRs-Fixed: 2210311 --- target_if/cp_stats/inc/target_if_cp_stats.h | 2 +- target_if/cp_stats/src/target_if_cp_stats.c | 6 + .../cp_stats/src/target_if_mc_cp_stats.c | 189 +++++++++++++++++- wmi/inc/wmi_unified_param.h | 2 + wmi/src/wmi_unified_tlv.c | 22 +- 5 files changed, 214 insertions(+), 7 deletions(-) diff --git a/target_if/cp_stats/inc/target_if_cp_stats.h b/target_if/cp_stats/inc/target_if_cp_stats.h index d5dd5a0d7233..eeef6fce7fae 100644 --- a/target_if/cp_stats/inc/target_if_cp_stats.h +++ b/target_if/cp_stats/inc/target_if_cp_stats.h @@ -72,7 +72,7 @@ target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error */ QDF_STATUS -target_if_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops *tx_ops); +target_if_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops); #else static inline QDF_STATUS target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) diff --git a/target_if/cp_stats/src/target_if_cp_stats.c b/target_if/cp_stats/src/target_if_cp_stats.c index a71aebc6680c..de5c4f441811 100644 --- a/target_if/cp_stats/src/target_if_cp_stats.c +++ b/target_if/cp_stats/src/target_if_cp_stats.c @@ -78,3 +78,9 @@ target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) return QDF_STATUS_SUCCESS; } + +QDF_STATUS +target_if_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) +{ + return QDF_STATUS_SUCCESS; +} diff --git a/target_if/cp_stats/src/target_if_mc_cp_stats.c b/target_if/cp_stats/src/target_if_mc_cp_stats.c index 339b13a21708..745c01a0c415 100644 --- a/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -40,7 +40,129 @@ #include #include #include -#include "wlan_cp_stats_utils_api.h" +#include +#include + +#define TGT_INVALID_SNR (0) +#define TGT_NOISE_FLOOR_DBM (-96) +#define TGT_MAX_SNR (TGT_NOISE_FLOOR_DBM * (-1)) +#define TGT_IS_VALID_SNR(x) ((x) >= 0 && (x) < TGT_MAX_SNR) + +static void target_if_cp_stats_free_stats_event(struct stats_event *ev) +{ + qdf_mem_free(ev->pdev_stats); + ev->pdev_stats = NULL; +} + +static QDF_STATUS target_if_cp_stats_extract_pdev_stats( + struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, + uint8_t *data) +{ + uint32_t i; + QDF_STATUS status; + wmi_host_pdev_stats pdev_stats; + + ev->num_pdev_stats = stats_param->num_pdev_stats; + if (!ev->num_pdev_stats) + return QDF_STATUS_SUCCESS; + + /* + * num_pdev_stats is validated within function wmi_extract_stats_param + * which is called to populated wmi_host_stats_event stats_param + */ + ev->pdev_stats = qdf_mem_malloc(sizeof(*ev->pdev_stats) * + ev->num_pdev_stats); + if (!ev->pdev_stats) { + cp_stats_err("malloc failed"); + return QDF_STATUS_E_NOMEM; + } + + for (i = 0; i < ev->num_pdev_stats; i++) { + status = wmi_extract_pdev_stats(wmi_hdl, data, i, &pdev_stats); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("wmi_extract_pdev_stats failed"); + return status; + } + ev->pdev_stats[i].max_pwr = pdev_stats.chan_tx_pwr; + } + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, + struct stats_event *ev, + uint8_t *data) +{ + QDF_STATUS status; + wmi_host_stats_event stats_param = {0}; + + status = wmi_extract_stats_param(wmi_hdl, data, &stats_param); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_debug("stats param extract failed: %d", status); + return status; + } + cp_stats_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d", + stats_param.num_pdev_stats, stats_param.num_vdev_stats, + stats_param.num_peer_stats, stats_param.num_rssi_stats); + + status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param, + ev, data); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_mc_cp_stats_stats_event_handler() - function to handle stats event + * from firmware. + * @scn: scn handle + * @data: data buffer for event + * @datalen: data length + * + * Return: status of operation. + */ +static int target_if_mc_cp_stats_stats_event_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct stats_event ev = {0}; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_cp_stats_rx_ops *rx_ops; + + if (!scn || !data) { + cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + cp_stats_err("null psoc"); + return -EINVAL; + } + wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); + + rx_ops = target_if_cp_stats_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->process_stats_event) { + cp_stats_err("callback not registered"); + return -EINVAL; + } + + status = target_if_cp_stats_extract_event(wmi_handle, &ev, data); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("extract event failed"); + goto end; + } + + status = rx_ops->process_stats_event(psoc, &ev); + +end: + target_if_cp_stats_free_stats_event(&ev); + return qdf_status_to_os_return(status); +} static void target_if_cp_stats_inc_wake_lock_stats(uint32_t reason, struct wake_lock_stats *stats, @@ -86,9 +208,20 @@ static void target_if_cp_stats_inc_wake_lock_stats(uint32_t reason, static QDF_STATUS target_if_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc) { + QDF_STATUS status; + if (!psoc) { cp_stats_err("PSOC is NULL!"); - return QDF_STATUS_E_INVAL; + return QDF_STATUS_E_NULL_VALUE; + } + + status = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), + wmi_update_stats_event_id, + target_if_mc_cp_stats_stats_event_handler, + WMI_RX_WORK_CTX); + if (status) { + cp_stats_err("Failed to register stats event cb"); + return status; } return QDF_STATUS_SUCCESS; @@ -102,9 +235,52 @@ target_if_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_E_INVAL; } + wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), + wmi_update_stats_event_id); + return QDF_STATUS_SUCCESS; } +static uint32_t get_stats_id(enum stats_req_type type) +{ + switch (type) { + default: + break; + case TYPE_CONNECTION_TX_POWER: + return WMI_REQUEST_PDEV_STAT; + } + return 0; +} + +/** + * target_if_cp_stats_send_stats_req() - API to send stats request to wmi + * @psoc: pointer to psoc object + * @req: pointer to object containing stats request parameters + * + * Return: status of operation. + */ +static QDF_STATUS target_if_cp_stats_send_stats_req( + struct wlan_objmgr_psoc *psoc, + enum stats_req_type type, + struct request_info *req) + +{ + struct wmi_unified *wmi_handle; + struct stats_request_params param = {0}; + + wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null."); + return QDF_STATUS_E_NULL_VALUE; + } + /* refer (WMI_REQUEST_STATS_CMDID) */ + param.stats_id = get_stats_id(type); + param.vdev_id = req->vdev_id; + param.pdev_id = req->pdev_id; + return wmi_unified_stats_request_send(wmi_handle, req->peer_mac_addr, + ¶m); +} + QDF_STATUS target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { @@ -127,7 +303,14 @@ target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) target_if_cp_stats_unregister_event_handler; cp_stats_tx_ops->inc_wake_lock_stats = target_if_cp_stats_inc_wake_lock_stats; - + cp_stats_tx_ops->send_req_stats = target_if_cp_stats_send_stats_req; return QDF_STATUS_SUCCESS; } +QDF_STATUS +target_if_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; + return QDF_STATUS_SUCCESS; +} diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 2e7a6481554e..9dfcbdd44514 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -4874,6 +4874,7 @@ struct rx_reorder_queue_remove_params { * @num_chan_stats: number of channel stats * @pdev_id: device id for the radio * @num_bcn_stats: number of beacon stats + * @num_rssi_stats: number of rssi stats */ typedef struct { wmi_host_stats_id stats_id; @@ -4885,6 +4886,7 @@ typedef struct { uint32_t num_chan_stats; uint32_t pdev_id; uint32_t num_bcn_stats; + uint32_t num_rssi_stats; } wmi_host_stats_event; /** diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index fd076056df8b..2c6bb3d30dd7 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -19145,14 +19145,16 @@ static QDF_STATUS extract_peer_sta_kickout_ev_tlv(wmi_unified_t wmi_handle, static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, void *evt_buf, wmi_host_stats_event *stats_param) { - WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; wmi_stats_event_fixed_param *ev; + wmi_per_chain_rssi_stats *rssi_event; + WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; + qdf_mem_zero(stats_param, sizeof(*stats_param)); param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; - ev = (wmi_stats_event_fixed_param *) param_buf->fixed_param; + rssi_event = param_buf->chain_stats; if (!ev) { - WMI_LOGE("%s: Failed to alloc memory\n", __func__); + WMI_LOGE("%s: event fixed param NULL\n", __func__); return QDF_STATUS_E_FAILURE; } @@ -19201,6 +19203,20 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( ev->pdev_id); + /* if chain_stats is not populated */ + if (!param_buf->chain_stats || !param_buf->num_chain_stats) + return QDF_STATUS_SUCCESS; + + if (WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats != + WMITLV_GET_TLVTAG(rssi_event->tlv_header)) + return QDF_STATUS_SUCCESS; + + if (WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats) != + WMITLV_GET_TLVTAG(rssi_event->tlv_header)) + return QDF_STATUS_SUCCESS; + + stats_param->num_rssi_stats = rssi_event->num_per_chain_rssi_stats; + return QDF_STATUS_SUCCESS; }