mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
qcacld-3.0: Add NAPI statistics to dumpstats
Currently NAPI stats are retrieved as a part of iwpriv getStats command. The buffer available for this command is limited and NAPI stats get truncated. Add a new dumpStats parameter (9) to dump NAPI stats. The following command will dump NAPI Stats into kmsg. >iwpriv wlan0 dumpStats 9 Cleanup existing getStats Change-Id: I0d804295d96a495b4afa576c8258f08c9c2b9bbb CRs-Fixed: 1076563
This commit is contained in:
parent
6876bd4738
commit
3e2115b6e2
9 changed files with 164 additions and 380 deletions
|
|
@ -3919,7 +3919,7 @@ ol_txrx_stats(uint8_t vdev_id, char *buffer, unsigned buf_len)
|
|||
}
|
||||
|
||||
len = scnprintf(buffer, buf_len,
|
||||
"\nTXRX stats:\n\nllQueue State : %s\n pause %u unpause %u\n overflow %u\n llQueue timer state : %s\n",
|
||||
"\n\nTXRX stats:\nllQueue State : %s\npause %u unpause %u\noverflow %u\nllQueue timer state : %s",
|
||||
((vdev->ll_pause.is_q_paused == false) ?
|
||||
"UNPAUSED" : "PAUSED"),
|
||||
vdev->ll_pause.q_pause_cnt,
|
||||
|
|
@ -4383,44 +4383,21 @@ static void ol_txrx_ipa_uc_get_stat(struct cdp_pdev *ppdev)
|
|||
#endif /* IPA_UC_OFFLOAD */
|
||||
|
||||
/**
|
||||
* ol_txrx_display_stats_help() - print statistics help
|
||||
* ol_txrx_display_stats() - Display OL TXRX display stats
|
||||
* @value: Module id for which stats needs to be displayed
|
||||
*
|
||||
* Return: none
|
||||
* Return: None
|
||||
*/
|
||||
static void ol_txrx_display_stats_help(void)
|
||||
{
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"iwpriv wlan0 dumpStats [option] - dump statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"iwpriv wlan0 clearStats [option] - clear statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"options:");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 1 -- TXRX Layer statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 2 -- Bandwidth compute timer stats");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 3 -- TSO statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 4 -- Network queue statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 5 -- Flow control statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 6 -- Per Layer statistics");
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
" 7 -- Copy engine interrupt statistics");
|
||||
|
||||
}
|
||||
|
||||
static void ol_txrx_display_stats(uint16_t value)
|
||||
static QDF_STATUS ol_txrx_display_stats(uint16_t value)
|
||||
{
|
||||
ol_txrx_pdev_handle pdev;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||
if (!pdev) {
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: pdev is NULL", __func__);
|
||||
return;
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
|
|
@ -4457,14 +4434,22 @@ static void ol_txrx_display_stats(uint16_t value)
|
|||
#endif
|
||||
#endif
|
||||
default:
|
||||
ol_txrx_display_stats_help();
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ol_txrx_clear_stats() - Clear OL TXRX stats
|
||||
* @value: Module id for which stats needs to be cleared
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void ol_txrx_clear_stats(uint16_t value)
|
||||
{
|
||||
ol_txrx_pdev_handle pdev;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||
if (!pdev) {
|
||||
|
|
@ -4500,9 +4485,11 @@ static void ol_txrx_clear_stats(uint16_t value)
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
ol_txrx_display_stats_help();
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ extern spinlock_t hdd_context_lock;
|
|||
#define WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME 100
|
||||
#define WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH 14
|
||||
|
||||
#define NUM_TX_RX_HISTOGRAM 1024
|
||||
#define NUM_TX_RX_HISTOGRAM 128
|
||||
#define NUM_TX_RX_HISTOGRAM_MASK (NUM_TX_RX_HISTOGRAM - 1)
|
||||
|
||||
/**
|
||||
|
|
@ -1984,7 +1984,7 @@ void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx);
|
|||
void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
|
||||
enum netif_action_type action, enum netif_reason_type reason);
|
||||
|
||||
void hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value);
|
||||
int hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value);
|
||||
void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx);
|
||||
void wlan_hdd_display_tx_rx_histogram(hdd_context_t *pHddCtx);
|
||||
void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *pHddCtx);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
|
|
@ -48,11 +48,7 @@ struct hdd_context_s;
|
|||
int hdd_napi_enabled(int id);
|
||||
int hdd_napi_create(void);
|
||||
int hdd_napi_destroy(int force);
|
||||
|
||||
int hdd_napi_stats(char *buf,
|
||||
int max,
|
||||
char *indp,
|
||||
struct qca_napi_data *napid);
|
||||
int hdd_display_napi_stats(void);
|
||||
|
||||
/* the following triggers napi_enable/disable as required */
|
||||
int hdd_napi_event(enum qca_napi_event event, void *data);
|
||||
|
|
@ -91,8 +87,7 @@ static inline int hdd_napi_serialize(int is_on)
|
|||
static inline int hdd_napi_enabled(int id) { return 0; }
|
||||
static inline int hdd_napi_create(void) { return 0; }
|
||||
static inline int hdd_napi_destroy(int force) { return 0; }
|
||||
static inline int hdd_napi_stats(char *buf, int max, char *indp,
|
||||
struct qca_napi_data *napid) { return 0; }
|
||||
static inline int hdd_display_napi_stats(void) { return 0; }
|
||||
static inline int hdd_napi_event(enum qca_napi_event event, void *data)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -301,6 +301,7 @@ typedef struct ccp_freq_chan_map_s {
|
|||
extern int hdd_unregister_wext(struct net_device *dev);
|
||||
extern int hdd_register_wext(struct net_device *dev);
|
||||
extern int hdd_wlan_get_freq(uint32_t chan, uint32_t *freq);
|
||||
extern void hdd_display_stats_help(void);
|
||||
extern void hdd_wlan_get_version(hdd_context_t *hdd_ctx,
|
||||
union iwreq_data *wrqu, char *extra);
|
||||
|
||||
|
|
|
|||
|
|
@ -3297,7 +3297,7 @@ static __iw_softap_setparam(struct net_device *dev,
|
|||
case QCASAP_DUMP_STATS:
|
||||
{
|
||||
hdd_notice("QCASAP_DUMP_STATS val %d", set_value);
|
||||
hdd_wlan_dump_stats(pHostapdAdapter, set_value);
|
||||
ret = hdd_wlan_dump_stats(pHostapdAdapter, set_value);
|
||||
break;
|
||||
}
|
||||
case QCASAP_CLEAR_STATS:
|
||||
|
|
|
|||
|
|
@ -6102,303 +6102,6 @@ static int drv_cmd_get_linkspeed(hdd_adapter_t *adapter,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_NAPI
|
||||
/**
|
||||
* hdd_parse_napi() - helper functions to drv_cmd_napi
|
||||
* @str : source string to parse
|
||||
* @cmd : pointer to cmd part after parsing
|
||||
* @sub : pointer to subcmd part after parsing
|
||||
* @aux : pointer to optional aux part after parsing
|
||||
*
|
||||
* Example:
|
||||
* NAPI SCALE <n> +-- IN str
|
||||
* | | +------ OUT aux
|
||||
* | +------------ OUT subcmd
|
||||
* +----------------- OUT cmd
|
||||
*
|
||||
* Return: ==0: success; !=0: failure
|
||||
*/
|
||||
static int hdd_parse_napi(char **str, char **cmd, char **sub, char **aux)
|
||||
{
|
||||
int rc;
|
||||
char *token, *lcmd = NULL, *lsub = NULL, *laux = NULL;
|
||||
|
||||
NAPI_DEBUG("-->\n");
|
||||
|
||||
token = strsep(str, " \t");
|
||||
if (NULL == token) {
|
||||
hdd_err("cannot parse cmd");
|
||||
goto parse_end;
|
||||
}
|
||||
lcmd = token;
|
||||
|
||||
token = strsep(str, " \t");
|
||||
if (NULL == token) {
|
||||
hdd_err("cannot parse subcmd");
|
||||
goto parse_end;
|
||||
}
|
||||
lsub = token;
|
||||
|
||||
token = strsep(str, " \t");
|
||||
if (NULL == token)
|
||||
hdd_warn("cannot parse aux\n");
|
||||
else
|
||||
laux = token;
|
||||
|
||||
parse_end:
|
||||
if ((NULL == lcmd) || (NULL == lsub))
|
||||
rc = -EINVAL;
|
||||
else {
|
||||
rc = 0;
|
||||
*cmd = lcmd;
|
||||
*sub = lsub;
|
||||
if (NULL != aux)
|
||||
*aux = laux;
|
||||
}
|
||||
NAPI_DEBUG("<--[rc=%d]\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hdd_parse_stats() - print NAPI stats into a buffer
|
||||
* @buf : buffer to write stats into
|
||||
* @max : "size of buffer"
|
||||
* @idp : NULL: all stats, otherwise, ptr to the NAPI instance
|
||||
* @napid: binary structure to retrieve the stats from
|
||||
*
|
||||
* Return: number of bytes written into the buffer
|
||||
*/
|
||||
int hdd_napi_stats(char *buf,
|
||||
int max,
|
||||
char *indp,
|
||||
struct qca_napi_data *napid)
|
||||
{
|
||||
int n = 0;
|
||||
int i, j, k; /* NAPI, CPU, bucket indices */
|
||||
int from, to;
|
||||
struct qca_napi_info *napii;
|
||||
struct qca_napi_stat *napis;
|
||||
|
||||
NAPI_DEBUG("-->\n");
|
||||
|
||||
if (NULL == napid)
|
||||
return n;
|
||||
if (NULL == indp) {
|
||||
from = 0;
|
||||
to = CE_COUNT_MAX;
|
||||
} else {
|
||||
if (0 > kstrtoint(indp, 10, &to)) {
|
||||
from = 0;
|
||||
to = CE_COUNT_MAX;
|
||||
} else
|
||||
from = to;
|
||||
}
|
||||
|
||||
for (i = from; i < to; i++)
|
||||
if (napid->ce_map & (0x01 << i)) {
|
||||
napii = &(napid->napis[i]);
|
||||
for (j = 0; j < NR_CPUS; j++) {
|
||||
napis = &(napii->stats[j]);
|
||||
n += scnprintf(buf + n, max - n,
|
||||
"STATS: NAPI[%d] CPU: %d scheds: %d polls: %d completes: %d done: %d ",
|
||||
i, j,
|
||||
napis->napi_schedules,
|
||||
napis->napi_polls,
|
||||
napis->napi_completes,
|
||||
napis->napi_workdone);
|
||||
|
||||
for (k = 0; k < QCA_NAPI_NUM_BUCKETS; k++) {
|
||||
n += scnprintf(
|
||||
buf + n, max - n,
|
||||
" %d",
|
||||
napis->napi_budget_uses[k]);
|
||||
}
|
||||
n += scnprintf(buf+n, max - n, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
NAPI_DEBUG("<--[n=%d]\n", n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* napi_set_scale() - sets the scale attribute in all NAPI entries
|
||||
* @sc : scale to set
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void napi_set_scale(uint8_t sc)
|
||||
{
|
||||
uint32_t i;
|
||||
struct qca_napi_data *napi_data;
|
||||
|
||||
napi_data = hdd_napi_get_all();
|
||||
if (likely(NULL != napi_data))
|
||||
for (i = 0; i < CE_COUNT_MAX; i++)
|
||||
if (napi_data->ce_map & (0x01 << i))
|
||||
napi_data->napis[i].scale = sc;
|
||||
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* drv_cmd_napi() - processes NAPI commands
|
||||
* @adapter : net_device
|
||||
* @hdd_ctx : HDD context
|
||||
* @command : command string from user command (including "NAPI")
|
||||
* @command_len: length of command
|
||||
* @priv_data : ifr_data
|
||||
*
|
||||
* Commands supported:
|
||||
* NAPI ENABLE : enables NAPI administratively. Note that this may not
|
||||
* enable NAPI functionally, as some other conditions
|
||||
* may not have been satisfied yet
|
||||
* NAPI DISABLE : reverse operation of "enable"
|
||||
* NAPI STATUS : get global status of NAPI instances
|
||||
* NAPI STATS [<n>] : get the stats for a given NAPI instance
|
||||
* NAPI SCALE <n> : set the scale factor
|
||||
*
|
||||
* Return: 0: success; !0: failure
|
||||
*/
|
||||
static int drv_cmd_napi(hdd_adapter_t *adapter,
|
||||
hdd_context_t *hdd_ctx,
|
||||
uint8_t *command,
|
||||
uint8_t command_len,
|
||||
hdd_priv_data_t *priv_data)
|
||||
{
|
||||
int rc = 0;
|
||||
int n, l;
|
||||
char *cmd = NULL, *subcmd = NULL, *aux = NULL;
|
||||
char *synopsis = "NAPI ENABLE\n"
|
||||
"NAPI DISABLE\n"
|
||||
"NAPI STATUS\n"
|
||||
"NAPI STATS [<n>] -- if no <n> then all\n"
|
||||
"NAPI SCALE <n> -- set the scale\n";
|
||||
char *reply = NULL;
|
||||
|
||||
/* make a local copy, as strsep modifies the str in place */
|
||||
char *str = NULL;
|
||||
|
||||
NAPI_DEBUG("-->\n");
|
||||
|
||||
/**
|
||||
* NOTE TO MAINTAINER: from this point to the end of the function,
|
||||
* please do not return anywhere in the code except the very end
|
||||
* to avoid memory leakage (goto end_drv_napi instead)
|
||||
* or make sure that reply+str is freed
|
||||
*/
|
||||
reply = kmalloc(MAX_USER_COMMAND_SIZE, GFP_KERNEL);
|
||||
if (NULL == reply) {
|
||||
hdd_err("could not allocate reply buffer");
|
||||
rc = -ENOMEM;
|
||||
goto end_drv_napi;
|
||||
}
|
||||
|
||||
str = kmalloc(strlen(command) + 1, GFP_KERNEL);
|
||||
if (NULL == str) {
|
||||
hdd_err("could not allocate copy of input buffer");
|
||||
rc = -ENOMEM;
|
||||
goto end_drv_napi;
|
||||
}
|
||||
|
||||
strlcpy(str, command, strlen(command) + 1);
|
||||
hdd_debug("parsing command into cmd=0x%p sub=0x%p aux=0x%p\n",
|
||||
cmd, subcmd, aux);
|
||||
|
||||
|
||||
rc = hdd_parse_napi(&str, &cmd, &subcmd, &aux);
|
||||
|
||||
if (0 != rc) {
|
||||
const char *msg = "unknown or badly formatted cmd\n%s";
|
||||
l = QDF_MIN(MAX_USER_COMMAND_SIZE,
|
||||
strlen(msg)+strlen(synopsis));
|
||||
n = scnprintf(reply, l, msg, synopsis);
|
||||
|
||||
if (copy_to_user(priv_data->buf, reply,
|
||||
QDF_MIN(priv_data->total_len, l)))
|
||||
hdd_err("failed to copy data to user buffer");
|
||||
hdd_debug("reply: %s", reply);
|
||||
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
hdd_debug("cmd=(%s) subcmd=(%s) aux=(%s)\n",
|
||||
cmd, subcmd, aux);
|
||||
if (!strcmp(subcmd, "ENABLE"))
|
||||
hdd_napi_event(NAPI_EVT_CMD_STATE, (void *)1);
|
||||
else if (!strcmp(subcmd, "DISABLE"))
|
||||
hdd_napi_event(NAPI_EVT_CMD_STATE, (void *)0);
|
||||
else if (!strcmp(subcmd, "STATUS")) {
|
||||
int n = 0;
|
||||
uint32_t i;
|
||||
struct qca_napi_data *napi_data;
|
||||
|
||||
napi_data = hdd_napi_get_all();
|
||||
if (unlikely(NULL == napi_data))
|
||||
goto status_end;
|
||||
n += scnprintf(reply+n, MAX_USER_COMMAND_SIZE - n,
|
||||
"NAPI state: 0x%08x map: 0x%08x\n",
|
||||
napi_data->state,
|
||||
napi_data->ce_map);
|
||||
|
||||
for (i = 0; i < CE_COUNT_MAX; i++)
|
||||
if (napi_data->ce_map & (0x01 << i)) {
|
||||
n += scnprintf(
|
||||
reply + n,
|
||||
MAX_USER_COMMAND_SIZE - n,
|
||||
"#%d: id: %d, scale=%d\n",
|
||||
i,
|
||||
napi_data->napis[i].id,
|
||||
napi_data->napis[i].scale);
|
||||
}
|
||||
status_end:
|
||||
hdd_info("wlan: STATUS DATA:\n%s", reply);
|
||||
if (copy_to_user(priv_data->buf, reply,
|
||||
QDF_MIN(n, priv_data->total_len)))
|
||||
rc = -EINVAL;
|
||||
} else if (!strcmp(subcmd, "STATS")) {
|
||||
int n = 0;
|
||||
struct qca_napi_data *napi_data;
|
||||
|
||||
napi_data = hdd_napi_get_all();
|
||||
if (NULL != napi_data) {
|
||||
n = hdd_napi_stats(reply, MAX_USER_COMMAND_SIZE,
|
||||
aux, napi_data);
|
||||
NAPI_DEBUG("STATS: returns %d\n", n);
|
||||
}
|
||||
if (n > 0) {
|
||||
if (copy_to_user(priv_data->buf, reply,
|
||||
QDF_MIN(priv_data->total_len,
|
||||
n)))
|
||||
rc = -EINVAL;
|
||||
hdd_info("wlan: STATS_DATA\n%s\n", reply);
|
||||
} else
|
||||
rc = -EINVAL;
|
||||
} else if (!strcmp(subcmd, "SCALE")) {
|
||||
if (NULL == aux) {
|
||||
rc = -EINVAL;
|
||||
hdd_err("wlan: SCALE cmd requires <n>");
|
||||
} else {
|
||||
uint8_t sc;
|
||||
rc = kstrtou8(aux, 10, &sc);
|
||||
if (rc) {
|
||||
hdd_err("wlan: bad scale (%s)", aux);
|
||||
rc = -EINVAL;
|
||||
} else
|
||||
napi_set_scale(sc);
|
||||
}
|
||||
} /* SCALE */
|
||||
}
|
||||
end_drv_napi:
|
||||
if (NULL != str)
|
||||
kfree(str);
|
||||
if (NULL != reply)
|
||||
kfree(reply);
|
||||
|
||||
NAPI_DEBUG("<--[rc=%d]\n", rc);
|
||||
return rc;
|
||||
}
|
||||
#endif /* FEATURE_NAPI */
|
||||
|
||||
/**
|
||||
* hdd_set_rx_filter() - set RX filter
|
||||
* @adapter: Pointer to adapter
|
||||
|
|
@ -7172,9 +6875,6 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = {
|
|||
#endif
|
||||
{"RSSI", drv_cmd_get_rssi},
|
||||
{"LINKSPEED", drv_cmd_get_linkspeed},
|
||||
#ifdef FEATURE_NAPI
|
||||
{"NAPI", drv_cmd_napi},
|
||||
#endif /* FEATURE_NAPI */
|
||||
{"RXFILTER-REMOVE", drv_cmd_rx_filter_remove},
|
||||
{"RXFILTER-ADD", drv_cmd_rx_filter_add},
|
||||
{"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel},
|
||||
|
|
|
|||
|
|
@ -6150,17 +6150,24 @@ void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
|
|||
hdd_err("index, total_rx, interval_rx, total_tx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
|
||||
|
||||
for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
|
||||
hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
|
||||
i, hdd_ctx->hdd_txrx_hist[i].total_rx,
|
||||
hdd_ctx->hdd_txrx_hist[i].interval_rx,
|
||||
hdd_ctx->hdd_txrx_hist[i].total_tx,
|
||||
hdd_ctx->hdd_txrx_hist[i].interval_tx,
|
||||
convert_level_to_string(
|
||||
hdd_ctx->hdd_txrx_hist[i].next_vote_level),
|
||||
convert_level_to_string(
|
||||
hdd_ctx->hdd_txrx_hist[i].next_rx_level),
|
||||
convert_level_to_string(
|
||||
hdd_ctx->hdd_txrx_hist[i].next_tx_level));
|
||||
/* using hdd_log to avoid printing function name */
|
||||
if (hdd_ctx->hdd_txrx_hist[i].total_rx != 0 ||
|
||||
hdd_ctx->hdd_txrx_hist[i].total_tx != 0)
|
||||
hdd_log(QDF_TRACE_LEVEL_ERROR,
|
||||
"%d: %llu, %llu, %llu, %llu, %s, %s, %s",
|
||||
i, hdd_ctx->hdd_txrx_hist[i].total_rx,
|
||||
hdd_ctx->hdd_txrx_hist[i].interval_rx,
|
||||
hdd_ctx->hdd_txrx_hist[i].total_tx,
|
||||
hdd_ctx->hdd_txrx_hist[i].interval_tx,
|
||||
convert_level_to_string(
|
||||
hdd_ctx->hdd_txrx_hist[i].
|
||||
next_vote_level),
|
||||
convert_level_to_string(
|
||||
hdd_ctx->hdd_txrx_hist[i].
|
||||
next_rx_level),
|
||||
convert_level_to_string(
|
||||
hdd_ctx->hdd_txrx_hist[i].
|
||||
next_tx_level));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -6197,7 +6204,7 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
|
|||
while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
|
||||
adapter = adapter_node->pAdapter;
|
||||
|
||||
hdd_err("\nNetif queue operation statistics:");
|
||||
hdd_err("Netif queue operation statistics:");
|
||||
hdd_err("Session_id %d device mode %d",
|
||||
adapter->sessionId, adapter->device_mode);
|
||||
hdd_err("Current pause_map value %x", adapter->pause_map);
|
||||
|
|
@ -6223,7 +6230,9 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
|
|||
if (adapter->pause_map & (1 << i))
|
||||
pause_delta = delta;
|
||||
|
||||
hdd_err("%s: %d: %d: %ums",
|
||||
/* using hdd_log to avoid printing function name */
|
||||
hdd_log(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: %d: %d: %ums",
|
||||
hdd_reason_type_to_string(i),
|
||||
adapter->queue_oper_stats[i].pause_count,
|
||||
adapter->queue_oper_stats[i].unpause_count,
|
||||
|
|
@ -6232,14 +6241,18 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
|
|||
pause_delta));
|
||||
}
|
||||
|
||||
hdd_err("\nNetif queue operation history:");
|
||||
hdd_err("Netif queue operation history:");
|
||||
hdd_err("Total entries: %d current index %d",
|
||||
WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
|
||||
|
||||
hdd_err("index: time: action_type: reason_type: pause_map");
|
||||
|
||||
for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
|
||||
hdd_err("%d: %u: %s: %s: %x",
|
||||
/* using hdd_log to avoid printing function name */
|
||||
if (adapter->queue_oper_history[i].time == 0)
|
||||
continue;
|
||||
hdd_log(QDF_TRACE_LEVEL_ERROR,
|
||||
"%d: %u: %s: %s: %x",
|
||||
i, qdf_system_ticks_to_msecs(
|
||||
adapter->queue_oper_history[i].time),
|
||||
hdd_action_type_to_string(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
|
|
@ -373,3 +373,62 @@ int hdd_napi_poll(struct napi_struct *napi, int budget)
|
|||
{
|
||||
return hif_napi_poll(cds_get_context(QDF_MODULE_ID_HIF), napi, budget);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_display_napi_stats() - print NAPI stats
|
||||
*
|
||||
* Return: == 0: success; !=0: failure
|
||||
*/
|
||||
int hdd_display_napi_stats(void)
|
||||
{
|
||||
int i, j, k, n; /* NAPI, CPU, bucket indices, bucket buf write index*/
|
||||
int max;
|
||||
struct qca_napi_data *napid;
|
||||
struct qca_napi_info *napii;
|
||||
struct qca_napi_stat *napis;
|
||||
/*
|
||||
* Expecting each NAPI bucket item to need at max 5 numerals + space for
|
||||
* formatting. For example "10000 " Thus the array needs to have
|
||||
* (5 + 1) * QCA_NAPI_NUM_BUCKETS bytes of space. Leaving one space at
|
||||
* the end of the "buf" arrary for end of string char.
|
||||
*/
|
||||
char buf[6 * QCA_NAPI_NUM_BUCKETS + 1] = {'\0'};
|
||||
|
||||
napid = hdd_napi_get_all();
|
||||
if (NULL == napid) {
|
||||
hdd_err("%s unable to retrieve napi structure", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
qdf_print("[NAPI -- STATS]: scheds polls comps done time-lim pkt-lim napi-buckets(%d)", QCA_NAPI_NUM_BUCKETS);
|
||||
|
||||
for (i = 0; i < CE_COUNT_MAX; i++)
|
||||
if (napid->ce_map & (0x01 << i)) {
|
||||
napii = &(napid->napis[i]);
|
||||
for (j = 0; j < NR_CPUS; j++) {
|
||||
napis = &(napii->stats[j]);
|
||||
n = 0;
|
||||
max = sizeof(buf);
|
||||
for (k = 0; k < QCA_NAPI_NUM_BUCKETS; k++) {
|
||||
n += scnprintf(
|
||||
buf + n, max - n,
|
||||
" %d",
|
||||
napis->napi_budget_uses[k]);
|
||||
}
|
||||
|
||||
if (napis->napi_schedules != 0)
|
||||
qdf_print("NAPI[%2d]CPU[%2d]: %7d %7d %7d %7d %8d %7d %s",
|
||||
i, j,
|
||||
napis->napi_schedules,
|
||||
napis->napi_polls,
|
||||
napis->napi_completes,
|
||||
napis->napi_workdone,
|
||||
napis->time_limit_reached,
|
||||
napis->rxpkt_thresh_reached,
|
||||
buf);
|
||||
}
|
||||
}
|
||||
|
||||
hif_napi_stats(napid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2931,14 +2931,14 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length,
|
|||
}
|
||||
|
||||
len = scnprintf(buffer, buf_len,
|
||||
"\nTransmit"
|
||||
"\ncalled %u, dropped %u,"
|
||||
"\n dropped BK %u, BE %u, VI %u, VO %u"
|
||||
"\n classified BK %u, BE %u, VI %u, VO %u"
|
||||
"\ncompleted %u,"
|
||||
"\n\nReceive Total"
|
||||
"\n packets %u, dropped %u, delivered %u, refused %u"
|
||||
"\nTransmit[%lu] - "
|
||||
"called %u, dropped %u,"
|
||||
"\n[dropped] BK %u, BE %u, VI %u, VO %u"
|
||||
"\n[classified] BK %u, BE %u, VI %u, VO %u"
|
||||
"\n\nReceive[%lu] - "
|
||||
"packets %u, dropped %u, delivered %u, refused %u"
|
||||
"\n",
|
||||
qdf_system_ticks(),
|
||||
pStats->txXmitCalled,
|
||||
pStats->txXmitDropped,
|
||||
|
||||
|
|
@ -2951,21 +2951,22 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length,
|
|||
pStats->txXmitClassifiedAC[SME_AC_BE],
|
||||
pStats->txXmitClassifiedAC[SME_AC_VI],
|
||||
pStats->txXmitClassifiedAC[SME_AC_VO],
|
||||
|
||||
pStats->txCompleted,
|
||||
qdf_system_ticks(),
|
||||
total_rx_pkt, total_rx_dropped, total_rx_delv, total_rx_refused
|
||||
);
|
||||
|
||||
for (i = 0; i < NUM_CPUS; i++) {
|
||||
if (pStats->rxPackets[i] == 0)
|
||||
continue;
|
||||
len += scnprintf(buffer + len, buf_len - len,
|
||||
"\nReceive CPU: %d"
|
||||
"\n packets %u, dropped %u, delivered %u, refused %u",
|
||||
"Rx CPU[%d]:"
|
||||
"packets %u, dropped %u, delivered %u, refused %u\n",
|
||||
i, pStats->rxPackets[i], pStats->rxDropped[i],
|
||||
pStats->rxDelivered[i], pStats->rxRefused[i]);
|
||||
}
|
||||
|
||||
len += scnprintf(buffer + len, buf_len - len,
|
||||
"\n\nTX_FLOW"
|
||||
"\nTX_FLOW"
|
||||
"\nCurrent status: %s"
|
||||
"\ntx-flow timer start count %u"
|
||||
"\npause count %u, unpause count %u",
|
||||
|
|
@ -2976,10 +2977,6 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length,
|
|||
|
||||
len += cdp_stats(cds_get_context(QDF_MODULE_ID_SOC),
|
||||
pAdapter->sessionId, &buffer[len], (buf_len - len));
|
||||
|
||||
len += hdd_napi_stats(buffer + len, buf_len - len,
|
||||
NULL, hdd_napi_get_all());
|
||||
|
||||
*length = len + 1;
|
||||
}
|
||||
|
||||
|
|
@ -3092,20 +3089,41 @@ void hdd_wlan_list_fw_profile(uint16_t *length,
|
|||
|
||||
*length = len + 1;
|
||||
}
|
||||
/**
|
||||
* hdd_display_stats_help() - print statistics help
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void hdd_display_stats_help(void)
|
||||
{
|
||||
hdd_err("iwpriv wlan0 dumpStats [option] - dump statistics");
|
||||
hdd_err("iwpriv wlan0 clearStats [option] - clear statistics");
|
||||
hdd_err("options:");
|
||||
hdd_err(" 1 -- TXRX Layer statistics");
|
||||
hdd_err(" 2 -- Bandwidth compute timer stats");
|
||||
hdd_err(" 3 -- TSO statistics");
|
||||
hdd_err(" 4 -- Network queue statistics");
|
||||
hdd_err(" 5 -- Flow control statistics");
|
||||
hdd_err(" 6 -- Per Layer statistics");
|
||||
hdd_err(" 7 -- Copy engine interrupt statistics");
|
||||
hdd_err(" 8 -- LRO statistics");
|
||||
hdd_err(" 9 -- NAPI statistics");
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_wlan_dump_stats() - display dump Stats
|
||||
* @adapter: adapter handle
|
||||
* @value: value from user
|
||||
*
|
||||
* Return: none
|
||||
* Return: 0 => success, error code on failure
|
||||
*/
|
||||
void hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value)
|
||||
int hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value)
|
||||
{
|
||||
int ret = 0;
|
||||
QDF_STATUS status;
|
||||
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
|
||||
switch (value) {
|
||||
|
||||
case WLAN_TXRX_HIST_STATS:
|
||||
wlan_hdd_display_tx_rx_histogram(hdd_ctx);
|
||||
break;
|
||||
|
|
@ -3117,11 +3135,22 @@ void hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value)
|
|||
break;
|
||||
case WLAN_LRO_STATS:
|
||||
hdd_lro_display_stats(hdd_ctx);
|
||||
case WLAN_NAPI_STATS:
|
||||
if (hdd_display_napi_stats()) {
|
||||
hdd_err("error displaying napi stats");
|
||||
ret = EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cdp_display_stats(cds_get_context(QDF_MODULE_ID_SOC), value);
|
||||
status = cdp_display_stats(cds_get_context(QDF_MODULE_ID_SOC),
|
||||
value);
|
||||
if (status == QDF_STATUS_E_INVAL) {
|
||||
hdd_display_stats_help();
|
||||
ret = EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -8369,7 +8398,7 @@ static int __iw_setint_getnone(struct net_device *dev,
|
|||
case WE_DUMP_STATS:
|
||||
{
|
||||
hdd_notice("WE_DUMP_STATS val %d", set_value);
|
||||
hdd_wlan_dump_stats(pAdapter, set_value);
|
||||
ret = hdd_wlan_dump_stats(pAdapter, set_value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue