numam-dpdk/drivers/net/octeontx2/otx2_stats.c
Igor Romanov 9970a9ad07 ethdev: make stats and xstats reset callbacks return int
Change return value of the callbacks from void to int. Make
implementations across all drivers return negative errno
values in case of error conditions.

Both callbacks are updated together because a large number of
drivers assign the same function to both callbacks.

Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
2019-10-07 15:00:54 +02:00

397 lines
10 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(C) 2019 Marvell International Ltd.
*/
#include <inttypes.h>
#include "otx2_ethdev.h"
struct otx2_nix_xstats_name {
char name[RTE_ETH_XSTATS_NAME_SIZE];
uint32_t offset;
};
static const struct otx2_nix_xstats_name nix_tx_xstats[] = {
{"tx_ucast", NIX_STAT_LF_TX_TX_UCAST},
{"tx_bcast", NIX_STAT_LF_TX_TX_BCAST},
{"tx_mcast", NIX_STAT_LF_TX_TX_MCAST},
{"tx_drop", NIX_STAT_LF_TX_TX_DROP},
{"tx_octs", NIX_STAT_LF_TX_TX_OCTS},
};
static const struct otx2_nix_xstats_name nix_rx_xstats[] = {
{"rx_octs", NIX_STAT_LF_RX_RX_OCTS},
{"rx_ucast", NIX_STAT_LF_RX_RX_UCAST},
{"rx_bcast", NIX_STAT_LF_RX_RX_BCAST},
{"rx_mcast", NIX_STAT_LF_RX_RX_MCAST},
{"rx_drop", NIX_STAT_LF_RX_RX_DROP},
{"rx_drop_octs", NIX_STAT_LF_RX_RX_DROP_OCTS},
{"rx_fcs", NIX_STAT_LF_RX_RX_FCS},
{"rx_err", NIX_STAT_LF_RX_RX_ERR},
{"rx_drp_bcast", NIX_STAT_LF_RX_RX_DRP_BCAST},
{"rx_drp_mcast", NIX_STAT_LF_RX_RX_DRP_MCAST},
{"rx_drp_l3bcast", NIX_STAT_LF_RX_RX_DRP_L3BCAST},
{"rx_drp_l3mcast", NIX_STAT_LF_RX_RX_DRP_L3MCAST},
};
static const struct otx2_nix_xstats_name nix_q_xstats[] = {
{"rq_op_re_pkts", NIX_LF_RQ_OP_RE_PKTS},
};
#define OTX2_NIX_NUM_RX_XSTATS RTE_DIM(nix_rx_xstats)
#define OTX2_NIX_NUM_TX_XSTATS RTE_DIM(nix_tx_xstats)
#define OTX2_NIX_NUM_QUEUE_XSTATS RTE_DIM(nix_q_xstats)
#define OTX2_NIX_NUM_XSTATS_REG (OTX2_NIX_NUM_RX_XSTATS + \
OTX2_NIX_NUM_TX_XSTATS + OTX2_NIX_NUM_QUEUE_XSTATS)
int
otx2_nix_dev_stats_get(struct rte_eth_dev *eth_dev,
struct rte_eth_stats *stats)
{
struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
uint64_t reg, val;
uint32_t qidx, i;
int64_t *addr;
stats->opackets = otx2_read64(dev->base +
NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_UCAST));
stats->opackets += otx2_read64(dev->base +
NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_MCAST));
stats->opackets += otx2_read64(dev->base +
NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_BCAST));
stats->oerrors = otx2_read64(dev->base +
NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_DROP));
stats->obytes = otx2_read64(dev->base +
NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_OCTS));
stats->ipackets = otx2_read64(dev->base +
NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_UCAST));
stats->ipackets += otx2_read64(dev->base +
NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_MCAST));
stats->ipackets += otx2_read64(dev->base +
NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_BCAST));
stats->imissed = otx2_read64(dev->base +
NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_DROP));
stats->ibytes = otx2_read64(dev->base +
NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_OCTS));
stats->ierrors = otx2_read64(dev->base +
NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_ERR));
for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
if (dev->txmap[i] & (1U << 31)) {
qidx = dev->txmap[i] & 0xFFFF;
reg = (((uint64_t)qidx) << 32);
addr = (int64_t *)(dev->base + NIX_LF_SQ_OP_PKTS);
val = otx2_atomic64_add_nosync(reg, addr);
if (val & OP_ERR)
val = 0;
stats->q_opackets[i] = val;
addr = (int64_t *)(dev->base + NIX_LF_SQ_OP_OCTS);
val = otx2_atomic64_add_nosync(reg, addr);
if (val & OP_ERR)
val = 0;
stats->q_obytes[i] = val;
addr = (int64_t *)(dev->base + NIX_LF_SQ_OP_DROP_PKTS);
val = otx2_atomic64_add_nosync(reg, addr);
if (val & OP_ERR)
val = 0;
stats->q_errors[i] = val;
}
}
for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
if (dev->rxmap[i] & (1U << 31)) {
qidx = dev->rxmap[i] & 0xFFFF;
reg = (((uint64_t)qidx) << 32);
addr = (int64_t *)(dev->base + NIX_LF_RQ_OP_PKTS);
val = otx2_atomic64_add_nosync(reg, addr);
if (val & OP_ERR)
val = 0;
stats->q_ipackets[i] = val;
addr = (int64_t *)(dev->base + NIX_LF_RQ_OP_OCTS);
val = otx2_atomic64_add_nosync(reg, addr);
if (val & OP_ERR)
val = 0;
stats->q_ibytes[i] = val;
addr = (int64_t *)(dev->base + NIX_LF_RQ_OP_DROP_PKTS);
val = otx2_atomic64_add_nosync(reg, addr);
if (val & OP_ERR)
val = 0;
stats->q_errors[i] += val;
}
}
return 0;
}
int
otx2_nix_dev_stats_reset(struct rte_eth_dev *eth_dev)
{
struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
struct otx2_mbox *mbox = dev->mbox;
if (otx2_mbox_alloc_msg_nix_stats_rst(mbox) == NULL)
return -ENOMEM;
return otx2_mbox_process(mbox);
}
int
otx2_nix_queue_stats_mapping(struct rte_eth_dev *eth_dev, uint16_t queue_id,
uint8_t stat_idx, uint8_t is_rx)
{
struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
if (is_rx)
dev->rxmap[stat_idx] = ((1U << 31) | queue_id);
else
dev->txmap[stat_idx] = ((1U << 31) | queue_id);
return 0;
}
int
otx2_nix_xstats_get(struct rte_eth_dev *eth_dev,
struct rte_eth_xstat *xstats,
unsigned int n)
{
struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
unsigned int i, count = 0;
uint64_t reg, val;
if (n < OTX2_NIX_NUM_XSTATS_REG)
return OTX2_NIX_NUM_XSTATS_REG;
if (xstats == NULL)
return 0;
for (i = 0; i < OTX2_NIX_NUM_TX_XSTATS; i++) {
xstats[count].value = otx2_read64(dev->base +
NIX_LF_TX_STATX(nix_tx_xstats[i].offset));
xstats[count].id = count;
count++;
}
for (i = 0; i < OTX2_NIX_NUM_RX_XSTATS; i++) {
xstats[count].value = otx2_read64(dev->base +
NIX_LF_RX_STATX(nix_rx_xstats[i].offset));
xstats[count].id = count;
count++;
}
for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
reg = (((uint64_t)i) << 32);
val = otx2_atomic64_add_nosync(reg, (int64_t *)(dev->base +
nix_q_xstats[0].offset));
if (val & OP_ERR)
val = 0;
xstats[count].value += val;
}
xstats[count].id = count;
count++;
return count;
}
int
otx2_nix_xstats_get_names(struct rte_eth_dev *eth_dev,
struct rte_eth_xstat_name *xstats_names,
unsigned int limit)
{
unsigned int i, count = 0;
RTE_SET_USED(eth_dev);
if (limit < OTX2_NIX_NUM_XSTATS_REG && xstats_names != NULL)
return -ENOMEM;
if (xstats_names) {
for (i = 0; i < OTX2_NIX_NUM_TX_XSTATS; i++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s", nix_tx_xstats[i].name);
count++;
}
for (i = 0; i < OTX2_NIX_NUM_RX_XSTATS; i++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s", nix_rx_xstats[i].name);
count++;
}
for (i = 0; i < OTX2_NIX_NUM_QUEUE_XSTATS; i++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s", nix_q_xstats[i].name);
count++;
}
}
return OTX2_NIX_NUM_XSTATS_REG;
}
int
otx2_nix_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,
struct rte_eth_xstat_name *xstats_names,
const uint64_t *ids, unsigned int limit)
{
struct rte_eth_xstat_name xstats_names_copy[OTX2_NIX_NUM_XSTATS_REG];
uint16_t i;
if (limit < OTX2_NIX_NUM_XSTATS_REG && ids == NULL)
return OTX2_NIX_NUM_XSTATS_REG;
if (limit > OTX2_NIX_NUM_XSTATS_REG)
return -EINVAL;
if (xstats_names == NULL)
return -ENOMEM;
otx2_nix_xstats_get_names(eth_dev, xstats_names_copy, limit);
for (i = 0; i < OTX2_NIX_NUM_XSTATS_REG; i++) {
if (ids[i] >= OTX2_NIX_NUM_XSTATS_REG) {
otx2_err("Invalid id value");
return -EINVAL;
}
strncpy(xstats_names[i].name, xstats_names_copy[ids[i]].name,
sizeof(xstats_names[i].name));
}
return limit;
}
int
otx2_nix_xstats_get_by_id(struct rte_eth_dev *eth_dev, const uint64_t *ids,
uint64_t *values, unsigned int n)
{
struct rte_eth_xstat xstats[OTX2_NIX_NUM_XSTATS_REG];
uint16_t i;
if (n < OTX2_NIX_NUM_XSTATS_REG && ids == NULL)
return OTX2_NIX_NUM_XSTATS_REG;
if (n > OTX2_NIX_NUM_XSTATS_REG)
return -EINVAL;
if (values == NULL)
return -ENOMEM;
otx2_nix_xstats_get(eth_dev, xstats, n);
for (i = 0; i < OTX2_NIX_NUM_XSTATS_REG; i++) {
if (ids[i] >= OTX2_NIX_NUM_XSTATS_REG) {
otx2_err("Invalid id value");
return -EINVAL;
}
values[i] = xstats[ids[i]].value;
}
return n;
}
static int
nix_queue_stats_reset(struct rte_eth_dev *eth_dev)
{
struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
struct otx2_mbox *mbox = dev->mbox;
struct nix_aq_enq_rsp *rsp;
struct nix_aq_enq_req *aq;
uint32_t i;
int rc;
for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
aq->qidx = i;
aq->ctype = NIX_AQ_CTYPE_RQ;
aq->op = NIX_AQ_INSTOP_READ;
rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
if (rc) {
otx2_err("Failed to read rq context");
return rc;
}
aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
aq->qidx = i;
aq->ctype = NIX_AQ_CTYPE_RQ;
aq->op = NIX_AQ_INSTOP_WRITE;
otx2_mbox_memcpy(&aq->rq, &rsp->rq, sizeof(rsp->rq));
otx2_mbox_memset(&aq->rq_mask, 0, sizeof(aq->rq_mask));
aq->rq.octs = 0;
aq->rq.pkts = 0;
aq->rq.drop_octs = 0;
aq->rq.drop_pkts = 0;
aq->rq.re_pkts = 0;
aq->rq_mask.octs = ~(aq->rq_mask.octs);
aq->rq_mask.pkts = ~(aq->rq_mask.pkts);
aq->rq_mask.drop_octs = ~(aq->rq_mask.drop_octs);
aq->rq_mask.drop_pkts = ~(aq->rq_mask.drop_pkts);
aq->rq_mask.re_pkts = ~(aq->rq_mask.re_pkts);
rc = otx2_mbox_process(mbox);
if (rc) {
otx2_err("Failed to write rq context");
return rc;
}
}
for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
aq->qidx = i;
aq->ctype = NIX_AQ_CTYPE_SQ;
aq->op = NIX_AQ_INSTOP_READ;
rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
if (rc) {
otx2_err("Failed to read sq context");
return rc;
}
aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
aq->qidx = i;
aq->ctype = NIX_AQ_CTYPE_SQ;
aq->op = NIX_AQ_INSTOP_WRITE;
otx2_mbox_memcpy(&aq->sq, &rsp->sq, sizeof(rsp->sq));
otx2_mbox_memset(&aq->sq_mask, 0, sizeof(aq->sq_mask));
aq->sq.octs = 0;
aq->sq.pkts = 0;
aq->sq.drop_octs = 0;
aq->sq.drop_pkts = 0;
aq->sq_mask.octs = ~(aq->sq_mask.octs);
aq->sq_mask.pkts = ~(aq->sq_mask.pkts);
aq->sq_mask.drop_octs = ~(aq->sq_mask.drop_octs);
aq->sq_mask.drop_pkts = ~(aq->sq_mask.drop_pkts);
rc = otx2_mbox_process(mbox);
if (rc) {
otx2_err("Failed to write sq context");
return rc;
}
}
return 0;
}
int
otx2_nix_xstats_reset(struct rte_eth_dev *eth_dev)
{
struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
struct otx2_mbox *mbox = dev->mbox;
int ret;
if (otx2_mbox_alloc_msg_nix_stats_rst(mbox) == NULL)
return -ENOMEM;
ret = otx2_mbox_process(mbox);
if (ret != 0)
return ret;
/* Reset queue stats */
return nix_queue_stats_reset(eth_dev);
}