qcacld-3.0: Support stats quota for sta + sap ipa offload
Implement metering stats quota to support ipa offload sta plus
sap wifi sharing use cases.
Change-Id: Ic9d5ad817ffb4d671a43f3f3aebb2d8cce293873
CRs-Fixed: 2517696
diff --git a/Kbuild b/Kbuild
index e4d0596..237d8a8 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2965,6 +2965,8 @@
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 9543783..825ba55 100644
--- a/components/ipa/core/inc/wlan_ipa_core.h
+++ b/components/ipa/core/inc/wlan_ipa_core.h
@@ -326,6 +326,7 @@
#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 @@
* 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 @@
* 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_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 7fe4a32..e719001 100644
--- a/components/ipa/core/inc/wlan_ipa_main.h
+++ b/components/ipa/core/inc/wlan_ipa_main.h
@@ -441,9 +441,15 @@
*
* 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 18b5cea..cf5cb05 100644
--- a/components/ipa/core/inc/wlan_ipa_priv.h
+++ b/components/ipa/core/inc/wlan_ipa_priv.h
@@ -664,6 +664,7 @@
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 a558ae5..bb96705 100644
--- a/components/ipa/core/src/wlan_ipa_core.c
+++ b/components/ipa/core/src/wlan_ipa_core.c
@@ -1952,6 +1952,7 @@
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 @@
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 @@
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 @@
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 @@
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 e8f4a7a..424062b 100644
--- a/components/ipa/core/src/wlan_ipa_main.c
+++ b/components/ipa/core/src/wlan_ipa_main.c
@@ -643,3 +643,20 @@
{
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 3e8fdee..c701bf2 100644
--- a/components/ipa/core/src/wlan_ipa_stats.c
+++ b/components/ipa/core/src/wlan_ipa_stats.c
@@ -748,6 +748,39 @@
}
#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 @@
}
}
-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 @@
}
}
+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 @@
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 4f34907..c0cdc5e 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 @@
*/
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 @@
{
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 b1fedfa..aa65a52 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 @@
{
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 3772246..ee791e1 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -198,6 +198,11 @@
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 c6136a3..3b9ef3e 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -8552,6 +8552,7 @@
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 @@
}
}
- 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 @@
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;