111e9eae4SChaoyong He /* SPDX-License-Identifier: BSD-3-Clause 211e9eae4SChaoyong He * Copyright (c) 2014-2018 Netronome Systems, Inc. 311e9eae4SChaoyong He * All rights reserved. 411e9eae4SChaoyong He * 511e9eae4SChaoyong He * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation. 611e9eae4SChaoyong He */ 711e9eae4SChaoyong He 811e9eae4SChaoyong He #include "nfp_net_common.h" 911e9eae4SChaoyong He 1011e9eae4SChaoyong He #include <rte_alarm.h> 1111e9eae4SChaoyong He 1211e9eae4SChaoyong He #include "flower/nfp_flower_representor.h" 1311e9eae4SChaoyong He #include "nfd3/nfp_nfd3.h" 1411e9eae4SChaoyong He #include "nfdk/nfp_nfdk.h" 1511e9eae4SChaoyong He #include "nfpcore/nfp_mip.h" 1611e9eae4SChaoyong He #include "nfpcore/nfp_nsp.h" 1711e9eae4SChaoyong He #include "nfp_logs.h" 1811e9eae4SChaoyong He 1911e9eae4SChaoyong He #define NFP_TX_MAX_SEG UINT8_MAX 2011e9eae4SChaoyong He #define NFP_TX_MAX_MTU_SEG 8 2111e9eae4SChaoyong He 2211e9eae4SChaoyong He /* 2311e9eae4SChaoyong He * This is used by the reconfig protocol. It sets the maximum time waiting in 2411e9eae4SChaoyong He * milliseconds before a reconfig timeout happens. 2511e9eae4SChaoyong He */ 2611e9eae4SChaoyong He #define NFP_NET_POLL_TIMEOUT 5000 2711e9eae4SChaoyong He 2811e9eae4SChaoyong He #define NFP_NET_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */ 2911e9eae4SChaoyong He #define NFP_NET_LINK_UP_CHECK_TIMEOUT 1000 /* ms */ 3011e9eae4SChaoyong He 3111e9eae4SChaoyong He /* Maximum supported NFP frame size (MTU + layer 2 headers) */ 3211e9eae4SChaoyong He #define NFP_FRAME_SIZE_MAX 10048 3311e9eae4SChaoyong He #define DEFAULT_FLBUF_SIZE 9216 3411e9eae4SChaoyong He 3511e9eae4SChaoyong He enum nfp_xstat_group { 3611e9eae4SChaoyong He NFP_XSTAT_GROUP_NET, 3711e9eae4SChaoyong He NFP_XSTAT_GROUP_MAC 3811e9eae4SChaoyong He }; 3911e9eae4SChaoyong He 4011e9eae4SChaoyong He struct nfp_xstat { 4111e9eae4SChaoyong He char name[RTE_ETH_XSTATS_NAME_SIZE]; 4211e9eae4SChaoyong He int offset; 4311e9eae4SChaoyong He enum nfp_xstat_group group; 4411e9eae4SChaoyong He }; 4511e9eae4SChaoyong He 4611e9eae4SChaoyong He #define NFP_XSTAT_NET(_name, _offset) { \ 4711e9eae4SChaoyong He .name = _name, \ 4811e9eae4SChaoyong He .offset = NFP_NET_CFG_STATS_##_offset, \ 4911e9eae4SChaoyong He .group = NFP_XSTAT_GROUP_NET, \ 5011e9eae4SChaoyong He } 5111e9eae4SChaoyong He 5211e9eae4SChaoyong He #define NFP_XSTAT_MAC(_name, _offset) { \ 5311e9eae4SChaoyong He .name = _name, \ 5411e9eae4SChaoyong He .offset = NFP_MAC_STATS_##_offset, \ 5511e9eae4SChaoyong He .group = NFP_XSTAT_GROUP_MAC, \ 5611e9eae4SChaoyong He } 5711e9eae4SChaoyong He 5811e9eae4SChaoyong He static const struct nfp_xstat nfp_net_xstats[] = { 5911e9eae4SChaoyong He /* 6011e9eae4SChaoyong He * Basic xstats available on both VF and PF. 6111e9eae4SChaoyong He * Note that in case new statistics of group NFP_XSTAT_GROUP_NET 6211e9eae4SChaoyong He * are added to this array, they must appear before any statistics 6311e9eae4SChaoyong He * of group NFP_XSTAT_GROUP_MAC. 6411e9eae4SChaoyong He */ 6511e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_packets_mc", RX_MC_FRAMES), 6611e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_packets_mc", TX_MC_FRAMES), 6711e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_packets_bc", RX_BC_FRAMES), 6811e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_packets_bc", TX_BC_FRAMES), 6911e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_uc", RX_UC_OCTETS), 7011e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_uc", TX_UC_OCTETS), 7111e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_mc", RX_MC_OCTETS), 7211e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_mc", TX_MC_OCTETS), 7311e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_bc", RX_BC_OCTETS), 7411e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_bc", TX_BC_OCTETS), 7511e9eae4SChaoyong He NFP_XSTAT_NET("tx_missed_erros", TX_DISCARDS), 7611e9eae4SChaoyong He NFP_XSTAT_NET("bpf_pass_pkts", APP0_FRAMES), 7711e9eae4SChaoyong He NFP_XSTAT_NET("bpf_pass_bytes", APP0_BYTES), 7811e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app1_pkts", APP1_FRAMES), 7911e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app1_bytes", APP1_BYTES), 8011e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app2_pkts", APP2_FRAMES), 8111e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app2_bytes", APP2_BYTES), 8211e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app3_pkts", APP3_FRAMES), 8311e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app3_bytes", APP3_BYTES), 8411e9eae4SChaoyong He /* 8511e9eae4SChaoyong He * MAC xstats available only on PF. These statistics are not available for VFs as the 8611e9eae4SChaoyong He * PF is not initialized when the VF is initialized as it is still bound to the kernel 8711e9eae4SChaoyong He * driver. As such, the PMD cannot obtain a CPP handle and access the rtsym_table in order 8811e9eae4SChaoyong He * to get the pointer to the start of the MAC statistics counters. 8911e9eae4SChaoyong He */ 9011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_octets", RX_IN_OCTS), 9111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frame_too_long_errors", RX_FRAME_TOO_LONG_ERRORS), 9211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_range_length_errors", RX_RANGE_LENGTH_ERRORS), 9311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_vlan_received_ok", RX_VLAN_RECEIVED_OK), 9411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_errors", RX_IN_ERRORS), 9511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_broadcast_pkts", RX_IN_BROADCAST_PKTS), 9611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_drop_events", RX_DROP_EVENTS), 9711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_alignment_errors", RX_ALIGNMENT_ERRORS), 9811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_mac_ctrl_frames", RX_PAUSE_MAC_CTRL_FRAMES), 9911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frames_received_ok", RX_FRAMES_RECEIVED_OK), 10011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frame_check_sequence_errors", RX_FRAME_CHECK_SEQ_ERRORS), 10111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_unicast_pkts", RX_UNICAST_PKTS), 10211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_multicast_pkts", RX_MULTICAST_PKTS), 10311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts", RX_PKTS), 10411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_undersize_pkts", RX_UNDERSIZE_PKTS), 10511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_64_octets", RX_PKTS_64_OCTS), 10611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_65_to_127_octets", RX_PKTS_65_TO_127_OCTS), 10711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_128_to_255_octets", RX_PKTS_128_TO_255_OCTS), 10811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_256_to_511_octets", RX_PKTS_256_TO_511_OCTS), 10911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_512_to_1023_octets", RX_PKTS_512_TO_1023_OCTS), 11011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_1024_to_1518_octets", RX_PKTS_1024_TO_1518_OCTS), 11111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_1519_to_max_octets", RX_PKTS_1519_TO_MAX_OCTS), 11211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_jabbers", RX_JABBERS), 11311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_fragments", RX_FRAGMENTS), 11411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_oversize_pkts", RX_OVERSIZE_PKTS), 11511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class0", RX_PAUSE_FRAMES_CLASS0), 11611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class1", RX_PAUSE_FRAMES_CLASS1), 11711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class2", RX_PAUSE_FRAMES_CLASS2), 11811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class3", RX_PAUSE_FRAMES_CLASS3), 11911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class4", RX_PAUSE_FRAMES_CLASS4), 12011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class5", RX_PAUSE_FRAMES_CLASS5), 12111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class6", RX_PAUSE_FRAMES_CLASS6), 12211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class7", RX_PAUSE_FRAMES_CLASS7), 12311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_mac_ctrl_frames_received", RX_MAC_CTRL_FRAMES_REC), 12411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_mac_head_drop", RX_MAC_HEAD_DROP), 12511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_queue_drop", TX_QUEUE_DROP), 12611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_octets", TX_OUT_OCTS), 12711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_vlan_transmitted_ok", TX_VLAN_TRANSMITTED_OK), 12811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_errors", TX_OUT_ERRORS), 12911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_broadcast_pkts", TX_BROADCAST_PKTS), 13011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_mac_ctrl_frames", TX_PAUSE_MAC_CTRL_FRAMES), 13111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_frames_transmitted_ok", TX_FRAMES_TRANSMITTED_OK), 13211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_unicast_pkts", TX_UNICAST_PKTS), 13311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_multicast_pkts", TX_MULTICAST_PKTS), 13411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_64_octets", TX_PKTS_64_OCTS), 13511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_65_to_127_octets", TX_PKTS_65_TO_127_OCTS), 13611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_128_to_255_octets", TX_PKTS_128_TO_255_OCTS), 13711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_256_to_511_octets", TX_PKTS_256_TO_511_OCTS), 13811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_512_to_1023_octets", TX_PKTS_512_TO_1023_OCTS), 13911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_1024_to_1518_octets", TX_PKTS_1024_TO_1518_OCTS), 14011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_1519_to_max_octets", TX_PKTS_1519_TO_MAX_OCTS), 14111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class0", TX_PAUSE_FRAMES_CLASS0), 14211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class1", TX_PAUSE_FRAMES_CLASS1), 14311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class2", TX_PAUSE_FRAMES_CLASS2), 14411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class3", TX_PAUSE_FRAMES_CLASS3), 14511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class4", TX_PAUSE_FRAMES_CLASS4), 14611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class5", TX_PAUSE_FRAMES_CLASS5), 14711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class6", TX_PAUSE_FRAMES_CLASS6), 14811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class7", TX_PAUSE_FRAMES_CLASS7), 14911e9eae4SChaoyong He }; 15011e9eae4SChaoyong He 15111e9eae4SChaoyong He static const uint32_t nfp_net_link_speed_nfp2rte[] = { 15211e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = RTE_ETH_SPEED_NUM_NONE, 15311e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = RTE_ETH_SPEED_NUM_NONE, 15411e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_1G] = RTE_ETH_SPEED_NUM_1G, 15511e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_10G] = RTE_ETH_SPEED_NUM_10G, 15611e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_25G] = RTE_ETH_SPEED_NUM_25G, 15711e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_40G] = RTE_ETH_SPEED_NUM_40G, 15811e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_50G] = RTE_ETH_SPEED_NUM_50G, 15911e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_100G] = RTE_ETH_SPEED_NUM_100G, 16011e9eae4SChaoyong He }; 16111e9eae4SChaoyong He 16211e9eae4SChaoyong He static uint16_t 16311e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(uint16_t speed) 16411e9eae4SChaoyong He { 16511e9eae4SChaoyong He uint16_t i; 16611e9eae4SChaoyong He 16711e9eae4SChaoyong He for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) { 16811e9eae4SChaoyong He if (speed == nfp_net_link_speed_nfp2rte[i]) 16911e9eae4SChaoyong He return i; 17011e9eae4SChaoyong He } 17111e9eae4SChaoyong He 17211e9eae4SChaoyong He return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN; 17311e9eae4SChaoyong He } 17411e9eae4SChaoyong He 17511e9eae4SChaoyong He static void 17611e9eae4SChaoyong He nfp_net_notify_port_speed(struct nfp_net_hw *hw, 17711e9eae4SChaoyong He struct rte_eth_link *link) 17811e9eae4SChaoyong He { 17911e9eae4SChaoyong He /* 18011e9eae4SChaoyong He * Read the link status from NFP_NET_CFG_STS. If the link is down 18111e9eae4SChaoyong He * then write the link speed NFP_NET_CFG_STS_LINK_RATE_UNKNOWN to 18211e9eae4SChaoyong He * NFP_NET_CFG_STS_NSP_LINK_RATE. 18311e9eae4SChaoyong He */ 18411e9eae4SChaoyong He if (link->link_status == RTE_ETH_LINK_DOWN) { 185f58bde00SChaoyong He nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE, 186f58bde00SChaoyong He NFP_NET_CFG_STS_LINK_RATE_UNKNOWN); 18711e9eae4SChaoyong He return; 18811e9eae4SChaoyong He } 18911e9eae4SChaoyong He 19011e9eae4SChaoyong He /* 19111e9eae4SChaoyong He * Link is up so write the link speed from the eth_table to 19211e9eae4SChaoyong He * NFP_NET_CFG_STS_NSP_LINK_RATE. 19311e9eae4SChaoyong He */ 194f58bde00SChaoyong He nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE, 19511e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(link->link_speed)); 19611e9eae4SChaoyong He } 19711e9eae4SChaoyong He 19811e9eae4SChaoyong He /* The length of firmware version string */ 19911e9eae4SChaoyong He #define FW_VER_LEN 32 20011e9eae4SChaoyong He 20111e9eae4SChaoyong He static int 202*72d1dea6SChaoyong He nfp_reconfig_real(struct nfp_hw *hw, 20311e9eae4SChaoyong He uint32_t update) 20411e9eae4SChaoyong He { 20511e9eae4SChaoyong He uint32_t cnt; 20611e9eae4SChaoyong He uint32_t new; 20711e9eae4SChaoyong He struct timespec wait; 20811e9eae4SChaoyong He 20911e9eae4SChaoyong He PMD_DRV_LOG(DEBUG, "Writing to the configuration queue (%p)...", 210*72d1dea6SChaoyong He hw->qcp_cfg); 21111e9eae4SChaoyong He 212*72d1dea6SChaoyong He if (hw->qcp_cfg == NULL) { 21311e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Bad configuration queue pointer"); 21411e9eae4SChaoyong He return -ENXIO; 21511e9eae4SChaoyong He } 21611e9eae4SChaoyong He 217*72d1dea6SChaoyong He nfp_qcp_ptr_add(hw->qcp_cfg, NFP_QCP_WRITE_PTR, 1); 21811e9eae4SChaoyong He 21911e9eae4SChaoyong He wait.tv_sec = 0; 22011e9eae4SChaoyong He wait.tv_nsec = 1000000; /* 1ms */ 22111e9eae4SChaoyong He 22211e9eae4SChaoyong He PMD_DRV_LOG(DEBUG, "Polling for update ack..."); 22311e9eae4SChaoyong He 22411e9eae4SChaoyong He /* Poll update field, waiting for NFP to ack the config */ 22511e9eae4SChaoyong He for (cnt = 0; ; cnt++) { 226*72d1dea6SChaoyong He new = nn_cfg_readl(hw, NFP_NET_CFG_UPDATE); 22711e9eae4SChaoyong He if (new == 0) 22811e9eae4SChaoyong He break; 22911e9eae4SChaoyong He 23011e9eae4SChaoyong He if ((new & NFP_NET_CFG_UPDATE_ERR) != 0) { 23111e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Reconfig error: %#08x", new); 23211e9eae4SChaoyong He return -1; 23311e9eae4SChaoyong He } 23411e9eae4SChaoyong He 23511e9eae4SChaoyong He if (cnt >= NFP_NET_POLL_TIMEOUT) { 23611e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Reconfig timeout for %#08x after %u ms", 23711e9eae4SChaoyong He update, cnt); 23811e9eae4SChaoyong He return -EIO; 23911e9eae4SChaoyong He } 24011e9eae4SChaoyong He 24111e9eae4SChaoyong He nanosleep(&wait, 0); /* Waiting for a 1ms */ 24211e9eae4SChaoyong He } 24311e9eae4SChaoyong He 24411e9eae4SChaoyong He PMD_DRV_LOG(DEBUG, "Ack DONE"); 24511e9eae4SChaoyong He return 0; 24611e9eae4SChaoyong He } 24711e9eae4SChaoyong He 24811e9eae4SChaoyong He /** 24911e9eae4SChaoyong He * Reconfigure the NIC. 25011e9eae4SChaoyong He * 25111e9eae4SChaoyong He * Write the update word to the BAR and ping the reconfig queue. Then poll 25211e9eae4SChaoyong He * until the firmware has acknowledged the update by zeroing the update word. 25311e9eae4SChaoyong He * 25411e9eae4SChaoyong He * @param hw 25511e9eae4SChaoyong He * Device to reconfigure. 25611e9eae4SChaoyong He * @param ctrl 25711e9eae4SChaoyong He * The value for the ctrl field in the BAR config. 25811e9eae4SChaoyong He * @param update 25911e9eae4SChaoyong He * The value for the update field in the BAR config. 26011e9eae4SChaoyong He * 26111e9eae4SChaoyong He * @return 26211e9eae4SChaoyong He * - (0) if OK to reconfigure the device. 26311e9eae4SChaoyong He * - (-EIO) if I/O err and fail to reconfigure the device. 26411e9eae4SChaoyong He */ 26511e9eae4SChaoyong He int 266*72d1dea6SChaoyong He nfp_reconfig(struct nfp_hw *hw, 26711e9eae4SChaoyong He uint32_t ctrl, 26811e9eae4SChaoyong He uint32_t update) 26911e9eae4SChaoyong He { 27011e9eae4SChaoyong He int ret; 27111e9eae4SChaoyong He 27211e9eae4SChaoyong He rte_spinlock_lock(&hw->reconfig_lock); 27311e9eae4SChaoyong He 274*72d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_CTRL, ctrl); 275*72d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update); 27611e9eae4SChaoyong He 27711e9eae4SChaoyong He rte_wmb(); 27811e9eae4SChaoyong He 279*72d1dea6SChaoyong He ret = nfp_reconfig_real(hw, update); 28011e9eae4SChaoyong He 28111e9eae4SChaoyong He rte_spinlock_unlock(&hw->reconfig_lock); 28211e9eae4SChaoyong He 28311e9eae4SChaoyong He if (ret != 0) { 284*72d1dea6SChaoyong He PMD_DRV_LOG(ERR, "Error nfp reconfig: ctrl=%#08x update=%#08x", 28511e9eae4SChaoyong He ctrl, update); 28611e9eae4SChaoyong He return -EIO; 28711e9eae4SChaoyong He } 28811e9eae4SChaoyong He 28911e9eae4SChaoyong He return 0; 29011e9eae4SChaoyong He } 29111e9eae4SChaoyong He 29211e9eae4SChaoyong He /** 29311e9eae4SChaoyong He * Reconfigure the NIC for the extend ctrl BAR. 29411e9eae4SChaoyong He * 29511e9eae4SChaoyong He * Write the update word to the BAR and ping the reconfig queue. Then poll 29611e9eae4SChaoyong He * until the firmware has acknowledged the update by zeroing the update word. 29711e9eae4SChaoyong He * 29811e9eae4SChaoyong He * @param hw 29911e9eae4SChaoyong He * Device to reconfigure. 30011e9eae4SChaoyong He * @param ctrl_ext 30111e9eae4SChaoyong He * The value for the first word of extend ctrl field in the BAR config. 30211e9eae4SChaoyong He * @param update 30311e9eae4SChaoyong He * The value for the update field in the BAR config. 30411e9eae4SChaoyong He * 30511e9eae4SChaoyong He * @return 30611e9eae4SChaoyong He * - (0) if OK to reconfigure the device. 30711e9eae4SChaoyong He * - (-EIO) if I/O err and fail to reconfigure the device. 30811e9eae4SChaoyong He */ 30911e9eae4SChaoyong He int 310*72d1dea6SChaoyong He nfp_ext_reconfig(struct nfp_hw *hw, 31111e9eae4SChaoyong He uint32_t ctrl_ext, 31211e9eae4SChaoyong He uint32_t update) 31311e9eae4SChaoyong He { 31411e9eae4SChaoyong He int ret; 31511e9eae4SChaoyong He 31611e9eae4SChaoyong He rte_spinlock_lock(&hw->reconfig_lock); 31711e9eae4SChaoyong He 318*72d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_CTRL_WORD1, ctrl_ext); 319*72d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update); 32011e9eae4SChaoyong He 32111e9eae4SChaoyong He rte_wmb(); 32211e9eae4SChaoyong He 323*72d1dea6SChaoyong He ret = nfp_reconfig_real(hw, update); 32411e9eae4SChaoyong He 32511e9eae4SChaoyong He rte_spinlock_unlock(&hw->reconfig_lock); 32611e9eae4SChaoyong He 32711e9eae4SChaoyong He if (ret != 0) { 328*72d1dea6SChaoyong He PMD_DRV_LOG(ERR, "Error nfp ext reconfig: ctrl_ext=%#08x update=%#08x", 32911e9eae4SChaoyong He ctrl_ext, update); 33011e9eae4SChaoyong He return -EIO; 33111e9eae4SChaoyong He } 33211e9eae4SChaoyong He 33311e9eae4SChaoyong He return 0; 33411e9eae4SChaoyong He } 33511e9eae4SChaoyong He 33611e9eae4SChaoyong He /** 33711e9eae4SChaoyong He * Reconfigure the firmware via the mailbox 33811e9eae4SChaoyong He * 33911e9eae4SChaoyong He * @param hw 34011e9eae4SChaoyong He * Device to reconfigure 34111e9eae4SChaoyong He * @param mbox_cmd 34211e9eae4SChaoyong He * The value for the mailbox command 34311e9eae4SChaoyong He * 34411e9eae4SChaoyong He * @return 34511e9eae4SChaoyong He * - (0) if OK to reconfigure by the mailbox. 34611e9eae4SChaoyong He * - (-EIO) if I/O err and fail to reconfigure by the mailbox 34711e9eae4SChaoyong He */ 34811e9eae4SChaoyong He int 34911e9eae4SChaoyong He nfp_net_mbox_reconfig(struct nfp_net_hw *hw, 35011e9eae4SChaoyong He uint32_t mbox_cmd) 35111e9eae4SChaoyong He { 35211e9eae4SChaoyong He int ret; 35311e9eae4SChaoyong He uint32_t mbox; 35411e9eae4SChaoyong He 35511e9eae4SChaoyong He mbox = hw->tlv_caps.mbox_off; 35611e9eae4SChaoyong He 357*72d1dea6SChaoyong He rte_spinlock_lock(&hw->super.reconfig_lock); 35811e9eae4SChaoyong He 359f58bde00SChaoyong He nn_cfg_writeq(&hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd); 360f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX); 36111e9eae4SChaoyong He 36211e9eae4SChaoyong He rte_wmb(); 36311e9eae4SChaoyong He 364*72d1dea6SChaoyong He ret = nfp_reconfig_real(&hw->super, NFP_NET_CFG_UPDATE_MBOX); 36511e9eae4SChaoyong He 366*72d1dea6SChaoyong He rte_spinlock_unlock(&hw->super.reconfig_lock); 36711e9eae4SChaoyong He 36811e9eae4SChaoyong He if (ret != 0) { 36911e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x", 37011e9eae4SChaoyong He mbox_cmd, NFP_NET_CFG_UPDATE_MBOX); 37111e9eae4SChaoyong He return -EIO; 37211e9eae4SChaoyong He } 37311e9eae4SChaoyong He 374f58bde00SChaoyong He return nn_cfg_readl(&hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET); 37511e9eae4SChaoyong He } 37611e9eae4SChaoyong He 37711e9eae4SChaoyong He /* 37811e9eae4SChaoyong He * Configure an Ethernet device. 37911e9eae4SChaoyong He * 38011e9eae4SChaoyong He * This function must be invoked first before any other function in the Ethernet API. 38111e9eae4SChaoyong He * This function can also be re-invoked when a device is in the stopped state. 38211e9eae4SChaoyong He * 38311e9eae4SChaoyong He * A DPDK app sends info about how many queues to use and how those queues 38411e9eae4SChaoyong He * need to be configured. This is used by the DPDK core and it makes sure no 38511e9eae4SChaoyong He * more queues than those advertised by the driver are requested. 38611e9eae4SChaoyong He * This function is called after that internal process. 38711e9eae4SChaoyong He */ 38811e9eae4SChaoyong He int 38911e9eae4SChaoyong He nfp_net_configure(struct rte_eth_dev *dev) 39011e9eae4SChaoyong He { 39111e9eae4SChaoyong He struct nfp_net_hw *hw; 39211e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 39311e9eae4SChaoyong He struct rte_eth_rxmode *rxmode; 39411e9eae4SChaoyong He struct rte_eth_txmode *txmode; 39511e9eae4SChaoyong He 39611e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 39711e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 39811e9eae4SChaoyong He rxmode = &dev_conf->rxmode; 39911e9eae4SChaoyong He txmode = &dev_conf->txmode; 40011e9eae4SChaoyong He 40111e9eae4SChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0) 40211e9eae4SChaoyong He rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 40311e9eae4SChaoyong He 40411e9eae4SChaoyong He /* Checking TX mode */ 40511e9eae4SChaoyong He if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) { 40611e9eae4SChaoyong He PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported"); 40711e9eae4SChaoyong He return -EINVAL; 40811e9eae4SChaoyong He } 40911e9eae4SChaoyong He 41011e9eae4SChaoyong He /* Checking RX mode */ 41111e9eae4SChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 && 41275a76c73SChaoyong He (hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) { 41311e9eae4SChaoyong He PMD_DRV_LOG(ERR, "RSS not supported"); 41411e9eae4SChaoyong He return -EINVAL; 41511e9eae4SChaoyong He } 41611e9eae4SChaoyong He 41711e9eae4SChaoyong He /* Checking MTU set */ 41811e9eae4SChaoyong He if (rxmode->mtu > NFP_FRAME_SIZE_MAX) { 41911e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MTU (%u) larger than NFP_FRAME_SIZE_MAX (%u)", 42011e9eae4SChaoyong He rxmode->mtu, NFP_FRAME_SIZE_MAX); 42111e9eae4SChaoyong He return -ERANGE; 42211e9eae4SChaoyong He } 42311e9eae4SChaoyong He 42411e9eae4SChaoyong He return 0; 42511e9eae4SChaoyong He } 42611e9eae4SChaoyong He 42711e9eae4SChaoyong He void 42811e9eae4SChaoyong He nfp_net_log_device_information(const struct nfp_net_hw *hw) 42911e9eae4SChaoyong He { 43075a76c73SChaoyong He uint32_t cap = hw->super.cap; 43175a76c73SChaoyong He 43211e9eae4SChaoyong He PMD_INIT_LOG(INFO, "VER: %u.%u, Maximum supported MTU: %d", 43311e9eae4SChaoyong He hw->ver.major, hw->ver.minor, hw->max_mtu); 43411e9eae4SChaoyong He 43575a76c73SChaoyong He PMD_INIT_LOG(INFO, "CAP: %#x, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cap, 43675a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "", 43775a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "", 43875a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_L2MC ? "L2MCFILT " : "", 43975a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXCSUM ? "RXCSUM " : "", 44075a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXCSUM ? "TXCSUM " : "", 44175a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXVLAN ? "RXVLAN " : "", 44275a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXVLAN ? "TXVLAN " : "", 44375a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ? "RXVLANv2 " : "", 44475a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXVLAN_V2 ? "TXVLANv2 " : "", 44575a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXQINQ ? "RXQINQ " : "", 44675a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_SCATTER ? "SCATTER " : "", 44775a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_GATHER ? "GATHER " : "", 44875a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "", 44975a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_LSO ? "TSO " : "", 45075a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_LSO2 ? "TSOv2 " : "", 45175a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RSS ? "RSS " : "", 45275a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RSS2 ? "RSSv2 " : ""); 45311e9eae4SChaoyong He 45411e9eae4SChaoyong He PMD_INIT_LOG(INFO, "max_rx_queues: %u, max_tx_queues: %u", 45511e9eae4SChaoyong He hw->max_rx_queues, hw->max_tx_queues); 45611e9eae4SChaoyong He } 45711e9eae4SChaoyong He 45811e9eae4SChaoyong He static inline void 45911e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(struct nfp_net_hw *hw, 46011e9eae4SChaoyong He uint32_t *ctrl) 46111e9eae4SChaoyong He { 46275a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) 46311e9eae4SChaoyong He *ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2; 46475a76c73SChaoyong He else if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN) != 0) 46511e9eae4SChaoyong He *ctrl |= NFP_NET_CFG_CTRL_RXVLAN; 46611e9eae4SChaoyong He } 46711e9eae4SChaoyong He 46811e9eae4SChaoyong He void 46911e9eae4SChaoyong He nfp_net_enable_queues(struct rte_eth_dev *dev) 47011e9eae4SChaoyong He { 47111e9eae4SChaoyong He uint16_t i; 47211e9eae4SChaoyong He struct nfp_net_hw *hw; 47311e9eae4SChaoyong He uint64_t enabled_queues; 47411e9eae4SChaoyong He 47511e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 47611e9eae4SChaoyong He 47711e9eae4SChaoyong He /* Enabling the required TX queues in the device */ 47811e9eae4SChaoyong He enabled_queues = 0; 47911e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) 48011e9eae4SChaoyong He enabled_queues |= (1 << i); 48111e9eae4SChaoyong He 482f58bde00SChaoyong He nn_cfg_writeq(&hw->super, NFP_NET_CFG_TXRS_ENABLE, enabled_queues); 48311e9eae4SChaoyong He 48411e9eae4SChaoyong He /* Enabling the required RX queues in the device */ 48511e9eae4SChaoyong He enabled_queues = 0; 48611e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) 48711e9eae4SChaoyong He enabled_queues |= (1 << i); 48811e9eae4SChaoyong He 489f58bde00SChaoyong He nn_cfg_writeq(&hw->super, NFP_NET_CFG_RXRS_ENABLE, enabled_queues); 49011e9eae4SChaoyong He } 49111e9eae4SChaoyong He 49211e9eae4SChaoyong He void 49311e9eae4SChaoyong He nfp_net_disable_queues(struct rte_eth_dev *dev) 49411e9eae4SChaoyong He { 49511e9eae4SChaoyong He uint32_t update; 49611e9eae4SChaoyong He uint32_t new_ctrl; 497*72d1dea6SChaoyong He struct nfp_hw *hw; 498*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 49911e9eae4SChaoyong He 500*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 501*72d1dea6SChaoyong He hw = &net_hw->super; 50211e9eae4SChaoyong He 503*72d1dea6SChaoyong He nn_cfg_writeq(hw, NFP_NET_CFG_TXRS_ENABLE, 0); 504*72d1dea6SChaoyong He nn_cfg_writeq(hw, NFP_NET_CFG_RXRS_ENABLE, 0); 50511e9eae4SChaoyong He 506*72d1dea6SChaoyong He new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_ENABLE; 50711e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN | 50811e9eae4SChaoyong He NFP_NET_CFG_UPDATE_RING | 50911e9eae4SChaoyong He NFP_NET_CFG_UPDATE_MSIX; 51011e9eae4SChaoyong He 511*72d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0) 51211e9eae4SChaoyong He new_ctrl &= ~NFP_NET_CFG_CTRL_RINGCFG; 51311e9eae4SChaoyong He 51411e9eae4SChaoyong He /* If an error when reconfig we avoid to change hw state */ 515*72d1dea6SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) 51611e9eae4SChaoyong He return; 51711e9eae4SChaoyong He 518*72d1dea6SChaoyong He hw->ctrl = new_ctrl; 51911e9eae4SChaoyong He } 52011e9eae4SChaoyong He 52111e9eae4SChaoyong He void 52211e9eae4SChaoyong He nfp_net_params_setup(struct nfp_net_hw *hw) 52311e9eae4SChaoyong He { 524f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, hw->mtu); 525f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_FLBUFSZ, hw->flbufsz); 52611e9eae4SChaoyong He } 52711e9eae4SChaoyong He 52811e9eae4SChaoyong He void 52911e9eae4SChaoyong He nfp_net_cfg_queue_setup(struct nfp_net_hw *hw) 53011e9eae4SChaoyong He { 531464a535bSChaoyong He hw->super.qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ; 53211e9eae4SChaoyong He } 53311e9eae4SChaoyong He 53411e9eae4SChaoyong He void 53511e9eae4SChaoyong He nfp_net_write_mac(struct nfp_net_hw *hw, 53611e9eae4SChaoyong He uint8_t *mac) 53711e9eae4SChaoyong He { 53811e9eae4SChaoyong He uint32_t mac0; 53911e9eae4SChaoyong He uint16_t mac1; 54011e9eae4SChaoyong He 54111e9eae4SChaoyong He mac0 = *(uint32_t *)mac; 5428980792dSChaoyong He nn_writel(rte_cpu_to_be_32(mac0), hw->super.ctrl_bar + NFP_NET_CFG_MACADDR); 54311e9eae4SChaoyong He 54411e9eae4SChaoyong He mac += 4; 54511e9eae4SChaoyong He mac1 = *(uint16_t *)mac; 54611e9eae4SChaoyong He nn_writew(rte_cpu_to_be_16(mac1), 5478980792dSChaoyong He hw->super.ctrl_bar + NFP_NET_CFG_MACADDR + 6); 54811e9eae4SChaoyong He } 54911e9eae4SChaoyong He 55011e9eae4SChaoyong He int 55111e9eae4SChaoyong He nfp_net_set_mac_addr(struct rte_eth_dev *dev, 55211e9eae4SChaoyong He struct rte_ether_addr *mac_addr) 55311e9eae4SChaoyong He { 55411e9eae4SChaoyong He uint32_t ctrl; 55511e9eae4SChaoyong He uint32_t update; 556*72d1dea6SChaoyong He struct nfp_hw *hw; 557*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 55811e9eae4SChaoyong He 559*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 560*72d1dea6SChaoyong He hw = &net_hw->super; 561*72d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 && 562*72d1dea6SChaoyong He (hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) { 56311e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MAC address unable to change when port enabled"); 56411e9eae4SChaoyong He return -EBUSY; 56511e9eae4SChaoyong He } 56611e9eae4SChaoyong He 56711e9eae4SChaoyong He /* Writing new MAC to the specific port BAR address */ 568*72d1dea6SChaoyong He nfp_net_write_mac(net_hw, (uint8_t *)mac_addr); 56911e9eae4SChaoyong He 57011e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_MACADDR; 571*72d1dea6SChaoyong He ctrl = hw->ctrl; 572*72d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 && 573*72d1dea6SChaoyong He (hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) != 0) 57411e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LIVE_ADDR; 57511e9eae4SChaoyong He 57611e9eae4SChaoyong He /* Signal the NIC about the change */ 577*72d1dea6SChaoyong He if (nfp_reconfig(hw, ctrl, update) != 0) { 57811e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MAC address update failed"); 57911e9eae4SChaoyong He return -EIO; 58011e9eae4SChaoyong He } 58111e9eae4SChaoyong He 58211e9eae4SChaoyong He return 0; 58311e9eae4SChaoyong He } 58411e9eae4SChaoyong He 58511e9eae4SChaoyong He int 58611e9eae4SChaoyong He nfp_configure_rx_interrupt(struct rte_eth_dev *dev, 58711e9eae4SChaoyong He struct rte_intr_handle *intr_handle) 58811e9eae4SChaoyong He { 58911e9eae4SChaoyong He uint16_t i; 59011e9eae4SChaoyong He struct nfp_net_hw *hw; 59111e9eae4SChaoyong He 59211e9eae4SChaoyong He if (rte_intr_vec_list_alloc(intr_handle, "intr_vec", 59311e9eae4SChaoyong He dev->data->nb_rx_queues) != 0) { 59411e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues intr_vec", 59511e9eae4SChaoyong He dev->data->nb_rx_queues); 59611e9eae4SChaoyong He return -ENOMEM; 59711e9eae4SChaoyong He } 59811e9eae4SChaoyong He 59911e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 60011e9eae4SChaoyong He 60111e9eae4SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 60211e9eae4SChaoyong He PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with UIO"); 60311e9eae4SChaoyong He /* UIO just supports one queue and no LSC */ 604f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(0), 0); 60511e9eae4SChaoyong He if (rte_intr_vec_list_index_set(intr_handle, 0, 0) != 0) 60611e9eae4SChaoyong He return -1; 60711e9eae4SChaoyong He } else { 60811e9eae4SChaoyong He PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with VFIO"); 60911e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 61011e9eae4SChaoyong He /* 61111e9eae4SChaoyong He * The first msix vector is reserved for non 61211e9eae4SChaoyong He * efd interrupts. 61311e9eae4SChaoyong He */ 614f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(i), i + 1); 61511e9eae4SChaoyong He if (rte_intr_vec_list_index_set(intr_handle, i, i + 1) != 0) 61611e9eae4SChaoyong He return -1; 61711e9eae4SChaoyong He } 61811e9eae4SChaoyong He } 61911e9eae4SChaoyong He 62011e9eae4SChaoyong He /* Avoiding TX interrupts */ 621b4b6988aSChaoyong He hw->super.ctrl |= NFP_NET_CFG_CTRL_MSIX_TX_OFF; 62211e9eae4SChaoyong He return 0; 62311e9eae4SChaoyong He } 62411e9eae4SChaoyong He 62511e9eae4SChaoyong He uint32_t 62611e9eae4SChaoyong He nfp_check_offloads(struct rte_eth_dev *dev) 62711e9eae4SChaoyong He { 62811e9eae4SChaoyong He uint32_t ctrl = 0; 62911e9eae4SChaoyong He uint64_t rx_offload; 63011e9eae4SChaoyong He uint64_t tx_offload; 63111e9eae4SChaoyong He struct nfp_net_hw *hw; 63211e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 63311e9eae4SChaoyong He 63411e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 63511e9eae4SChaoyong He 63611e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 63711e9eae4SChaoyong He rx_offload = dev_conf->rxmode.offloads; 63811e9eae4SChaoyong He tx_offload = dev_conf->txmode.offloads; 63911e9eae4SChaoyong He 64011e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0) { 64175a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXCSUM) != 0) 64211e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_RXCSUM; 64311e9eae4SChaoyong He } 64411e9eae4SChaoyong He 64511e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0) 64611e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(hw, &ctrl); 64711e9eae4SChaoyong He 64811e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) { 64975a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXQINQ) != 0) 65011e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_RXQINQ; 65111e9eae4SChaoyong He } 65211e9eae4SChaoyong He 65311e9eae4SChaoyong He hw->mtu = dev->data->mtu; 65411e9eae4SChaoyong He 65511e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) != 0) { 65675a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) 65711e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXVLAN_V2; 65875a76c73SChaoyong He else if ((hw->super.cap & NFP_NET_CFG_CTRL_TXVLAN) != 0) 65911e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXVLAN; 66011e9eae4SChaoyong He } 66111e9eae4SChaoyong He 66211e9eae4SChaoyong He /* L2 broadcast */ 66375a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_L2BC) != 0) 66411e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_L2BC; 66511e9eae4SChaoyong He 66611e9eae4SChaoyong He /* L2 multicast */ 66775a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_L2MC) != 0) 66811e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_L2MC; 66911e9eae4SChaoyong He 67011e9eae4SChaoyong He /* TX checksum offload */ 67111e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0 || 67211e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0 || 67311e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0) 67411e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXCSUM; 67511e9eae4SChaoyong He 67611e9eae4SChaoyong He /* LSO offload */ 67711e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0 || 67811e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) != 0) { 67975a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO) != 0) 68011e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LSO; 68111e9eae4SChaoyong He else 68211e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LSO2; 68311e9eae4SChaoyong He } 68411e9eae4SChaoyong He 68511e9eae4SChaoyong He /* RX gather */ 68611e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0) 68711e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_GATHER; 68811e9eae4SChaoyong He 68911e9eae4SChaoyong He return ctrl; 69011e9eae4SChaoyong He } 69111e9eae4SChaoyong He 69211e9eae4SChaoyong He int 69311e9eae4SChaoyong He nfp_net_promisc_enable(struct rte_eth_dev *dev) 69411e9eae4SChaoyong He { 69511e9eae4SChaoyong He int ret; 696*72d1dea6SChaoyong He uint32_t update; 69711e9eae4SChaoyong He uint32_t new_ctrl; 698*72d1dea6SChaoyong He struct nfp_hw *hw; 699*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 70011e9eae4SChaoyong He struct nfp_flower_representor *repr; 70111e9eae4SChaoyong He 70211e9eae4SChaoyong He if ((dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0) { 70311e9eae4SChaoyong He repr = dev->data->dev_private; 704*72d1dea6SChaoyong He net_hw = repr->app_fw_flower->pf_hw; 70511e9eae4SChaoyong He } else { 706*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 70711e9eae4SChaoyong He } 70811e9eae4SChaoyong He 709*72d1dea6SChaoyong He hw = &net_hw->super; 710*72d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) { 71111e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Promiscuous mode not supported"); 71211e9eae4SChaoyong He return -ENOTSUP; 71311e9eae4SChaoyong He } 71411e9eae4SChaoyong He 715*72d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) != 0) { 71611e9eae4SChaoyong He PMD_DRV_LOG(INFO, "Promiscuous mode already enabled"); 71711e9eae4SChaoyong He return 0; 71811e9eae4SChaoyong He } 71911e9eae4SChaoyong He 720*72d1dea6SChaoyong He new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_PROMISC; 72111e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 72211e9eae4SChaoyong He 723*72d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 72411e9eae4SChaoyong He if (ret != 0) 72511e9eae4SChaoyong He return ret; 72611e9eae4SChaoyong He 727*72d1dea6SChaoyong He hw->ctrl = new_ctrl; 72811e9eae4SChaoyong He 72911e9eae4SChaoyong He return 0; 73011e9eae4SChaoyong He } 73111e9eae4SChaoyong He 73211e9eae4SChaoyong He int 73311e9eae4SChaoyong He nfp_net_promisc_disable(struct rte_eth_dev *dev) 73411e9eae4SChaoyong He { 73511e9eae4SChaoyong He int ret; 736*72d1dea6SChaoyong He uint32_t update; 73711e9eae4SChaoyong He uint32_t new_ctrl; 738*72d1dea6SChaoyong He struct nfp_hw *hw; 739*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 74011e9eae4SChaoyong He 741*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 742*72d1dea6SChaoyong He hw = &net_hw->super; 74311e9eae4SChaoyong He 744*72d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) == 0) { 74511e9eae4SChaoyong He PMD_DRV_LOG(INFO, "Promiscuous mode already disabled"); 74611e9eae4SChaoyong He return 0; 74711e9eae4SChaoyong He } 74811e9eae4SChaoyong He 749*72d1dea6SChaoyong He new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_PROMISC; 75011e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 75111e9eae4SChaoyong He 752*72d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 75311e9eae4SChaoyong He if (ret != 0) 75411e9eae4SChaoyong He return ret; 75511e9eae4SChaoyong He 756*72d1dea6SChaoyong He hw->ctrl = new_ctrl; 75711e9eae4SChaoyong He 75811e9eae4SChaoyong He return 0; 75911e9eae4SChaoyong He } 76011e9eae4SChaoyong He 76111e9eae4SChaoyong He /* 76211e9eae4SChaoyong He * Return 0 means link status changed, -1 means not changed 76311e9eae4SChaoyong He * 76411e9eae4SChaoyong He * Wait to complete is needed as it can take up to 9 seconds to get the Link 76511e9eae4SChaoyong He * status. 76611e9eae4SChaoyong He */ 76711e9eae4SChaoyong He int 76811e9eae4SChaoyong He nfp_net_link_update(struct rte_eth_dev *dev, 76911e9eae4SChaoyong He __rte_unused int wait_to_complete) 77011e9eae4SChaoyong He { 77111e9eae4SChaoyong He int ret; 77211e9eae4SChaoyong He uint32_t i; 77311e9eae4SChaoyong He struct nfp_net_hw *hw; 77411e9eae4SChaoyong He uint32_t nn_link_status; 77511e9eae4SChaoyong He struct rte_eth_link link; 77611e9eae4SChaoyong He struct nfp_eth_table *nfp_eth_table; 77711e9eae4SChaoyong He 77811e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 77911e9eae4SChaoyong He 78011e9eae4SChaoyong He memset(&link, 0, sizeof(struct rte_eth_link)); 78111e9eae4SChaoyong He 78211e9eae4SChaoyong He /* Read link status */ 783f58bde00SChaoyong He nn_link_status = nn_cfg_readw(&hw->super, NFP_NET_CFG_STS); 78411e9eae4SChaoyong He if ((nn_link_status & NFP_NET_CFG_STS_LINK) != 0) 78511e9eae4SChaoyong He link.link_status = RTE_ETH_LINK_UP; 78611e9eae4SChaoyong He 78711e9eae4SChaoyong He link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 78811e9eae4SChaoyong He link.link_speed = RTE_ETH_SPEED_NUM_NONE; 78911e9eae4SChaoyong He 79011e9eae4SChaoyong He if (link.link_status == RTE_ETH_LINK_UP) { 79111e9eae4SChaoyong He if (hw->pf_dev != NULL) { 79211e9eae4SChaoyong He nfp_eth_table = hw->pf_dev->nfp_eth_table; 79311e9eae4SChaoyong He if (nfp_eth_table != NULL) { 79411e9eae4SChaoyong He uint32_t speed = nfp_eth_table->ports[hw->idx].speed; 79511e9eae4SChaoyong He for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) { 79611e9eae4SChaoyong He if (nfp_net_link_speed_nfp2rte[i] == speed) { 79711e9eae4SChaoyong He link.link_speed = speed; 79811e9eae4SChaoyong He break; 79911e9eae4SChaoyong He } 80011e9eae4SChaoyong He } 80111e9eae4SChaoyong He } 80211e9eae4SChaoyong He } else { 80311e9eae4SChaoyong He /* 80411e9eae4SChaoyong He * Shift and mask nn_link_status so that it is effectively the value 80511e9eae4SChaoyong He * at offset NFP_NET_CFG_STS_NSP_LINK_RATE. 80611e9eae4SChaoyong He */ 80711e9eae4SChaoyong He nn_link_status = (nn_link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) & 80811e9eae4SChaoyong He NFP_NET_CFG_STS_LINK_RATE_MASK; 80911e9eae4SChaoyong He if (nn_link_status < RTE_DIM(nfp_net_link_speed_nfp2rte)) 81011e9eae4SChaoyong He link.link_speed = nfp_net_link_speed_nfp2rte[nn_link_status]; 81111e9eae4SChaoyong He } 81211e9eae4SChaoyong He } 81311e9eae4SChaoyong He 81411e9eae4SChaoyong He ret = rte_eth_linkstatus_set(dev, &link); 81511e9eae4SChaoyong He if (ret == 0) { 81611e9eae4SChaoyong He if (link.link_status != 0) 81711e9eae4SChaoyong He PMD_DRV_LOG(INFO, "NIC Link is Up"); 81811e9eae4SChaoyong He else 81911e9eae4SChaoyong He PMD_DRV_LOG(INFO, "NIC Link is Down"); 82011e9eae4SChaoyong He } 82111e9eae4SChaoyong He 82211e9eae4SChaoyong He /* 82311e9eae4SChaoyong He * Notify the port to update the speed value in the CTRL BAR from NSP. 82411e9eae4SChaoyong He * Not applicable for VFs as the associated PF is still attached to the 82511e9eae4SChaoyong He * kernel driver. 82611e9eae4SChaoyong He */ 82711e9eae4SChaoyong He if (hw->pf_dev != NULL) 82811e9eae4SChaoyong He nfp_net_notify_port_speed(hw, &link); 82911e9eae4SChaoyong He 83011e9eae4SChaoyong He return ret; 83111e9eae4SChaoyong He } 83211e9eae4SChaoyong He 83311e9eae4SChaoyong He int 83411e9eae4SChaoyong He nfp_net_stats_get(struct rte_eth_dev *dev, 83511e9eae4SChaoyong He struct rte_eth_stats *stats) 83611e9eae4SChaoyong He { 83711e9eae4SChaoyong He uint16_t i; 83811e9eae4SChaoyong He struct nfp_net_hw *hw; 83911e9eae4SChaoyong He struct rte_eth_stats nfp_dev_stats; 84011e9eae4SChaoyong He 84111e9eae4SChaoyong He if (stats == NULL) 84211e9eae4SChaoyong He return -EINVAL; 84311e9eae4SChaoyong He 84411e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 84511e9eae4SChaoyong He 84611e9eae4SChaoyong He memset(&nfp_dev_stats, 0, sizeof(nfp_dev_stats)); 84711e9eae4SChaoyong He 84811e9eae4SChaoyong He /* Reading per RX ring stats */ 84911e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 85011e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 85111e9eae4SChaoyong He break; 85211e9eae4SChaoyong He 85311e9eae4SChaoyong He nfp_dev_stats.q_ipackets[i] = 854f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i)); 85511e9eae4SChaoyong He nfp_dev_stats.q_ipackets[i] -= 85611e9eae4SChaoyong He hw->eth_stats_base.q_ipackets[i]; 85711e9eae4SChaoyong He 85811e9eae4SChaoyong He nfp_dev_stats.q_ibytes[i] = 859f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8); 86011e9eae4SChaoyong He nfp_dev_stats.q_ibytes[i] -= 86111e9eae4SChaoyong He hw->eth_stats_base.q_ibytes[i]; 86211e9eae4SChaoyong He } 86311e9eae4SChaoyong He 86411e9eae4SChaoyong He /* Reading per TX ring stats */ 86511e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 86611e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 86711e9eae4SChaoyong He break; 86811e9eae4SChaoyong He 86911e9eae4SChaoyong He nfp_dev_stats.q_opackets[i] = 870f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i)); 87111e9eae4SChaoyong He nfp_dev_stats.q_opackets[i] -= hw->eth_stats_base.q_opackets[i]; 87211e9eae4SChaoyong He 87311e9eae4SChaoyong He nfp_dev_stats.q_obytes[i] = 874f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8); 87511e9eae4SChaoyong He nfp_dev_stats.q_obytes[i] -= hw->eth_stats_base.q_obytes[i]; 87611e9eae4SChaoyong He } 87711e9eae4SChaoyong He 878f58bde00SChaoyong He nfp_dev_stats.ipackets = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES); 87911e9eae4SChaoyong He nfp_dev_stats.ipackets -= hw->eth_stats_base.ipackets; 88011e9eae4SChaoyong He 881f58bde00SChaoyong He nfp_dev_stats.ibytes = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS); 88211e9eae4SChaoyong He nfp_dev_stats.ibytes -= hw->eth_stats_base.ibytes; 88311e9eae4SChaoyong He 88411e9eae4SChaoyong He nfp_dev_stats.opackets = 885f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES); 88611e9eae4SChaoyong He nfp_dev_stats.opackets -= hw->eth_stats_base.opackets; 88711e9eae4SChaoyong He 88811e9eae4SChaoyong He nfp_dev_stats.obytes = 889f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS); 89011e9eae4SChaoyong He nfp_dev_stats.obytes -= hw->eth_stats_base.obytes; 89111e9eae4SChaoyong He 89211e9eae4SChaoyong He /* Reading general device stats */ 89311e9eae4SChaoyong He nfp_dev_stats.ierrors = 894f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS); 89511e9eae4SChaoyong He nfp_dev_stats.ierrors -= hw->eth_stats_base.ierrors; 89611e9eae4SChaoyong He 89711e9eae4SChaoyong He nfp_dev_stats.oerrors = 898f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS); 89911e9eae4SChaoyong He nfp_dev_stats.oerrors -= hw->eth_stats_base.oerrors; 90011e9eae4SChaoyong He 90111e9eae4SChaoyong He /* RX ring mbuf allocation failures */ 90211e9eae4SChaoyong He nfp_dev_stats.rx_nombuf = dev->data->rx_mbuf_alloc_failed; 90311e9eae4SChaoyong He 90411e9eae4SChaoyong He nfp_dev_stats.imissed = 905f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS); 90611e9eae4SChaoyong He nfp_dev_stats.imissed -= hw->eth_stats_base.imissed; 90711e9eae4SChaoyong He 90811e9eae4SChaoyong He memcpy(stats, &nfp_dev_stats, sizeof(*stats)); 90911e9eae4SChaoyong He return 0; 91011e9eae4SChaoyong He } 91111e9eae4SChaoyong He 91211e9eae4SChaoyong He /* 91311e9eae4SChaoyong He * hw->eth_stats_base records the per counter starting point. 91411e9eae4SChaoyong He * Lets update it now. 91511e9eae4SChaoyong He */ 91611e9eae4SChaoyong He int 91711e9eae4SChaoyong He nfp_net_stats_reset(struct rte_eth_dev *dev) 91811e9eae4SChaoyong He { 91911e9eae4SChaoyong He uint16_t i; 92011e9eae4SChaoyong He struct nfp_net_hw *hw; 92111e9eae4SChaoyong He 92211e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 92311e9eae4SChaoyong He 92411e9eae4SChaoyong He /* Reading per RX ring stats */ 92511e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 92611e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 92711e9eae4SChaoyong He break; 92811e9eae4SChaoyong He 92911e9eae4SChaoyong He hw->eth_stats_base.q_ipackets[i] = 930f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i)); 93111e9eae4SChaoyong He 93211e9eae4SChaoyong He hw->eth_stats_base.q_ibytes[i] = 933f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8); 93411e9eae4SChaoyong He } 93511e9eae4SChaoyong He 93611e9eae4SChaoyong He /* Reading per TX ring stats */ 93711e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 93811e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 93911e9eae4SChaoyong He break; 94011e9eae4SChaoyong He 94111e9eae4SChaoyong He hw->eth_stats_base.q_opackets[i] = 942f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i)); 94311e9eae4SChaoyong He 94411e9eae4SChaoyong He hw->eth_stats_base.q_obytes[i] = 945f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8); 94611e9eae4SChaoyong He } 94711e9eae4SChaoyong He 94811e9eae4SChaoyong He hw->eth_stats_base.ipackets = 949f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES); 95011e9eae4SChaoyong He 95111e9eae4SChaoyong He hw->eth_stats_base.ibytes = 952f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS); 95311e9eae4SChaoyong He 95411e9eae4SChaoyong He hw->eth_stats_base.opackets = 955f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES); 95611e9eae4SChaoyong He 95711e9eae4SChaoyong He hw->eth_stats_base.obytes = 958f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS); 95911e9eae4SChaoyong He 96011e9eae4SChaoyong He /* Reading general device stats */ 96111e9eae4SChaoyong He hw->eth_stats_base.ierrors = 962f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS); 96311e9eae4SChaoyong He 96411e9eae4SChaoyong He hw->eth_stats_base.oerrors = 965f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS); 96611e9eae4SChaoyong He 96711e9eae4SChaoyong He /* RX ring mbuf allocation failures */ 96811e9eae4SChaoyong He dev->data->rx_mbuf_alloc_failed = 0; 96911e9eae4SChaoyong He 97011e9eae4SChaoyong He hw->eth_stats_base.imissed = 971f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS); 97211e9eae4SChaoyong He 97311e9eae4SChaoyong He return 0; 97411e9eae4SChaoyong He } 97511e9eae4SChaoyong He 97611e9eae4SChaoyong He uint32_t 97711e9eae4SChaoyong He nfp_net_xstats_size(const struct rte_eth_dev *dev) 97811e9eae4SChaoyong He { 97911e9eae4SChaoyong He uint32_t count; 98011e9eae4SChaoyong He struct nfp_net_hw *hw; 98111e9eae4SChaoyong He const uint32_t size = RTE_DIM(nfp_net_xstats); 98211e9eae4SChaoyong He 98311e9eae4SChaoyong He /* If the device is a VF, then there will be no MAC stats */ 98411e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 98511e9eae4SChaoyong He if (hw->mac_stats == NULL) { 98611e9eae4SChaoyong He for (count = 0; count < size; count++) { 98711e9eae4SChaoyong He if (nfp_net_xstats[count].group == NFP_XSTAT_GROUP_MAC) 98811e9eae4SChaoyong He break; 98911e9eae4SChaoyong He } 99011e9eae4SChaoyong He 99111e9eae4SChaoyong He return count; 99211e9eae4SChaoyong He } 99311e9eae4SChaoyong He 99411e9eae4SChaoyong He return size; 99511e9eae4SChaoyong He } 99611e9eae4SChaoyong He 99711e9eae4SChaoyong He static const struct nfp_xstat * 99811e9eae4SChaoyong He nfp_net_xstats_info(const struct rte_eth_dev *dev, 99911e9eae4SChaoyong He uint32_t index) 100011e9eae4SChaoyong He { 100111e9eae4SChaoyong He if (index >= nfp_net_xstats_size(dev)) { 100211e9eae4SChaoyong He PMD_DRV_LOG(ERR, "xstat index out of bounds"); 100311e9eae4SChaoyong He return NULL; 100411e9eae4SChaoyong He } 100511e9eae4SChaoyong He 100611e9eae4SChaoyong He return &nfp_net_xstats[index]; 100711e9eae4SChaoyong He } 100811e9eae4SChaoyong He 100911e9eae4SChaoyong He static uint64_t 101011e9eae4SChaoyong He nfp_net_xstats_value(const struct rte_eth_dev *dev, 101111e9eae4SChaoyong He uint32_t index, 101211e9eae4SChaoyong He bool raw) 101311e9eae4SChaoyong He { 101411e9eae4SChaoyong He uint64_t value; 101511e9eae4SChaoyong He struct nfp_net_hw *hw; 101611e9eae4SChaoyong He struct nfp_xstat xstat; 101711e9eae4SChaoyong He 101811e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 101911e9eae4SChaoyong He xstat = nfp_net_xstats[index]; 102011e9eae4SChaoyong He 102111e9eae4SChaoyong He if (xstat.group == NFP_XSTAT_GROUP_MAC) 102211e9eae4SChaoyong He value = nn_readq(hw->mac_stats + xstat.offset); 102311e9eae4SChaoyong He else 1024f58bde00SChaoyong He value = nn_cfg_readq(&hw->super, xstat.offset); 102511e9eae4SChaoyong He 102611e9eae4SChaoyong He if (raw) 102711e9eae4SChaoyong He return value; 102811e9eae4SChaoyong He 102911e9eae4SChaoyong He /* 103011e9eae4SChaoyong He * A baseline value of each statistic counter is recorded when stats are "reset". 103111e9eae4SChaoyong He * Thus, the value returned by this function need to be decremented by this 103211e9eae4SChaoyong He * baseline value. The result is the count of this statistic since the last time 103311e9eae4SChaoyong He * it was "reset". 103411e9eae4SChaoyong He */ 103511e9eae4SChaoyong He return value - hw->eth_xstats_base[index].value; 103611e9eae4SChaoyong He } 103711e9eae4SChaoyong He 103811e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */ 103911e9eae4SChaoyong He int 104011e9eae4SChaoyong He nfp_net_xstats_get_names(struct rte_eth_dev *dev, 104111e9eae4SChaoyong He struct rte_eth_xstat_name *xstats_names, 104211e9eae4SChaoyong He unsigned int size) 104311e9eae4SChaoyong He { 104411e9eae4SChaoyong He uint32_t id; 104511e9eae4SChaoyong He uint32_t nfp_size; 104611e9eae4SChaoyong He uint32_t read_size; 104711e9eae4SChaoyong He 104811e9eae4SChaoyong He nfp_size = nfp_net_xstats_size(dev); 104911e9eae4SChaoyong He 105011e9eae4SChaoyong He if (xstats_names == NULL) 105111e9eae4SChaoyong He return nfp_size; 105211e9eae4SChaoyong He 105311e9eae4SChaoyong He /* Read at most NFP xstats number of names. */ 105411e9eae4SChaoyong He read_size = RTE_MIN(size, nfp_size); 105511e9eae4SChaoyong He 105611e9eae4SChaoyong He for (id = 0; id < read_size; id++) 105711e9eae4SChaoyong He rte_strlcpy(xstats_names[id].name, nfp_net_xstats[id].name, 105811e9eae4SChaoyong He RTE_ETH_XSTATS_NAME_SIZE); 105911e9eae4SChaoyong He 106011e9eae4SChaoyong He return read_size; 106111e9eae4SChaoyong He } 106211e9eae4SChaoyong He 106311e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */ 106411e9eae4SChaoyong He int 106511e9eae4SChaoyong He nfp_net_xstats_get(struct rte_eth_dev *dev, 106611e9eae4SChaoyong He struct rte_eth_xstat *xstats, 106711e9eae4SChaoyong He unsigned int n) 106811e9eae4SChaoyong He { 106911e9eae4SChaoyong He uint32_t id; 107011e9eae4SChaoyong He uint32_t nfp_size; 107111e9eae4SChaoyong He uint32_t read_size; 107211e9eae4SChaoyong He 107311e9eae4SChaoyong He nfp_size = nfp_net_xstats_size(dev); 107411e9eae4SChaoyong He 107511e9eae4SChaoyong He if (xstats == NULL) 107611e9eae4SChaoyong He return nfp_size; 107711e9eae4SChaoyong He 107811e9eae4SChaoyong He /* Read at most NFP xstats number of values. */ 107911e9eae4SChaoyong He read_size = RTE_MIN(n, nfp_size); 108011e9eae4SChaoyong He 108111e9eae4SChaoyong He for (id = 0; id < read_size; id++) { 108211e9eae4SChaoyong He xstats[id].id = id; 108311e9eae4SChaoyong He xstats[id].value = nfp_net_xstats_value(dev, id, false); 108411e9eae4SChaoyong He } 108511e9eae4SChaoyong He 108611e9eae4SChaoyong He return read_size; 108711e9eae4SChaoyong He } 108811e9eae4SChaoyong He 108911e9eae4SChaoyong He /* 109011e9eae4SChaoyong He * NOTE: The only caller rte_eth_xstats_get_names_by_id() ensures dev, 109111e9eae4SChaoyong He * ids, xstats_names and size are valid, and non-NULL. 109211e9eae4SChaoyong He */ 109311e9eae4SChaoyong He int 109411e9eae4SChaoyong He nfp_net_xstats_get_names_by_id(struct rte_eth_dev *dev, 109511e9eae4SChaoyong He const uint64_t *ids, 109611e9eae4SChaoyong He struct rte_eth_xstat_name *xstats_names, 109711e9eae4SChaoyong He unsigned int size) 109811e9eae4SChaoyong He { 109911e9eae4SChaoyong He uint32_t i; 110011e9eae4SChaoyong He uint32_t read_size; 110111e9eae4SChaoyong He 110211e9eae4SChaoyong He /* Read at most NFP xstats number of names. */ 110311e9eae4SChaoyong He read_size = RTE_MIN(size, nfp_net_xstats_size(dev)); 110411e9eae4SChaoyong He 110511e9eae4SChaoyong He for (i = 0; i < read_size; i++) { 110611e9eae4SChaoyong He const struct nfp_xstat *xstat; 110711e9eae4SChaoyong He 110811e9eae4SChaoyong He /* Make sure ID is valid for device. */ 110911e9eae4SChaoyong He xstat = nfp_net_xstats_info(dev, ids[i]); 111011e9eae4SChaoyong He if (xstat == NULL) 111111e9eae4SChaoyong He return -EINVAL; 111211e9eae4SChaoyong He 111311e9eae4SChaoyong He rte_strlcpy(xstats_names[i].name, xstat->name, 111411e9eae4SChaoyong He RTE_ETH_XSTATS_NAME_SIZE); 111511e9eae4SChaoyong He } 111611e9eae4SChaoyong He 111711e9eae4SChaoyong He return read_size; 111811e9eae4SChaoyong He } 111911e9eae4SChaoyong He 112011e9eae4SChaoyong He /* 112111e9eae4SChaoyong He * NOTE: The only caller rte_eth_xstats_get_by_id() ensures dev, 112211e9eae4SChaoyong He * ids, values and n are valid, and non-NULL. 112311e9eae4SChaoyong He */ 112411e9eae4SChaoyong He int 112511e9eae4SChaoyong He nfp_net_xstats_get_by_id(struct rte_eth_dev *dev, 112611e9eae4SChaoyong He const uint64_t *ids, 112711e9eae4SChaoyong He uint64_t *values, 112811e9eae4SChaoyong He unsigned int n) 112911e9eae4SChaoyong He { 113011e9eae4SChaoyong He uint32_t i; 113111e9eae4SChaoyong He uint32_t read_size; 113211e9eae4SChaoyong He 113311e9eae4SChaoyong He /* Read at most NFP xstats number of values. */ 113411e9eae4SChaoyong He read_size = RTE_MIN(n, nfp_net_xstats_size(dev)); 113511e9eae4SChaoyong He 113611e9eae4SChaoyong He for (i = 0; i < read_size; i++) { 113711e9eae4SChaoyong He const struct nfp_xstat *xstat; 113811e9eae4SChaoyong He 113911e9eae4SChaoyong He /* Make sure index is valid for device. */ 114011e9eae4SChaoyong He xstat = nfp_net_xstats_info(dev, ids[i]); 114111e9eae4SChaoyong He if (xstat == NULL) 114211e9eae4SChaoyong He return -EINVAL; 114311e9eae4SChaoyong He 114411e9eae4SChaoyong He values[i] = nfp_net_xstats_value(dev, ids[i], false); 114511e9eae4SChaoyong He } 114611e9eae4SChaoyong He 114711e9eae4SChaoyong He return read_size; 114811e9eae4SChaoyong He } 114911e9eae4SChaoyong He 115011e9eae4SChaoyong He int 115111e9eae4SChaoyong He nfp_net_xstats_reset(struct rte_eth_dev *dev) 115211e9eae4SChaoyong He { 115311e9eae4SChaoyong He uint32_t id; 115411e9eae4SChaoyong He uint32_t read_size; 115511e9eae4SChaoyong He struct nfp_net_hw *hw; 115611e9eae4SChaoyong He 115711e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 115811e9eae4SChaoyong He read_size = nfp_net_xstats_size(dev); 115911e9eae4SChaoyong He 116011e9eae4SChaoyong He for (id = 0; id < read_size; id++) { 116111e9eae4SChaoyong He hw->eth_xstats_base[id].id = id; 116211e9eae4SChaoyong He hw->eth_xstats_base[id].value = nfp_net_xstats_value(dev, id, true); 116311e9eae4SChaoyong He } 116411e9eae4SChaoyong He 116511e9eae4SChaoyong He /* Successfully reset xstats, now call function to reset basic stats. */ 116611e9eae4SChaoyong He return nfp_net_stats_reset(dev); 116711e9eae4SChaoyong He } 116811e9eae4SChaoyong He 116911e9eae4SChaoyong He void 117011e9eae4SChaoyong He nfp_net_rx_desc_limits(struct nfp_net_hw *hw, 117111e9eae4SChaoyong He uint16_t *min_rx_desc, 117211e9eae4SChaoyong He uint16_t *max_rx_desc) 117311e9eae4SChaoyong He { 117411e9eae4SChaoyong He *max_rx_desc = hw->dev_info->max_qc_size; 117511e9eae4SChaoyong He *min_rx_desc = hw->dev_info->min_qc_size; 117611e9eae4SChaoyong He } 117711e9eae4SChaoyong He 117811e9eae4SChaoyong He void 117911e9eae4SChaoyong He nfp_net_tx_desc_limits(struct nfp_net_hw *hw, 118011e9eae4SChaoyong He uint16_t *min_tx_desc, 118111e9eae4SChaoyong He uint16_t *max_tx_desc) 118211e9eae4SChaoyong He { 118311e9eae4SChaoyong He uint16_t tx_dpp; 118411e9eae4SChaoyong He 118511e9eae4SChaoyong He if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 118611e9eae4SChaoyong He tx_dpp = NFD3_TX_DESC_PER_PKT; 118711e9eae4SChaoyong He else 118811e9eae4SChaoyong He tx_dpp = NFDK_TX_DESC_PER_SIMPLE_PKT; 118911e9eae4SChaoyong He 119011e9eae4SChaoyong He *max_tx_desc = hw->dev_info->max_qc_size / tx_dpp; 119111e9eae4SChaoyong He *min_tx_desc = hw->dev_info->min_qc_size / tx_dpp; 119211e9eae4SChaoyong He } 119311e9eae4SChaoyong He 119411e9eae4SChaoyong He int 119511e9eae4SChaoyong He nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 119611e9eae4SChaoyong He { 119711e9eae4SChaoyong He uint32_t cap_extend; 119811e9eae4SChaoyong He uint16_t min_rx_desc; 119911e9eae4SChaoyong He uint16_t max_rx_desc; 120011e9eae4SChaoyong He uint16_t min_tx_desc; 120111e9eae4SChaoyong He uint16_t max_tx_desc; 120211e9eae4SChaoyong He struct nfp_net_hw *hw; 120311e9eae4SChaoyong He 120411e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 120511e9eae4SChaoyong He 120611e9eae4SChaoyong He nfp_net_rx_desc_limits(hw, &min_rx_desc, &max_rx_desc); 120711e9eae4SChaoyong He nfp_net_tx_desc_limits(hw, &min_tx_desc, &max_tx_desc); 120811e9eae4SChaoyong He 120911e9eae4SChaoyong He dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues; 121011e9eae4SChaoyong He dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues; 121111e9eae4SChaoyong He dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU; 121211e9eae4SChaoyong He 121311e9eae4SChaoyong He /** 121411e9eae4SChaoyong He * The maximum rx packet length (max_rx_pktlen) is set to the 121511e9eae4SChaoyong He * maximum supported frame size that the NFP can handle. This 121611e9eae4SChaoyong He * includes layer 2 headers, CRC and other metadata that can 121711e9eae4SChaoyong He * optionally be used. 121811e9eae4SChaoyong He * The maximum layer 3 MTU (max_mtu) is read from hardware, 121911e9eae4SChaoyong He * which was set by the firmware loaded onto the card. 122011e9eae4SChaoyong He */ 122111e9eae4SChaoyong He dev_info->max_rx_pktlen = NFP_FRAME_SIZE_MAX; 122211e9eae4SChaoyong He dev_info->max_mtu = hw->max_mtu; 122311e9eae4SChaoyong He dev_info->min_mtu = RTE_ETHER_MIN_MTU; 122411e9eae4SChaoyong He /* Next should change when PF support is implemented */ 122511e9eae4SChaoyong He dev_info->max_mac_addrs = 1; 122611e9eae4SChaoyong He 122775a76c73SChaoyong He if ((hw->super.cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) != 0) 122811e9eae4SChaoyong He dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 122911e9eae4SChaoyong He 123075a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXQINQ) != 0) 123111e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP; 123211e9eae4SChaoyong He 123375a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXCSUM) != 0) 123411e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | 123511e9eae4SChaoyong He RTE_ETH_RX_OFFLOAD_UDP_CKSUM | 123611e9eae4SChaoyong He RTE_ETH_RX_OFFLOAD_TCP_CKSUM; 123711e9eae4SChaoyong He 123875a76c73SChaoyong He if ((hw->super.cap & (NFP_NET_CFG_CTRL_TXVLAN | NFP_NET_CFG_CTRL_TXVLAN_V2)) != 0) 123911e9eae4SChaoyong He dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT; 124011e9eae4SChaoyong He 124175a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_TXCSUM) != 0) 124211e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | 124311e9eae4SChaoyong He RTE_ETH_TX_OFFLOAD_UDP_CKSUM | 124411e9eae4SChaoyong He RTE_ETH_TX_OFFLOAD_TCP_CKSUM; 124511e9eae4SChaoyong He 124675a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0) { 124711e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO; 124875a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_VXLAN) != 0) 124911e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO; 125011e9eae4SChaoyong He } 125111e9eae4SChaoyong He 125275a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_GATHER) != 0) 125311e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 125411e9eae4SChaoyong He 125575a76c73SChaoyong He cap_extend = hw->super.cap_ext; 125611e9eae4SChaoyong He if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) { 125711e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY; 125811e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY; 125911e9eae4SChaoyong He } 126011e9eae4SChaoyong He 126111e9eae4SChaoyong He dev_info->default_rxconf = (struct rte_eth_rxconf) { 126211e9eae4SChaoyong He .rx_thresh = { 126311e9eae4SChaoyong He .pthresh = DEFAULT_RX_PTHRESH, 126411e9eae4SChaoyong He .hthresh = DEFAULT_RX_HTHRESH, 126511e9eae4SChaoyong He .wthresh = DEFAULT_RX_WTHRESH, 126611e9eae4SChaoyong He }, 126711e9eae4SChaoyong He .rx_free_thresh = DEFAULT_RX_FREE_THRESH, 126811e9eae4SChaoyong He .rx_drop_en = 0, 126911e9eae4SChaoyong He }; 127011e9eae4SChaoyong He 127111e9eae4SChaoyong He dev_info->default_txconf = (struct rte_eth_txconf) { 127211e9eae4SChaoyong He .tx_thresh = { 127311e9eae4SChaoyong He .pthresh = DEFAULT_TX_PTHRESH, 127411e9eae4SChaoyong He .hthresh = DEFAULT_TX_HTHRESH, 127511e9eae4SChaoyong He .wthresh = DEFAULT_TX_WTHRESH, 127611e9eae4SChaoyong He }, 127711e9eae4SChaoyong He .tx_free_thresh = DEFAULT_TX_FREE_THRESH, 127811e9eae4SChaoyong He .tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH, 127911e9eae4SChaoyong He }; 128011e9eae4SChaoyong He 128111e9eae4SChaoyong He dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 128211e9eae4SChaoyong He .nb_max = max_rx_desc, 128311e9eae4SChaoyong He .nb_min = min_rx_desc, 128411e9eae4SChaoyong He .nb_align = NFP_ALIGN_RING_DESC, 128511e9eae4SChaoyong He }; 128611e9eae4SChaoyong He 128711e9eae4SChaoyong He dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 128811e9eae4SChaoyong He .nb_max = max_tx_desc, 128911e9eae4SChaoyong He .nb_min = min_tx_desc, 129011e9eae4SChaoyong He .nb_align = NFP_ALIGN_RING_DESC, 129111e9eae4SChaoyong He .nb_seg_max = NFP_TX_MAX_SEG, 129211e9eae4SChaoyong He .nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG, 129311e9eae4SChaoyong He }; 129411e9eae4SChaoyong He 129575a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) { 129611e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 129711e9eae4SChaoyong He 129811e9eae4SChaoyong He dev_info->flow_type_rss_offloads = RTE_ETH_RSS_IPV4 | 129911e9eae4SChaoyong He RTE_ETH_RSS_NONFRAG_IPV4_TCP | 130011e9eae4SChaoyong He RTE_ETH_RSS_NONFRAG_IPV4_UDP | 130111e9eae4SChaoyong He RTE_ETH_RSS_NONFRAG_IPV4_SCTP | 130211e9eae4SChaoyong He RTE_ETH_RSS_IPV6 | 130311e9eae4SChaoyong He RTE_ETH_RSS_NONFRAG_IPV6_TCP | 130411e9eae4SChaoyong He RTE_ETH_RSS_NONFRAG_IPV6_UDP | 130511e9eae4SChaoyong He RTE_ETH_RSS_NONFRAG_IPV6_SCTP; 130611e9eae4SChaoyong He 130711e9eae4SChaoyong He dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ; 130811e9eae4SChaoyong He dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ; 130911e9eae4SChaoyong He } 131011e9eae4SChaoyong He 131111e9eae4SChaoyong He dev_info->speed_capa = RTE_ETH_LINK_SPEED_1G | 131211e9eae4SChaoyong He RTE_ETH_LINK_SPEED_10G | 131311e9eae4SChaoyong He RTE_ETH_LINK_SPEED_25G | 131411e9eae4SChaoyong He RTE_ETH_LINK_SPEED_40G | 131511e9eae4SChaoyong He RTE_ETH_LINK_SPEED_50G | 131611e9eae4SChaoyong He RTE_ETH_LINK_SPEED_100G; 131711e9eae4SChaoyong He 131811e9eae4SChaoyong He return 0; 131911e9eae4SChaoyong He } 132011e9eae4SChaoyong He 132111e9eae4SChaoyong He int 132211e9eae4SChaoyong He nfp_net_common_init(struct rte_pci_device *pci_dev, 132311e9eae4SChaoyong He struct nfp_net_hw *hw) 132411e9eae4SChaoyong He { 132511e9eae4SChaoyong He const int stride = 4; 132611e9eae4SChaoyong He 132711e9eae4SChaoyong He hw->device_id = pci_dev->id.device_id; 132811e9eae4SChaoyong He hw->vendor_id = pci_dev->id.vendor_id; 132911e9eae4SChaoyong He hw->subsystem_device_id = pci_dev->id.subsystem_device_id; 133011e9eae4SChaoyong He hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; 133111e9eae4SChaoyong He 1332f58bde00SChaoyong He hw->max_rx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_RXRINGS); 1333f58bde00SChaoyong He hw->max_tx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_TXRINGS); 133411e9eae4SChaoyong He if (hw->max_rx_queues == 0 || hw->max_tx_queues == 0) { 133511e9eae4SChaoyong He PMD_INIT_LOG(ERR, "Device %s can not be used, there are no valid queue " 133611e9eae4SChaoyong He "pairs for use", pci_dev->name); 133711e9eae4SChaoyong He return -ENODEV; 133811e9eae4SChaoyong He } 133911e9eae4SChaoyong He 134011e9eae4SChaoyong He nfp_net_cfg_read_version(hw); 134111e9eae4SChaoyong He if (!nfp_net_is_valid_nfd_version(hw->ver)) 134211e9eae4SChaoyong He return -EINVAL; 134311e9eae4SChaoyong He 134411e9eae4SChaoyong He if (nfp_net_check_dma_mask(hw, pci_dev->name) != 0) 134511e9eae4SChaoyong He return -ENODEV; 134611e9eae4SChaoyong He 134711e9eae4SChaoyong He /* Get some of the read-only fields from the config BAR */ 1348f58bde00SChaoyong He hw->super.cap = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP); 1349f58bde00SChaoyong He hw->super.cap_ext = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP_WORD1); 1350f58bde00SChaoyong He hw->max_mtu = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_MTU); 135111e9eae4SChaoyong He hw->flbufsz = DEFAULT_FLBUF_SIZE; 135211e9eae4SChaoyong He 135311e9eae4SChaoyong He nfp_net_init_metadata_format(hw); 135411e9eae4SChaoyong He 135511e9eae4SChaoyong He /* Read the Rx offset configured from firmware */ 135611e9eae4SChaoyong He if (hw->ver.major < 2) 135711e9eae4SChaoyong He hw->rx_offset = NFP_NET_RX_OFFSET; 135811e9eae4SChaoyong He else 1359f58bde00SChaoyong He hw->rx_offset = nn_cfg_readl(&hw->super, NFP_NET_CFG_RX_OFFSET_ADDR); 136011e9eae4SChaoyong He 1361b4b6988aSChaoyong He hw->super.ctrl = 0; 136211e9eae4SChaoyong He hw->stride_rx = stride; 136311e9eae4SChaoyong He hw->stride_tx = stride; 136411e9eae4SChaoyong He 136511e9eae4SChaoyong He return 0; 136611e9eae4SChaoyong He } 136711e9eae4SChaoyong He 136811e9eae4SChaoyong He const uint32_t * 136911e9eae4SChaoyong He nfp_net_supported_ptypes_get(struct rte_eth_dev *dev) 137011e9eae4SChaoyong He { 137111e9eae4SChaoyong He struct nfp_net_hw *net_hw; 137211e9eae4SChaoyong He static const uint32_t ptypes[] = { 137311e9eae4SChaoyong He RTE_PTYPE_L2_ETHER, 137411e9eae4SChaoyong He RTE_PTYPE_L3_IPV4, 137511e9eae4SChaoyong He RTE_PTYPE_L3_IPV4_EXT, 137611e9eae4SChaoyong He RTE_PTYPE_L3_IPV6, 137711e9eae4SChaoyong He RTE_PTYPE_L3_IPV6_EXT, 137811e9eae4SChaoyong He RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 137911e9eae4SChaoyong He RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 138011e9eae4SChaoyong He RTE_PTYPE_L4_TCP, 138111e9eae4SChaoyong He RTE_PTYPE_L4_UDP, 138211e9eae4SChaoyong He RTE_PTYPE_L4_FRAG, 138311e9eae4SChaoyong He RTE_PTYPE_L4_NONFRAG, 138411e9eae4SChaoyong He RTE_PTYPE_L4_ICMP, 138511e9eae4SChaoyong He RTE_PTYPE_L4_SCTP, 138611e9eae4SChaoyong He RTE_PTYPE_TUNNEL_VXLAN, 138711e9eae4SChaoyong He RTE_PTYPE_TUNNEL_NVGRE, 138811e9eae4SChaoyong He RTE_PTYPE_TUNNEL_GENEVE, 138911e9eae4SChaoyong He RTE_PTYPE_INNER_L2_ETHER, 139011e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4, 139111e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4_EXT, 139211e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6, 139311e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6_EXT, 139411e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 139511e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 139611e9eae4SChaoyong He RTE_PTYPE_INNER_L4_TCP, 139711e9eae4SChaoyong He RTE_PTYPE_INNER_L4_UDP, 139811e9eae4SChaoyong He RTE_PTYPE_INNER_L4_FRAG, 139911e9eae4SChaoyong He RTE_PTYPE_INNER_L4_NONFRAG, 140011e9eae4SChaoyong He RTE_PTYPE_INNER_L4_ICMP, 140111e9eae4SChaoyong He RTE_PTYPE_INNER_L4_SCTP, 140211e9eae4SChaoyong He }; 140311e9eae4SChaoyong He 140411e9eae4SChaoyong He if (dev->rx_pkt_burst != nfp_net_recv_pkts) 140511e9eae4SChaoyong He return NULL; 140611e9eae4SChaoyong He 140711e9eae4SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 140875a76c73SChaoyong He if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0) 140911e9eae4SChaoyong He return NULL; 141011e9eae4SChaoyong He 141111e9eae4SChaoyong He return ptypes; 141211e9eae4SChaoyong He } 141311e9eae4SChaoyong He 141411e9eae4SChaoyong He int 141511e9eae4SChaoyong He nfp_rx_queue_intr_enable(struct rte_eth_dev *dev, 141611e9eae4SChaoyong He uint16_t queue_id) 141711e9eae4SChaoyong He { 141811e9eae4SChaoyong He uint16_t base = 0; 141911e9eae4SChaoyong He struct nfp_net_hw *hw; 142011e9eae4SChaoyong He struct rte_pci_device *pci_dev; 142111e9eae4SChaoyong He 142211e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 142311e9eae4SChaoyong He if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO) 142411e9eae4SChaoyong He base = 1; 142511e9eae4SChaoyong He 142611e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 142711e9eae4SChaoyong He rte_wmb(); 142811e9eae4SChaoyong He 142911e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1430f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), 143111e9eae4SChaoyong He NFP_NET_CFG_ICR_UNMASKED); 143211e9eae4SChaoyong He return 0; 143311e9eae4SChaoyong He } 143411e9eae4SChaoyong He 143511e9eae4SChaoyong He int 143611e9eae4SChaoyong He nfp_rx_queue_intr_disable(struct rte_eth_dev *dev, 143711e9eae4SChaoyong He uint16_t queue_id) 143811e9eae4SChaoyong He { 143911e9eae4SChaoyong He uint16_t base = 0; 144011e9eae4SChaoyong He struct nfp_net_hw *hw; 144111e9eae4SChaoyong He struct rte_pci_device *pci_dev; 144211e9eae4SChaoyong He 144311e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 144411e9eae4SChaoyong He if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO) 144511e9eae4SChaoyong He base = 1; 144611e9eae4SChaoyong He 144711e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 144811e9eae4SChaoyong He rte_wmb(); 144911e9eae4SChaoyong He 145011e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1451f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), NFP_NET_CFG_ICR_RXTX); 145211e9eae4SChaoyong He 145311e9eae4SChaoyong He return 0; 145411e9eae4SChaoyong He } 145511e9eae4SChaoyong He 145611e9eae4SChaoyong He static void 145711e9eae4SChaoyong He nfp_net_dev_link_status_print(struct rte_eth_dev *dev) 145811e9eae4SChaoyong He { 145911e9eae4SChaoyong He struct rte_eth_link link; 146011e9eae4SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 146111e9eae4SChaoyong He 146211e9eae4SChaoyong He rte_eth_linkstatus_get(dev, &link); 146311e9eae4SChaoyong He if (link.link_status != 0) 146411e9eae4SChaoyong He PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s", 146511e9eae4SChaoyong He dev->data->port_id, link.link_speed, 146611e9eae4SChaoyong He link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX ? 146711e9eae4SChaoyong He "full-duplex" : "half-duplex"); 146811e9eae4SChaoyong He else 146911e9eae4SChaoyong He PMD_DRV_LOG(INFO, " Port %d: Link Down", dev->data->port_id); 147011e9eae4SChaoyong He 147111e9eae4SChaoyong He PMD_DRV_LOG(INFO, "PCI Address: " PCI_PRI_FMT, 147211e9eae4SChaoyong He pci_dev->addr.domain, pci_dev->addr.bus, 147311e9eae4SChaoyong He pci_dev->addr.devid, pci_dev->addr.function); 147411e9eae4SChaoyong He } 147511e9eae4SChaoyong He 147611e9eae4SChaoyong He /* 147711e9eae4SChaoyong He * Unmask an interrupt 147811e9eae4SChaoyong He * 147911e9eae4SChaoyong He * If MSI-X auto-masking is enabled clear the mask bit, otherwise 148011e9eae4SChaoyong He * clear the ICR for the entry. 148111e9eae4SChaoyong He */ 148211e9eae4SChaoyong He static void 148311e9eae4SChaoyong He nfp_net_irq_unmask(struct rte_eth_dev *dev) 148411e9eae4SChaoyong He { 148511e9eae4SChaoyong He struct nfp_net_hw *hw; 148611e9eae4SChaoyong He struct rte_pci_device *pci_dev; 148711e9eae4SChaoyong He 148811e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 148911e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 149011e9eae4SChaoyong He 149111e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 149211e9eae4SChaoyong He rte_wmb(); 149311e9eae4SChaoyong He 1494b4b6988aSChaoyong He if ((hw->super.ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) != 0) { 149511e9eae4SChaoyong He /* If MSI-X auto-masking is used, clear the entry */ 149611e9eae4SChaoyong He rte_intr_ack(pci_dev->intr_handle); 149711e9eae4SChaoyong He } else { 1498f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(NFP_NET_IRQ_LSC_IDX), 149911e9eae4SChaoyong He NFP_NET_CFG_ICR_UNMASKED); 150011e9eae4SChaoyong He } 150111e9eae4SChaoyong He } 150211e9eae4SChaoyong He 150311e9eae4SChaoyong He /** 150411e9eae4SChaoyong He * Interrupt handler which shall be registered for alarm callback for delayed 150511e9eae4SChaoyong He * handling specific interrupt to wait for the stable nic state. As the NIC 150611e9eae4SChaoyong He * interrupt state is not stable for nfp after link is just down, it needs 150711e9eae4SChaoyong He * to wait 4 seconds to get the stable status. 150811e9eae4SChaoyong He * 150911e9eae4SChaoyong He * @param param 151011e9eae4SChaoyong He * The address of parameter (struct rte_eth_dev *) 151111e9eae4SChaoyong He */ 151211e9eae4SChaoyong He void 151311e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler(void *param) 151411e9eae4SChaoyong He { 151511e9eae4SChaoyong He struct rte_eth_dev *dev = param; 151611e9eae4SChaoyong He 151711e9eae4SChaoyong He nfp_net_link_update(dev, 0); 151811e9eae4SChaoyong He rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 151911e9eae4SChaoyong He 152011e9eae4SChaoyong He nfp_net_dev_link_status_print(dev); 152111e9eae4SChaoyong He 152211e9eae4SChaoyong He /* Unmasking */ 152311e9eae4SChaoyong He nfp_net_irq_unmask(dev); 152411e9eae4SChaoyong He } 152511e9eae4SChaoyong He 152611e9eae4SChaoyong He void 152711e9eae4SChaoyong He nfp_net_dev_interrupt_handler(void *param) 152811e9eae4SChaoyong He { 152911e9eae4SChaoyong He int64_t timeout; 153011e9eae4SChaoyong He struct rte_eth_link link; 153111e9eae4SChaoyong He struct rte_eth_dev *dev = param; 153211e9eae4SChaoyong He 153311e9eae4SChaoyong He PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!"); 153411e9eae4SChaoyong He 153511e9eae4SChaoyong He rte_eth_linkstatus_get(dev, &link); 153611e9eae4SChaoyong He 153711e9eae4SChaoyong He nfp_net_link_update(dev, 0); 153811e9eae4SChaoyong He 153911e9eae4SChaoyong He /* Likely to up */ 154011e9eae4SChaoyong He if (link.link_status == 0) { 154111e9eae4SChaoyong He /* Handle it 1 sec later, wait it being stable */ 154211e9eae4SChaoyong He timeout = NFP_NET_LINK_UP_CHECK_TIMEOUT; 154311e9eae4SChaoyong He } else { /* Likely to down */ 154411e9eae4SChaoyong He /* Handle it 4 sec later, wait it being stable */ 154511e9eae4SChaoyong He timeout = NFP_NET_LINK_DOWN_CHECK_TIMEOUT; 154611e9eae4SChaoyong He } 154711e9eae4SChaoyong He 154811e9eae4SChaoyong He if (rte_eal_alarm_set(timeout * 1000, 154911e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler, 155011e9eae4SChaoyong He (void *)dev) != 0) { 155111e9eae4SChaoyong He PMD_INIT_LOG(ERR, "Error setting alarm"); 155211e9eae4SChaoyong He /* Unmasking */ 155311e9eae4SChaoyong He nfp_net_irq_unmask(dev); 155411e9eae4SChaoyong He } 155511e9eae4SChaoyong He } 155611e9eae4SChaoyong He 155711e9eae4SChaoyong He int 155811e9eae4SChaoyong He nfp_net_dev_mtu_set(struct rte_eth_dev *dev, 155911e9eae4SChaoyong He uint16_t mtu) 156011e9eae4SChaoyong He { 156111e9eae4SChaoyong He struct nfp_net_hw *hw; 156211e9eae4SChaoyong He 156311e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 156411e9eae4SChaoyong He 156511e9eae4SChaoyong He /* MTU setting is forbidden if port is started */ 156611e9eae4SChaoyong He if (dev->data->dev_started) { 156711e9eae4SChaoyong He PMD_DRV_LOG(ERR, "port %d must be stopped before configuration", 156811e9eae4SChaoyong He dev->data->port_id); 156911e9eae4SChaoyong He return -EBUSY; 157011e9eae4SChaoyong He } 157111e9eae4SChaoyong He 157211e9eae4SChaoyong He /* MTU larger than current mbufsize not supported */ 157311e9eae4SChaoyong He if (mtu > hw->flbufsz) { 157411e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MTU (%u) larger than current mbufsize (%u) not supported", 157511e9eae4SChaoyong He mtu, hw->flbufsz); 157611e9eae4SChaoyong He return -ERANGE; 157711e9eae4SChaoyong He } 157811e9eae4SChaoyong He 157911e9eae4SChaoyong He /* Writing to configuration space */ 1580f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, mtu); 158111e9eae4SChaoyong He 158211e9eae4SChaoyong He hw->mtu = mtu; 158311e9eae4SChaoyong He 158411e9eae4SChaoyong He return 0; 158511e9eae4SChaoyong He } 158611e9eae4SChaoyong He 158711e9eae4SChaoyong He int 158811e9eae4SChaoyong He nfp_net_vlan_offload_set(struct rte_eth_dev *dev, 158911e9eae4SChaoyong He int mask) 159011e9eae4SChaoyong He { 159111e9eae4SChaoyong He int ret; 159211e9eae4SChaoyong He uint32_t update; 159311e9eae4SChaoyong He uint32_t new_ctrl; 1594*72d1dea6SChaoyong He struct nfp_hw *hw; 159511e9eae4SChaoyong He uint64_t rx_offload; 1596*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 159711e9eae4SChaoyong He uint32_t rxvlan_ctrl = 0; 159811e9eae4SChaoyong He 1599*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1600*72d1dea6SChaoyong He hw = &net_hw->super; 1601*72d1dea6SChaoyong He 160211e9eae4SChaoyong He rx_offload = dev->data->dev_conf.rxmode.offloads; 1603*72d1dea6SChaoyong He new_ctrl = hw->ctrl; 160411e9eae4SChaoyong He 160511e9eae4SChaoyong He /* VLAN stripping setting */ 160611e9eae4SChaoyong He if ((mask & RTE_ETH_VLAN_STRIP_MASK) != 0) { 1607*72d1dea6SChaoyong He nfp_net_enable_rxvlan_cap(net_hw, &rxvlan_ctrl); 160811e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0) 160911e9eae4SChaoyong He new_ctrl |= rxvlan_ctrl; 161011e9eae4SChaoyong He else 161111e9eae4SChaoyong He new_ctrl &= ~rxvlan_ctrl; 161211e9eae4SChaoyong He } 161311e9eae4SChaoyong He 161411e9eae4SChaoyong He /* QinQ stripping setting */ 161511e9eae4SChaoyong He if ((mask & RTE_ETH_QINQ_STRIP_MASK) != 0) { 161611e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) 161711e9eae4SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ; 161811e9eae4SChaoyong He else 161911e9eae4SChaoyong He new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ; 162011e9eae4SChaoyong He } 162111e9eae4SChaoyong He 1622*72d1dea6SChaoyong He if (new_ctrl == hw->ctrl) 162311e9eae4SChaoyong He return 0; 162411e9eae4SChaoyong He 162511e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 162611e9eae4SChaoyong He 1627*72d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 162811e9eae4SChaoyong He if (ret != 0) 162911e9eae4SChaoyong He return ret; 163011e9eae4SChaoyong He 1631*72d1dea6SChaoyong He hw->ctrl = new_ctrl; 163211e9eae4SChaoyong He 163311e9eae4SChaoyong He return 0; 163411e9eae4SChaoyong He } 163511e9eae4SChaoyong He 163611e9eae4SChaoyong He static int 163711e9eae4SChaoyong He nfp_net_rss_reta_write(struct rte_eth_dev *dev, 163811e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 163911e9eae4SChaoyong He uint16_t reta_size) 164011e9eae4SChaoyong He { 164111e9eae4SChaoyong He uint16_t i; 164211e9eae4SChaoyong He uint16_t j; 164311e9eae4SChaoyong He uint16_t idx; 164411e9eae4SChaoyong He uint8_t mask; 164511e9eae4SChaoyong He uint32_t reta; 164611e9eae4SChaoyong He uint16_t shift; 164711e9eae4SChaoyong He struct nfp_net_hw *hw; 164811e9eae4SChaoyong He 164911e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 165011e9eae4SChaoyong He 165111e9eae4SChaoyong He if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) { 165211e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%hu)" 165311e9eae4SChaoyong He " doesn't match hardware can supported (%d)", 165411e9eae4SChaoyong He reta_size, NFP_NET_CFG_RSS_ITBL_SZ); 165511e9eae4SChaoyong He return -EINVAL; 165611e9eae4SChaoyong He } 165711e9eae4SChaoyong He 165811e9eae4SChaoyong He /* 165911e9eae4SChaoyong He * Update Redirection Table. There are 128 8bit-entries which can be 166011e9eae4SChaoyong He * manage as 32 32bit-entries. 166111e9eae4SChaoyong He */ 166211e9eae4SChaoyong He for (i = 0; i < reta_size; i += 4) { 166311e9eae4SChaoyong He /* Handling 4 RSS entries per loop */ 166411e9eae4SChaoyong He idx = i / RTE_ETH_RETA_GROUP_SIZE; 166511e9eae4SChaoyong He shift = i % RTE_ETH_RETA_GROUP_SIZE; 166611e9eae4SChaoyong He mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF); 166711e9eae4SChaoyong He if (mask == 0) 166811e9eae4SChaoyong He continue; 166911e9eae4SChaoyong He 167011e9eae4SChaoyong He reta = 0; 167111e9eae4SChaoyong He 167211e9eae4SChaoyong He /* If all 4 entries were set, don't need read RETA register */ 167311e9eae4SChaoyong He if (mask != 0xF) 1674f58bde00SChaoyong He reta = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_ITBL + i); 167511e9eae4SChaoyong He 167611e9eae4SChaoyong He for (j = 0; j < 4; j++) { 167711e9eae4SChaoyong He if ((mask & (0x1 << j)) == 0) 167811e9eae4SChaoyong He continue; 167911e9eae4SChaoyong He 168011e9eae4SChaoyong He /* Clearing the entry bits */ 168111e9eae4SChaoyong He if (mask != 0xF) 168211e9eae4SChaoyong He reta &= ~(0xFF << (8 * j)); 168311e9eae4SChaoyong He 168411e9eae4SChaoyong He reta |= reta_conf[idx].reta[shift + j] << (8 * j); 168511e9eae4SChaoyong He } 168611e9eae4SChaoyong He 1687f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift, reta); 168811e9eae4SChaoyong He } 168911e9eae4SChaoyong He 169011e9eae4SChaoyong He return 0; 169111e9eae4SChaoyong He } 169211e9eae4SChaoyong He 169311e9eae4SChaoyong He /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */ 169411e9eae4SChaoyong He int 169511e9eae4SChaoyong He nfp_net_reta_update(struct rte_eth_dev *dev, 169611e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 169711e9eae4SChaoyong He uint16_t reta_size) 169811e9eae4SChaoyong He { 169911e9eae4SChaoyong He int ret; 170011e9eae4SChaoyong He uint32_t update; 1701*72d1dea6SChaoyong He struct nfp_hw *hw; 1702*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 170311e9eae4SChaoyong He 1704*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1705*72d1dea6SChaoyong He hw = &net_hw->super; 1706*72d1dea6SChaoyong He 1707*72d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 170811e9eae4SChaoyong He return -EINVAL; 170911e9eae4SChaoyong He 171011e9eae4SChaoyong He ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size); 171111e9eae4SChaoyong He if (ret != 0) 171211e9eae4SChaoyong He return ret; 171311e9eae4SChaoyong He 171411e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_RSS; 171511e9eae4SChaoyong He 1716*72d1dea6SChaoyong He if (nfp_reconfig(hw, hw->ctrl, update) != 0) 171711e9eae4SChaoyong He return -EIO; 171811e9eae4SChaoyong He 171911e9eae4SChaoyong He return 0; 172011e9eae4SChaoyong He } 172111e9eae4SChaoyong He 172211e9eae4SChaoyong He /* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */ 172311e9eae4SChaoyong He int 172411e9eae4SChaoyong He nfp_net_reta_query(struct rte_eth_dev *dev, 172511e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 172611e9eae4SChaoyong He uint16_t reta_size) 172711e9eae4SChaoyong He { 172811e9eae4SChaoyong He uint16_t i; 172911e9eae4SChaoyong He uint16_t j; 173011e9eae4SChaoyong He uint16_t idx; 173111e9eae4SChaoyong He uint8_t mask; 173211e9eae4SChaoyong He uint32_t reta; 173311e9eae4SChaoyong He uint16_t shift; 173411e9eae4SChaoyong He struct nfp_net_hw *hw; 173511e9eae4SChaoyong He 173611e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1737b4b6988aSChaoyong He if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 173811e9eae4SChaoyong He return -EINVAL; 173911e9eae4SChaoyong He 174011e9eae4SChaoyong He if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) { 174111e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d)" 174211e9eae4SChaoyong He " doesn't match hardware can supported (%d)", 174311e9eae4SChaoyong He reta_size, NFP_NET_CFG_RSS_ITBL_SZ); 174411e9eae4SChaoyong He return -EINVAL; 174511e9eae4SChaoyong He } 174611e9eae4SChaoyong He 174711e9eae4SChaoyong He /* 174811e9eae4SChaoyong He * Reading Redirection Table. There are 128 8bit-entries which can be 174911e9eae4SChaoyong He * manage as 32 32bit-entries. 175011e9eae4SChaoyong He */ 175111e9eae4SChaoyong He for (i = 0; i < reta_size; i += 4) { 175211e9eae4SChaoyong He /* Handling 4 RSS entries per loop */ 175311e9eae4SChaoyong He idx = i / RTE_ETH_RETA_GROUP_SIZE; 175411e9eae4SChaoyong He shift = i % RTE_ETH_RETA_GROUP_SIZE; 175511e9eae4SChaoyong He mask = (reta_conf[idx].mask >> shift) & 0xF; 175611e9eae4SChaoyong He 175711e9eae4SChaoyong He if (mask == 0) 175811e9eae4SChaoyong He continue; 175911e9eae4SChaoyong He 1760f58bde00SChaoyong He reta = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift); 176111e9eae4SChaoyong He for (j = 0; j < 4; j++) { 176211e9eae4SChaoyong He if ((mask & (0x1 << j)) == 0) 176311e9eae4SChaoyong He continue; 176411e9eae4SChaoyong He 176511e9eae4SChaoyong He reta_conf[idx].reta[shift + j] = 176611e9eae4SChaoyong He (uint8_t)((reta >> (8 * j)) & 0xF); 176711e9eae4SChaoyong He } 176811e9eae4SChaoyong He } 176911e9eae4SChaoyong He 177011e9eae4SChaoyong He return 0; 177111e9eae4SChaoyong He } 177211e9eae4SChaoyong He 177311e9eae4SChaoyong He static int 177411e9eae4SChaoyong He nfp_net_rss_hash_write(struct rte_eth_dev *dev, 177511e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 177611e9eae4SChaoyong He { 177711e9eae4SChaoyong He uint8_t i; 177811e9eae4SChaoyong He uint8_t key; 177911e9eae4SChaoyong He uint64_t rss_hf; 178011e9eae4SChaoyong He struct nfp_net_hw *hw; 178111e9eae4SChaoyong He uint32_t cfg_rss_ctrl = 0; 178211e9eae4SChaoyong He 178311e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 178411e9eae4SChaoyong He 178511e9eae4SChaoyong He /* Writing the key byte by byte */ 178611e9eae4SChaoyong He for (i = 0; i < rss_conf->rss_key_len; i++) { 178711e9eae4SChaoyong He memcpy(&key, &rss_conf->rss_key[i], 1); 1788f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RSS_KEY + i, key); 178911e9eae4SChaoyong He } 179011e9eae4SChaoyong He 179111e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 179211e9eae4SChaoyong He 179311e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_IPV4) != 0) 179411e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4; 179511e9eae4SChaoyong He 179611e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0) 179711e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_TCP; 179811e9eae4SChaoyong He 179911e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0) 180011e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_UDP; 180111e9eae4SChaoyong He 180211e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) != 0) 180311e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_SCTP; 180411e9eae4SChaoyong He 180511e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_IPV6) != 0) 180611e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6; 180711e9eae4SChaoyong He 180811e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0) 180911e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_TCP; 181011e9eae4SChaoyong He 181111e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0) 181211e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_UDP; 181311e9eae4SChaoyong He 181411e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) != 0) 181511e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_SCTP; 181611e9eae4SChaoyong He 181711e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_MASK; 181811e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_TOEPLITZ; 181911e9eae4SChaoyong He 182011e9eae4SChaoyong He /* Configuring where to apply the RSS hash */ 1821f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl); 182211e9eae4SChaoyong He 182311e9eae4SChaoyong He /* Writing the key size */ 1824f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len); 182511e9eae4SChaoyong He 182611e9eae4SChaoyong He return 0; 182711e9eae4SChaoyong He } 182811e9eae4SChaoyong He 182911e9eae4SChaoyong He int 183011e9eae4SChaoyong He nfp_net_rss_hash_update(struct rte_eth_dev *dev, 183111e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 183211e9eae4SChaoyong He { 183311e9eae4SChaoyong He uint32_t update; 183411e9eae4SChaoyong He uint64_t rss_hf; 1835*72d1dea6SChaoyong He struct nfp_hw *hw; 1836*72d1dea6SChaoyong He struct nfp_net_hw *net_hw; 183711e9eae4SChaoyong He 1838*72d1dea6SChaoyong He net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1839*72d1dea6SChaoyong He hw = &net_hw->super; 184011e9eae4SChaoyong He 184111e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 184211e9eae4SChaoyong He 184311e9eae4SChaoyong He /* Checking if RSS is enabled */ 1844*72d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) { 184511e9eae4SChaoyong He if (rss_hf != 0) { 184611e9eae4SChaoyong He PMD_DRV_LOG(ERR, "RSS unsupported"); 184711e9eae4SChaoyong He return -EINVAL; 184811e9eae4SChaoyong He } 184911e9eae4SChaoyong He 185011e9eae4SChaoyong He return 0; /* Nothing to do */ 185111e9eae4SChaoyong He } 185211e9eae4SChaoyong He 185311e9eae4SChaoyong He if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) { 185411e9eae4SChaoyong He PMD_DRV_LOG(ERR, "RSS hash key too long"); 185511e9eae4SChaoyong He return -EINVAL; 185611e9eae4SChaoyong He } 185711e9eae4SChaoyong He 185811e9eae4SChaoyong He nfp_net_rss_hash_write(dev, rss_conf); 185911e9eae4SChaoyong He 186011e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_RSS; 186111e9eae4SChaoyong He 1862*72d1dea6SChaoyong He if (nfp_reconfig(hw, hw->ctrl, update) != 0) 186311e9eae4SChaoyong He return -EIO; 186411e9eae4SChaoyong He 186511e9eae4SChaoyong He return 0; 186611e9eae4SChaoyong He } 186711e9eae4SChaoyong He 186811e9eae4SChaoyong He int 186911e9eae4SChaoyong He nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev, 187011e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 187111e9eae4SChaoyong He { 187211e9eae4SChaoyong He uint8_t i; 187311e9eae4SChaoyong He uint8_t key; 187411e9eae4SChaoyong He uint64_t rss_hf; 187511e9eae4SChaoyong He uint32_t cfg_rss_ctrl; 187611e9eae4SChaoyong He struct nfp_net_hw *hw; 187711e9eae4SChaoyong He 187811e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 187911e9eae4SChaoyong He 1880b4b6988aSChaoyong He if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 188111e9eae4SChaoyong He return -EINVAL; 188211e9eae4SChaoyong He 188311e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 1884f58bde00SChaoyong He cfg_rss_ctrl = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_CTRL); 188511e9eae4SChaoyong He 188611e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4) != 0) 188711e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_IPV4; 188811e9eae4SChaoyong He 188911e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP) != 0) 189011e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP; 189111e9eae4SChaoyong He 189211e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP) != 0) 189311e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP; 189411e9eae4SChaoyong He 189511e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP) != 0) 189611e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP; 189711e9eae4SChaoyong He 189811e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP) != 0) 189911e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP; 190011e9eae4SChaoyong He 190111e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6) != 0) 190211e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_IPV6; 190311e9eae4SChaoyong He 190411e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_SCTP) != 0) 190511e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_SCTP; 190611e9eae4SChaoyong He 190711e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_SCTP) != 0) 190811e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_SCTP; 190911e9eae4SChaoyong He 191011e9eae4SChaoyong He /* Propagate current RSS hash functions to caller */ 191111e9eae4SChaoyong He rss_conf->rss_hf = rss_hf; 191211e9eae4SChaoyong He 191311e9eae4SChaoyong He /* Reading the key size */ 1914f58bde00SChaoyong He rss_conf->rss_key_len = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_KEY_SZ); 191511e9eae4SChaoyong He 191611e9eae4SChaoyong He /* Reading the key byte a byte */ 191711e9eae4SChaoyong He for (i = 0; i < rss_conf->rss_key_len; i++) { 1918f58bde00SChaoyong He key = nn_cfg_readb(&hw->super, NFP_NET_CFG_RSS_KEY + i); 191911e9eae4SChaoyong He memcpy(&rss_conf->rss_key[i], &key, 1); 192011e9eae4SChaoyong He } 192111e9eae4SChaoyong He 192211e9eae4SChaoyong He return 0; 192311e9eae4SChaoyong He } 192411e9eae4SChaoyong He 192511e9eae4SChaoyong He int 192611e9eae4SChaoyong He nfp_net_rss_config_default(struct rte_eth_dev *dev) 192711e9eae4SChaoyong He { 192811e9eae4SChaoyong He int ret; 192911e9eae4SChaoyong He uint8_t i; 193011e9eae4SChaoyong He uint8_t j; 193111e9eae4SChaoyong He uint16_t queue = 0; 193211e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 193311e9eae4SChaoyong He struct rte_eth_rss_conf rss_conf; 193411e9eae4SChaoyong He uint16_t rx_queues = dev->data->nb_rx_queues; 193511e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 nfp_reta_conf[2]; 193611e9eae4SChaoyong He 193711e9eae4SChaoyong He nfp_reta_conf[0].mask = ~0x0; 193811e9eae4SChaoyong He nfp_reta_conf[1].mask = ~0x0; 193911e9eae4SChaoyong He 194011e9eae4SChaoyong He for (i = 0; i < 0x40; i += 8) { 194111e9eae4SChaoyong He for (j = i; j < (i + 8); j++) { 194211e9eae4SChaoyong He nfp_reta_conf[0].reta[j] = queue; 194311e9eae4SChaoyong He nfp_reta_conf[1].reta[j] = queue++; 194411e9eae4SChaoyong He queue %= rx_queues; 194511e9eae4SChaoyong He } 194611e9eae4SChaoyong He } 194711e9eae4SChaoyong He 194811e9eae4SChaoyong He ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80); 194911e9eae4SChaoyong He if (ret != 0) 195011e9eae4SChaoyong He return ret; 195111e9eae4SChaoyong He 195211e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 195311e9eae4SChaoyong He if (dev_conf == NULL) { 195411e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Wrong rss conf"); 195511e9eae4SChaoyong He return -EINVAL; 195611e9eae4SChaoyong He } 195711e9eae4SChaoyong He 195811e9eae4SChaoyong He rss_conf = dev_conf->rx_adv_conf.rss_conf; 195911e9eae4SChaoyong He ret = nfp_net_rss_hash_write(dev, &rss_conf); 196011e9eae4SChaoyong He 196111e9eae4SChaoyong He return ret; 196211e9eae4SChaoyong He } 196311e9eae4SChaoyong He 196411e9eae4SChaoyong He void 196511e9eae4SChaoyong He nfp_net_stop_rx_queue(struct rte_eth_dev *dev) 196611e9eae4SChaoyong He { 196711e9eae4SChaoyong He uint16_t i; 196811e9eae4SChaoyong He struct nfp_net_rxq *this_rx_q; 196911e9eae4SChaoyong He 197011e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 197111e9eae4SChaoyong He this_rx_q = dev->data->rx_queues[i]; 197211e9eae4SChaoyong He nfp_net_reset_rx_queue(this_rx_q); 197311e9eae4SChaoyong He dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 197411e9eae4SChaoyong He } 197511e9eae4SChaoyong He } 197611e9eae4SChaoyong He 197711e9eae4SChaoyong He void 197811e9eae4SChaoyong He nfp_net_close_rx_queue(struct rte_eth_dev *dev) 197911e9eae4SChaoyong He { 198011e9eae4SChaoyong He uint16_t i; 198111e9eae4SChaoyong He struct nfp_net_rxq *this_rx_q; 198211e9eae4SChaoyong He 198311e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 198411e9eae4SChaoyong He this_rx_q = dev->data->rx_queues[i]; 198511e9eae4SChaoyong He nfp_net_reset_rx_queue(this_rx_q); 198611e9eae4SChaoyong He nfp_net_rx_queue_release(dev, i); 198711e9eae4SChaoyong He } 198811e9eae4SChaoyong He } 198911e9eae4SChaoyong He 199011e9eae4SChaoyong He void 199111e9eae4SChaoyong He nfp_net_stop_tx_queue(struct rte_eth_dev *dev) 199211e9eae4SChaoyong He { 199311e9eae4SChaoyong He uint16_t i; 199411e9eae4SChaoyong He struct nfp_net_txq *this_tx_q; 199511e9eae4SChaoyong He 199611e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 199711e9eae4SChaoyong He this_tx_q = dev->data->tx_queues[i]; 199811e9eae4SChaoyong He nfp_net_reset_tx_queue(this_tx_q); 199911e9eae4SChaoyong He dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 200011e9eae4SChaoyong He } 200111e9eae4SChaoyong He } 200211e9eae4SChaoyong He 200311e9eae4SChaoyong He void 200411e9eae4SChaoyong He nfp_net_close_tx_queue(struct rte_eth_dev *dev) 200511e9eae4SChaoyong He { 200611e9eae4SChaoyong He uint16_t i; 200711e9eae4SChaoyong He struct nfp_net_txq *this_tx_q; 200811e9eae4SChaoyong He 200911e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 201011e9eae4SChaoyong He this_tx_q = dev->data->tx_queues[i]; 201111e9eae4SChaoyong He nfp_net_reset_tx_queue(this_tx_q); 201211e9eae4SChaoyong He nfp_net_tx_queue_release(dev, i); 201311e9eae4SChaoyong He } 201411e9eae4SChaoyong He } 201511e9eae4SChaoyong He 201611e9eae4SChaoyong He int 2017*72d1dea6SChaoyong He nfp_net_set_vxlan_port(struct nfp_net_hw *net_hw, 201811e9eae4SChaoyong He size_t idx, 201911e9eae4SChaoyong He uint16_t port) 202011e9eae4SChaoyong He { 202111e9eae4SChaoyong He int ret; 202211e9eae4SChaoyong He uint32_t i; 2023*72d1dea6SChaoyong He struct nfp_hw *hw = &net_hw->super; 202411e9eae4SChaoyong He 202511e9eae4SChaoyong He if (idx >= NFP_NET_N_VXLAN_PORTS) { 202611e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The idx value is out of range."); 202711e9eae4SChaoyong He return -ERANGE; 202811e9eae4SChaoyong He } 202911e9eae4SChaoyong He 2030*72d1dea6SChaoyong He net_hw->vxlan_ports[idx] = port; 203111e9eae4SChaoyong He 203211e9eae4SChaoyong He for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) { 2033*72d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port), 2034*72d1dea6SChaoyong He (net_hw->vxlan_ports[i + 1] << 16) | net_hw->vxlan_ports[i]); 203511e9eae4SChaoyong He } 203611e9eae4SChaoyong He 203711e9eae4SChaoyong He rte_spinlock_lock(&hw->reconfig_lock); 203811e9eae4SChaoyong He 2039*72d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_VXLAN); 204011e9eae4SChaoyong He rte_wmb(); 204111e9eae4SChaoyong He 2042*72d1dea6SChaoyong He ret = nfp_reconfig_real(hw, NFP_NET_CFG_UPDATE_VXLAN); 204311e9eae4SChaoyong He 204411e9eae4SChaoyong He rte_spinlock_unlock(&hw->reconfig_lock); 204511e9eae4SChaoyong He 204611e9eae4SChaoyong He return ret; 204711e9eae4SChaoyong He } 204811e9eae4SChaoyong He 204911e9eae4SChaoyong He /* 205011e9eae4SChaoyong He * The firmware with NFD3 can not handle DMA address requiring more 205111e9eae4SChaoyong He * than 40 bits. 205211e9eae4SChaoyong He */ 205311e9eae4SChaoyong He int 205411e9eae4SChaoyong He nfp_net_check_dma_mask(struct nfp_net_hw *hw, 205511e9eae4SChaoyong He char *name) 205611e9eae4SChaoyong He { 205711e9eae4SChaoyong He if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3 && 205811e9eae4SChaoyong He rte_mem_check_dma_mask(40) != 0) { 205911e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Device %s can't be used: restricted dma mask to 40 bits!", 206011e9eae4SChaoyong He name); 206111e9eae4SChaoyong He return -ENODEV; 206211e9eae4SChaoyong He } 206311e9eae4SChaoyong He 206411e9eae4SChaoyong He return 0; 206511e9eae4SChaoyong He } 206611e9eae4SChaoyong He 206711e9eae4SChaoyong He void 206811e9eae4SChaoyong He nfp_net_init_metadata_format(struct nfp_net_hw *hw) 206911e9eae4SChaoyong He { 207011e9eae4SChaoyong He /* 207111e9eae4SChaoyong He * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of 207211e9eae4SChaoyong He * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2) 207311e9eae4SChaoyong He * also indicate that we are using chained metadata. 207411e9eae4SChaoyong He */ 207511e9eae4SChaoyong He if (hw->ver.major == 4) { 207611e9eae4SChaoyong He hw->meta_format = NFP_NET_METAFORMAT_CHAINED; 207775a76c73SChaoyong He } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) { 207811e9eae4SChaoyong He hw->meta_format = NFP_NET_METAFORMAT_CHAINED; 207911e9eae4SChaoyong He /* 208075a76c73SChaoyong He * RSS is incompatible with chained metadata. hw->super.cap just represents 208111e9eae4SChaoyong He * firmware's ability rather than the firmware's configuration. We decide 208275a76c73SChaoyong He * to reduce the confusion to allow us can use hw->super.cap to identify RSS later. 208311e9eae4SChaoyong He */ 208475a76c73SChaoyong He hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS; 208511e9eae4SChaoyong He } else { 208611e9eae4SChaoyong He hw->meta_format = NFP_NET_METAFORMAT_SINGLE; 208711e9eae4SChaoyong He } 208811e9eae4SChaoyong He } 208911e9eae4SChaoyong He 209011e9eae4SChaoyong He void 209111e9eae4SChaoyong He nfp_net_cfg_read_version(struct nfp_net_hw *hw) 209211e9eae4SChaoyong He { 209311e9eae4SChaoyong He union { 209411e9eae4SChaoyong He uint32_t whole; 209511e9eae4SChaoyong He struct nfp_net_fw_ver split; 209611e9eae4SChaoyong He } version; 209711e9eae4SChaoyong He 2098f58bde00SChaoyong He version.whole = nn_cfg_readl(&hw->super, NFP_NET_CFG_VERSION); 209911e9eae4SChaoyong He hw->ver = version.split; 210011e9eae4SChaoyong He } 210111e9eae4SChaoyong He 210211e9eae4SChaoyong He static void 210311e9eae4SChaoyong He nfp_net_get_nsp_info(struct nfp_net_hw *hw, 210411e9eae4SChaoyong He char *nsp_version) 210511e9eae4SChaoyong He { 210611e9eae4SChaoyong He struct nfp_nsp *nsp; 210711e9eae4SChaoyong He 210811e9eae4SChaoyong He nsp = nfp_nsp_open(hw->cpp); 210911e9eae4SChaoyong He if (nsp == NULL) 211011e9eae4SChaoyong He return; 211111e9eae4SChaoyong He 211211e9eae4SChaoyong He snprintf(nsp_version, FW_VER_LEN, "%hu.%hu", 211311e9eae4SChaoyong He nfp_nsp_get_abi_ver_major(nsp), 211411e9eae4SChaoyong He nfp_nsp_get_abi_ver_minor(nsp)); 211511e9eae4SChaoyong He 211611e9eae4SChaoyong He nfp_nsp_close(nsp); 211711e9eae4SChaoyong He } 211811e9eae4SChaoyong He 211911e9eae4SChaoyong He static void 212011e9eae4SChaoyong He nfp_net_get_mip_name(struct nfp_net_hw *hw, 212111e9eae4SChaoyong He char *mip_name) 212211e9eae4SChaoyong He { 212311e9eae4SChaoyong He struct nfp_mip *mip; 212411e9eae4SChaoyong He 212511e9eae4SChaoyong He mip = nfp_mip_open(hw->cpp); 212611e9eae4SChaoyong He if (mip == NULL) 212711e9eae4SChaoyong He return; 212811e9eae4SChaoyong He 212911e9eae4SChaoyong He snprintf(mip_name, FW_VER_LEN, "%s", nfp_mip_name(mip)); 213011e9eae4SChaoyong He 213111e9eae4SChaoyong He nfp_mip_close(mip); 213211e9eae4SChaoyong He } 213311e9eae4SChaoyong He 213411e9eae4SChaoyong He static void 213511e9eae4SChaoyong He nfp_net_get_app_name(struct nfp_net_hw *hw, 213611e9eae4SChaoyong He char *app_name) 213711e9eae4SChaoyong He { 213811e9eae4SChaoyong He switch (hw->pf_dev->app_fw_id) { 213911e9eae4SChaoyong He case NFP_APP_FW_CORE_NIC: 214011e9eae4SChaoyong He snprintf(app_name, FW_VER_LEN, "%s", "nic"); 214111e9eae4SChaoyong He break; 214211e9eae4SChaoyong He case NFP_APP_FW_FLOWER_NIC: 214311e9eae4SChaoyong He snprintf(app_name, FW_VER_LEN, "%s", "flower"); 214411e9eae4SChaoyong He break; 214511e9eae4SChaoyong He default: 214611e9eae4SChaoyong He snprintf(app_name, FW_VER_LEN, "%s", "unknown"); 214711e9eae4SChaoyong He break; 214811e9eae4SChaoyong He } 214911e9eae4SChaoyong He } 215011e9eae4SChaoyong He 215111e9eae4SChaoyong He int 215211e9eae4SChaoyong He nfp_net_firmware_version_get(struct rte_eth_dev *dev, 215311e9eae4SChaoyong He char *fw_version, 215411e9eae4SChaoyong He size_t fw_size) 215511e9eae4SChaoyong He { 215611e9eae4SChaoyong He struct nfp_net_hw *hw; 215711e9eae4SChaoyong He char mip_name[FW_VER_LEN]; 215811e9eae4SChaoyong He char app_name[FW_VER_LEN]; 215911e9eae4SChaoyong He char nsp_version[FW_VER_LEN]; 216011e9eae4SChaoyong He char vnic_version[FW_VER_LEN]; 216111e9eae4SChaoyong He 216211e9eae4SChaoyong He if (fw_size < FW_VER_LEN) 216311e9eae4SChaoyong He return FW_VER_LEN; 216411e9eae4SChaoyong He 216511e9eae4SChaoyong He hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private); 216611e9eae4SChaoyong He 216711e9eae4SChaoyong He snprintf(vnic_version, FW_VER_LEN, "%d.%d.%d.%d", 216811e9eae4SChaoyong He hw->ver.extend, hw->ver.class, 216911e9eae4SChaoyong He hw->ver.major, hw->ver.minor); 217011e9eae4SChaoyong He 217111e9eae4SChaoyong He nfp_net_get_nsp_info(hw, nsp_version); 217211e9eae4SChaoyong He nfp_net_get_mip_name(hw, mip_name); 217311e9eae4SChaoyong He nfp_net_get_app_name(hw, app_name); 217411e9eae4SChaoyong He 217511e9eae4SChaoyong He snprintf(fw_version, FW_VER_LEN, "%s %s %s %s", 217611e9eae4SChaoyong He vnic_version, nsp_version, mip_name, app_name); 217711e9eae4SChaoyong He 217811e9eae4SChaoyong He return 0; 217911e9eae4SChaoyong He } 218011e9eae4SChaoyong He 218111e9eae4SChaoyong He int 218211e9eae4SChaoyong He nfp_repr_firmware_version_get(struct rte_eth_dev *dev, 218311e9eae4SChaoyong He char *fw_version, 218411e9eae4SChaoyong He size_t fw_size) 218511e9eae4SChaoyong He { 218611e9eae4SChaoyong He struct nfp_net_hw *hw; 218711e9eae4SChaoyong He char mip_name[FW_VER_LEN]; 218811e9eae4SChaoyong He char app_name[FW_VER_LEN]; 218911e9eae4SChaoyong He char nsp_version[FW_VER_LEN]; 219011e9eae4SChaoyong He struct nfp_flower_representor *repr; 219111e9eae4SChaoyong He 219211e9eae4SChaoyong He if (fw_size < FW_VER_LEN) 219311e9eae4SChaoyong He return FW_VER_LEN; 219411e9eae4SChaoyong He 219511e9eae4SChaoyong He repr = dev->data->dev_private; 219611e9eae4SChaoyong He hw = repr->app_fw_flower->pf_hw; 219711e9eae4SChaoyong He 219811e9eae4SChaoyong He nfp_net_get_nsp_info(hw, nsp_version); 219911e9eae4SChaoyong He nfp_net_get_mip_name(hw, mip_name); 220011e9eae4SChaoyong He nfp_net_get_app_name(hw, app_name); 220111e9eae4SChaoyong He 220211e9eae4SChaoyong He snprintf(fw_version, FW_VER_LEN, "* %s %s %s", 220311e9eae4SChaoyong He nsp_version, mip_name, app_name); 220411e9eae4SChaoyong He 220511e9eae4SChaoyong He return 0; 220611e9eae4SChaoyong He } 220711e9eae4SChaoyong He 220811e9eae4SChaoyong He bool 220911e9eae4SChaoyong He nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version) 221011e9eae4SChaoyong He { 221111e9eae4SChaoyong He uint8_t nfd_version = version.extend; 221211e9eae4SChaoyong He 221311e9eae4SChaoyong He if (nfd_version == NFP_NET_CFG_VERSION_DP_NFD3) 221411e9eae4SChaoyong He return true; 221511e9eae4SChaoyong He 221611e9eae4SChaoyong He if (nfd_version == NFP_NET_CFG_VERSION_DP_NFDK) { 221711e9eae4SChaoyong He if (version.major < 5) { 221811e9eae4SChaoyong He PMD_INIT_LOG(ERR, "NFDK must use ABI 5 or newer, found: %d", 221911e9eae4SChaoyong He version.major); 222011e9eae4SChaoyong He return false; 222111e9eae4SChaoyong He } 222211e9eae4SChaoyong He 222311e9eae4SChaoyong He return true; 222411e9eae4SChaoyong He } 222511e9eae4SChaoyong He 222611e9eae4SChaoyong He return false; 222711e9eae4SChaoyong He } 2228