From: Jiawen Wu Date: Thu, 25 Feb 2021 08:08:52 +0000 (+0800) Subject: net/txgbe: support VF stats and xstats X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=27890a34ca39762e1229bf18dc133e9eabe53b62;p=dpdk.git net/txgbe: support VF stats and xstats Add VF device stats and extended stats get from reading hardware registers. Signed-off-by: Jiawen Wu --- diff --git a/doc/guides/nics/features/txgbe_vf.ini b/doc/guides/nics/features/txgbe_vf.ini index 8f36af0e32..675e1af83b 100644 --- a/doc/guides/nics/features/txgbe_vf.ini +++ b/doc/guides/nics/features/txgbe_vf.ini @@ -20,6 +20,8 @@ Inner L3 checksum = P Inner L4 checksum = P Rx descriptor status = Y Tx descriptor status = Y +Basic stats = Y +Extended stats = Y Multiprocess aware = Y Linux = Y ARMv8 = Y diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 052609e3c1..2799e5588f 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1698,6 +1698,29 @@ enum txgbe_5tuple_protocol { #define TXGBE_REG_RSSTBL TXGBE_RSSTBL(0) #define TXGBE_REG_RSSKEY TXGBE_RSSKEY(0) +/* + * read non-rc counters + */ +#define TXGBE_UPDCNT32(reg, last, cur) \ +do { \ + uint32_t latest = rd32(hw, reg); \ + if (hw->offset_loaded || hw->rx_loaded) \ + last = 0; \ + cur += (latest - last) & UINT_MAX; \ + last = latest; \ +} while (0) + +#define TXGBE_UPDCNT36(regl, last, cur) \ +do { \ + uint64_t new_lsb = rd32(hw, regl); \ + uint64_t new_msb = rd32(hw, regl + 4); \ + uint64_t latest = ((new_msb << 32) | new_lsb); \ + if (hw->offset_loaded || hw->rx_loaded) \ + last = 0; \ + cur += (0x1000000000LL + latest - last) & 0xFFFFFFFFFLL; \ + last = latest; \ +} while (0) + /** * register operations **/ diff --git a/drivers/net/txgbe/base/txgbe_vf.h b/drivers/net/txgbe/base/txgbe_vf.h index 7c84c68925..70d81ca831 100644 --- a/drivers/net/txgbe/base/txgbe_vf.h +++ b/drivers/net/txgbe/base/txgbe_vf.h @@ -10,6 +10,33 @@ #define TXGBE_VF_MAX_TX_QUEUES 8 #define TXGBE_VF_MAX_RX_QUEUES 8 +struct txgbevf_hw_stats { + u64 base_vfgprc; + u64 base_vfgptc; + u64 base_vfgorc; + u64 base_vfgotc; + u64 base_vfmprc; + + struct{ + u64 last_vfgprc; + u64 last_vfgptc; + u64 last_vfgorc; + u64 last_vfgotc; + u64 last_vfmprc; + u64 vfgprc; + u64 vfgptc; + u64 vfgorc; + u64 vfgotc; + u64 vfmprc; + } qp[8]; + + u64 saved_reset_vfgprc; + u64 saved_reset_vfgptc; + u64 saved_reset_vfgorc; + u64 saved_reset_vfgotc; + u64 saved_reset_vfmprc; +}; + s32 txgbe_init_ops_vf(struct txgbe_hw *hw); s32 txgbe_start_hw_vf(struct txgbe_hw *hw); s32 txgbe_reset_hw_vf(struct txgbe_hw *hw); diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c index 559af5b16c..8fec75efe3 100644 --- a/drivers/net/txgbe/txgbe_ethdev_vf.c +++ b/drivers/net/txgbe/txgbe_ethdev_vf.c @@ -15,6 +15,8 @@ #include "txgbe_ethdev.h" #include "txgbe_rxtx.h" +static int txgbevf_dev_xstats_get(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, unsigned int n); static int txgbevf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int txgbevf_dev_configure(struct rte_eth_dev *dev); @@ -23,6 +25,7 @@ static int txgbevf_dev_link_update(struct rte_eth_dev *dev, static int txgbevf_dev_close(struct rte_eth_dev *dev); static void txgbevf_intr_disable(struct rte_eth_dev *dev); static void txgbevf_intr_enable(struct rte_eth_dev *dev); +static int txgbevf_dev_stats_reset(struct rte_eth_dev *dev); static void txgbevf_configure_msix(struct rte_eth_dev *dev); static void txgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index); static void txgbevf_dev_interrupt_handler(void *param); @@ -52,6 +55,28 @@ static const struct rte_eth_desc_lim tx_desc_lim = { static const struct eth_dev_ops txgbevf_eth_dev_ops; +static const struct rte_txgbe_xstats_name_off rte_txgbevf_stats_strings[] = { + {"rx_multicast_packets_0", + offsetof(struct txgbevf_hw_stats, qp[0].vfmprc)}, + {"rx_multicast_packets_1", + offsetof(struct txgbevf_hw_stats, qp[1].vfmprc)}, + {"rx_multicast_packets_2", + offsetof(struct txgbevf_hw_stats, qp[2].vfmprc)}, + {"rx_multicast_packets_3", + offsetof(struct txgbevf_hw_stats, qp[3].vfmprc)}, + {"rx_multicast_packets_4", + offsetof(struct txgbevf_hw_stats, qp[4].vfmprc)}, + {"rx_multicast_packets_5", + offsetof(struct txgbevf_hw_stats, qp[5].vfmprc)}, + {"rx_multicast_packets_6", + offsetof(struct txgbevf_hw_stats, qp[6].vfmprc)}, + {"rx_multicast_packets_7", + offsetof(struct txgbevf_hw_stats, qp[7].vfmprc)} +}; + +#define TXGBEVF_NB_XSTATS (sizeof(rte_txgbevf_stats_strings) / \ + sizeof(rte_txgbevf_stats_strings[0])) + /* * Negotiate mailbox API version with the PF. * After reset API version is always set to the basic one (txgbe_mbox_api_10). @@ -159,6 +184,9 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev) /* init_mailbox_params */ hw->mbx.init_params(hw); + /* Reset the hw statistics */ + txgbevf_dev_stats_reset(eth_dev); + /* Disable the interrupts for VF */ txgbevf_intr_disable(eth_dev); @@ -275,6 +303,131 @@ static struct rte_pci_driver rte_txgbevf_pmd = { .remove = eth_txgbevf_pci_remove, }; +static int txgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, unsigned int limit) +{ + unsigned int i; + + if (limit < TXGBEVF_NB_XSTATS && xstats_names != NULL) + return -ENOMEM; + + if (xstats_names != NULL) + for (i = 0; i < TXGBEVF_NB_XSTATS; i++) + snprintf(xstats_names[i].name, + sizeof(xstats_names[i].name), + "%s", rte_txgbevf_stats_strings[i].name); + return TXGBEVF_NB_XSTATS; +} + +static void +txgbevf_update_stats(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbevf_hw_stats *hw_stats = (struct txgbevf_hw_stats *) + TXGBE_DEV_STATS(dev); + unsigned int i; + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + /* Good Rx packet, include VF loopback */ + TXGBE_UPDCNT32(TXGBE_QPRXPKT(i), + hw_stats->qp[i].last_vfgprc, hw_stats->qp[i].vfgprc); + + /* Good Rx octets, include VF loopback */ + TXGBE_UPDCNT36(TXGBE_QPRXOCTL(i), + hw_stats->qp[i].last_vfgorc, hw_stats->qp[i].vfgorc); + + /* Rx Multicst Packet */ + TXGBE_UPDCNT32(TXGBE_QPRXMPKT(i), + hw_stats->qp[i].last_vfmprc, hw_stats->qp[i].vfmprc); + } + hw->rx_loaded = 0; + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + /* Good Tx packet, include VF loopback */ + TXGBE_UPDCNT32(TXGBE_QPTXPKT(i), + hw_stats->qp[i].last_vfgptc, hw_stats->qp[i].vfgptc); + + /* Good Tx octets, include VF loopback */ + TXGBE_UPDCNT36(TXGBE_QPTXOCTL(i), + hw_stats->qp[i].last_vfgotc, hw_stats->qp[i].vfgotc); + } + hw->offset_loaded = 0; +} + +static int +txgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, + unsigned int n) +{ + struct txgbevf_hw_stats *hw_stats = (struct txgbevf_hw_stats *) + TXGBE_DEV_STATS(dev); + unsigned int i; + + if (n < TXGBEVF_NB_XSTATS) + return TXGBEVF_NB_XSTATS; + + txgbevf_update_stats(dev); + + if (!xstats) + return 0; + + /* Extended stats */ + for (i = 0; i < TXGBEVF_NB_XSTATS; i++) { + xstats[i].id = i; + xstats[i].value = *(uint64_t *)(((char *)hw_stats) + + rte_txgbevf_stats_strings[i].offset); + } + + return TXGBEVF_NB_XSTATS; +} + +static int +txgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) +{ + struct txgbevf_hw_stats *hw_stats = (struct txgbevf_hw_stats *) + TXGBE_DEV_STATS(dev); + uint32_t i; + + txgbevf_update_stats(dev); + + if (stats == NULL) + return -EINVAL; + + stats->ipackets = 0; + stats->ibytes = 0; + stats->opackets = 0; + stats->obytes = 0; + + for (i = 0; i < 8; i++) { + stats->ipackets += hw_stats->qp[i].vfgprc; + stats->ibytes += hw_stats->qp[i].vfgorc; + stats->opackets += hw_stats->qp[i].vfgptc; + stats->obytes += hw_stats->qp[i].vfgotc; + } + + return 0; +} + +static int +txgbevf_dev_stats_reset(struct rte_eth_dev *dev) +{ + struct txgbevf_hw_stats *hw_stats = (struct txgbevf_hw_stats *) + TXGBE_DEV_STATS(dev); + uint32_t i; + + /* Sync HW register to the last stats */ + txgbevf_dev_stats_get(dev, NULL); + + /* reset HW current stats*/ + for (i = 0; i < 8; i++) { + hw_stats->qp[i].vfgprc = 0; + hw_stats->qp[i].vfgorc = 0; + hw_stats->qp[i].vfgptc = 0; + hw_stats->qp[i].vfgotc = 0; + } + + return 0; +} + static int txgbevf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) @@ -707,6 +860,11 @@ txgbevf_dev_interrupt_handler(void *param) static const struct eth_dev_ops txgbevf_eth_dev_ops = { .dev_configure = txgbevf_dev_configure, .link_update = txgbevf_dev_link_update, + .stats_get = txgbevf_dev_stats_get, + .xstats_get = txgbevf_dev_xstats_get, + .stats_reset = txgbevf_dev_stats_reset, + .xstats_reset = txgbevf_dev_stats_reset, + .xstats_get_names = txgbevf_dev_xstats_get_names, .dev_infos_get = txgbevf_dev_info_get, .rx_queue_intr_enable = txgbevf_dev_rx_queue_intr_enable, .rx_queue_intr_disable = txgbevf_dev_rx_queue_intr_disable,