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
Dieser Commit ist enthalten in:
Sravan Kumar Kairam
2019-08-22 23:46:27 +05:30
committet von nshrivas
Ursprung 44f9ab7ee1
Commit 3bc886df40
11 geänderte Dateien mit 193 neuen und 55 gelöschten Zeilen

Datei anzeigen

@@ -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 */
/**

Datei anzeigen

@@ -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);

Datei anzeigen

@@ -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)

Datei anzeigen

@@ -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,

Datei anzeigen

@@ -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);
}

Datei anzeigen

@@ -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 */