numam-dpdk/drivers/net/ipn3ke/ipn3ke_representor.c
Andy Pei e579172633 net/ipn3ke: use control thread to check link status
ipn3ke driver creates a thread to check link status.

Before this patch, pthread_create() is used to create
thread, leaving the new thread unrestrained wrt cpu
affinity.

After this patch, rte_ctrl_thread_create() is used to
create thread. The affinity of the new thread is based
on the CPU affinity retrieved at the time rte_eal_init()
was called, the dataplane and service lcores are then
excluded.

Fixes: 70d6b7f550 ("net/ipn3ke: add representor")
Cc: stable@dpdk.org

Signed-off-by: Andy Pei <andy.pei@intel.com>
Reviewed-by: Rosen Xu <rosen.xu@intel.com>
2020-04-21 13:57:04 +02:00

2986 lines
84 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019 Intel Corporation
*/
#include <stdint.h>
#include <unistd.h>
#include <rte_bus_pci.h>
#include <rte_ethdev.h>
#include <rte_pci.h>
#include <rte_malloc.h>
#include <rte_mbuf.h>
#include <rte_sched.h>
#include <rte_ethdev_driver.h>
#include <rte_spinlock.h>
#include <rte_io.h>
#include <rte_rawdev.h>
#include <rte_rawdev_pmd.h>
#include <rte_bus_ifpga.h>
#include <ifpga_logs.h>
#include "ipn3ke_rawdev_api.h"
#include "ipn3ke_flow.h"
#include "ipn3ke_logs.h"
#include "ipn3ke_ethdev.h"
static int ipn3ke_rpst_scan_num;
static pthread_t ipn3ke_rpst_scan_thread;
/** Double linked list of representor port. */
TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
static struct ipn3ke_rpst_list ipn3ke_rpst_list =
TAILQ_HEAD_INITIALIZER(ipn3ke_rpst_list);
static rte_spinlock_t ipn3ke_link_notify_list_lk = RTE_SPINLOCK_INITIALIZER;
static int
ipn3ke_rpst_link_check(struct ipn3ke_rpst *rpst);
static int
ipn3ke_rpst_dev_infos_get(struct rte_eth_dev *ethdev,
struct rte_eth_dev_info *dev_info)
{
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
dev_info->speed_capa =
(hw->retimer.mac_type ==
IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) ?
ETH_LINK_SPEED_10G :
((hw->retimer.mac_type ==
IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) ?
ETH_LINK_SPEED_25G :
ETH_LINK_SPEED_AUTONEG);
dev_info->max_rx_queues = 1;
dev_info->max_tx_queues = 1;
dev_info->min_rx_bufsize = IPN3KE_AFU_BUF_SIZE_MIN;
dev_info->max_rx_pktlen = IPN3KE_AFU_FRAME_SIZE_MAX;
dev_info->max_mac_addrs = hw->port_num;
dev_info->max_vfs = 0;
dev_info->default_txconf = (struct rte_eth_txconf) {
.offloads = 0,
};
dev_info->rx_queue_offload_capa = 0;
dev_info->rx_offload_capa =
DEV_RX_OFFLOAD_VLAN_STRIP |
DEV_RX_OFFLOAD_QINQ_STRIP |
DEV_RX_OFFLOAD_IPV4_CKSUM |
DEV_RX_OFFLOAD_UDP_CKSUM |
DEV_RX_OFFLOAD_TCP_CKSUM |
DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
DEV_RX_OFFLOAD_VLAN_EXTEND |
DEV_RX_OFFLOAD_VLAN_FILTER |
DEV_RX_OFFLOAD_JUMBO_FRAME;
dev_info->tx_queue_offload_capa = DEV_TX_OFFLOAD_MBUF_FAST_FREE;
dev_info->tx_offload_capa =
DEV_TX_OFFLOAD_VLAN_INSERT |
DEV_TX_OFFLOAD_QINQ_INSERT |
DEV_TX_OFFLOAD_IPV4_CKSUM |
DEV_TX_OFFLOAD_UDP_CKSUM |
DEV_TX_OFFLOAD_TCP_CKSUM |
DEV_TX_OFFLOAD_SCTP_CKSUM |
DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
DEV_TX_OFFLOAD_TCP_TSO |
DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
DEV_TX_OFFLOAD_GRE_TNL_TSO |
DEV_TX_OFFLOAD_IPIP_TNL_TSO |
DEV_TX_OFFLOAD_GENEVE_TNL_TSO |
DEV_TX_OFFLOAD_MULTI_SEGS |
dev_info->tx_queue_offload_capa;
dev_info->dev_capa =
RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
dev_info->switch_info.name = ethdev->device->name;
dev_info->switch_info.domain_id = rpst->switch_domain_id;
dev_info->switch_info.port_id = rpst->port_id;
return 0;
}
static int
ipn3ke_rpst_dev_configure(__rte_unused struct rte_eth_dev *dev)
{
return 0;
}
static int
ipn3ke_rpst_dev_start(struct rte_eth_dev *dev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(dev);
struct rte_rawdev *rawdev;
uint64_t base_mac;
uint32_t val;
char attr_name[IPN3KE_RAWDEV_ATTR_LEN_MAX];
rawdev = hw->rawdev;
memset(attr_name, 0, sizeof(attr_name));
snprintf(attr_name, IPN3KE_RAWDEV_ATTR_LEN_MAX, "%s",
"LineSideBaseMAC");
rawdev->dev_ops->attr_get(rawdev, attr_name, &base_mac);
rte_ether_addr_copy((struct rte_ether_addr *)&base_mac,
&rpst->mac_addr);
rte_ether_addr_copy(&rpst->mac_addr, &dev->data->mac_addrs[0]);
dev->data->mac_addrs->addr_bytes[RTE_ETHER_ADDR_LEN - 1] =
(uint8_t)rpst->port_id + 1;
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Set mac address */
rte_memcpy(((char *)(&val)),
(char *)&dev->data->mac_addrs->addr_bytes[0],
sizeof(uint32_t));
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_PRIMARY_MAC_ADDR0,
rpst->port_id,
0);
rte_memcpy(((char *)(&val)),
(char *)&dev->data->mac_addrs->addr_bytes[4],
sizeof(uint16_t));
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_PRIMARY_MAC_ADDR1,
rpst->port_id,
0);
/* Enable the TX path */
ipn3ke_xmac_tx_enable(hw, rpst->port_id, 0);
/* Disables source address override */
ipn3ke_xmac_smac_ovd_dis(hw, rpst->port_id, 0);
/* Enable the RX path */
ipn3ke_xmac_rx_enable(hw, rpst->port_id, 0);
/* Clear line side TX statistics counters */
ipn3ke_xmac_tx_clr_10G_stcs(hw, rpst->port_id, 0);
/* Clear line side RX statistics counters */
ipn3ke_xmac_rx_clr_10G_stcs(hw, rpst->port_id, 0);
/* Clear NIC side TX statistics counters */
ipn3ke_xmac_tx_clr_10G_stcs(hw, rpst->port_id, 1);
/* Clear NIC side RX statistics counters */
ipn3ke_xmac_rx_clr_10G_stcs(hw, rpst->port_id, 1);
} else if (hw->retimer.mac_type ==
IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
/* Clear line side TX statistics counters */
ipn3ke_xmac_tx_clr_25G_stcs(hw, rpst->port_id, 0);
/* Clear line side RX statistics counters */
ipn3ke_xmac_rx_clr_25G_stcs(hw, rpst->port_id, 0);
/* Clear NIC side TX statistics counters */
ipn3ke_xmac_tx_clr_25G_stcs(hw, rpst->port_id, 1);
/* Clear NIC side RX statistics counters */
ipn3ke_xmac_rx_clr_25G_stcs(hw, rpst->port_id, 1);
}
ipn3ke_rpst_link_update(dev, 0);
return 0;
}
static void
ipn3ke_rpst_dev_stop(struct rte_eth_dev *dev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(dev);
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Disable the TX path */
ipn3ke_xmac_tx_disable(hw, rpst->port_id, 0);
/* Disable the RX path */
ipn3ke_xmac_rx_disable(hw, rpst->port_id, 0);
}
}
static void
ipn3ke_rpst_dev_close(struct rte_eth_dev *dev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(dev);
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Disable the TX path */
ipn3ke_xmac_tx_disable(hw, rpst->port_id, 0);
/* Disable the RX path */
ipn3ke_xmac_rx_disable(hw, rpst->port_id, 0);
}
}
/*
* Reset PF device only to re-initialize resources in PMD layer
*/
static int
ipn3ke_rpst_dev_reset(struct rte_eth_dev *dev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(dev);
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Disable the TX path */
ipn3ke_xmac_tx_disable(hw, rpst->port_id, 0);
/* Disable the RX path */
ipn3ke_xmac_rx_disable(hw, rpst->port_id, 0);
}
return 0;
}
static int
ipn3ke_rpst_rx_queue_start(__rte_unused struct rte_eth_dev *dev,
__rte_unused uint16_t rx_queue_id)
{
return 0;
}
static int
ipn3ke_rpst_rx_queue_stop(__rte_unused struct rte_eth_dev *dev,
__rte_unused uint16_t rx_queue_id)
{
return 0;
}
static int
ipn3ke_rpst_tx_queue_start(__rte_unused struct rte_eth_dev *dev,
__rte_unused uint16_t tx_queue_id)
{
return 0;
}
static int
ipn3ke_rpst_tx_queue_stop(__rte_unused struct rte_eth_dev *dev,
__rte_unused uint16_t tx_queue_id)
{
return 0;
}
static int
ipn3ke_rpst_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
__rte_unused uint16_t queue_idx, __rte_unused uint16_t nb_desc,
__rte_unused unsigned int socket_id,
__rte_unused const struct rte_eth_rxconf *rx_conf,
__rte_unused struct rte_mempool *mp)
{
return 0;
}
static void
ipn3ke_rpst_rx_queue_release(__rte_unused void *rxq)
{
}
static int
ipn3ke_rpst_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
__rte_unused uint16_t queue_idx, __rte_unused uint16_t nb_desc,
__rte_unused unsigned int socket_id,
__rte_unused const struct rte_eth_txconf *tx_conf)
{
return 0;
}
static void
ipn3ke_rpst_tx_queue_release(__rte_unused void *txq)
{
}
/* Statistics collected by each port, VSI, VEB, and S-channel */
struct ipn3ke_rpst_eth_stats {
uint64_t tx_bytes; /* gotc */
uint64_t tx_multicast; /* mptc */
uint64_t tx_broadcast; /* bptc */
uint64_t tx_unicast; /* uptc */
uint64_t tx_discards; /* tdpc */
uint64_t tx_errors; /* tepc */
uint64_t rx_bytes; /* gorc */
uint64_t rx_multicast; /* mprc */
uint64_t rx_broadcast; /* bprc */
uint64_t rx_unicast; /* uprc */
uint64_t rx_discards; /* rdpc */
uint64_t rx_unknown_protocol; /* rupp */
};
/* store statistics names and its offset in stats structure */
struct ipn3ke_rpst_xstats_name_offset {
char name[RTE_ETH_XSTATS_NAME_SIZE];
unsigned int offset;
};
static const struct ipn3ke_rpst_xstats_name_offset
ipn3ke_rpst_stats_strings[] = {
{"tx_multicast_packets", offsetof(struct ipn3ke_rpst_eth_stats,
tx_multicast)},
{"tx_broadcast_packets", offsetof(struct ipn3ke_rpst_eth_stats,
tx_broadcast)},
{"tx_unicast_packets", offsetof(struct ipn3ke_rpst_eth_stats,
tx_unicast)},
{"tx_dropped_packets", offsetof(struct ipn3ke_rpst_eth_stats,
tx_discards)},
{"rx_multicast_packets", offsetof(struct ipn3ke_rpst_eth_stats,
rx_multicast)},
{"rx_broadcast_packets", offsetof(struct ipn3ke_rpst_eth_stats,
rx_broadcast)},
{"rx_unicast_packets", offsetof(struct ipn3ke_rpst_eth_stats,
rx_unicast)},
{"rx_dropped_packets", offsetof(struct ipn3ke_rpst_eth_stats,
rx_discards)},
{"rx_unknown_protocol_packets", offsetof(struct ipn3ke_rpst_eth_stats,
rx_unknown_protocol)},
};
#define IPN3KE_RPST_ETH_XSTATS_CNT (sizeof(ipn3ke_rpst_stats_strings) / \
sizeof(ipn3ke_rpst_stats_strings[0]))
#define IPN3KE_RPST_PRIO_XSTATS_CNT 8
/* Statistics collected by the MAC */
struct ipn3ke_rpst_hw_port_stats {
/* eth stats collected by the port */
struct ipn3ke_rpst_eth_stats eth;
/* additional port specific stats */
uint64_t tx_dropped_link_down;
uint64_t crc_errors;
uint64_t illegal_bytes;
uint64_t error_bytes;
uint64_t mac_local_faults;
uint64_t mac_remote_faults;
uint64_t rx_length_errors;
uint64_t link_xon_rx;
uint64_t link_xoff_rx;
uint64_t priority_xon_rx[IPN3KE_RPST_PRIO_XSTATS_CNT];
uint64_t priority_xoff_rx[IPN3KE_RPST_PRIO_XSTATS_CNT];
uint64_t link_xon_tx;
uint64_t link_xoff_tx;
uint64_t priority_xon_tx[IPN3KE_RPST_PRIO_XSTATS_CNT];
uint64_t priority_xoff_tx[IPN3KE_RPST_PRIO_XSTATS_CNT];
uint64_t priority_xon_2_xoff[IPN3KE_RPST_PRIO_XSTATS_CNT];
uint64_t rx_size_64;
uint64_t rx_size_65_127;
uint64_t rx_size_128_255;
uint64_t rx_size_256_511;
uint64_t rx_size_512_1023;
uint64_t rx_size_1024_1518;
uint64_t rx_size_big;
uint64_t rx_undersize;
uint64_t rx_fragments;
uint64_t rx_oversize;
uint64_t rx_jabber;
uint64_t tx_size_64;
uint64_t tx_size_65_127;
uint64_t tx_size_128_255;
uint64_t tx_size_256_511;
uint64_t tx_size_512_1023;
uint64_t tx_size_1024_1518;
uint64_t tx_size_1519_to_max;
uint64_t mac_short_packet_dropped;
uint64_t checksum_error;
/* flow director stats */
uint64_t fd_atr_match;
uint64_t fd_sb_match;
uint64_t fd_atr_tunnel_match;
uint32_t fd_atr_status;
uint32_t fd_sb_status;
/* EEE LPI */
uint32_t tx_lpi_status;
uint32_t rx_lpi_status;
uint64_t tx_lpi_count;
uint64_t rx_lpi_count;
};
static const struct ipn3ke_rpst_xstats_name_offset
ipn3ke_rpst_hw_port_strings[] = {
{"tx_link_down_dropped", offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_dropped_link_down)},
{"rx_crc_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
crc_errors)},
{"rx_illegal_byte_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
illegal_bytes)},
{"rx_error_bytes", offsetof(struct ipn3ke_rpst_hw_port_stats,
error_bytes)},
{"mac_local_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
mac_local_faults)},
{"mac_remote_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
mac_remote_faults)},
{"rx_length_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_length_errors)},
{"tx_xon_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
link_xon_tx)},
{"rx_xon_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
link_xon_rx)},
{"tx_xoff_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
link_xoff_tx)},
{"rx_xoff_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
link_xoff_rx)},
{"rx_size_64_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_64)},
{"rx_size_65_to_127_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_65_127)},
{"rx_size_128_to_255_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_128_255)},
{"rx_size_256_to_511_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_256_511)},
{"rx_size_512_to_1023_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_512_1023)},
{"rx_size_1024_to_1518_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_1024_1518)},
{"rx_size_1519_to_max_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_size_big)},
{"rx_undersized_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_undersize)},
{"rx_oversize_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_oversize)},
{"rx_mac_short_dropped", offsetof(struct ipn3ke_rpst_hw_port_stats,
mac_short_packet_dropped)},
{"rx_fragmented_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_fragments)},
{"rx_jabber_errors", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_jabber)},
{"tx_size_64_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_64)},
{"tx_size_65_to_127_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_65_127)},
{"tx_size_128_to_255_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_128_255)},
{"tx_size_256_to_511_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_256_511)},
{"tx_size_512_to_1023_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_512_1023)},
{"tx_size_1024_to_1518_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_1024_1518)},
{"tx_size_1519_to_max_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_size_1519_to_max)},
{"rx_flow_director_atr_match_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
fd_atr_match)},
{"rx_flow_director_sb_match_packets",
offsetof(struct ipn3ke_rpst_hw_port_stats,
fd_sb_match)},
{"tx_low_power_idle_status", offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_lpi_status)},
{"rx_low_power_idle_status", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_lpi_status)},
{"tx_low_power_idle_count", offsetof(struct ipn3ke_rpst_hw_port_stats,
tx_lpi_count)},
{"rx_low_power_idle_count", offsetof(struct ipn3ke_rpst_hw_port_stats,
rx_lpi_count)},
};
#define IPN3KE_RPST_HW_PORT_XSTATS_CNT (sizeof(ipn3ke_rpst_hw_port_strings) \
/ sizeof(ipn3ke_rpst_hw_port_strings[0]))
static const struct ipn3ke_rpst_xstats_name_offset
ipn3ke_rpst_rxq_prio_strings[] = {
{"xon_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
priority_xon_rx)},
{"xoff_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
priority_xoff_rx)},
};
#define IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT (sizeof(ipn3ke_rpst_rxq_prio_strings) \
/ sizeof(ipn3ke_rpst_rxq_prio_strings[0]))
static const struct ipn3ke_rpst_xstats_name_offset
ipn3ke_rpst_txq_prio_strings[] = {
{"xon_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
priority_xon_tx)},
{"xoff_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
priority_xoff_tx)},
{"xon_to_xoff_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
priority_xon_2_xoff)},
};
#define IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT (sizeof(ipn3ke_rpst_txq_prio_strings) \
/ sizeof(ipn3ke_rpst_txq_prio_strings[0]))
static uint32_t
ipn3ke_rpst_xstats_calc_num(void)
{
return IPN3KE_RPST_ETH_XSTATS_CNT
+ IPN3KE_RPST_HW_PORT_XSTATS_CNT
+ (IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT
* IPN3KE_RPST_PRIO_XSTATS_CNT)
+ (IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT
* IPN3KE_RPST_PRIO_XSTATS_CNT);
}
static void
ipn3ke_rpst_25g_nic_side_tx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp = 0x00000001;
/* Bit[0]: Software can set this bit to the value of 1
* to reset all of the TX statistics registers at the same time.
* This bit is selfclearing.
*/
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
1);
while (tmp & 0x00000001) {
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
1);
if (tmp & 0x00000001)
usleep(5);
else
return;
}
}
static void
ipn3ke_rpst_25g_nic_side_rx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp = 0x00000001;
/* Bit[0]: Software can set this bit to the value of 1
* to reset all of the RX statistics registers at the same time.
* This bit is selfclearing.
*/
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
1);
while (tmp & 0x00000001) {
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
1);
if (tmp & 0x00000001)
usleep(5);
else
return;
}
}
static void
ipn3ke_rpst_10g_nic_side_tx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp;
/*Bit [0]: Set this register to 1 to clear all TX statistics
*counters.
*The IP core clears this bit when all counters are cleared.
*Bits [31:1]: Reserved.
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_10G_TX_STATS_CLR,
port_id,
1);
tmp |= 0x00000001;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_10G_TX_STATS_CLR,
port_id,
1);
}
static void
ipn3ke_rpst_10g_nic_side_rx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp;
/*Bit [0]: Set this register to 1 to clear all RX statistics
*counters.
*The IP core clears this bit when all counters are cleared.
*Bits [31:1]: Reserved
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_10G_RX_STATS_CLR,
port_id,
1);
tmp |= 0x00000001;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_10G_RX_STATS_CLR,
port_id,
1);
}
static uint64_t
ipn3ke_rpst_read_64bits_statistics_register(uint32_t addr_lo,
uint32_t addr_hi, struct ipn3ke_hw *hw, uint16_t port_id)
{
uint32_t statistics_lo = 0x00000000;
uint32_t statistics_hi = 0x00000000;
uint64_t statistics = 0x0000000000000000;
(*hw->f_mac_read)(hw,
&statistics_lo,
addr_lo,
port_id,
0);
(*hw->f_mac_read)(hw,
&statistics_hi,
addr_hi,
port_id,
0);
statistics += statistics_hi;
statistics = statistics << IPN3KE_REGISTER_WIDTH;
statistics += statistics_lo;
return statistics;
}
static int
ipn3ke_rpst_read_25g_lineside_stats_registers
(struct ipn3ke_hw *hw,
uint16_t port_id,
struct ipn3ke_rpst_hw_port_stats *hw_stats)
{
uint32_t tmp;
uint64_t statistics;
memset(hw_stats, 0, sizeof(*hw_stats));
/*check Tx statistics is real time.
*if statistics has been paused, make it real time.
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
if (tmp & IPN3KE_25G_TX_STATISTICS_CONFIG_SHADOW_REQUEST_MASK) {
tmp &= 0xfffffffb;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
}
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_STATUS,
port_id,
0);
if (tmp & IPN3KE_25G_TX_STATISTICS_STATUS_SHADOW_REQUEST_MASK) {
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
tmp &= 0xfffffffb;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
}
/*check Rx statistics is real time.
*if statistics has been paused, make it real time.
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
if (tmp & IPN3KE_25G_RX_STATISTICS_CONFIG_SHADOW_REQUEST_MASK) {
tmp &= 0xfffffffb;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
}
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_STATUS,
port_id,
0);
if (tmp & IPN3KE_25G_RX_STATISTICS_STATUS_SHADOW_REQUEST_MASK) {
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
tmp &= 0xfffffffb;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
}
/* pause Tx counter to read the statistics */
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
tmp |= 0x00000004;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
/* pause Rx counter to read the statistics */
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
tmp |= 0x00000004;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
/*Number of transmitted frames less than 64 bytes
*and reporting a CRC error
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_FRAGMENTS_LO,
IPN3KE_25G_CNTR_TX_FRAGMENTS_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
hw_stats->crc_errors += statistics;
/*Number of transmitted oversized frames reporting a CRC error*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_JABBERS_LO,
IPN3KE_25G_CNTR_TX_JABBERS_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
hw_stats->crc_errors += statistics;
/* Number of transmitted packets with FCS errors */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_FCS_LO,
IPN3KE_25G_CNTR_TX_FCS_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
hw_stats->checksum_error += statistics;
/*Number of transmitted frames with a frame of length at
*least 64 reporting a CRC error
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_CRCERR_LO,
IPN3KE_25G_CNTR_TX_CRCERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
hw_stats->crc_errors += statistics;
/*Number of errored multicast frames transmitted,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_MCAST_DATA_ERR_LO,
IPN3KE_25G_CNTR_TX_MCAST_DATA_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/*Number of errored broadcast frames transmitted,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_BCAST_DATA_ERR_LO,
IPN3KE_25G_CNTR_TX_BCAST_DATA_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/*Number of errored unicast frames transmitted,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_UCAST_DATA_ERR_LO,
IPN3KE_25G_CNTR_TX_UCAST_DATA_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/* Number of errored multicast control frames transmitted */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_MCAST_CTRL_ERR_LO,
IPN3KE_25G_CNTR_TX_MCAST_CTRL_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/* Number of errored broadcast control frames transmitted */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_BCAST_CTRL_ERR_LO,
IPN3KE_25G_CNTR_TX_BCAST_CTRL_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/* Number of errored unicast control frames transmitted */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_UCAST_CTRL_ERR_LO,
IPN3KE_25G_CNTR_TX_UCAST_CTRL_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/* Number of errored pause frames transmitted */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_PAUSE_ERR_LO,
IPN3KE_25G_CNTR_TX_PAUSE_ERR_HI,
hw, port_id);
hw_stats->eth.tx_errors += statistics;
/*Number of 64-byte transmitted frames,
*including the CRC field but excluding the preamble
*and SFD bytes
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_64B_LO,
IPN3KE_25G_CNTR_TX_64B_HI,
hw, port_id);
hw_stats->tx_size_64 += statistics;
/* Number of transmitted frames between 65 and 127 bytes */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_65_127B_LO,
IPN3KE_25G_CNTR_TX_65_127B_HI,
hw, port_id);
hw_stats->tx_size_65_127 += statistics;
/* Number of transmitted frames between 128 and 255 bytes */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_128_255B_LO,
IPN3KE_25G_CNTR_TX_128_255B_HI,
hw, port_id);
hw_stats->tx_size_128_255 += statistics;
/* Number of transmitted frames between 256 and 511 bytes */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_256_511B_LO,
IPN3KE_25G_CNTR_TX_256_511B_HI,
hw, port_id);
hw_stats->tx_size_256_511 += statistics;
/* Number of transmitted frames between 512 and 1023 bytes */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_512_1023B_LO,
IPN3KE_25G_CNTR_TX_512_1023B_HI,
hw, port_id);
hw_stats->tx_size_512_1023 += statistics;
/* Number of transmitted frames between 1024 and 1518 bytes */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_1024_1518B_LO,
IPN3KE_25G_CNTR_TX_1024_1518B_HI,
hw, port_id);
hw_stats->tx_size_1024_1518 += statistics;
/*Number of transmitted frames of size between 1519 bytes
*and the number of bytes specified in the MAX_TX_SIZE_CONFIG
*register
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_1519_MAXB_LO,
IPN3KE_25G_CNTR_TX_1519_MAXB_HI,
hw, port_id);
hw_stats->tx_size_1519_to_max += statistics;
/*Number of oversized frames (frames with more bytes than the
*number specified in the MAX_TX_SIZE_CONFIG register)
*transmitted
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_OVERSIZE_LO,
IPN3KE_25G_CNTR_TX_OVERSIZE_HI,
hw, port_id);
/*Number of valid multicast frames transmitted,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_MCAST_DATA_OK_LO,
IPN3KE_25G_CNTR_TX_MCAST_DATA_OK_HI,
hw, port_id);
hw_stats->eth.tx_multicast += statistics;
/*Number of valid broadcast frames transmitted,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_BCAST_DATA_OK_LO,
IPN3KE_25G_CNTR_TX_BCAST_DATA_OK_HI,
hw, port_id);
hw_stats->eth.tx_broadcast += statistics;
/*Number of valid unicast frames transmitted,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_UCAST_DATA_OK_LO,
IPN3KE_25G_CNTR_TX_UCAST_DATA_OK_HI,
hw, port_id);
hw_stats->eth.tx_unicast += statistics;
/*Number of valid multicast frames transmitted,
*excluding data frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_MCAST_CTRL_LO,
IPN3KE_25G_CNTR_TX_MCAST_CTRL_HI,
hw, port_id);
hw_stats->eth.tx_multicast += statistics;
/*Number of valid broadcast frames transmitted,
*excluding data frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_BCAST_CTRL_LO,
IPN3KE_25G_CNTR_TX_BCAST_CTRL_HI,
hw, port_id);
hw_stats->eth.tx_broadcast += statistics;
/*Number of valid unicast frames transmitted,
*excluding data frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_UCAST_CTRL_LO,
IPN3KE_25G_CNTR_TX_UCAST_CTRL_HI,
hw, port_id);
hw_stats->eth.tx_unicast += statistics;
/* Number of valid pause frames transmitted */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_PAUSE_LO,
IPN3KE_25G_CNTR_TX_PAUSE_HI,
hw, port_id);
/*Number of transmitted runt packets. The IP core does not
*transmit frames of length less than nine bytes.
*The IP core pads frames of length nine bytes to 64 bytes to
*extend them to 64 bytes. Therefore, this counter does not
*increment in normal operating conditions.
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_TX_RUNT_LO,
IPN3KE_25G_CNTR_TX_RUNT_HI,
hw, port_id);
/*Number of transmitted payload bytes in frames with no FCS,
*undersized, oversized, or payload length errors.
*If VLAN detection is turned off for the TX MAC (bit[1]
*of the TX_MAC_CONTROL register at offset 0x40A has
*the value of 1), the IP core counts the VLAN header bytes
*(4 bytes for VLAN and 8 bytes for stacked VLAN)
*as payload bytes. This register is compliant with
*the requirements for aOctetsTransmittedOK in section
*5.2.2.1.8 of the IEEE Standard 802.3-2008.
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_TX_PAYLOAD_OCTETS_OK_LO,
IPN3KE_25G_TX_PAYLOAD_OCTETS_OK_HI,
hw, port_id);
hw_stats->eth.tx_bytes += statistics;
/*Number of transmitted bytes in frames with no FCS, undersized,
*oversized, or payload length errors. This register is
*compliant with the requirements for ifOutOctets in RFC3635
*(Managed Objects for Ethernet-like Interface Types)
*and TX etherStatsOctets in RFC2819(Remote Network Monitoring
*Management Information Base (RMON)).
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_TX_FRAME_OCTETS_OK_LO,
IPN3KE_25G_TX_FRAME_OCTETS_OK_HI,
hw, port_id);
/*Number of received frames less than 64 bytes
*and reporting a CRC error
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_FRAGMENTS_LO,
IPN3KE_25G_CNTR_RX_FRAGMENTS_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
hw_stats->crc_errors += statistics;
hw_stats->rx_length_errors += statistics;
/* Number of received oversized frames reporting a CRC error */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_JABBERS_LO,
IPN3KE_25G_CNTR_RX_JABBERS_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
hw_stats->crc_errors += statistics;
hw_stats->rx_length_errors += statistics;
/*Number of received packets with FCS errors.
*This register maintains a count of the number of pulses
*on the "l<n>_rx_fcs_error" or "rx_fcs_error" output signal
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_FCS_LO,
IPN3KE_25G_CNTR_RX_FCS_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
hw_stats->checksum_error += statistics;
/*Number of received frames with a frame of length at least 64
*with CRC error
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_CRCERR_LO,
IPN3KE_25G_CNTR_RX_CRCERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
hw_stats->crc_errors += statistics;
/*Number of errored multicast frames received,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_MCAST_DATA_ERR_LO,
IPN3KE_25G_CNTR_RX_MCAST_DATA_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/*Number of errored broadcast frames received,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_BCAST_DATA_ERR_LO,
IPN3KE_25G_CNTR_RX_BCAST_DATA_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/*Number of errored unicast frames received,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_UCAST_DATA_ERR_LO,
IPN3KE_25G_CNTR_RX_UCAST_DATA_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/* Number of errored multicast control frames received */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_MCAST_CTRL_ERR_LO,
IPN3KE_25G_CNTR_RX_MCAST_CTRL_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/* Number of errored broadcast control frames received */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_BCAST_CTRL_ERR_LO,
IPN3KE_25G_CNTR_RX_BCAST_CTRL_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/* Number of errored unicast control frames received */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_UCAST_CTRL_ERR_LO,
IPN3KE_25G_CNTR_RX_UCAST_CTRL_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/* Number of errored pause frames received */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_PAUSE_ERR_LO,
IPN3KE_25G_CNTR_RX_PAUSE_ERR_HI,
hw, port_id);
hw_stats->eth.rx_discards += statistics;
/*Number of 64-byte received frames,
*including the CRC field but excluding the preamble
*and SFD bytes
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_64B_LO,
IPN3KE_25G_CNTR_RX_64B_HI,
hw, port_id);
hw_stats->rx_size_64 += statistics;
/*Number of received frames between 65 and 127 bytes */
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_65_127B_LO,
IPN3KE_25G_CNTR_RX_65_127B_HI,
hw, port_id);
hw_stats->rx_size_65_127 += statistics;
/*Number of received frames between 128 and 255 bytes
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_128_255B_LO,
IPN3KE_25G_CNTR_RX_128_255B_HI,
hw, port_id);
hw_stats->rx_size_128_255 += statistics;
/*Number of received frames between 256 and 511 bytes
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_256_511B_LO,
IPN3KE_25G_CNTR_RX_256_511B_HI,
hw, port_id);
hw_stats->rx_size_256_511 += statistics;
/*Number of received frames between 512 and 1023 bytes
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_512_1023B_LO,
IPN3KE_25G_CNTR_RX_512_1023B_HI,
hw, port_id);
hw_stats->rx_size_512_1023 += statistics;
/*Number of received frames between 1024 and 1518 bytes
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_1024_1518B_LO,
IPN3KE_25G_CNTR_RX_1024_1518B_HI,
hw, port_id);
hw_stats->rx_size_1024_1518 += statistics;
/*Number of received frames of size between 1519 bytes
*and the number of bytes specified in the MAX_TX_SIZE_CONFIG
*register
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_1519_MAXB_LO,
IPN3KE_25G_CNTR_RX_1519_MAXB_HI,
hw, port_id);
hw_stats->rx_size_big += statistics;
/*Number of oversized frames (frames with more bytes
*than the number specified in the MAX_TX_SIZE_CONFIG register)
*received
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_OVERSIZE_LO,
IPN3KE_25G_CNTR_RX_OVERSIZE_HI,
hw, port_id);
hw_stats->rx_jabber += statistics;
/*Number of valid multicast frames received,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_MCAST_DATA_OK_LO,
IPN3KE_25G_CNTR_RX_MCAST_DATA_OK_HI,
hw, port_id);
hw_stats->eth.rx_multicast += statistics;
/*Number of valid broadcast frames received,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_BCAST_DATA_OK_LO,
IPN3KE_25G_CNTR_RX_BCAST_DATA_OK_HI,
hw, port_id);
hw_stats->eth.rx_broadcast += statistics;
/*Number of valid unicast frames received,
*excluding control frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_UCAST_DATA_OK_LO,
IPN3KE_25G_CNTR_RX_UCAST_DATA_OK_HI,
hw, port_id);
hw_stats->eth.rx_unicast += statistics;
/*Number of valid multicast frames received,
*excluding data frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_MCAST_CTRL_LO,
IPN3KE_25G_CNTR_RX_MCAST_CTRL_HI,
hw, port_id);
hw_stats->eth.rx_multicast += statistics;
/*Number of valid broadcast frames received,
*excluding data frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_BCAST_CTRL_LO,
IPN3KE_25G_CNTR_RX_BCAST_CTRL_HI,
hw, port_id);
hw_stats->eth.rx_broadcast += statistics;
/*Number of valid unicast frames received,
*excluding data frames
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_UCAST_CTRL_LO,
IPN3KE_25G_CNTR_RX_UCAST_CTRL_HI,
hw, port_id);
hw_stats->eth.rx_unicast += statistics;
/*Number of received pause frames, with or without error
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_PAUSE_LO,
IPN3KE_25G_CNTR_RX_PAUSE_HI,
hw, port_id);
/*Number of received runt packets. A runt is a packet of size
*less than 64 bytes but greater than eight bytes.
*If a packet is eight bytes or smaller, it is considered
*a decoding error and not a runt frame, and the IP core
*does not flag it nor count it as a runt.
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_CNTR_RX_RUNT_LO,
IPN3KE_25G_CNTR_RX_RUNT_HI,
hw, port_id);
/*Number of received payload bytes in frames with no FCS,
*undersized, oversized, or payload length errors.
*If VLAN detection is turned off for the RX MAC (bit [1] of the
*"RXMAC_CONTROL" register at offset 0x50A has the value of 1),
*the IP core counts the VLAN header bytes (4 bytes for VLAN and
*8 bytes for stacked VLAN) as payload bytes.
*This register is compliant with the requirements for
*aOctetsReceivedOK in section 5.2.2.1.14 of the IEEE Standard
*802.3-2008
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_RX_PAYLOAD_OCTETS_OK_LO,
IPN3KE_25G_RX_PAYLOAD_OCTETS_OK_HI,
hw, port_id);
hw_stats->eth.rx_bytes += statistics;
/*Number of received bytes in frames with no FCS, undersized,
*oversized, or payload length errors.
*This register is compliant with the requirements for
*ifInOctets in RFC3635 (Managed Objects for Ethernet-like
*Interface Types) and RX etherStatsOctets in RFC2819
*(Remote Network Monitoring Management Information Base
*(RMON)).
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_25G_RX_FRAME_OCTETS_OK_LO,
IPN3KE_25G_RX_FRAME_OCTETS_OK_HI,
hw, port_id);
/*resume Tx counter to real time
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
tmp &= 0xfffffffb;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
/*resume Rx counter to real time
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
tmp &= 0xfffffffb;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
return 0;
}
static void
ipn3ke_rpst_25g_lineside_tx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp = 0x00000001;
/* Bit[0]: Software can set this bit to the value of 1
* to reset all of the TX statistics registers at the same time.
* This bit is selfclearing.
*/
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
while (tmp & 0x00000001) {
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_TX_STATISTICS_CONFIG,
port_id,
0);
if (tmp & 0x00000001)
usleep(5);
else
return;
}
}
static void
ipn3ke_rpst_25g_lineside_rx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp = 0x00000001;
/* Bit[0]: Software can set this bit to the value of 1
* to reset all of the RX statistics registers at the same time.
* This bit is selfclearing.
*/
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
while (tmp & 0x00000001) {
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_25G_RX_STATISTICS_CONFIG,
port_id,
0);
if (tmp & 0x00000001)
usleep(5);
else
return;
}
}
static uint64_t
ipn3ke_rpst_read_36bits_statistics_register(uint32_t addr_lo,
uint32_t addr_hi, struct ipn3ke_hw *hw, uint16_t port_id)
{
uint32_t statistics_lo = 0x00000000;
uint32_t statistics_hi = 0x00000000;
uint64_t statistics = 0x0000000000000000;
(*hw->f_mac_read)(hw,
&statistics_lo,
addr_lo,
port_id,
0);
(*hw->f_mac_read)(hw,
&statistics_hi,
addr_hi,
port_id,
0);
statistics_hi &= IPN3KE_10G_STATS_HI_VALID_MASK;
statistics += statistics_hi;
statistics = statistics << IPN3KE_REGISTER_WIDTH;
statistics += statistics_lo;
return statistics;
}
static int
ipn3ke_rpst_read_10g_lineside_stats_registers
(struct ipn3ke_hw *hw,
uint16_t port_id,
struct ipn3ke_rpst_hw_port_stats *hw_stats,
struct rte_eth_stats *stats)
{
uint64_t statistics = 0;
memset(hw_stats, 0, sizeof(*hw_stats));
memset(stats, 0, sizeof(*stats));
/*36-bit statistics counter that collects the number of frames
*that are successfully transmitted, including control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_FRAME_OK_LO,
IPN3KE_10G_TX_STATS_FRAME_OK_HI,
hw, port_id);
stats->opackets = statistics;
/*36-bit statistics counter that collects the number of frames
*that are successfully received, including control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_FRAME_OK_LO,
IPN3KE_10G_RX_STATS_FRAME_OK_HI,
hw, port_id);
stats->ipackets = statistics;
/*36-bit statistics counter that collects the number of frames
*transmitted with error, including control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_FRAME_ERR_LO,
IPN3KE_10G_TX_STATS_FRAME_ERR_HI,
hw, port_id);
stats->oerrors = statistics;
hw_stats->eth.tx_errors = statistics;
/*36-bit statistics counter that collects the number of frames
*received with error, including control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_FRAME_ERR_LO,
IPN3KE_10G_RX_STATS_FRAME_ERR_HI,
hw, port_id);
stats->ierrors = statistics;
hw_stats->eth.rx_discards = statistics;
/*36-bit statistics counter that collects the number
*of RX frames with CRC error.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_FRAME_CRC_ERR_LO,
IPN3KE_10G_RX_STATS_FRAME_CRC_ERR_HI,
hw, port_id);
hw_stats->crc_errors = statistics;
/*64-bit statistics counter that collects the payload length,
*including the bytes in control frames.
*The payload length is the number of data and padding bytes
*transmitted.
*If the tx_vlan_detection[0] register bit is set to 1,
*the VLAN and stacked VLAN tags are counted as part of
*the TX payload.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_OCTETS_OK_LO,
IPN3KE_10G_TX_STATS_OCTETS_OK_HI,
hw, port_id);
stats->obytes = statistics;
hw_stats->eth.tx_bytes = statistics;
/*64-bit statistics counter that collects the payload length,
*including the bytes in control frames.
*The payload length is the number of data and padding bytes
*received.
*If the rx_vlan_detection[0] register bit is set to 1,
*the VLAN and stacked VLAN tags are counted as part of
*the RX payload.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_OCTETS_OK_LO,
IPN3KE_10G_RX_STATS_OCTETS_OK_HI,
hw, port_id);
stats->ibytes = statistics;
hw_stats->eth.rx_bytes = statistics;
/*36-bit statistics counter that collects the number of
*valid pause frames transmitted.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_PAUSE_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_TX_STATS_PAUSE_MAC_CTRL_FRAMES_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*valid pause frames received.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_PAUSE_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_RX_STATS_PAUSE_MAC_CTRL_FRAMES_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of frames
*transmitted that are invalid and with error.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_IF_ERRORS_LO,
IPN3KE_10G_TX_STATS_IF_ERRORS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of frames
*received that are invalid and with error.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_IF_ERRORS_LO,
IPN3KE_10G_RX_STATS_IF_ERRORS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*good unicast frames transmitted,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_UNICAST_FRAME_OK_LO,
IPN3KE_10G_TX_STATS_UNICAST_FRAME_OK_HI,
hw, port_id);
hw_stats->eth.tx_unicast = statistics;
/*36-bit statistics counter that collects the number of
*good unicast frames received,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_UNICAST_FRAME_OK_LO,
IPN3KE_10G_RX_STATS_UNICAST_FRAME_OK_HI,
hw, port_id);
hw_stats->eth.rx_unicast = statistics;
/*36-bit statistics counter that collects the number of
*unicast frames transmitted with error,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_UNICAST_FRAME_ERR_LO,
IPN3KE_10G_TX_STATS_UNICAST_FRAME_ERR_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*unicast frames received with error,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_UNICAST_FRAME_ERR_LO,
IPN3KE_10G_RX_STATS_UNICAST_FRAME_ERR_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*good multicast frames transmitted,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_MULTICAST_FRAME_OK_LO,
IPN3KE_10G_TX_STATS_MULTICAST_FRAME_OK_HI,
hw, port_id);
hw_stats->eth.tx_multicast = statistics;
/*36-bit statistics counter that collects the number of
*good multicast frames received,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_MULTICAST_FRAME_OK_LO,
IPN3KE_10G_RX_STATS_MULTICAST_FRAME_OK_HI,
hw, port_id);
hw_stats->eth.rx_multicast = statistics;
/*36-bit statistics counter that collects the number of
*multicast frames transmitted with error,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_MULTICAST_FRAME_ERR_LO,
IPN3KE_10G_TX_STATS_MULTICAST_FRAME_ERR_HI,
hw, port_id);
/*36-bit statistics counter that collects the number
*of multicast frames received with error,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_MULTICAST_FRAME_ERR_LO,
IPN3KE_10G_RX_STATS_MULTICAST_FRAME_ERR_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*good broadcast frames transmitted,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_BROADCAST_FRAME_OK_LO,
IPN3KE_10G_TX_STATS_BROADCAST_FRAME_OK_HI,
hw, port_id);
hw_stats->eth.tx_broadcast = statistics;
/*36-bit statistics counter that collects the number of
*good broadcast frames received,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_BROADCAST_FRAME_OK_LO,
IPN3KE_10G_RX_STATS_BROADCAST_FRAME_OK_HI,
hw, port_id);
hw_stats->eth.rx_broadcast = statistics;
/*36-bit statistics counter that collects the number
*of broadcast frames transmitted with error,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_BROADCAST_FRAME_ERR_LO,
IPN3KE_10G_TX_STATS_BROADCAST_FRAME_ERR_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*broadcast frames received with error,
*excluding control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_BROADCAST_FRAME_ERR_LO,
IPN3KE_10G_RX_STATS_BROADCAST_FRAME_ERR_HI,
hw, port_id);
/*64-bit statistics counter that collects the total number of
*octets transmitted.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_OCTETS_HI,
hw, port_id);
/*64-bit statistics counter that collects the total number of
*octets received.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_64bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_OCTETS_HI,
hw, port_id);
/*36-bit statistics counter that collects the total number of
*good, errored, and invalid frames transmitted.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_HI,
hw, port_id);
/*36-bit statistics counter that collects the total number of
*good, errored, and invalid frames received.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*undersized TX frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*undersized RX frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_HI,
hw, port_id);
hw_stats->rx_undersize = statistics;
/*36-bit statistics counter that collects the number of
*TX frames whose length exceeds the maximum frame length
*specified.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_OVER_SIZE_PKTS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_OVER_SIZE_PKTS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*RX frames whose length exceeds the maximum frame length
*specified.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_OVER_SIZE_PKTS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_OVER_SIZE_PKTS_HI,
hw, port_id);
hw_stats->rx_oversize = statistics;
/*36-bit statistics counter that collects the number of
*64-byte TX frames,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_64_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_64_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_64 = statistics;
/*36-bit statistics counter that collects the number of
*64-byte RX frames,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_64_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_64_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_64 = statistics;
/*36-bit statistics counter that collects the number of
*TX frames between the length of 65 and 127 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_65_127 = statistics;
/*36-bit statistics counter that collects the number of
*RX frames between the length of 65 and 127 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_65_127 = statistics;
/*36-bit statistics counter that collects the number of
*TX frames between the length of 128 and 255 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_128_255 = statistics;
/*36-bit statistics counter that collects the number of
*RX frames between the length of 128 and 255 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_128_255 = statistics;
/*36-bit statistics counter that collects the number of
*TX frames between the length of 256 and 511 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_256_511 = statistics;
/*36-bit statistics counter that collects the number of
*RX frames between the length of 256 and 511 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_256_511 = statistics;
/*36-bit statistics counter that collects the number of
*TX frames between the length of 512 and 1023 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_512_1023 = statistics;
/*36-bit statistics counter that collects the number of
*RX frames between the length of 512 and 1023 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_512_1023 = statistics;
/*36-bit statistics counter that collects the number of
*TX frames between the length of 1024 and 1518 bytes,
*including the CRC field but
*excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_1024_1518 = statistics;
/*36-bit statistics counter that collects the number of
*RX frames between the length of 1024 and 1518 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_1024_1518 = statistics;
/*36-bit statistics counter that collects the number of
*TX frames equal or more than the length of 1,519 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good, errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_LO,
IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_HI,
hw, port_id);
hw_stats->tx_size_1519_to_max = statistics;
/*36-bit statistics counter that collects the number of
*RX frames equal or more than the length of 1,519 bytes,
*including the CRC field
*but excluding the preamble and SFD bytes.
*This count includes good,
*errored, and invalid frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_HI,
hw, port_id);
hw_stats->rx_size_big = statistics;
/*36-bit statistics counter that collects the total number of
*RX frames with length less than 64 bytes and CRC error.
*The MAC does not drop these frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_FRAGMENTS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_FRAGMENTS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*oversized RX frames with CRC error.
*The MAC does not drop these frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_JABBERS_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_JABBERS_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*RX frames with CRC error,
*whose length is between 64 and the maximum frame length
*specified in the register.
*The MAC does not drop these frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_ETHER_STATS_CRC_ERR_LO,
IPN3KE_10G_RX_STATS_ETHER_STATS_CRC_ERR_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*valid TX unicast control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_UNICAST_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_TX_STATS_UNICAST_MAC_CTRL_FRAMES_HI,
hw, port_id);
hw_stats->eth.tx_unicast += statistics;
/*36-bit statistics counter that collects the number of
*valid RX unicast control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_UNICAST_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_RX_STATS_UNICAST_MAC_CTRL_FRAMES_HI,
hw, port_id);
hw_stats->eth.rx_unicast += statistics;
/*36-bit statistics counter that collects the number of
*valid TX multicast control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_MULTICAST_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_TX_STATS_MULTICAST_MAC_CTRL_FRAMES_HI,
hw, port_id);
hw_stats->eth.tx_multicast += statistics;
/*36-bit statistics counter that collects the number of
*valid RX multicast control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_MULTICAST_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_RX_STATS_MULTICAST_MAC_CTRL_FRAMES_HI,
hw, port_id);
hw_stats->eth.rx_multicast += statistics;
/*36-bit statistics counter that collects the number of
*valid TX broadcast control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_BROADCAST_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_TX_STATS_BROADCAST_MAC_CTRL_FRAMES_HI,
hw, port_id);
hw_stats->eth.tx_broadcast += statistics;
/*36-bit statistics counter that collects the number of
*valid RX broadcast control frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_BROADCAST_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_RX_STATS_BROADCAST_MAC_CTRL_FRAMES_HI,
hw, port_id);
hw_stats->eth.rx_broadcast += statistics;
/*36-bit statistics counter that collects the number of
*valid TX PFC frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_TX_STATS_PFC_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_TX_STATS_PFC_MAC_CTRL_FRAMES_HI,
hw, port_id);
/*36-bit statistics counter that collects the number of
*valid RX PFC frames.
*/
statistics = ipn3ke_rpst_read_36bits_statistics_register(
IPN3KE_10G_RX_STATS_PFC_MAC_CTRL_FRAMES_LO,
IPN3KE_10G_RX_STATS_PFC_MAC_CTRL_FRAMES_HI,
hw, port_id);
return 0;
}
static void
ipn3ke_rpst_10g_lineside_tx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp;
/*Bit [0]: Set this register to 1 to clear all TX statistics
*counters.
*The IP core clears this bit when all counters are cleared.
*Bits [31:1]: Reserved.
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_10G_TX_STATS_CLR,
port_id,
0);
tmp |= 0x00000001;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_10G_TX_STATS_CLR,
port_id,
0);
}
static void
ipn3ke_rpst_10g_lineside_rx_stats_reset(struct ipn3ke_hw *hw,
uint16_t port_id)
{
uint32_t tmp;
/*Bit [0]: Set this register to 1 to clear all RX statistics
*counters.
*The IP core clears this bit when all counters are cleared.
*Bits [31:1]: Reserved
*/
tmp = 0x00000000;
(*hw->f_mac_read)(hw,
&tmp,
IPN3KE_10G_RX_STATS_CLR,
port_id,
0);
tmp |= 0x00000001;
(*hw->f_mac_write)(hw,
tmp,
IPN3KE_10G_RX_STATS_CLR,
port_id,
0);
}
static int
ipn3ke_rpst_stats_reset(struct rte_eth_dev *ethdev)
{
uint16_t port_id = 0;
char *ch;
int cnt = 0;
struct rte_afu_device *afu_dev = NULL;
struct ipn3ke_hw *hw = NULL;
if (!ethdev) {
IPN3KE_AFU_PMD_ERR("ethernet device to reset is NULL!");
return -EINVAL;
}
afu_dev = RTE_ETH_DEV_TO_AFU(ethdev);
if (!afu_dev) {
IPN3KE_AFU_PMD_ERR("afu device to reset is NULL!");
return -EINVAL;
}
if (!afu_dev->shared.data) {
IPN3KE_AFU_PMD_ERR("hardware data to reset is NULL!");
return -EINVAL;
}
hw = afu_dev->shared.data;
ch = ethdev->data->name;
if (!ch) {
IPN3KE_AFU_PMD_ERR("ethdev name is NULL!");
return -EINVAL;
}
while (ch) {
if (*ch == '_')
cnt++;
ch++;
if (cnt == 3)
break;
}
if (!ch) {
IPN3KE_AFU_PMD_ERR("Can not get port_id from ethdev name!");
return -EINVAL;
}
port_id = atoi(ch);
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
ipn3ke_rpst_25g_nic_side_tx_stats_reset(hw, port_id);
ipn3ke_rpst_25g_nic_side_rx_stats_reset(hw, port_id);
ipn3ke_rpst_25g_lineside_tx_stats_reset(hw, port_id);
ipn3ke_rpst_25g_lineside_rx_stats_reset(hw, port_id);
} else if (hw->retimer.mac_type ==
IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
ipn3ke_rpst_10g_nic_side_tx_stats_reset(hw, port_id);
ipn3ke_rpst_10g_nic_side_rx_stats_reset(hw, port_id);
ipn3ke_rpst_10g_lineside_tx_stats_reset(hw, port_id);
ipn3ke_rpst_10g_lineside_rx_stats_reset(hw, port_id);
}
return 0;
}
static int
ipn3ke_rpst_stats_get
(struct rte_eth_dev *ethdev, struct rte_eth_stats *stats)
{
uint16_t port_id = 0;
char *ch;
int cnt = 0;
int i = 0;
struct rte_afu_device *afu_dev = NULL;
struct ipn3ke_hw *hw = NULL;
struct ipn3ke_rpst_hw_port_stats hw_stats;
if (!ethdev) {
IPN3KE_AFU_PMD_ERR("ethernet device to get statistics is NULL");
return -EINVAL;
}
if (!stats) {
IPN3KE_AFU_PMD_ERR("Address to return statistics is NULL!");
return -EINVAL;
}
afu_dev = RTE_ETH_DEV_TO_AFU(ethdev);
if (!afu_dev) {
IPN3KE_AFU_PMD_ERR("afu device to get statistics is NULL!");
return -EINVAL;
}
if (!afu_dev->shared.data) {
IPN3KE_AFU_PMD_ERR("hardware data to get statistics is NULL!");
return -EINVAL;
}
hw = afu_dev->shared.data;
ch = ethdev->data->name;
if (!ch) {
IPN3KE_AFU_PMD_ERR("ethdev name is NULL!");
return -EINVAL;
}
while (ch) {
if (*ch == '_')
cnt++;
ch++;
if (cnt == 3)
break;
}
if (!ch) {
IPN3KE_AFU_PMD_ERR("Can not get port_id from ethdev name!");
return -EINVAL;
}
port_id = atoi(ch);
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
ipn3ke_rpst_read_25g_lineside_stats_registers(hw,
port_id,
&hw_stats);
stats->ipackets = hw_stats.rx_size_64
+ hw_stats.rx_size_65_127
+ hw_stats.rx_size_128_255
+ hw_stats.rx_size_256_511
+ hw_stats.rx_size_512_1023
+ hw_stats.rx_size_1024_1518
+ hw_stats.rx_size_big
+ hw_stats.rx_undersize
+ hw_stats.rx_fragments
+ hw_stats.rx_oversize
+ hw_stats.rx_jabber;
stats->opackets = hw_stats.tx_size_64
+ hw_stats.tx_size_65_127
+ hw_stats.tx_size_128_255
+ hw_stats.tx_size_256_511
+ hw_stats.tx_size_512_1023
+ hw_stats.tx_size_1024_1518
+ hw_stats.tx_size_1519_to_max;
stats->ibytes = hw_stats.eth.rx_bytes;
stats->obytes = hw_stats.eth.tx_bytes;
stats->imissed = 0;
stats->ierrors = hw_stats.eth.rx_discards
+ hw_stats.eth.rx_unknown_protocol;
stats->oerrors = hw_stats.eth.tx_discards
+ hw_stats.eth.tx_errors;
stats->rx_nombuf = 0;
for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
stats->q_ipackets[i] = 0;
stats->q_opackets[i] = 0;
stats->q_ibytes[i] = 0;
stats->q_obytes[i] = 0;
stats->q_errors[i] = 0;
}
} else {
ipn3ke_rpst_read_10g_lineside_stats_registers(hw,
port_id,
&hw_stats,
stats);
}
return 0;
}
static int
ipn3ke_rpst_xstats_get
(struct rte_eth_dev *ethdev, struct rte_eth_xstat *xstats, unsigned int n)
{
uint16_t port_id = 0;
char *ch = NULL;
int cnt = 0;
unsigned int i, count, prio;
struct rte_afu_device *afu_dev = NULL;
struct ipn3ke_hw *hw = NULL;
struct ipn3ke_rpst_hw_port_stats hw_stats;
struct rte_eth_stats stats;
if (!xstats)
return 0;
if (!ethdev) {
IPN3KE_AFU_PMD_ERR("ethernet device to get statistics is NULL");
return -EINVAL;
}
afu_dev = RTE_ETH_DEV_TO_AFU(ethdev);
if (!afu_dev) {
IPN3KE_AFU_PMD_ERR("afu device to get statistics is NULL!");
return -EINVAL;
}
if (!afu_dev->shared.data) {
IPN3KE_AFU_PMD_ERR("hardware data to get statistics is NULL!");
return -EINVAL;
}
hw = afu_dev->shared.data;
ch = ethdev->data->name;
if (!ch) {
IPN3KE_AFU_PMD_ERR("ethdev name is NULL!");
return -EINVAL;
}
while (ch) {
if (*ch == '_')
cnt++;
ch++;
if (cnt == 3)
break;
}
if (!ch) {
IPN3KE_AFU_PMD_ERR("Can not get port_id from ethdev name!");
return -EINVAL;
}
port_id = atoi(ch);
count = ipn3ke_rpst_xstats_calc_num();
if (n < count)
return count;
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
ipn3ke_rpst_read_25g_lineside_stats_registers(hw,
port_id,
&hw_stats);
} else {
ipn3ke_rpst_read_10g_lineside_stats_registers(hw,
port_id,
&hw_stats,
&stats);
}
count = 0;
/* Get stats from ipn3ke_rpst_stats */
for (i = 0; i < IPN3KE_RPST_ETH_XSTATS_CNT; i++) {
xstats[count].value = *(uint64_t *)(((char *)&hw_stats.eth)
+ ipn3ke_rpst_stats_strings[i].offset);
xstats[count].id = count;
count++;
}
/* Get individiual stats from ipn3ke_rpst_hw_port */
for (i = 0; i < IPN3KE_RPST_HW_PORT_XSTATS_CNT; i++) {
xstats[count].value = *(uint64_t *)(((char *)(&hw_stats)) +
ipn3ke_rpst_hw_port_strings[i].offset);
xstats[count].id = count;
count++;
}
/* Get individiual stats from ipn3ke_rpst_rxq_pri */
for (i = 0; i < IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT; i++) {
for (prio = 0; prio < IPN3KE_RPST_PRIO_XSTATS_CNT; prio++) {
xstats[count].value =
*(uint64_t *)(((char *)(&hw_stats)) +
ipn3ke_rpst_rxq_prio_strings[i].offset +
(sizeof(uint64_t) * prio));
xstats[count].id = count;
count++;
}
}
/* Get individiual stats from ipn3ke_rpst_txq_prio */
for (i = 0; i < IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT; i++) {
for (prio = 0; prio < IPN3KE_RPST_PRIO_XSTATS_CNT; prio++) {
xstats[count].value =
*(uint64_t *)(((char *)(&hw_stats)) +
ipn3ke_rpst_txq_prio_strings[i].offset +
(sizeof(uint64_t) * prio));
xstats[count].id = count;
count++;
}
}
return count;
}
static int
ipn3ke_rpst_xstats_get_names
(__rte_unused struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names,
__rte_unused unsigned int limit)
{
unsigned int count = 0;
unsigned int i, prio;
if (!xstats_names)
return ipn3ke_rpst_xstats_calc_num();
/* Note: limit checked in rte_eth_xstats_names() */
/* Get stats from ipn3ke_rpst_stats */
for (i = 0; i < IPN3KE_RPST_ETH_XSTATS_CNT; i++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s",
ipn3ke_rpst_stats_strings[i].name);
count++;
}
/* Get individiual stats from ipn3ke_rpst_hw_port */
for (i = 0; i < IPN3KE_RPST_HW_PORT_XSTATS_CNT; i++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s",
ipn3ke_rpst_hw_port_strings[i].name);
count++;
}
/* Get individiual stats from ipn3ke_rpst_rxq_pri */
for (i = 0; i < IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT; i++) {
for (prio = 0; prio < 8; prio++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"rx_priority%u_%s",
prio,
ipn3ke_rpst_rxq_prio_strings[i].name);
count++;
}
}
/* Get individiual stats from ipn3ke_rpst_txq_prio */
for (i = 0; i < IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT; i++) {
for (prio = 0; prio < 8; prio++) {
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"tx_priority%u_%s",
prio,
ipn3ke_rpst_txq_prio_strings[i].name);
count++;
}
}
return count;
}
static void
ipn3ke_update_link(struct rte_rawdev *rawdev,
uint16_t port, struct rte_eth_link *link)
{
uint64_t line_link_bitmap = 0;
enum ifpga_rawdev_link_speed link_speed;
rawdev->dev_ops->attr_get(rawdev,
"LineSideLinkStatus",
(uint64_t *)&line_link_bitmap);
/* Parse the link status */
if ((1 << port) & line_link_bitmap)
link->link_status = 1;
else
link->link_status = 0;
IPN3KE_AFU_PMD_DEBUG("port is %d\n", port);
IPN3KE_AFU_PMD_DEBUG("link->link_status is %d\n", link->link_status);
rawdev->dev_ops->attr_get(rawdev,
"LineSideLinkSpeed",
(uint64_t *)&link_speed);
switch (link_speed) {
case IFPGA_RAWDEV_LINK_SPEED_10GB:
link->link_speed = ETH_SPEED_NUM_10G;
break;
case IFPGA_RAWDEV_LINK_SPEED_25GB:
link->link_speed = ETH_SPEED_NUM_25G;
break;
default:
IPN3KE_AFU_PMD_ERR("Unknown link speed info %u", link_speed);
break;
}
}
/*
* Set device link up.
*/
int
ipn3ke_rpst_dev_set_link_up(struct rte_eth_dev *dev)
{
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(dev);
struct rte_eth_dev *pf;
int ret = 0;
if (rpst->i40e_pf_eth) {
ret = rte_eth_dev_set_link_up(rpst->i40e_pf_eth_port_id);
pf = rpst->i40e_pf_eth;
(*rpst->i40e_pf_eth->dev_ops->link_update)(pf, 1);
}
return ret;
}
/*
* Set device link down.
*/
int
ipn3ke_rpst_dev_set_link_down(struct rte_eth_dev *dev)
{
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(dev);
struct rte_eth_dev *pf;
int ret = 0;
if (rpst->i40e_pf_eth) {
ret = rte_eth_dev_set_link_down(rpst->i40e_pf_eth_port_id);
pf = rpst->i40e_pf_eth;
(*rpst->i40e_pf_eth->dev_ops->link_update)(pf, 1);
}
return ret;
}
int
ipn3ke_rpst_link_update(struct rte_eth_dev *ethdev,
__rte_unused int wait_to_complete)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
struct rte_rawdev *rawdev;
struct rte_eth_link link;
struct rte_eth_dev *pf;
memset(&link, 0, sizeof(link));
link.link_duplex = ETH_LINK_FULL_DUPLEX;
link.link_autoneg = !(ethdev->data->dev_conf.link_speeds &
ETH_LINK_SPEED_FIXED);
rawdev = hw->rawdev;
ipn3ke_update_link(rawdev, rpst->port_id, &link);
if (!rpst->ori_linfo.link_status &&
link.link_status) {
IPN3KE_AFU_PMD_DEBUG("Update Rpst %d Up\n", rpst->port_id);
rpst->ori_linfo.link_status = link.link_status;
rpst->ori_linfo.link_speed = link.link_speed;
rte_eth_linkstatus_set(ethdev, &link);
if (rpst->i40e_pf_eth) {
IPN3KE_AFU_PMD_DEBUG("Update FVL PF %d Up\n",
rpst->i40e_pf_eth_port_id);
rte_eth_dev_set_link_up(rpst->i40e_pf_eth_port_id);
pf = rpst->i40e_pf_eth;
(*rpst->i40e_pf_eth->dev_ops->link_update)(pf, 1);
}
} else if (rpst->ori_linfo.link_status &&
!link.link_status) {
IPN3KE_AFU_PMD_DEBUG("Update Rpst %d Down\n",
rpst->port_id);
rpst->ori_linfo.link_status = link.link_status;
rpst->ori_linfo.link_speed = link.link_speed;
rte_eth_linkstatus_set(ethdev, &link);
if (rpst->i40e_pf_eth) {
IPN3KE_AFU_PMD_DEBUG("Update FVL PF %d Down\n",
rpst->i40e_pf_eth_port_id);
rte_eth_dev_set_link_down(rpst->i40e_pf_eth_port_id);
pf = rpst->i40e_pf_eth;
(*rpst->i40e_pf_eth->dev_ops->link_update)(pf, 1);
}
}
return 0;
}
static int
ipn3ke_rpst_link_check(struct ipn3ke_rpst *rpst)
{
struct ipn3ke_hw *hw;
struct rte_rawdev *rawdev;
struct rte_eth_link link;
struct rte_eth_dev *pf;
if (rpst == NULL)
return -1;
hw = rpst->hw;
memset(&link, 0, sizeof(link));
link.link_duplex = ETH_LINK_FULL_DUPLEX;
link.link_autoneg = !(rpst->ethdev->data->dev_conf.link_speeds &
ETH_LINK_SPEED_FIXED);
rawdev = hw->rawdev;
ipn3ke_update_link(rawdev, rpst->port_id, &link);
if (!rpst->ori_linfo.link_status &&
link.link_status) {
IPN3KE_AFU_PMD_DEBUG("Check Rpst %d Up\n", rpst->port_id);
rpst->ori_linfo.link_status = link.link_status;
rpst->ori_linfo.link_speed = link.link_speed;
rte_eth_linkstatus_set(rpst->ethdev, &link);
if (rpst->i40e_pf_eth) {
IPN3KE_AFU_PMD_DEBUG("Check FVL PF %d Up\n",
rpst->i40e_pf_eth_port_id);
rte_eth_dev_set_link_up(rpst->i40e_pf_eth_port_id);
pf = rpst->i40e_pf_eth;
(*rpst->i40e_pf_eth->dev_ops->link_update)(pf, 1);
}
} else if (rpst->ori_linfo.link_status &&
!link.link_status) {
IPN3KE_AFU_PMD_DEBUG("Check Rpst %d Down\n", rpst->port_id);
rpst->ori_linfo.link_status = link.link_status;
rpst->ori_linfo.link_speed = link.link_speed;
rte_eth_linkstatus_set(rpst->ethdev, &link);
if (rpst->i40e_pf_eth) {
IPN3KE_AFU_PMD_DEBUG("Check FVL PF %d Down\n",
rpst->i40e_pf_eth_port_id);
rte_eth_dev_set_link_down(rpst->i40e_pf_eth_port_id);
pf = rpst->i40e_pf_eth;
(*rpst->i40e_pf_eth->dev_ops->link_update)(pf, 1);
}
}
return 0;
}
static void *
ipn3ke_rpst_scan_handle_request(__rte_unused void *param)
{
struct ipn3ke_rpst *rpst;
int num = 0;
#define MS 1000
#define SCAN_NUM 32
for (;;) {
num = 0;
TAILQ_FOREACH(rpst, &ipn3ke_rpst_list, next) {
if (rpst->i40e_pf_eth &&
rpst->ethdev->data->dev_started &&
rpst->i40e_pf_eth->data->dev_started)
ipn3ke_rpst_link_check(rpst);
if (++num > SCAN_NUM)
rte_delay_us(1 * MS);
}
rte_delay_us(50 * MS);
if (num == 0xffffff)
return NULL;
}
return NULL;
}
static int
ipn3ke_rpst_scan_check(void)
{
int ret;
if (ipn3ke_rpst_scan_num == 1) {
ret = rte_ctrl_thread_create(&ipn3ke_rpst_scan_thread,
"ipn3ke scanner",
NULL,
ipn3ke_rpst_scan_handle_request, NULL);
if (ret) {
IPN3KE_AFU_PMD_ERR("Fail to create ipn3ke rpst scan thread");
return -1;
}
} else if (ipn3ke_rpst_scan_num == 0) {
ret = pthread_cancel(ipn3ke_rpst_scan_thread);
if (ret)
IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
if (ret)
IPN3KE_AFU_PMD_ERR("Can't join the thread");
return ret;
}
return 0;
}
int
ipn3ke_rpst_promiscuous_enable(struct rte_eth_dev *ethdev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
uint32_t rddata, val;
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Enable all unicast */
(*hw->f_mac_read)(hw,
&rddata,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
val = 1;
val &= IPN3KE_MAC_RX_FRAME_CONTROL_EN_ALLUCAST_MASK;
val |= rddata;
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
}
return 0;
}
int
ipn3ke_rpst_promiscuous_disable(struct rte_eth_dev *ethdev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
uint32_t rddata, val;
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Disable all unicast */
(*hw->f_mac_read)(hw,
&rddata,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
val = 0;
val &= IPN3KE_MAC_RX_FRAME_CONTROL_EN_ALLUCAST_MASK;
val |= rddata;
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
}
return 0;
}
int
ipn3ke_rpst_allmulticast_enable(struct rte_eth_dev *ethdev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
uint32_t rddata, val;
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Enable all unicast */
(*hw->f_mac_read)(hw,
&rddata,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
val = 1;
val <<= IPN3KE_MAC_RX_FRAME_CONTROL_EN_ALLMCAST_SHIFT;
val &= IPN3KE_MAC_RX_FRAME_CONTROL_EN_ALLMCAST_MASK;
val |= rddata;
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
}
return 0;
}
int
ipn3ke_rpst_allmulticast_disable(struct rte_eth_dev *ethdev)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
uint32_t rddata, val;
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
/* Disable all unicast */
(*hw->f_mac_read)(hw,
&rddata,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
val = 0;
val <<= IPN3KE_MAC_RX_FRAME_CONTROL_EN_ALLMCAST_SHIFT;
val &= IPN3KE_MAC_RX_FRAME_CONTROL_EN_ALLMCAST_MASK;
val |= rddata;
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_RX_FRAME_CONTROL,
rpst->port_id,
0);
}
return 0;
}
int
ipn3ke_rpst_mac_addr_set(struct rte_eth_dev *ethdev,
struct rte_ether_addr *mac_addr)
{
struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
uint32_t val;
if (!rte_is_valid_assigned_ether_addr(mac_addr)) {
IPN3KE_AFU_PMD_ERR("Tried to set invalid MAC address.");
return -EINVAL;
}
if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
rte_ether_addr_copy(&mac_addr[0], &rpst->mac_addr);
/* Set mac address */
rte_memcpy(((char *)(&val)), &mac_addr[0], sizeof(uint32_t));
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_PRIMARY_MAC_ADDR0,
rpst->port_id,
0);
rte_memcpy(((char *)(&val)), &mac_addr[4], sizeof(uint16_t));
(*hw->f_mac_write)(hw,
val,
IPN3KE_MAC_PRIMARY_MAC_ADDR0,
rpst->port_id,
0);
}
return 0;
}
int
ipn3ke_rpst_mtu_set(struct rte_eth_dev *ethdev, uint16_t mtu)
{
int ret = 0;
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
struct rte_eth_dev_data *dev_data = ethdev->data;
uint32_t frame_size = mtu + IPN3KE_ETH_OVERHEAD;
/* check if mtu is within the allowed range */
if (mtu < RTE_ETHER_MIN_MTU ||
frame_size > IPN3KE_MAC_FRAME_SIZE_MAX)
return -EINVAL;
/* mtu setting is forbidden if port is start */
/* make sure NIC port is stopped */
if (rpst->i40e_pf_eth && rpst->i40e_pf_eth->data->dev_started) {
IPN3KE_AFU_PMD_ERR("NIC port %d must "
"be stopped before configuration",
rpst->i40e_pf_eth->data->port_id);
return -EBUSY;
}
/* mtu setting is forbidden if port is start */
if (dev_data->dev_started) {
IPN3KE_AFU_PMD_ERR("FPGA port %d must "
"be stopped before configuration",
dev_data->port_id);
return -EBUSY;
}
if (frame_size > RTE_ETHER_MAX_LEN)
dev_data->dev_conf.rxmode.offloads |=
(uint64_t)(DEV_RX_OFFLOAD_JUMBO_FRAME);
else
dev_data->dev_conf.rxmode.offloads &=
(uint64_t)(~DEV_RX_OFFLOAD_JUMBO_FRAME);
dev_data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
if (rpst->i40e_pf_eth) {
ret = rpst->i40e_pf_eth->dev_ops->mtu_set(rpst->i40e_pf_eth,
mtu);
if (!ret)
rpst->i40e_pf_eth->data->mtu = mtu;
}
return ret;
}
static int
ipn3ke_afu_filter_ctrl(struct rte_eth_dev *ethdev,
enum rte_filter_type filter_type, enum rte_filter_op filter_op,
void *arg)
{
int ret = 0;
struct ipn3ke_hw *hw;
struct ipn3ke_rpst *rpst;
if (ethdev == NULL)
return -EINVAL;
hw = IPN3KE_DEV_PRIVATE_TO_HW(ethdev);
rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
if (hw->acc_flow)
switch (filter_type) {
case RTE_ETH_FILTER_GENERIC:
if (filter_op != RTE_ETH_FILTER_GET)
return -EINVAL;
*(const void **)arg = &ipn3ke_flow_ops;
break;
default:
IPN3KE_AFU_PMD_WARN("Filter type (%d) not supported",
filter_type);
ret = -EINVAL;
break;
}
else if (rpst->i40e_pf_eth)
(*rpst->i40e_pf_eth->dev_ops->filter_ctrl)(ethdev,
filter_type,
filter_op,
arg);
else
return -EINVAL;
return ret;
}
static const struct eth_dev_ops ipn3ke_rpst_dev_ops = {
.dev_infos_get = ipn3ke_rpst_dev_infos_get,
.dev_configure = ipn3ke_rpst_dev_configure,
.dev_start = ipn3ke_rpst_dev_start,
.dev_stop = ipn3ke_rpst_dev_stop,
.dev_close = ipn3ke_rpst_dev_close,
.dev_reset = ipn3ke_rpst_dev_reset,
.stats_get = ipn3ke_rpst_stats_get,
.xstats_get = ipn3ke_rpst_xstats_get,
.xstats_get_names = ipn3ke_rpst_xstats_get_names,
.stats_reset = ipn3ke_rpst_stats_reset,
.xstats_reset = ipn3ke_rpst_stats_reset,
.filter_ctrl = ipn3ke_afu_filter_ctrl,
.rx_queue_start = ipn3ke_rpst_rx_queue_start,
.rx_queue_stop = ipn3ke_rpst_rx_queue_stop,
.tx_queue_start = ipn3ke_rpst_tx_queue_start,
.tx_queue_stop = ipn3ke_rpst_tx_queue_stop,
.rx_queue_setup = ipn3ke_rpst_rx_queue_setup,
.rx_queue_release = ipn3ke_rpst_rx_queue_release,
.tx_queue_setup = ipn3ke_rpst_tx_queue_setup,
.tx_queue_release = ipn3ke_rpst_tx_queue_release,
.dev_set_link_up = ipn3ke_rpst_dev_set_link_up,
.dev_set_link_down = ipn3ke_rpst_dev_set_link_down,
.link_update = ipn3ke_rpst_link_update,
.promiscuous_enable = ipn3ke_rpst_promiscuous_enable,
.promiscuous_disable = ipn3ke_rpst_promiscuous_disable,
.allmulticast_enable = ipn3ke_rpst_allmulticast_enable,
.allmulticast_disable = ipn3ke_rpst_allmulticast_disable,
.mac_addr_set = ipn3ke_rpst_mac_addr_set,
.mtu_set = ipn3ke_rpst_mtu_set,
.tm_ops_get = ipn3ke_tm_ops_get,
};
static uint16_t ipn3ke_rpst_recv_pkts(__rte_unused void *rx_q,
__rte_unused struct rte_mbuf **rx_pkts, __rte_unused uint16_t nb_pkts)
{
return 0;
}
static uint16_t
ipn3ke_rpst_xmit_pkts(__rte_unused void *tx_queue,
__rte_unused struct rte_mbuf **tx_pkts, __rte_unused uint16_t nb_pkts)
{
return 0;
}
int
ipn3ke_rpst_init(struct rte_eth_dev *ethdev, void *init_params)
{
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
struct ipn3ke_rpst *representor_param =
(struct ipn3ke_rpst *)init_params;
if (representor_param->port_id >= representor_param->hw->port_num)
return -ENODEV;
if (ipn3ke_bridge_func.set_i40e_sw_dev == NULL)
return -ENOMEM;
rpst->ethdev = ethdev;
rpst->switch_domain_id = representor_param->switch_domain_id;
rpst->port_id = representor_param->port_id;
rpst->hw = representor_param->hw;
rpst->i40e_pf_eth = representor_param->i40e_pf_eth;
rpst->i40e_pf_eth_port_id = representor_param->i40e_pf_eth_port_id;
if (rpst->i40e_pf_eth)
ipn3ke_bridge_func.set_i40e_sw_dev(rpst->i40e_pf_eth_port_id,
rpst->ethdev);
ethdev->data->mac_addrs = rte_zmalloc("ipn3ke", RTE_ETHER_ADDR_LEN, 0);
if (!ethdev->data->mac_addrs) {
IPN3KE_AFU_PMD_ERR("Failed to "
"allocated memory for storing mac address");
return -ENODEV;
}
if (rpst->hw->tm_hw_enable)
ipn3ke_tm_init(rpst);
/* Set representor device ops */
ethdev->dev_ops = &ipn3ke_rpst_dev_ops;
/* No data-path, but need stub Rx/Tx functions to avoid crash
* when testing with the likes of testpmd.
*/
ethdev->rx_pkt_burst = ipn3ke_rpst_recv_pkts;
ethdev->tx_pkt_burst = ipn3ke_rpst_xmit_pkts;
ethdev->data->nb_rx_queues = 1;
ethdev->data->nb_tx_queues = 1;
ethdev->data->mac_addrs = rte_zmalloc("ipn3ke_afu_representor",
RTE_ETHER_ADDR_LEN,
0);
if (!ethdev->data->mac_addrs) {
IPN3KE_AFU_PMD_ERR("Failed to "
"allocated memory for storing mac address");
return -ENODEV;
}
ethdev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
rte_spinlock_lock(&ipn3ke_link_notify_list_lk);
TAILQ_INSERT_TAIL(&ipn3ke_rpst_list, rpst, next);
ipn3ke_rpst_scan_num++;
ipn3ke_rpst_scan_check();
rte_spinlock_unlock(&ipn3ke_link_notify_list_lk);
return 0;
}
int
ipn3ke_rpst_uninit(struct rte_eth_dev *ethdev)
{
struct ipn3ke_rpst *rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
rte_spinlock_lock(&ipn3ke_link_notify_list_lk);
TAILQ_REMOVE(&ipn3ke_rpst_list, rpst, next);
ipn3ke_rpst_scan_num--;
ipn3ke_rpst_scan_check();
rte_spinlock_unlock(&ipn3ke_link_notify_list_lk);
return 0;
}