Signed-off-by: Howard Wang <howard_w...@realsil.com.cn> --- doc/guides/nics/features/r8169.ini | 1 + drivers/net/r8169/r8169_compat.h | 15 ++++++ drivers/net/r8169/r8169_ethdev.c | 48 ++++++++++++++++++ drivers/net/r8169/r8169_ethdev.h | 3 ++ drivers/net/r8169/r8169_hw.c | 80 ++++++++++++++++++++++++++++++ drivers/net/r8169/r8169_hw.h | 6 +++ 6 files changed, 153 insertions(+)
diff --git a/doc/guides/nics/features/r8169.ini b/doc/guides/nics/features/r8169.ini index 7e3c2a823c..a9a4bd6a90 100644 --- a/doc/guides/nics/features/r8169.ini +++ b/doc/guides/nics/features/r8169.ini @@ -13,6 +13,7 @@ TSO = Y Flow control = Y L3 checksum offload = Y L4 checksum offload = Y +Basic stats = Y Linux = Y x86-32 = Y x86-64 = Y diff --git a/drivers/net/r8169/r8169_compat.h b/drivers/net/r8169/r8169_compat.h index 3cb7eab3cb..48b689d895 100644 --- a/drivers/net/r8169/r8169_compat.h +++ b/drivers/net/r8169/r8169_compat.h @@ -18,6 +18,21 @@ typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; +struct rtl_counters { + u64 tx_packets; + u64 rx_packets; + u64 tx_errors; + u32 rx_errors; + u16 rx_missed; + u16 align_errors; + u32 tx_one_collision; + u32 tx_multi_collision; + u64 rx_unicast; + u64 rx_broadcast; + u32 rx_multicast; + u16 tx_aborted; +}; + enum mcfg { CFG_METHOD_1 = 1, CFG_METHOD_2, diff --git a/drivers/net/r8169/r8169_ethdev.c b/drivers/net/r8169/r8169_ethdev.c index fbe0eb2e06..f0792681a3 100644 --- a/drivers/net/r8169/r8169_ethdev.c +++ b/drivers/net/r8169/r8169_ethdev.c @@ -35,6 +35,9 @@ static int rtl_dev_set_link_up(struct rte_eth_dev *dev); static int rtl_dev_set_link_down(struct rte_eth_dev *dev); static int rtl_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); +static int rtl_dev_stats_get(struct rte_eth_dev *dev, + struct rte_eth_stats *rte_stats); +static int rtl_dev_stats_reset(struct rte_eth_dev *dev); /* * The set of PCI devices this driver supports @@ -73,6 +76,9 @@ static const struct eth_dev_ops rtl_eth_dev_ops = { .link_update = rtl_dev_link_update, + .stats_get = rtl_dev_stats_get, + .stats_reset = rtl_dev_stats_reset, + .rx_queue_setup = rtl_rx_queue_setup, .rx_queue_release = rtl_rx_queue_release, .rxq_info_get = rtl_rxq_info_get, @@ -236,6 +242,11 @@ rtl_dev_start(struct rte_eth_dev *dev) goto error; } + /* This can fail when allocating mem for tally counters */ + err = rtl_tally_init(dev); + if (err) + goto error; + /* Enable uio/vfio intr/eventfd mapping */ rte_intr_enable(intr_handle); @@ -277,6 +288,8 @@ rtl_dev_stop(struct rte_eth_dev *dev) rtl_stop_queues(dev); + rtl_tally_free(dev); + /* Clear the recorded link status */ memset(&link, 0, sizeof(link)); rte_eth_linkstatus_set(dev, &link); @@ -359,6 +372,41 @@ rtl_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) return 0; } +static int +rtl_dev_stats_reset(struct rte_eth_dev *dev) +{ + struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev); + struct rtl_hw *hw = &adapter->hw; + + rtl_clear_tally_stats(hw); + + memset(&adapter->sw_stats, 0, sizeof(adapter->sw_stats)); + + return 0; +} + +static void +rtl_sw_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) +{ + struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev); + struct rtl_sw_stats *sw_stats = &adapter->sw_stats; + + rte_stats->ibytes = sw_stats->rx_bytes; + rte_stats->obytes = sw_stats->tx_bytes; +} + +static int +rtl_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) +{ + struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev); + struct rtl_hw *hw = &adapter->hw; + + rtl_get_tally_stats(hw, rte_stats); + rtl_sw_stats_get(dev, rte_stats); + + return 0; +} + /* Return 0 means link status changed, -1 means not changed */ static int rtl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused) diff --git a/drivers/net/r8169/r8169_ethdev.h b/drivers/net/r8169/r8169_ethdev.h index ef57288be5..36bf9ec41a 100644 --- a/drivers/net/r8169/r8169_ethdev.h +++ b/drivers/net/r8169/r8169_ethdev.h @@ -45,6 +45,9 @@ struct rtl_hw { u8 mac_addr[MAC_ADDR_LEN]; u32 rx_buf_sz; + struct rtl_counters *tally_vaddr; + u64 tally_paddr; + u8 RequirePhyMdiSwapPatch; u8 NotWrMcuPatchCode; u8 HwSuppMacMcuVer; diff --git a/drivers/net/r8169/r8169_hw.c b/drivers/net/r8169/r8169_hw.c index 2a4f58732f..58c13302e3 100644 --- a/drivers/net/r8169/r8169_hw.c +++ b/drivers/net/r8169/r8169_hw.c @@ -1500,3 +1500,83 @@ rtl_rar_set(struct rtl_hw *hw, uint8_t *addr) rtl_disable_cfg9346_write(hw); } + +void +rtl_get_tally_stats(struct rtl_hw *hw, struct rte_eth_stats *rte_stats) +{ + struct rtl_counters *counters; + uint64_t paddr; + u32 cmd; + u32 wait_cnt; + + counters = hw->tally_vaddr; + paddr = hw->tally_paddr; + if (!counters) + return; + + RTL_W32(hw, CounterAddrHigh, (u64)paddr >> 32); + cmd = (u64)paddr & DMA_BIT_MASK(32); + RTL_W32(hw, CounterAddrLow, cmd); + RTL_W32(hw, CounterAddrLow, cmd | CounterDump); + + wait_cnt = 0; + while (RTL_R32(hw, CounterAddrLow) & CounterDump) { + rte_delay_us(10); + + wait_cnt++; + if (wait_cnt > 20) + break; + } + + /* RX errors */ + rte_stats->imissed = rte_le_to_cpu_64(counters->rx_missed); + rte_stats->ierrors = rte_le_to_cpu_64(counters->rx_errors); + + /* TX errors */ + rte_stats->oerrors = rte_le_to_cpu_64(counters->tx_errors); + + rte_stats->ipackets = rte_le_to_cpu_64(counters->rx_packets); + rte_stats->opackets = rte_le_to_cpu_64(counters->tx_packets); +} + +void +rtl_clear_tally_stats(struct rtl_hw *hw) +{ + if (!hw->tally_paddr) + return; + + RTL_W32(hw, CounterAddrHigh, (u64)hw->tally_paddr >> 32); + RTL_W32(hw, CounterAddrLow, + ((u64)hw->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); +} + +int +rtl_tally_init(struct rte_eth_dev *dev) +{ + struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev); + struct rtl_hw *hw = &adapter->hw; + const struct rte_memzone *mz; + + mz = rte_eth_dma_zone_reserve(dev, "tally_counters", 0, + sizeof(struct rtl_counters), 64, rte_socket_id()); + if (mz == NULL) + return -ENOMEM; + + hw->tally_vaddr = mz->addr; + hw->tally_paddr = mz->iova; + + /* Fill tally addrs */ + RTL_W32(hw, CounterAddrHigh, (u64)hw->tally_paddr >> 32); + RTL_W32(hw, CounterAddrLow, (u64)hw->tally_paddr & (DMA_BIT_MASK(32))); + + /* Reset the hw statistics */ + rtl_clear_tally_stats(hw); + + return 0; +} + +void +rtl_tally_free(struct rte_eth_dev *dev) +{ + rte_eth_dma_zone_free(dev, "tally_counters", 0); +} diff --git a/drivers/net/r8169/r8169_hw.h b/drivers/net/r8169/r8169_hw.h index e6f27531a8..9664057cf1 100644 --- a/drivers/net/r8169/r8169_hw.h +++ b/drivers/net/r8169/r8169_hw.h @@ -54,6 +54,12 @@ void rtl_rar_set(struct rtl_hw *hw, uint8_t *addr); void rtl_set_link_option(struct rtl_hw *hw, u8 autoneg, u32 speed, u8 duplex, enum rtl_fc_mode fc); +void rtl_get_tally_stats(struct rtl_hw *hw, struct rte_eth_stats *rte_stats); +void rtl_clear_tally_stats(struct rtl_hw *hw); + +int rtl_tally_init(struct rte_eth_dev *dev); +void rtl_tally_free(struct rte_eth_dev *dev); + extern const struct rtl_hw_ops rtl8125a_ops; extern const struct rtl_hw_ops rtl8125b_ops; extern const struct rtl_hw_ops rtl8125bp_ops; -- 2.34.1