diff --git a/Kbuild b/Kbuild index 4895e9be354a..441ee43ec19c 100644 --- a/Kbuild +++ b/Kbuild @@ -2953,6 +2953,7 @@ cppflags-$(CONFIG_HL_DP_SUPPORT) += -DQCA_COMPUTE_TX_DELAY cppflags-$(CONFIG_HL_DP_SUPPORT) += -DQCA_COMPUTE_TX_DELAY_PER_TID cppflags-$(CONFIG_LL_DP_SUPPORT) += -DCONFIG_LL_DP_SUPPORT cppflags-$(CONFIG_LL_DP_SUPPORT) += -DWLAN_FULL_REORDER_OFFLOAD +cppflags-$(CONFIG_WLAN_FEATURE_BIG_DATA_STATS) += -DWLAN_FEATURE_BIG_DATA_STATS # For PCIe GEN switch cppflags-$(CONFIG_PCIE_GEN_SWITCH) += -DPCIE_GEN_SWITCH diff --git a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h index 510ca3bda98e..d1a4bf9fdafc 100644 --- a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h +++ b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h @@ -60,6 +60,7 @@ * @TYPE_PEER_STATS: peer stats was requested * @TYPE_MIB_STATS: MIB stats was requested * @TYPE_PEER_STATS_INFO_EXT: peer stats info ext was requested + * @TYPE_BIG_DATA_STATS: big data stats was requested */ enum stats_req_type { TYPE_CONNECTION_TX_POWER = 0, @@ -67,6 +68,7 @@ enum stats_req_type { TYPE_PEER_STATS, TYPE_MIB_STATS, TYPE_PEER_STATS_INFO_EXT, + TYPE_BIG_DATA_STATS, TYPE_MAX, }; @@ -178,6 +180,28 @@ struct wake_lock_stats { struct stats_event; +/** + * struct big_data_stats_event - big data stats event param + * @vdev_id: vdev id + * @tsf_out_of_sync: tsf out of sync + * @ani_level: ani level + * @last_data_tx_pwr: tx pwr last data frm + * @target_power_dsss: tx power dsss + * @target_power_ofdm: target power ofdm + * @last_tx_data_rix: rx lateset data frame + * @last_tx_data_rate_kbps: tx latest data frame + */ +struct big_data_stats_event { + uint32_t vdev_id; + uint32_t tsf_out_of_sync; + int32_t ani_level; + uint32_t last_data_tx_pwr; + uint32_t target_power_dsss; + uint32_t target_power_ofdm; + uint32_t last_tx_data_rix; + uint32_t last_tx_data_rate_kbps; +}; + /** * struct request_info: details of each request * @cookie: identifier for os_if request @@ -198,6 +222,10 @@ struct request_info { void *cookie); void (*get_peer_stats_cb)(struct stats_event *ev, void *cookie); +#ifdef WLAN_FEATURE_BIG_DATA_STATS + void (*get_big_data_stats_cb)(struct big_data_stats_event *ev, + void *cookie); +#endif } u; uint32_t vdev_id; uint32_t pdev_id; diff --git a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h index f822c39094ae..a8d19857076f 100644 --- a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h +++ b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h @@ -94,5 +94,31 @@ 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); +#ifdef WLAN_FEATURE_BIG_DATA_STATS +/** + * tgt_mc_cp_stats_process_big_data_stats_event(): API to process big data + * stats event + * @psoc: pointer to psoc object + * @event: big data stats event parameters + * + * Return: status of operation + */ +QDF_STATUS +tgt_mc_cp_stats_process_big_data_stats_event( + struct wlan_objmgr_psoc *psoc, + struct big_data_stats_event *event); + +/** + * tgt_send_cp_big_data_stats_req(): API to send big data stats request + * to lmac + * @psoc: pointer to psoc object + * @req: pointer to request info + * + * Return: status of operation + */ +QDF_STATUS tgt_send_cp_big_data_stats_req(struct wlan_objmgr_psoc *psoc, + struct request_info *req); + +#endif #endif /* QCA_SUPPORT_CP_STATS */ #endif /* __WLAN_CP_STATS_MC_TGT_API_H__ */ diff --git a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h index 9b5788deadcc..7ff3110f853d 100644 --- a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h +++ b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h @@ -152,7 +152,6 @@ QDF_STATUS ucfg_mc_cp_stats_write_wow_stats( QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev, enum stats_req_type type, struct request_info *info); - /** * wlan_cfg80211_mc_twt_clear_infra_cp_stats() - send request to reset * control path statistics @@ -301,6 +300,30 @@ 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 */ + +#ifdef WLAN_FEATURE_BIG_DATA_STATS +/** + * ucfg_send_big_data_stats_request() - API to send big data stats + * request + * @vdev: pointer to vdev object + * @type: request type + * @info: request info + * + * Return: status of operation + */ +QDF_STATUS ucfg_send_big_data_stats_request(struct wlan_objmgr_vdev *vdev, + enum stats_req_type type, + struct request_info *info); +#else +static inline +QDF_STATUS ucfg_send_big_data_stats_request(struct wlan_objmgr_vdev *vdev, + enum stats_req_type type, + struct request_info *info) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #else void static inline ucfg_mc_cp_stats_register_pmo_handler(void) { }; static inline QDF_STATUS ucfg_mc_cp_stats_send_stats_request( @@ -354,5 +377,14 @@ static inline QDF_STATUS ucfg_mc_cp_stats_get_vdev_wake_lock_stats( { return QDF_STATUS_SUCCESS; } + +static inline +QDF_STATUS ucfg_send_big_data_stats_request(struct wlan_objmgr_vdev *vdev, + enum stats_req_type type, + struct request_info *info) +{ + return QDF_STATUS_SUCCESS; +} #endif /* QCA_SUPPORT_CP_STATS */ + #endif /* __WLAN_CP_STATS_MC_UCFG_API_H__ */ diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 77daf6c0bd76..046abc275522 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -53,6 +53,40 @@ static bool tgt_mc_cp_stats_is_last_event(struct stats_event *ev, return is_last_event; } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +static void +tgt_cp_stats_register_big_data_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) +{ + rx_ops->cp_stats_rx_ops.process_big_data_stats_event = + tgt_mc_cp_stats_process_big_data_stats_event; +} + +static QDF_STATUS +send_big_data_stats_req(struct wlan_lmac_if_cp_stats_tx_ops *tx_ops, + struct wlan_objmgr_psoc *psoc, + struct request_info *req) +{ + if (!tx_ops->send_req_big_data_stats) { + cp_stats_err("could not get send_req_big_data_stats"); + return QDF_STATUS_E_NULL_VALUE; + } + + return tx_ops->send_req_big_data_stats(psoc, req); +} +#else +static void +tgt_cp_stats_register_big_data_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) +{} + +static QDF_STATUS +send_big_data_stats_req(struct wlan_lmac_if_cp_stats_tx_ops *tx_ops, + struct wlan_objmgr_psoc *psoc, + struct request_info *req) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS static void tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) @@ -72,11 +106,12 @@ 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; tgt_cp_stats_register_infra_cp_stats_rx_ops(rx_ops); + tgt_cp_stats_register_big_data_rx_ops(rx_ops); } static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc, - struct stats_event *ev, - bool is_station_stats) + struct stats_event *ev, + bool is_station_stats) { int32_t max_pwr; uint8_t pdev_id; @@ -1063,6 +1098,43 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +QDF_STATUS +tgt_mc_cp_stats_process_big_data_stats_event(struct wlan_objmgr_psoc *psoc, + struct big_data_stats_event *ev) +{ + QDF_STATUS status; + struct request_info last_req = {0}; + bool pending = false; + + if (!ev) { + cp_stats_err("invalid data"); + return QDF_STATUS_E_INVAL; + } + + status = ucfg_mc_cp_stats_get_pending_req(psoc, + TYPE_BIG_DATA_STATS, + &last_req); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed"); + return QDF_STATUS_E_FAILURE; + } + + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_BIG_DATA_STATS, + &last_req, &pending); + + if (last_req.u.get_big_data_stats_cb && pending) { + last_req.u.get_big_data_stats_cb(ev, last_req.cookie); + last_req.u.get_big_data_stats_cb = NULL; + } else { + cp_stats_err("callback to send big data stats not found"); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#endif + QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc, uint32_t reason, struct wake_lock_stats *stats, @@ -1100,6 +1172,9 @@ QDF_STATUS tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc *psoc, } status = tx_ops->send_req_peer_stats(psoc, req); break; + case TYPE_BIG_DATA_STATS: + status = send_big_data_stats_req(tx_ops, psoc, req); + break; default: if (!tx_ops->send_req_stats) { cp_stats_err("could not get send_req_stats"); diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index 0579ef5c246c..f6971db171ff 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021 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 @@ -710,6 +710,24 @@ QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev, return tgt_send_mc_cp_stats_req(wlan_vdev_get_psoc(vdev), type, info); } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +QDF_STATUS ucfg_send_big_data_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); +} +#endif + QDF_STATUS ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, int *dbm) { diff --git a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c index 5cf11c77c933..212cf43db57f 100644 --- a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -872,6 +872,78 @@ end: return qdf_status_to_os_return(status); } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +static int target_if_mc_cp_stats_big_data_stats_event_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct big_data_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; + } + + rx_ops = target_if_cp_stats_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->process_big_data_stats_event) { + cp_stats_err("callback not registered"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null"); + return -EINVAL; + } + + status = wmi_extract_big_data_stats_param(wmi_handle, data, &ev); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("extract event failed"); + goto end; + } + + status = rx_ops->process_big_data_stats_event(psoc, &ev); + +end: + return qdf_status_to_os_return(status); +} + +/** + * target_if_cp_stats_send_big_data_stats_req() - API to send 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_big_data_stats_req( + struct wlan_objmgr_psoc *psoc, + struct request_info *req) + +{ + struct wmi_unified *wmi_handle; + struct stats_request_params param = {0}; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null."); + return QDF_STATUS_E_NULL_VALUE; + } + param.vdev_id = req->vdev_id; + + return wmi_unified_big_data_stats_request_send(wmi_handle, + ¶m); +} +#endif + static QDF_STATUS target_if_cp_stats_extract_peer_stats_event(struct wmi_unified *wmi_hdl, struct stats_event *ev, @@ -1082,6 +1154,62 @@ static void target_if_cp_stats_inc_wake_lock_stats(uint32_t reason, } } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +static QDF_STATUS +target_if_register_big_data_event_handler(struct wmi_unified *wmi_handle) +{ + return wmi_unified_register_event_handler( + wmi_handle, wmi_vdev_send_big_data_p2_eventid, + target_if_mc_cp_stats_big_data_stats_event_handler, + WMI_RX_WORK_CTX); +} + +static void +target_if_unregister_big_data_event_handler(struct wmi_unified *wmi_handle) +{ + wmi_unified_unregister_event_handler(wmi_handle, + wmi_vdev_send_big_data_p2_eventid); +} + +static QDF_STATUS +target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops + *cp_stats_tx_ops) +{ + cp_stats_tx_ops->send_req_big_data_stats = + target_if_cp_stats_send_big_data_stats_req; + return QDF_STATUS_SUCCESS; +} + +static void +target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops + *cp_stats_tx_ops) +{ + cp_stats_tx_ops->send_req_big_data_stats = NULL; +} +#else +static QDF_STATUS +target_if_register_big_data_event_handler(struct wmi_unified *wmi_handle) +{ + return QDF_STATUS_SUCCESS; +} + +static void +target_if_unregister_big_data_event_handler(struct wmi_unified *wmi_handle) +{} + +static QDF_STATUS +target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops + *cp_stats_tx_ops) +{ + return QDF_STATUS_SUCCESS; +} + +static void +target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops + *cp_stats_tx_ops) +{} +#endif + static QDF_STATUS target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc) { @@ -1114,6 +1242,10 @@ target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc) if (ret_val) cp_stats_err("Failed to register peer stats info event cb"); + ret_val = target_if_register_big_data_event_handler(wmi_handle); + if (QDF_IS_STATUS_ERROR(ret_val)) + cp_stats_err("Failed to register big data stats info event cb"); + return qdf_status_from_os_return(ret_val); } @@ -1132,6 +1264,9 @@ target_if_mc_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc) cp_stats_err("wmi_handle is null"); return QDF_STATUS_E_INVAL; } + + target_if_unregister_big_data_event_handler(wmi_handle); + wmi_unified_unregister_event_handler(wmi_handle, wmi_peer_stats_info_event_id); wmi_unified_unregister_event_handler(wmi_handle, @@ -1289,6 +1424,8 @@ target_if_mc_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) cp_stats_tx_ops->send_req_peer_stats = target_if_cp_stats_send_peer_stats_req; + target_if_big_data_stats_register_tx_ops(cp_stats_tx_ops); + return QDF_STATUS_SUCCESS; } @@ -1307,7 +1444,7 @@ target_if_mc_cp_stats_unregister_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) cp_stats_err("lmac tx ops is NULL!"); return QDF_STATUS_E_FAILURE; } - + target_if_big_data_stats_unregister_tx_ops(cp_stats_tx_ops); cp_stats_tx_ops->inc_wake_lock_stats = NULL; cp_stats_tx_ops->send_req_stats = NULL; cp_stats_tx_ops->send_req_peer_stats = NULL; diff --git a/configs/default_defconfig b/configs/default_defconfig index 7ae9ff65004c..17c12a605af9 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -990,6 +990,7 @@ CONFIG_FEATURE_MONITOR_MODE_SUPPORT := y CONFIG_WLAN_ALLOCATE_GLOBAL_BUFFERS_DYNAMICALLY := n CONFIG_WLAN_FEATURE_TWT := y CONFIG_FW_THERMAL_THROTTLE := y +CONFIG_WLAN_FEATURE_BIG_DATA_STATS := y ifeq (y,$(findstring y,$(CONFIG_LITHIUM) $(CONFIG_ICNSS) $(CONFIG_ICNSS_MODULE) $(CONFIG_ICNSS2_HELIUM))) CONFIG_WLAN_FEATURE_BMI := n diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ff48c0a0d4bc..31aeb61d57f6 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1525,6 +1525,9 @@ struct hdd_adapter { enum hdd_work_status netdev_features_update_work_status; /* Flag to indicate whether it is a pre cac adapter or not */ bool is_pre_cac_adapter; +#ifdef WLAN_FEATURE_BIG_DATA_STATS + struct big_data_stats_event big_data_stats; +#endif bool delete_in_progress; qdf_atomic_t net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX]; }; diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c index 1253c99f9ad1..304f9a53070c 100644 --- a/core/hdd/src/wlan_hdd_station_info.c +++ b/core/hdd/src/wlan_hdd_station_info.c @@ -1834,6 +1834,36 @@ hdd_get_umac_to_osif_connect_fail_reason(enum wlan_status_code internal_reason) return reason; } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +/** + * hdd_big_data_pack_resp_nlmsg() - pack big data nl resp msg + * @skb: pointer to response skb buffer + * @adapter: adapter holding big data stats + * @hdd_ctx: hdd context + * + * This function adds big data stats in response. + * + * Return: 0 on success + */ +static int +hdd_big_data_pack_resp_nlmsg(struct sk_buff *skb, + struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx) +{ + //add stats + + return 0; +} +#else +static int +hdd_big_data_pack_resp_nlmsg(struct sk_buff *skb, + struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx) +{ + return 0; +} +#endif + /** * hdd_add_connect_fail_reason_code() - Fills connect fail reason code * @skb: pointer to skb @@ -2095,12 +2125,24 @@ static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx, struct sk_buff *skb; uint32_t nl_buf_len, connect_fail_rsn_len; struct hdd_station_ctx *hdd_sta_ctx; + bool big_data_stats_req = false; hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (!hdd_conn_is_connected(hdd_sta_ctx)) + big_data_stats_req = true; + if (wlan_hdd_get_station_stats(adapter)) hdd_err_rl("wlan_hdd_get_station_stats fail"); + if (big_data_stats_req) { + if (wlan_hdd_get_big_data_station_stats(adapter)) { + hdd_err_rl("wlan_hdd_get_big_data_station_stats fail"); + return -EINVAL; + } + // allocate memory to nl_buf_len to send data + } + nl_buf_len = hdd_get_pmf_bcn_protect_stats_len(adapter); connect_fail_rsn_len = hdd_get_connect_fail_reason_code_len(adapter); nl_buf_len += connect_fail_rsn_len; @@ -2109,6 +2151,7 @@ static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx, hdd_err_rl("Failed to get bcn pmf stats"); return -EINVAL; } + nl_buf_len += NLMSG_HDRLEN; skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); @@ -2130,6 +2173,13 @@ static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx, } } + if (big_data_stats_req) { + if (hdd_big_data_pack_resp_nlmsg(skb, adapter, hdd_ctx)) { + kfree_skb(skb); + return -EINVAL; + } + } + return cfg80211_vendor_cmd_reply(skb); } diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 5e2c809fe940..d774b04d9df9 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -200,6 +200,33 @@ static bool wlan_hdd_is_he_mcs_12_13_supported(uint16_t he_mcs_12_13_map) static bool get_station_fw_request_needed = true; +#ifdef WLAN_FEATURE_BIG_DATA_STATS +/* + * copy_station_big_data_stats_to_adapter() - Copy big data stats to adapter + * @adapter: Pointer to the adapter + * @stats: Pointer to the big data stats event + * + * Return: 0 if success, non-zero for failure + */ +static void copy_station_big_data_stats_to_adapter( + struct hdd_adapter *adapter, + struct big_data_stats_event *stats) +{ + adapter->big_data_stats.vdev_id = stats->vdev_id; + adapter->big_data_stats.tsf_out_of_sync = stats->tsf_out_of_sync; + adapter->big_data_stats.ani_level = stats->ani_level; + adapter->big_data_stats.last_data_tx_pwr = + stats->last_data_tx_pwr; + adapter->big_data_stats.target_power_dsss = + stats->target_power_dsss; + adapter->big_data_stats.target_power_ofdm = + stats->target_power_ofdm; + adapter->big_data_stats.last_tx_data_rix = stats->last_tx_data_rix; + adapter->big_data_stats.last_tx_data_rate_kbps = + stats->last_tx_data_rate_kbps; +} +#endif + #ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION static void hdd_update_station_stats_cached_timestamp(struct hdd_adapter *adapter) @@ -6479,6 +6506,32 @@ out: return ret; } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +int wlan_hdd_get_big_data_station_stats(struct hdd_adapter *adapter) +{ + int ret = 0; + struct big_data_stats_event *big_data_stats; + struct wlan_objmgr_vdev *vdev; + + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) + return -EINVAL; + + big_data_stats = wlan_cfg80211_mc_cp_get_big_data_stats(vdev, + &ret); + if (ret || !big_data_stats) + goto out; + + copy_station_big_data_stats_to_adapter(adapter, big_data_stats); +out: + if (big_data_stats) + wlan_cfg80211_mc_cp_stats_free_big_data_stats_event( + big_data_stats); + hdd_objmgr_put_vdev(vdev); + return ret; +} +#endif + struct temperature_priv { int temperature; }; diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index 8b29d6bba268..312c439800a8 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -473,6 +473,58 @@ int wlan_hdd_get_link_speed(struct hdd_adapter *adapter, uint32_t *link_speed); */ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter); +#ifdef WLAN_FEATURE_BIG_DATA_STATS +/** + * wlan_hdd_get_big_data_station_stats() - Get big data station statistics + * @adapter: adapter for which statistics are desired + * + * Return: status of operation + */ +int wlan_hdd_get_big_data_station_stats(struct hdd_adapter *adapter); + +/** + * wlan_cfg80211_mc_cp_get_big_data_stats() - API to get big data + * statistics from firmware + * @vdev: Pointer to vdev + * @errno: error type in case of failure + * + * Return: big data stats buffer on success, Null on failure + */ +struct big_data_stats_event * +wlan_cfg80211_mc_cp_get_big_data_stats(struct wlan_objmgr_vdev *vdev, + int *errno); + +/** + * wlan_cfg80211_mc_cp_stats_free_big_data_stats_event() - API to release big + * data statistics buffer + * @vdev: Pointer to vdev + * @info: pointer to object to populate with big data stats + * + * Return: None + */ +void wlan_cfg80211_mc_cp_stats_free_big_data_stats_event( + struct big_data_stats_event *info); +#else +static inline int wlan_hdd_get_big_data_station_stats( + struct hdd_adapter *adapter) +{ + return 0; +} + +static inline struct big_data_stats_event * +wlan_cfg80211_mc_cp_get_big_data_stats(struct wlan_objmgr_vdev *vdev, + int *errno) +{ + return 0; +} + +static inline +void wlan_cfg80211_mc_cp_stats_free_big_data_stats_event( + struct big_data_stats_event *info) +{ +} +#endif + /** * wlan_hdd_get_temperature() - get current device temperature * @adapter: device upon which the request was made diff --git a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 7222ae5ca8e4..cae113c97905 100644 --- a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -29,6 +29,9 @@ #include #include "wlan_osif_request_manager.h" #include "wlan_objmgr_peer_obj.h" +#include "cds_utils.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_stats.h" /* max time in ms, caller may wait for stats request get serviced */ #define CP_STATS_WAIT_TIME_STAT 800 @@ -489,6 +492,34 @@ get_peer_rssi_fail: return NULL; } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +static void get_big_data_stats_cb(struct big_data_stats_event *ev, void *cookie) +{ + struct big_data_stats_event *priv; + struct osif_request *request; + + request = osif_request_get(cookie); + if (!request) { + osif_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + priv->tsf_out_of_sync = ev->tsf_out_of_sync; + priv->vdev_id = ev->vdev_id; + priv->ani_level = ev->ani_level; + + priv->last_data_tx_pwr = ev->last_data_tx_pwr; + priv->target_power_dsss = ev->target_power_dsss; + priv->target_power_ofdm = ev->target_power_ofdm; + priv->last_tx_data_rix = ev->last_tx_data_rix; + priv->last_tx_data_rate_kbps = ev->last_tx_data_rate_kbps; + + osif_request_complete(request); + osif_request_put(request); +} +#endif + /** * get_station_stats_cb() - get_station_stats_cb callback function * @ev: station stats buffer @@ -997,6 +1028,97 @@ get_station_stats_fail: return NULL; } +#ifdef WLAN_FEATURE_BIG_DATA_STATS +struct big_data_stats_event * +wlan_cfg80211_mc_cp_get_big_data_stats(struct wlan_objmgr_vdev *vdev, + int *errno) +{ + void *cookie; + QDF_STATUS status; + struct big_data_stats_event *priv, *out; + struct hdd_context *hdd_ctx = NULL; + struct osif_request *request; + struct request_info info = {0}; + struct request_info last_req = {0}; + bool pending = false; + + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT, + }; + + osif_debug("Enter"); + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (wlan_hdd_validate_context(hdd_ctx)) + return NULL; + + out = qdf_mem_malloc(sizeof(*out)); + if (!out) + return NULL; + + request = osif_request_alloc(¶ms); + if (!request) { + qdf_mem_free(out); + return NULL; + } + + cookie = osif_request_cookie(request); + priv = osif_request_priv(request); + info.cookie = cookie; + info.u.get_big_data_stats_cb = get_big_data_stats_cb; + info.vdev_id = wlan_vdev_get_id(vdev); + info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); + + status = ucfg_send_big_data_stats_request(vdev, + TYPE_BIG_DATA_STATS, + &info); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to send stats request status: %d", status); + *errno = qdf_status_to_os_return(status); + goto get_station_stats_fail; + } + + *errno = osif_request_wait_for_response(request); + if (*errno) { + osif_err("wait failed or timed out ret: %d", *errno); + ucfg_mc_cp_stats_reset_pending_req(hdd_ctx->psoc, + TYPE_BIG_DATA_STATS, + &last_req, &pending); + goto get_station_stats_fail; + } + + osif_debug("vdev_id: %d tsf_out_of_sync: %d ani_level: %d tx_pwr_last_data_frm: %d target_power_dsss: %d target_power_ofdm: %d rix_last_data_frm: %d tx_rate_last_data_frm: %d", + priv->vdev_id, + priv->tsf_out_of_sync, priv->ani_level, + priv->last_data_tx_pwr, priv->target_power_dsss, + priv->target_power_ofdm, priv->last_tx_data_rix, + priv->last_tx_data_rate_kbps); + + out->vdev_id = priv->vdev_id; + out->tsf_out_of_sync = priv->tsf_out_of_sync; + out->ani_level = priv->ani_level; + out->last_data_tx_pwr = priv->last_data_tx_pwr; + out->target_power_dsss = priv->target_power_dsss; + out->target_power_ofdm = priv->target_power_ofdm; + out->last_tx_data_rix = priv->last_tx_data_rix; + out->last_tx_data_rate_kbps = priv->last_tx_data_rate_kbps; + osif_request_put(request); + + osif_debug("Exit"); + + return out; + +get_station_stats_fail: + osif_request_put(request); + wlan_cfg80211_mc_cp_stats_free_big_data_stats_event(out); + + osif_debug("Exit"); + + return NULL; +} +#endif + #ifdef WLAN_FEATURE_MIB_STATS /** * get_mib_stats_cb() - get mib stats from fw callback function @@ -1320,3 +1442,15 @@ void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats) qdf_mem_free(stats->peer_stats_info_ext); qdf_mem_free(stats); } + +#ifdef WLAN_FEATURE_BIG_DATA_STATS +void +wlan_cfg80211_mc_cp_stats_free_big_data_stats_event( + struct big_data_stats_event *stats) +{ + if (!stats) + return; + + qdf_mem_free(stats); +} +#endif