qcacmn: Extract and populate peer_extd2 stats from fw

Presently, the driver doesnot extract the peer extended2 stats
(rx_bytes, rx_count, fcs_err) that are received from firmware.

Provide the support to extract and populate the peer extended stats2 at
the driver level.

Change-Id: If1f1bb1ef2d1202581744dd509d0da1da718d8c1
CRs-Fixed: 2397638
Este commit está contenido en:
Sourav Mohapatra
2018-08-30 16:14:00 +05:30
cometido por nshrivas
padre 9a6ee7d0ce
commit d768fd9e1e
Se han modificado 6 ficheros con 206 adiciones y 15 borrados

Ver fichero

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2019 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
@@ -87,12 +87,14 @@ struct vdev_cp_stats {
* struct peer_cp_stats - defines cp stats at peer object
* @peer_obj: pointer to peer
* @peer_stats: pointer to ic/mc specific stats
* @peer_adv_stats: pointer to peer adv stats
* @peer_comp_priv_obj[]: component's private object pointers
* @peer_cp_stats_lock: lock to protect object
*/
struct peer_cp_stats {
struct wlan_objmgr_peer *peer_obj;
void *peer_stats;
void *peer_adv_stats;
void *peer_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS];
qdf_spinlock_t peer_cp_stats_lock;
};

Ver fichero

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2019 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
@@ -33,6 +33,9 @@
#define MAX_NUM_CHAINS 2
#define IS_MSB_SET(__num) ((__num) & BIT(31))
#define IS_LSB_SET(__num) ((__num) & BIT(0))
/**
* enum stats_req_type - enum indicating bit position of various stats type in
* request map
@@ -248,6 +251,20 @@ struct peer_mc_cp_stats {
uint8_t peer_macaddr[WLAN_MACADDR_LEN];
};
/**
* struct peer_adv_mc_cp_stats - peer specific adv stats
* @peer_macaddr: mac address
* @fcs_count: fcs count
* @rx_bytes: rx bytes
* @rx_count: rx count
*/
struct peer_adv_mc_cp_stats {
uint8_t peer_macaddr[WLAN_MACADDR_LEN];
uint32_t fcs_count;
uint32_t rx_count;
uint64_t rx_bytes;
};
/**
* struct congestion_stats_event: congestion stats event param
* @vdev_id: vdev_id of the event
@@ -284,6 +301,8 @@ struct chain_rssi_event {
* @pdev_stats: if populated array indicating pdev stats (index = pdev_id)
* @num_peer_stats: num peer stats
* @peer_stats: if populated array indicating peer stats
* @peer_adv_stats: if populated, indicates peer adv (extd2) stats
* @num_peer_adv_stats: number of peer adv (extd2) stats
* @cca_stats: if populated indicates congestion stats
* @num_summary_stats: number of summary stats
* @vdev_summary_stats: if populated indicates array of summary stats per vdev
@@ -291,12 +310,16 @@ struct chain_rssi_event {
* @vdev_chain_rssi: if populated indicates array of chain rssi per vdev
* @tx_rate: tx rate (kbps)
* @tx_rate_flags: tx rate flags, (enum tx_rate_info)
* @last_event: The LSB indicates if the event is the last event or not and the
* MSB indicates if this feature is supported by FW or not.
*/
struct stats_event {
uint32_t num_pdev_stats;
struct pdev_mc_cp_stats *pdev_stats;
uint32_t num_peer_stats;
struct peer_mc_cp_stats *peer_stats;
uint32_t num_peer_adv_stats;
struct peer_adv_mc_cp_stats *peer_adv_stats;
struct congestion_stats_event *cca_stats;
uint32_t num_summary_stats;
struct summary_stats_event *vdev_summary_stats;
@@ -305,6 +328,7 @@ struct stats_event {
uint32_t tx_rate;
uint32_t rx_rate;
enum tx_rate_info tx_rate_flags;
uint32_t last_event;
};
#endif /* CONFIG_MCL */

Ver fichero

@@ -212,6 +212,54 @@ end:
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
}
static QDF_STATUS
tgt_mc_cp_stats_update_peer_adv_stats(struct wlan_objmgr_psoc *psoc,
struct peer_adv_mc_cp_stats
*peer_adv_stats, uint32_t size)
{
uint8_t *peer_mac_addr;
struct wlan_objmgr_peer *peer;
struct peer_adv_mc_cp_stats *peer_adv_mc_stats;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct peer_cp_stats *peer_cp_stats_priv;
if (!peer_adv_stats)
return QDF_STATUS_E_INVAL;
peer_mac_addr = peer_adv_stats->peer_macaddr;
peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
WLAN_CP_STATS_ID);
if (!peer) {
cp_stats_err("peer is null");
return QDF_STATUS_E_EXISTS;
}
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
if (!peer_cp_stats_priv) {
cp_stats_err("peer_cp_stats_priv is null");
status = QDF_STATUS_E_EXISTS;
goto end;
}
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_adv_mc_stats = peer_cp_stats_priv->peer_adv_stats;
qdf_mem_copy(peer_adv_mc_stats->peer_macaddr,
peer_adv_stats->peer_macaddr,
WLAN_MACADDR_LEN);
if (peer_adv_stats->fcs_count)
peer_adv_mc_stats->fcs_count = peer_adv_stats->fcs_count;
if (peer_adv_stats->rx_bytes)
peer_adv_mc_stats->rx_bytes = peer_adv_stats->rx_bytes;
if (peer_adv_stats->rx_count)
peer_adv_mc_stats->rx_count = peer_adv_stats->rx_count;
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
end:
if (peer)
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
return status;
}
static QDF_STATUS
tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc *psoc,
struct peer_mc_cp_stats *peer_stats)
@@ -273,10 +321,6 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
struct request_info last_req = {0};
uint32_t selected;
if (!ev->peer_stats) {
cp_stats_err("no peer stats");
return;
}
if (is_station_stats)
status = ucfg_mc_cp_stats_get_pending_req(psoc,
@@ -292,6 +336,11 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
return;
}
if (!ev->peer_stats) {
cp_stats_debug("no peer stats");
goto extd2_stats;
}
selected = ev->num_peer_stats;
for (i = 0; i < ev->num_peer_stats; i++) {
status = tgt_mc_cp_stats_update_peer_stats(psoc,
@@ -311,10 +360,40 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
/* no matched peer */
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
selected == ev->num_peer_stats) {
cp_stats_err("peer not found stats");
cp_stats_err("peer not found for stats");
}
extd2_stats:
if (!ev->peer_adv_stats) {
cp_stats_err("no peer_extd2 stats");
goto complete;
}
selected = ev->num_peer_adv_stats;
for (i = 0; i < ev->num_peer_adv_stats; i++) {
status = tgt_mc_cp_stats_update_peer_adv_stats(
psoc, &ev->peer_adv_stats[i],
ev->num_peer_adv_stats);
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
!qdf_mem_cmp(ev->peer_adv_stats[i].peer_macaddr,
last_req.peer_mac_addr,
WLAN_MACADDR_LEN)) {
/* mac is specified, but failed to update the peer */
if (QDF_IS_STATUS_ERROR(status))
return;
selected = i;
}
}
/* no matched peer */
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
selected == ev->num_peer_adv_stats) {
cp_stats_err("peer not found for extd stats");
return;
}
complete:
if (is_station_stats)
return;
@@ -563,6 +642,10 @@ tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
info.tx_rate_flags = vdev_mc_stats->tx_rate_flags;
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
info.peer_adv_stats = qdf_mem_malloc(sizeof(*info.peer_adv_stats));
if (!info.peer_adv_stats)
goto end;
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
peer_mc_stats = peer_cp_stats_priv->peer_stats;
/*
@@ -571,6 +654,14 @@ tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
*/
info.tx_rate = peer_mc_stats->tx_rate / 100;
info.rx_rate = peer_mc_stats->rx_rate / 100;
if (peer_cp_stats_priv->peer_adv_stats) {
info.num_peer_adv_stats = 1;
qdf_mem_copy(info.peer_adv_stats,
peer_cp_stats_priv->peer_adv_stats,
sizeof(peer_cp_stats_priv->peer_adv_stats));
}
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
end:
@@ -590,10 +681,14 @@ static void tgt_mc_cp_stats_extract_station_stats(
struct stats_event *ev)
{
QDF_STATUS status;
bool is_peer_stats;
bool is_last_event;
struct request_info last_req = {0};
is_peer_stats = (ev->peer_stats != NULL);
if (IS_MSB_SET(ev->last_event))
is_last_event = IS_LSB_SET(ev->last_event);
else
is_last_event = !!ev->peer_stats;
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS,
&last_req);
@@ -611,7 +706,7 @@ static void tgt_mc_cp_stats_extract_station_stats(
* PEER stats are the last stats sent for get_station statistics.
* reset type_map bit for station stats .
*/
if (is_peer_stats) {
if (is_last_event) {
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(psoc,
&last_req);
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS);

Ver fichero

@@ -85,11 +85,20 @@ QDF_STATUS wlan_cp_stats_peer_cs_init(struct peer_cp_stats *peer_cs)
if (!peer_cs->peer_stats)
return QDF_STATUS_E_NOMEM;
peer_cs->peer_adv_stats = qdf_mem_malloc(sizeof
(struct peer_adv_mc_cp_stats));
if (!peer_cs->peer_adv_stats) {
cp_stats_err("malloc failed");
qdf_mem_free(peer_cs->peer_stats);
return QDF_STATUS_E_NOMEM;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS wlan_cp_stats_peer_cs_deinit(struct peer_cp_stats *peer_cs)
{
qdf_mem_free(peer_cs->peer_adv_stats);
peer_cs->peer_adv_stats = NULL;
qdf_mem_free(peer_cs->peer_stats);
peer_cs->peer_stats = NULL;
return QDF_STATUS_SUCCESS;
@@ -554,6 +563,7 @@ void ucfg_mc_cp_stats_free_stats_resources(struct stats_event *ev)
return;
qdf_mem_free(ev->pdev_stats);
qdf_mem_free(ev->peer_adv_stats);
qdf_mem_free(ev->peer_stats);
qdf_mem_free(ev->cca_stats);
qdf_mem_free(ev->vdev_summary_stats);