diff --git a/Kbuild b/Kbuild index e4d0596c12db..237d8a8b8866 100644 --- a/Kbuild +++ b/Kbuild @@ -2965,6 +2965,8 @@ cppflags-$(CONFIG_SLUB_DEBUG_ON) += -DHIF_CONFIG_SLUB_DEBUG_ON ccflags-$(CONFIG_FOURTH_CONNECTION) += -DFEATURE_FOURTH_CONNECTION ccflags-$(CONFIG_WMI_SEND_RECV_QMI) += -DWLAN_FEATURE_WMI_SEND_RECV_QMI +cppflags-$(CONFIG_WDI3_STATS_UPDATE) += -DWDI3_STATS_UPDATE + KBUILD_CPPFLAGS += $(cppflags-y) # Currently, for versions of gcc which support it, the kernel Makefile diff --git a/components/ipa/core/inc/wlan_ipa_core.h b/components/ipa/core/inc/wlan_ipa_core.h index 9543783166f8..825ba55eee65 100644 --- a/components/ipa/core/inc/wlan_ipa_core.h +++ b/components/ipa/core/inc/wlan_ipa_core.h @@ -326,6 +326,7 @@ bool wlan_ipa_is_rm_released(struct wlan_ipa_priv *ipa_ctx) #ifdef FEATURE_METERING +#ifndef WDI3_STATS_UPDATE /** * wlan_ipa_uc_op_metering() - IPA uC operation for stats and quota limit * @ipa_ctx: IPA context @@ -334,7 +335,15 @@ bool wlan_ipa_is_rm_released(struct wlan_ipa_priv *ipa_ctx) * Return: QDF_STATUS enumeration */ QDF_STATUS wlan_ipa_uc_op_metering(struct wlan_ipa_priv *ipa_ctx, - struct op_msg_type *op_msg); + struct op_msg_type *op_msg); +#else +static inline +QDF_STATUS wlan_ipa_uc_op_metering(struct wlan_ipa_priv *ipa_ctx, + struct op_msg_type *op_msg) +{ + return QDF_STATUS_SUCCESS; +} +#endif /** * wlan_ipa_wdi_meter_notifier_cb() - SSR wrapper for @@ -356,6 +365,25 @@ void wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, * Return: QDF_STATUS enumeration */ void wlan_ipa_init_metering(struct wlan_ipa_priv *ipa_ctx); + +#ifdef WDI3_STATS_UPDATE +/** + * wlan_ipa_update_tx_stats() - send embedded tx traffic in bytes to IPA + * @ipa_ctx: IPA context + * @sta_tx: tx in bytes on sta interface + * @sap_tx: tx in bytes on sap interface + * + * Return: void + */ +void wlan_ipa_update_tx_stats(struct wlan_ipa_priv *ipa_ctx, uint64_t sta_tx, + uint64_t sap_tx); +#else +static inline void wlan_ipa_update_tx_stats(struct wlan_ipa_priv *ipa_ctx, + uint64_t sta_tx, uint64_t sap_tx) +{ +} +#endif /* WDI3_STATS_UPDATE */ + #else static inline @@ -372,6 +400,11 @@ static inline void wlan_ipa_wdi_meter_notifier_cb(void) static inline void wlan_ipa_init_metering(struct wlan_ipa_priv *ipa_ctx) { } + +static inline void wlan_ipa_update_tx_stats(struct wlan_ipa_priv *ipa_ctx, + uint64_t sta_tx, uint64_t sap_tx) +{ +} #endif /* FEATURE_METERING */ /** diff --git a/components/ipa/core/inc/wlan_ipa_main.h b/components/ipa/core/inc/wlan_ipa_main.h index 7fe4a3277fa1..e719001d60a3 100644 --- a/components/ipa/core/inc/wlan_ipa_main.h +++ b/components/ipa/core/inc/wlan_ipa_main.h @@ -441,9 +441,15 @@ void ipa_component_config_update(struct wlan_objmgr_psoc *psoc); * * Return: IPA config tx buffer count */ - uint32_t ipa_get_tx_buf_count(void); +/** + * ipa_update_tx_stats() - Update embedded tx traffic in bytes to IPA + * + * Return: IPA config tx buffer count + */ +void ipa_update_tx_stats(struct wlan_objmgr_pdev *pdev, uint64_t sta_tx, + uint64_t ap_tx); #else /* Not IPA_OFFLOAD */ typedef QDF_STATUS (*wlan_ipa_softap_xmit)(qdf_nbuf_t nbuf, qdf_netdev_t dev); typedef void (*wlan_ipa_send_to_nw)(qdf_nbuf_t nbuf, qdf_netdev_t dev); diff --git a/components/ipa/core/inc/wlan_ipa_priv.h b/components/ipa/core/inc/wlan_ipa_priv.h index 18b5ceac86d7..cf5cb05d5f6e 100644 --- a/components/ipa/core/inc/wlan_ipa_priv.h +++ b/components/ipa/core/inc/wlan_ipa_priv.h @@ -664,6 +664,7 @@ struct wlan_ipa_priv { uint32_t wdi_version; bool is_smmu_enabled; /* IPA caps returned from ipa_wdi_init */ + qdf_atomic_t stats_quota; }; #define WLAN_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header) diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c index a558ae5bf43f..bb967053fdcb 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -1952,6 +1952,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, SIR_STA_RX_DATA_OFFLOAD, session_id, true); qdf_mutex_acquire(&ipa_ctx->event_lock); + qdf_atomic_set(&ipa_ctx->stats_quota, 1); } if (!wlan_ipa_is_sta_only_offload_enabled()) { @@ -2075,6 +2076,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) && (ipa_ctx->sap_num_connected_sta > 0 || wlan_ipa_is_sta_only_offload_enabled())) { + qdf_atomic_set(&ipa_ctx->stats_quota, 0); qdf_mutex_release(&ipa_ctx->event_lock); wlan_ipa_uc_offload_enable_disable(ipa_ctx, SIR_STA_RX_DATA_OFFLOAD, session_id, false); @@ -2178,6 +2180,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, SIR_STA_RX_DATA_OFFLOAD, sta_session_id, true); qdf_mutex_acquire(&ipa_ctx->event_lock); + qdf_atomic_set(&ipa_ctx->stats_quota, 1); } /* @@ -2195,6 +2198,8 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, ipa_ctx->config) && ipa_ctx->sta_connected && !wlan_ipa_is_sta_only_offload_enabled()) { + qdf_atomic_set(&ipa_ctx->stats_quota, + 0); qdf_mutex_release(&ipa_ctx->event_lock); wlan_ipa_uc_offload_enable_disable( ipa_ctx, @@ -2304,6 +2309,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) && ipa_ctx->sta_connected && !wlan_ipa_is_sta_only_offload_enabled()) { + qdf_atomic_set(&ipa_ctx->stats_quota, 0); qdf_mutex_release(&ipa_ctx->event_lock); wlan_ipa_uc_offload_enable_disable(ipa_ctx, SIR_STA_RX_DATA_OFFLOAD, diff --git a/components/ipa/core/src/wlan_ipa_main.c b/components/ipa/core/src/wlan_ipa_main.c index e8f4a7a3652a..424062b69f1b 100644 --- a/components/ipa/core/src/wlan_ipa_main.c +++ b/components/ipa/core/src/wlan_ipa_main.c @@ -643,3 +643,20 @@ uint32_t ipa_get_tx_buf_count(void) { return g_ipa_config ? g_ipa_config->txbuf_count : 0; } + +void ipa_update_tx_stats(struct wlan_objmgr_pdev *pdev, uint64_t sta_tx, + uint64_t ap_tx) +{ + struct wlan_ipa_priv *ipa_obj; + + if (!ipa_config_is_enabled()) + return; + + ipa_obj = ipa_pdev_get_priv_obj(pdev); + if (!ipa_obj) { + ipa_err("IPA object is NULL"); + return; + } + + wlan_ipa_update_tx_stats(ipa_obj, sta_tx, ap_tx); +} diff --git a/components/ipa/core/src/wlan_ipa_stats.c b/components/ipa/core/src/wlan_ipa_stats.c index 3e8fdeec1d4f..c701bf25606b 100644 --- a/components/ipa/core/src/wlan_ipa_stats.c +++ b/components/ipa/core/src/wlan_ipa_stats.c @@ -748,6 +748,39 @@ void wlan_ipa_uc_stat(struct wlan_ipa_priv *ipa_ctx) } #ifdef FEATURE_METERING + +#ifdef WDI3_STATS_UPDATE +/** + * wlan_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler. + * IPA calls to get WLAN stats or set quota limit. + * @priv: pointer to private data registered with IPA (we register a + * pointer to the IPA context) + * @evt: the IPA event which triggered the callback + * @data: data associated with the event + * + * Return: None + */ +static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, + void *data) +{ +} + +void wlan_ipa_update_tx_stats(struct wlan_ipa_priv *ipa_ctx, uint64_t sta_tx, + uint64_t ap_tx) +{ + qdf_ipa_wdi_tx_info_t tx_stats; + + if (!qdf_atomic_read(&ipa_ctx->stats_quota)) + return; + + QDF_IPA_WDI_TX_INFO_STA_TX_BYTES(&tx_stats) = sta_tx; + QDF_IPA_WDI_TX_INFO_SAP_TX_BYTES(&tx_stats) = ap_tx; + + qdf_ipa_wdi_wlan_stats(&tx_stats); +} + +#else + /** * wlan_ipa_uc_sharing_stats_request() - Get IPA stats from IPA. * @ipa_ctx: IPA context @@ -793,56 +826,6 @@ static void wlan_ipa_uc_set_quota(struct wlan_ipa_priv *ipa_ctx, } } -QDF_STATUS wlan_ipa_uc_op_metering(struct wlan_ipa_priv *ipa_ctx, - struct op_msg_type *op_msg) -{ - struct op_msg_type *msg = op_msg; - struct ipa_uc_sharing_stats *uc_sharing_stats; - struct ipa_uc_quota_rsp *uc_quota_rsp; - struct ipa_uc_quota_ind *uc_quota_ind; - struct wlan_ipa_iface_context *iface_ctx; - - if (msg->op_code == WLAN_IPA_UC_OPCODE_SHARING_STATS) { - /* fill-up ipa_uc_sharing_stats structure from FW */ - uc_sharing_stats = (struct ipa_uc_sharing_stats *) - ((uint8_t *)op_msg + sizeof(struct op_msg_type)); - - memcpy(&(ipa_ctx->ipa_sharing_stats), uc_sharing_stats, - sizeof(struct ipa_uc_sharing_stats)); - - qdf_event_set(&ipa_ctx->ipa_uc_sharing_stats_comp); - } else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_RSP) { - /* received set quota response */ - uc_quota_rsp = (struct ipa_uc_quota_rsp *) - ((uint8_t *)op_msg + sizeof(struct op_msg_type)); - - memcpy(&(ipa_ctx->ipa_quota_rsp), uc_quota_rsp, - sizeof(struct ipa_uc_quota_rsp)); - - qdf_event_set(&ipa_ctx->ipa_uc_set_quota_comp); - } else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_IND) { - /* hit quota limit */ - uc_quota_ind = (struct ipa_uc_quota_ind *) - ((uint8_t *)op_msg + sizeof(struct op_msg_type)); - - ipa_ctx->ipa_quota_ind.quota_bytes = - uc_quota_ind->quota_bytes; - - /* send quota exceeded indication to IPA */ - iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE); - if (iface_ctx) - qdf_ipa_broadcast_wdi_quota_reach_ind( - iface_ctx->dev->ifindex, - uc_quota_ind->quota_bytes); - else - ipa_err("Failed quota_reach_ind: NULL interface"); - } else { - return QDF_STATUS_E_INVAL; - } - - return QDF_STATUS_SUCCESS; -} - /** * __wlan_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler. * IPA calls to get WLAN stats or set quota limit. @@ -940,6 +923,60 @@ static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, } } +QDF_STATUS wlan_ipa_uc_op_metering(struct wlan_ipa_priv *ipa_ctx, + struct op_msg_type *op_msg) +{ + struct op_msg_type *msg = op_msg; + struct ipa_uc_sharing_stats *uc_sharing_stats; + struct ipa_uc_quota_rsp *uc_quota_rsp; + struct ipa_uc_quota_ind *uc_quota_ind; + struct wlan_ipa_iface_context *iface_ctx; + uint32_t ifindex; + uint64_t quota_bytes; + + if (msg->op_code == WLAN_IPA_UC_OPCODE_SHARING_STATS) { + /* fill-up ipa_uc_sharing_stats structure from FW */ + uc_sharing_stats = (struct ipa_uc_sharing_stats *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + + memcpy(&ipa_ctx->ipa_sharing_stats, uc_sharing_stats, + sizeof(struct ipa_uc_sharing_stats)); + + qdf_event_set(&ipa_ctx->ipa_uc_sharing_stats_comp); + } else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_RSP) { + /* received set quota response */ + uc_quota_rsp = (struct ipa_uc_quota_rsp *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + + memcpy(&ipa_ctx->ipa_quota_rsp, uc_quota_rsp, + sizeof(struct ipa_uc_quota_rsp)); + + qdf_event_set(&ipa_ctx->ipa_uc_set_quota_comp); + } else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_IND) { + /* hit quota limit */ + uc_quota_ind = (struct ipa_uc_quota_ind *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + + ipa_ctx->ipa_quota_ind.quota_bytes = + uc_quota_ind->quota_bytes; + + /* send quota exceeded indication to IPA */ + iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE); + ifindex = iface_ctx->dev->ifindex; + quota_bytes = uc_quota_ind->quota_bytes; + if (iface_ctx) + qdf_ipa_broadcast_wdi_quota_reach_ind(ifindex, + quota_bytes); + else + ipa_err("Failed quota_reach_ind: NULL interface"); + } else { + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} +#endif /* WDI3_STATS_UPDATE */ + /** * wlan_ipa_wdi_meter_notifier_cb() - SSR wrapper for * __wlan_ipa_wdi_meter_notifier_cb @@ -962,5 +999,4 @@ void wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, qdf_op_unprotect(op_sync); } - #endif /* FEATURE_METERING */ diff --git a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h index 4f349076d0fb..c0cdc5eeac9f 100644 --- a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h +++ b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h @@ -355,6 +355,17 @@ void ucfg_ipa_component_config_update(struct wlan_objmgr_psoc *psoc); */ uint32_t ucfg_ipa_get_tx_buf_count(void); +/** + * ucfg_ipa_update_tx_stats() - send embedded tx traffic in bytes to IPA + * @pdev: pdev obj + * @sta_tx: tx in bytes on sta vdev + * @ap_tx: tx in bytes on sap vdev + * + * Return: void + */ +void ucfg_ipa_update_tx_stats(struct wlan_objmgr_pdev *pdev, uint64_t sta_tx, + uint64_t ap_tx); + #else static inline bool ucfg_ipa_is_present(void) @@ -559,5 +570,11 @@ uint32_t ucfg_ipa_get_tx_buf_count(void) { return 0; } + +static inline +void ucfg_ipa_update_tx_stats(struct wlan_objmgr_pdev *pdev, uint64_t sta_tx, + uint64_t ap_tx) +{ +} #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_UCFG_API_H_ */ diff --git a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c index b1fedfaf4921..aa65a5253ce6 100644 --- a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c +++ b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c @@ -211,3 +211,9 @@ uint32_t ucfg_ipa_get_tx_buf_count(void) { return ipa_get_tx_buf_count(); } + +void ucfg_ipa_update_tx_stats(struct wlan_objmgr_pdev *pdev, uint64_t sta_tx, + uint64_t ap_tx) +{ + ipa_update_tx_stats(pdev, sta_tx, ap_tx); +} diff --git a/configs/default_defconfig b/configs/default_defconfig index 37722467a76c..ee791e1674fe 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -198,6 +198,11 @@ ifeq ($(CONFIG_ARCH_LITO), y) CONFIG_QCACLD_FEATURE_METERING := y endif +ifeq ($(CONFIG_ARCH_KONA), y) +CONFIG_QCACLD_FEATURE_METERING := y +CONFIG_WDI3_STATS_UPDATE := y +endif + #Flag to enable Fast Transition (11r) feature CONFIG_QCOM_VOWIFI_11R := y diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c6136a389ba4..3b9ef3ed4027 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8552,6 +8552,7 @@ static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) A_STATUS ret; bool connected = false; uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0; + uint64_t sta_tx_bytes, sap_tx_bytes; if (wlan_hdd_validate_context(hdd_ctx)) goto stop_work; @@ -8606,8 +8607,13 @@ static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) } } - if (adapter->device_mode == QDF_SAP_MODE) + if (adapter->device_mode == QDF_SAP_MODE) { con_sap_adapter = adapter; + sap_tx_bytes = adapter->stats.tx_bytes; + } + + if (adapter->device_mode == QDF_STA_MODE) + sta_tx_bytes = adapter->stats.tx_bytes; hdd_set_driver_del_ack_enable(adapter->vdev_id, hdd_ctx, rx_packets); @@ -8633,9 +8639,12 @@ static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) tx_packets += fwd_tx_packets_diff; rx_packets += fwd_rx_packets_diff; + /* Send embedded Tx packet bytes on STA & SAP interface to IPA driver */ + ucfg_ipa_update_tx_stats(hdd_ctx->pdev, sta_tx_bytes, sap_tx_bytes); + if (ucfg_ipa_is_fw_wdi_activated(hdd_ctx->pdev)) { ucfg_ipa_uc_stat_query(hdd_ctx->pdev, &ipa_tx_packets, - &ipa_rx_packets); + &ipa_rx_packets); tx_packets += (uint64_t)ipa_tx_packets; rx_packets += (uint64_t)ipa_rx_packets;