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 #define NFP_NET_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */ 2311e9eae4SChaoyong He #define NFP_NET_LINK_UP_CHECK_TIMEOUT 1000 /* ms */ 2411e9eae4SChaoyong He 2511e9eae4SChaoyong He #define DEFAULT_FLBUF_SIZE 9216 262f1bfbf4SJames Hershaw #define NFP_ETH_OVERHEAD \ 272f1bfbf4SJames Hershaw (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + RTE_VLAN_HLEN * 2) 2811e9eae4SChaoyong He 290786add9SZerun Fu /* Only show FEC capability supported by the current speed. */ 300786add9SZerun Fu #define NFP_FEC_CAPA_ENTRY_NUM 1 310786add9SZerun Fu 3211e9eae4SChaoyong He enum nfp_xstat_group { 3311e9eae4SChaoyong He NFP_XSTAT_GROUP_NET, 3411e9eae4SChaoyong He NFP_XSTAT_GROUP_MAC 3511e9eae4SChaoyong He }; 3611e9eae4SChaoyong He 3711e9eae4SChaoyong He struct nfp_xstat { 3811e9eae4SChaoyong He char name[RTE_ETH_XSTATS_NAME_SIZE]; 3911e9eae4SChaoyong He int offset; 4011e9eae4SChaoyong He enum nfp_xstat_group group; 4111e9eae4SChaoyong He }; 4211e9eae4SChaoyong He 4311e9eae4SChaoyong He #define NFP_XSTAT_NET(_name, _offset) { \ 4411e9eae4SChaoyong He .name = _name, \ 4511e9eae4SChaoyong He .offset = NFP_NET_CFG_STATS_##_offset, \ 4611e9eae4SChaoyong He .group = NFP_XSTAT_GROUP_NET, \ 4711e9eae4SChaoyong He } 4811e9eae4SChaoyong He 4911e9eae4SChaoyong He #define NFP_XSTAT_MAC(_name, _offset) { \ 5011e9eae4SChaoyong He .name = _name, \ 5111e9eae4SChaoyong He .offset = NFP_MAC_STATS_##_offset, \ 5211e9eae4SChaoyong He .group = NFP_XSTAT_GROUP_MAC, \ 5311e9eae4SChaoyong He } 5411e9eae4SChaoyong He 5511e9eae4SChaoyong He static const struct nfp_xstat nfp_net_xstats[] = { 5611e9eae4SChaoyong He /* 5711e9eae4SChaoyong He * Basic xstats available on both VF and PF. 5811e9eae4SChaoyong He * Note that in case new statistics of group NFP_XSTAT_GROUP_NET 5911e9eae4SChaoyong He * are added to this array, they must appear before any statistics 6011e9eae4SChaoyong He * of group NFP_XSTAT_GROUP_MAC. 6111e9eae4SChaoyong He */ 6211e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_packets_mc", RX_MC_FRAMES), 6311e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_packets_mc", TX_MC_FRAMES), 6411e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_packets_bc", RX_BC_FRAMES), 6511e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_packets_bc", TX_BC_FRAMES), 6611e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_uc", RX_UC_OCTETS), 6711e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_uc", TX_UC_OCTETS), 6811e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_mc", RX_MC_OCTETS), 6911e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_mc", TX_MC_OCTETS), 7011e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_bc", RX_BC_OCTETS), 7111e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_bc", TX_BC_OCTETS), 7211e9eae4SChaoyong He NFP_XSTAT_NET("tx_missed_erros", TX_DISCARDS), 7311e9eae4SChaoyong He NFP_XSTAT_NET("bpf_pass_pkts", APP0_FRAMES), 7411e9eae4SChaoyong He NFP_XSTAT_NET("bpf_pass_bytes", APP0_BYTES), 7511e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app1_pkts", APP1_FRAMES), 7611e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app1_bytes", APP1_BYTES), 7711e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app2_pkts", APP2_FRAMES), 7811e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app2_bytes", APP2_BYTES), 7911e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app3_pkts", APP3_FRAMES), 8011e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app3_bytes", APP3_BYTES), 8111e9eae4SChaoyong He /* 8211e9eae4SChaoyong He * MAC xstats available only on PF. These statistics are not available for VFs as the 8311e9eae4SChaoyong He * PF is not initialized when the VF is initialized as it is still bound to the kernel 8411e9eae4SChaoyong He * driver. As such, the PMD cannot obtain a CPP handle and access the rtsym_table in order 8511e9eae4SChaoyong He * to get the pointer to the start of the MAC statistics counters. 8611e9eae4SChaoyong He */ 8711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_octets", RX_IN_OCTS), 8811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frame_too_long_errors", RX_FRAME_TOO_LONG_ERRORS), 8911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_range_length_errors", RX_RANGE_LENGTH_ERRORS), 9011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_vlan_received_ok", RX_VLAN_RECEIVED_OK), 9111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_errors", RX_IN_ERRORS), 9211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_broadcast_pkts", RX_IN_BROADCAST_PKTS), 9311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_drop_events", RX_DROP_EVENTS), 9411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_alignment_errors", RX_ALIGNMENT_ERRORS), 9511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_mac_ctrl_frames", RX_PAUSE_MAC_CTRL_FRAMES), 9611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frames_received_ok", RX_FRAMES_RECEIVED_OK), 9711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frame_check_sequence_errors", RX_FRAME_CHECK_SEQ_ERRORS), 9811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_unicast_pkts", RX_UNICAST_PKTS), 9911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_multicast_pkts", RX_MULTICAST_PKTS), 10011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts", RX_PKTS), 10111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_undersize_pkts", RX_UNDERSIZE_PKTS), 10211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_64_octets", RX_PKTS_64_OCTS), 10311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_65_to_127_octets", RX_PKTS_65_TO_127_OCTS), 10411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_128_to_255_octets", RX_PKTS_128_TO_255_OCTS), 10511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_256_to_511_octets", RX_PKTS_256_TO_511_OCTS), 10611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_512_to_1023_octets", RX_PKTS_512_TO_1023_OCTS), 10711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_1024_to_1518_octets", RX_PKTS_1024_TO_1518_OCTS), 10811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_1519_to_max_octets", RX_PKTS_1519_TO_MAX_OCTS), 10911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_jabbers", RX_JABBERS), 11011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_fragments", RX_FRAGMENTS), 11111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_oversize_pkts", RX_OVERSIZE_PKTS), 11211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class0", RX_PAUSE_FRAMES_CLASS0), 11311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class1", RX_PAUSE_FRAMES_CLASS1), 11411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class2", RX_PAUSE_FRAMES_CLASS2), 11511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class3", RX_PAUSE_FRAMES_CLASS3), 11611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class4", RX_PAUSE_FRAMES_CLASS4), 11711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class5", RX_PAUSE_FRAMES_CLASS5), 11811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class6", RX_PAUSE_FRAMES_CLASS6), 11911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class7", RX_PAUSE_FRAMES_CLASS7), 12011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_mac_ctrl_frames_received", RX_MAC_CTRL_FRAMES_REC), 12111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_mac_head_drop", RX_MAC_HEAD_DROP), 12211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_queue_drop", TX_QUEUE_DROP), 12311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_octets", TX_OUT_OCTS), 12411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_vlan_transmitted_ok", TX_VLAN_TRANSMITTED_OK), 12511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_errors", TX_OUT_ERRORS), 12611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_broadcast_pkts", TX_BROADCAST_PKTS), 12711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_mac_ctrl_frames", TX_PAUSE_MAC_CTRL_FRAMES), 12811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_frames_transmitted_ok", TX_FRAMES_TRANSMITTED_OK), 12911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_unicast_pkts", TX_UNICAST_PKTS), 13011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_multicast_pkts", TX_MULTICAST_PKTS), 13111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_64_octets", TX_PKTS_64_OCTS), 13211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_65_to_127_octets", TX_PKTS_65_TO_127_OCTS), 13311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_128_to_255_octets", TX_PKTS_128_TO_255_OCTS), 13411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_256_to_511_octets", TX_PKTS_256_TO_511_OCTS), 13511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_512_to_1023_octets", TX_PKTS_512_TO_1023_OCTS), 13611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_1024_to_1518_octets", TX_PKTS_1024_TO_1518_OCTS), 13711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_1519_to_max_octets", TX_PKTS_1519_TO_MAX_OCTS), 13811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class0", TX_PAUSE_FRAMES_CLASS0), 13911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class1", TX_PAUSE_FRAMES_CLASS1), 14011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class2", TX_PAUSE_FRAMES_CLASS2), 14111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class3", TX_PAUSE_FRAMES_CLASS3), 14211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class4", TX_PAUSE_FRAMES_CLASS4), 14311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class5", TX_PAUSE_FRAMES_CLASS5), 14411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class6", TX_PAUSE_FRAMES_CLASS6), 14511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class7", TX_PAUSE_FRAMES_CLASS7), 14611e9eae4SChaoyong He }; 14711e9eae4SChaoyong He 14811e9eae4SChaoyong He static const uint32_t nfp_net_link_speed_nfp2rte[] = { 14911e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = RTE_ETH_SPEED_NUM_NONE, 15011e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = RTE_ETH_SPEED_NUM_NONE, 15111e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_1G] = RTE_ETH_SPEED_NUM_1G, 15211e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_10G] = RTE_ETH_SPEED_NUM_10G, 15311e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_25G] = RTE_ETH_SPEED_NUM_25G, 15411e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_40G] = RTE_ETH_SPEED_NUM_40G, 15511e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_50G] = RTE_ETH_SPEED_NUM_50G, 15611e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_100G] = RTE_ETH_SPEED_NUM_100G, 15711e9eae4SChaoyong He }; 15811e9eae4SChaoyong He 15911e9eae4SChaoyong He static uint16_t 16011e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(uint16_t speed) 16111e9eae4SChaoyong He { 16211e9eae4SChaoyong He uint16_t i; 16311e9eae4SChaoyong He 16411e9eae4SChaoyong He for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) { 16511e9eae4SChaoyong He if (speed == nfp_net_link_speed_nfp2rte[i]) 16611e9eae4SChaoyong He return i; 16711e9eae4SChaoyong He } 16811e9eae4SChaoyong He 16911e9eae4SChaoyong He return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN; 17011e9eae4SChaoyong He } 17111e9eae4SChaoyong He 17211e9eae4SChaoyong He static void 17311e9eae4SChaoyong He nfp_net_notify_port_speed(struct nfp_net_hw *hw, 17411e9eae4SChaoyong He struct rte_eth_link *link) 17511e9eae4SChaoyong He { 17611e9eae4SChaoyong He /* 17711e9eae4SChaoyong He * Read the link status from NFP_NET_CFG_STS. If the link is down 17811e9eae4SChaoyong He * then write the link speed NFP_NET_CFG_STS_LINK_RATE_UNKNOWN to 17911e9eae4SChaoyong He * NFP_NET_CFG_STS_NSP_LINK_RATE. 18011e9eae4SChaoyong He */ 18111e9eae4SChaoyong He if (link->link_status == RTE_ETH_LINK_DOWN) { 182f58bde00SChaoyong He nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE, 183f58bde00SChaoyong He NFP_NET_CFG_STS_LINK_RATE_UNKNOWN); 18411e9eae4SChaoyong He return; 18511e9eae4SChaoyong He } 18611e9eae4SChaoyong He 18711e9eae4SChaoyong He /* 18811e9eae4SChaoyong He * Link is up so write the link speed from the eth_table to 18911e9eae4SChaoyong He * NFP_NET_CFG_STS_NSP_LINK_RATE. 19011e9eae4SChaoyong He */ 191f58bde00SChaoyong He nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE, 19211e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(link->link_speed)); 19311e9eae4SChaoyong He } 19411e9eae4SChaoyong He 19511e9eae4SChaoyong He /* The length of firmware version string */ 19611e9eae4SChaoyong He #define FW_VER_LEN 32 19711e9eae4SChaoyong He 19811e9eae4SChaoyong He /** 19911e9eae4SChaoyong He * Reconfigure the firmware via the mailbox 20011e9eae4SChaoyong He * 2014a9bb682SChaoyong He * @param net_hw 20211e9eae4SChaoyong He * Device to reconfigure 20311e9eae4SChaoyong He * @param mbox_cmd 20411e9eae4SChaoyong He * The value for the mailbox command 20511e9eae4SChaoyong He * 20611e9eae4SChaoyong He * @return 20711e9eae4SChaoyong He * - (0) if OK to reconfigure by the mailbox. 20811e9eae4SChaoyong He * - (-EIO) if I/O err and fail to reconfigure by the mailbox 20911e9eae4SChaoyong He */ 21011e9eae4SChaoyong He int 2114a9bb682SChaoyong He nfp_net_mbox_reconfig(struct nfp_net_hw *net_hw, 21211e9eae4SChaoyong He uint32_t mbox_cmd) 21311e9eae4SChaoyong He { 21411e9eae4SChaoyong He int ret; 21511e9eae4SChaoyong He uint32_t mbox; 21611e9eae4SChaoyong He 2174a9bb682SChaoyong He mbox = net_hw->tlv_caps.mbox_off; 21811e9eae4SChaoyong He 2194a9bb682SChaoyong He rte_spinlock_lock(&net_hw->super.reconfig_lock); 22011e9eae4SChaoyong He 2214a9bb682SChaoyong He nn_cfg_writeq(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd); 2224a9bb682SChaoyong He nn_cfg_writel(&net_hw->super, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX); 22311e9eae4SChaoyong He 22411e9eae4SChaoyong He rte_wmb(); 22511e9eae4SChaoyong He 2264a9bb682SChaoyong He ret = nfp_reconfig_real(&net_hw->super, NFP_NET_CFG_UPDATE_MBOX); 22711e9eae4SChaoyong He 2284a9bb682SChaoyong He rte_spinlock_unlock(&net_hw->super.reconfig_lock); 22911e9eae4SChaoyong He 23011e9eae4SChaoyong He if (ret != 0) { 23111e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x", 23211e9eae4SChaoyong He mbox_cmd, NFP_NET_CFG_UPDATE_MBOX); 23311e9eae4SChaoyong He return -EIO; 23411e9eae4SChaoyong He } 23511e9eae4SChaoyong He 2364a9bb682SChaoyong He return nn_cfg_readl(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET); 23711e9eae4SChaoyong He } 23811e9eae4SChaoyong He 239b12d2b2eSChaoyong He struct nfp_net_hw * 240b12d2b2eSChaoyong He nfp_net_get_hw(const struct rte_eth_dev *dev) 241b12d2b2eSChaoyong He { 242b12d2b2eSChaoyong He struct nfp_net_hw *hw; 243b12d2b2eSChaoyong He 244c99e1db8SLong Wu if (rte_eth_dev_is_repr(dev)) { 245b12d2b2eSChaoyong He struct nfp_flower_representor *repr; 246b12d2b2eSChaoyong He repr = dev->data->dev_private; 247b12d2b2eSChaoyong He hw = repr->app_fw_flower->pf_hw; 248b12d2b2eSChaoyong He } else { 249b12d2b2eSChaoyong He hw = dev->data->dev_private; 250b12d2b2eSChaoyong He } 251b12d2b2eSChaoyong He 252b12d2b2eSChaoyong He return hw; 253b12d2b2eSChaoyong He } 254b12d2b2eSChaoyong He 25511e9eae4SChaoyong He /* 25611e9eae4SChaoyong He * Configure an Ethernet device. 25711e9eae4SChaoyong He * 25811e9eae4SChaoyong He * This function must be invoked first before any other function in the Ethernet API. 25911e9eae4SChaoyong He * This function can also be re-invoked when a device is in the stopped state. 26011e9eae4SChaoyong He * 26111e9eae4SChaoyong He * A DPDK app sends info about how many queues to use and how those queues 26211e9eae4SChaoyong He * need to be configured. This is used by the DPDK core and it makes sure no 26311e9eae4SChaoyong He * more queues than those advertised by the driver are requested. 26411e9eae4SChaoyong He * This function is called after that internal process. 26511e9eae4SChaoyong He */ 26611e9eae4SChaoyong He int 26711e9eae4SChaoyong He nfp_net_configure(struct rte_eth_dev *dev) 26811e9eae4SChaoyong He { 26911e9eae4SChaoyong He struct nfp_net_hw *hw; 27011e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 27111e9eae4SChaoyong He struct rte_eth_rxmode *rxmode; 27211e9eae4SChaoyong He struct rte_eth_txmode *txmode; 27311e9eae4SChaoyong He 274b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 27511e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 27611e9eae4SChaoyong He rxmode = &dev_conf->rxmode; 27711e9eae4SChaoyong He txmode = &dev_conf->txmode; 27811e9eae4SChaoyong He 27911e9eae4SChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0) 28011e9eae4SChaoyong He rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 28111e9eae4SChaoyong He 28211e9eae4SChaoyong He /* Checking TX mode */ 28311e9eae4SChaoyong He if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) { 28411e9eae4SChaoyong He PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported"); 28511e9eae4SChaoyong He return -EINVAL; 28611e9eae4SChaoyong He } 28711e9eae4SChaoyong He 28811e9eae4SChaoyong He /* Checking RX mode */ 28911e9eae4SChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 && 29075a76c73SChaoyong He (hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) { 29111e9eae4SChaoyong He PMD_DRV_LOG(ERR, "RSS not supported"); 29211e9eae4SChaoyong He return -EINVAL; 29311e9eae4SChaoyong He } 29411e9eae4SChaoyong He 29511e9eae4SChaoyong He /* Checking MTU set */ 2962f1bfbf4SJames Hershaw if (rxmode->mtu > hw->max_mtu + NFP_ETH_OVERHEAD) { 2972f1bfbf4SJames Hershaw PMD_DRV_LOG(ERR, "MTU (%u) larger than the maximum possible frame size (%u)", 2982f1bfbf4SJames Hershaw rxmode->mtu, hw->max_mtu + NFP_ETH_OVERHEAD); 29911e9eae4SChaoyong He return -ERANGE; 30011e9eae4SChaoyong He } 30111e9eae4SChaoyong He 30211e9eae4SChaoyong He return 0; 30311e9eae4SChaoyong He } 30411e9eae4SChaoyong He 30511e9eae4SChaoyong He void 30611e9eae4SChaoyong He nfp_net_log_device_information(const struct nfp_net_hw *hw) 30711e9eae4SChaoyong He { 30875a76c73SChaoyong He uint32_t cap = hw->super.cap; 309cbf062e9SChaoyong He uint32_t cap_ext = hw->super.cap_ext; 31075a76c73SChaoyong He 31111e9eae4SChaoyong He PMD_INIT_LOG(INFO, "VER: %u.%u, Maximum supported MTU: %d", 31211e9eae4SChaoyong He hw->ver.major, hw->ver.minor, hw->max_mtu); 31311e9eae4SChaoyong He 314cbf062e9SChaoyong He PMD_INIT_LOG(INFO, "CAP: %#x", cap); 315df77f704SChaoyong He PMD_INIT_LOG(INFO, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 316cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_ENABLE ? "ENABLE " : "", 31775a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "", 31875a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "", 31975a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_L2MC ? "L2MCFILT " : "", 32075a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXCSUM ? "RXCSUM " : "", 32175a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXCSUM ? "TXCSUM " : "", 32275a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXVLAN ? "RXVLAN " : "", 32375a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXVLAN ? "TXVLAN " : "", 32475a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_SCATTER ? "SCATTER " : "", 32575a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_GATHER ? "GATHER " : "", 32675a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_LSO ? "TSO " : "", 327cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RXQINQ ? "RXQINQ " : "", 328cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ? "RXVLANv2 " : "", 329cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RINGCFG ? "RINGCFG " : "", 33075a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RSS ? "RSS " : "", 331cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_IRQMOD ? "IRQMOD " : "", 332cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RINGPRIO ? "RINGPRIO " : "", 333cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_MSIXAUTO ? "MSIXAUTO " : "", 334cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_TXRWB ? "TXRWB " : "", 335cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_L2SWITCH ? "L2SWITCH " : "", 336cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_TXVLAN_V2 ? "TXVLANv2 " : "", 337cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_VXLAN ? "VXLAN " : "", 338cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_NVGRE ? "NVGRE " : "", 339cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_MSIX_TX_OFF ? "MSIX_TX_OFF " : "", 340cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_LSO2 ? "TSOv2 " : "", 341cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RSS2 ? "RSSv2 " : "", 342cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ? "CSUM " : "", 343df77f704SChaoyong He cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "", 344df77f704SChaoyong He cap & NFP_NET_CFG_CTRL_USO ? "USO" : ""); 345cbf062e9SChaoyong He 346cbf062e9SChaoyong He PMD_INIT_LOG(INFO, "CAP_WORD1: %#x", cap_ext); 347cbf062e9SChaoyong He PMD_INIT_LOG(INFO, "%s%s%s%s%s%s%s", 348cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE ? "PKT_TYPE " : "", 349cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IPSEC ? "IPSEC " : "", 350cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP ? "IPSEC_SM " : "", 351cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP ? "IPSEC_LM " : "", 352cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_MULTI_PF ? "MULTI_PF " : "", 353cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER ? "FLOW_STEER " : "", 354cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IN_ORDER ? "VIRTIO_IN_ORDER " : ""); 35511e9eae4SChaoyong He 35611e9eae4SChaoyong He PMD_INIT_LOG(INFO, "max_rx_queues: %u, max_tx_queues: %u", 35711e9eae4SChaoyong He hw->max_rx_queues, hw->max_tx_queues); 35811e9eae4SChaoyong He } 35911e9eae4SChaoyong He 36011e9eae4SChaoyong He static inline void 36111e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(struct nfp_net_hw *hw, 36211e9eae4SChaoyong He uint32_t *ctrl) 36311e9eae4SChaoyong He { 36475a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) 36511e9eae4SChaoyong He *ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2; 36675a76c73SChaoyong He else if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN) != 0) 36711e9eae4SChaoyong He *ctrl |= NFP_NET_CFG_CTRL_RXVLAN; 36811e9eae4SChaoyong He } 36911e9eae4SChaoyong He 37011e9eae4SChaoyong He void 37111e9eae4SChaoyong He nfp_net_enable_queues(struct rte_eth_dev *dev) 37211e9eae4SChaoyong He { 37311e9eae4SChaoyong He struct nfp_net_hw *hw; 37411e9eae4SChaoyong He 375b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 37611e9eae4SChaoyong He 37787f5b35bSChaoyong He nfp_enable_queues(&hw->super, dev->data->nb_rx_queues, 37887f5b35bSChaoyong He dev->data->nb_tx_queues); 37911e9eae4SChaoyong He } 38011e9eae4SChaoyong He 38111e9eae4SChaoyong He void 38211e9eae4SChaoyong He nfp_net_disable_queues(struct rte_eth_dev *dev) 38311e9eae4SChaoyong He { 38472d1dea6SChaoyong He struct nfp_net_hw *net_hw; 38511e9eae4SChaoyong He 386b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 38711e9eae4SChaoyong He 38887f5b35bSChaoyong He nfp_disable_queues(&net_hw->super); 38911e9eae4SChaoyong He } 39011e9eae4SChaoyong He 39111e9eae4SChaoyong He void 39211e9eae4SChaoyong He nfp_net_params_setup(struct nfp_net_hw *hw) 39311e9eae4SChaoyong He { 394f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, hw->mtu); 395f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_FLBUFSZ, hw->flbufsz); 39611e9eae4SChaoyong He } 39711e9eae4SChaoyong He 39811e9eae4SChaoyong He void 39911e9eae4SChaoyong He nfp_net_cfg_queue_setup(struct nfp_net_hw *hw) 40011e9eae4SChaoyong He { 401464a535bSChaoyong He hw->super.qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ; 40211e9eae4SChaoyong He } 40311e9eae4SChaoyong He 40411e9eae4SChaoyong He int 40511e9eae4SChaoyong He nfp_net_set_mac_addr(struct rte_eth_dev *dev, 40611e9eae4SChaoyong He struct rte_ether_addr *mac_addr) 40711e9eae4SChaoyong He { 40811e9eae4SChaoyong He uint32_t update; 409d6702227SChaoyong He uint32_t new_ctrl; 41072d1dea6SChaoyong He struct nfp_hw *hw; 41172d1dea6SChaoyong He struct nfp_net_hw *net_hw; 41211e9eae4SChaoyong He 413b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 41472d1dea6SChaoyong He hw = &net_hw->super; 41572d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 && 41672d1dea6SChaoyong He (hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) { 41711e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MAC address unable to change when port enabled"); 41811e9eae4SChaoyong He return -EBUSY; 41911e9eae4SChaoyong He } 42011e9eae4SChaoyong He 421edbb4e1cSChaoyong He if (rte_is_valid_assigned_ether_addr(mac_addr) == 0) { 422edbb4e1cSChaoyong He PMD_DRV_LOG(ERR, "Invalid MAC address"); 423edbb4e1cSChaoyong He return -EINVAL; 424edbb4e1cSChaoyong He } 425edbb4e1cSChaoyong He 42611e9eae4SChaoyong He /* Writing new MAC to the specific port BAR address */ 427503ac807SChaoyong He nfp_write_mac(hw, (uint8_t *)mac_addr); 42811e9eae4SChaoyong He 42911e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_MACADDR; 430d6702227SChaoyong He new_ctrl = hw->ctrl; 43172d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 && 43272d1dea6SChaoyong He (hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) != 0) 433d6702227SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_LIVE_ADDR; 43411e9eae4SChaoyong He 43511e9eae4SChaoyong He /* Signal the NIC about the change */ 436d6702227SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) { 43711e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MAC address update failed"); 43811e9eae4SChaoyong He return -EIO; 43911e9eae4SChaoyong He } 44011e9eae4SChaoyong He 441d6702227SChaoyong He hw->ctrl = new_ctrl; 442d6702227SChaoyong He 44311e9eae4SChaoyong He return 0; 44411e9eae4SChaoyong He } 44511e9eae4SChaoyong He 44611e9eae4SChaoyong He int 44711e9eae4SChaoyong He nfp_configure_rx_interrupt(struct rte_eth_dev *dev, 44811e9eae4SChaoyong He struct rte_intr_handle *intr_handle) 44911e9eae4SChaoyong He { 45011e9eae4SChaoyong He uint16_t i; 45111e9eae4SChaoyong He struct nfp_net_hw *hw; 45211e9eae4SChaoyong He 45311e9eae4SChaoyong He if (rte_intr_vec_list_alloc(intr_handle, "intr_vec", 45411e9eae4SChaoyong He dev->data->nb_rx_queues) != 0) { 45511e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues intr_vec", 45611e9eae4SChaoyong He dev->data->nb_rx_queues); 45711e9eae4SChaoyong He return -ENOMEM; 45811e9eae4SChaoyong He } 45911e9eae4SChaoyong He 460b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 46111e9eae4SChaoyong He 46211e9eae4SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 46311e9eae4SChaoyong He PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with UIO"); 46411e9eae4SChaoyong He /* UIO just supports one queue and no LSC */ 465f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(0), 0); 46611e9eae4SChaoyong He if (rte_intr_vec_list_index_set(intr_handle, 0, 0) != 0) 46711e9eae4SChaoyong He return -1; 46811e9eae4SChaoyong He } else { 46911e9eae4SChaoyong He PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with VFIO"); 47011e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 47111e9eae4SChaoyong He /* 47211e9eae4SChaoyong He * The first msix vector is reserved for non 47311e9eae4SChaoyong He * efd interrupts. 47411e9eae4SChaoyong He */ 475f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(i), i + 1); 47611e9eae4SChaoyong He if (rte_intr_vec_list_index_set(intr_handle, i, i + 1) != 0) 47711e9eae4SChaoyong He return -1; 47811e9eae4SChaoyong He } 47911e9eae4SChaoyong He } 48011e9eae4SChaoyong He 48111e9eae4SChaoyong He /* Avoiding TX interrupts */ 482b4b6988aSChaoyong He hw->super.ctrl |= NFP_NET_CFG_CTRL_MSIX_TX_OFF; 48311e9eae4SChaoyong He return 0; 48411e9eae4SChaoyong He } 48511e9eae4SChaoyong He 48611e9eae4SChaoyong He uint32_t 48711e9eae4SChaoyong He nfp_check_offloads(struct rte_eth_dev *dev) 48811e9eae4SChaoyong He { 4894a9bb682SChaoyong He uint32_t cap; 49011e9eae4SChaoyong He uint32_t ctrl = 0; 49111e9eae4SChaoyong He uint64_t rx_offload; 49211e9eae4SChaoyong He uint64_t tx_offload; 49311e9eae4SChaoyong He struct nfp_net_hw *hw; 49411e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 49511e9eae4SChaoyong He 496b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 4974a9bb682SChaoyong He cap = hw->super.cap; 49811e9eae4SChaoyong He 49911e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 50011e9eae4SChaoyong He rx_offload = dev_conf->rxmode.offloads; 50111e9eae4SChaoyong He tx_offload = dev_conf->txmode.offloads; 50211e9eae4SChaoyong He 50311e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0) { 5044a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0) 50511e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_RXCSUM; 50611e9eae4SChaoyong He } 50711e9eae4SChaoyong He 50811e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0) 50911e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(hw, &ctrl); 51011e9eae4SChaoyong He 51111e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) { 5124a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0) 51311e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_RXQINQ; 51411e9eae4SChaoyong He } 51511e9eae4SChaoyong He 51611e9eae4SChaoyong He hw->mtu = dev->data->mtu; 51711e9eae4SChaoyong He 51811e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) != 0) { 5194a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) 52011e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXVLAN_V2; 5214a9bb682SChaoyong He else if ((cap & NFP_NET_CFG_CTRL_TXVLAN) != 0) 52211e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXVLAN; 52311e9eae4SChaoyong He } 52411e9eae4SChaoyong He 52511e9eae4SChaoyong He /* L2 broadcast */ 5264a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_L2BC) != 0) 52711e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_L2BC; 52811e9eae4SChaoyong He 52911e9eae4SChaoyong He /* L2 multicast */ 5304a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_L2MC) != 0) 53111e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_L2MC; 53211e9eae4SChaoyong He 53311e9eae4SChaoyong He /* TX checksum offload */ 53411e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0 || 53511e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0 || 53611e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0) 53711e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXCSUM; 53811e9eae4SChaoyong He 53911e9eae4SChaoyong He /* LSO offload */ 54011e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0 || 541df77f704SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_UDP_TSO) != 0 || 54211e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) != 0) { 5434a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_LSO) != 0) 54411e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LSO; 545afa83796SChaoyong He else if ((cap & NFP_NET_CFG_CTRL_LSO2) != 0) 54611e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LSO2; 54711e9eae4SChaoyong He } 54811e9eae4SChaoyong He 54911e9eae4SChaoyong He /* RX gather */ 55011e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0) 55111e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_GATHER; 55211e9eae4SChaoyong He 55311e9eae4SChaoyong He return ctrl; 55411e9eae4SChaoyong He } 55511e9eae4SChaoyong He 55611e9eae4SChaoyong He int 55711e9eae4SChaoyong He nfp_net_promisc_enable(struct rte_eth_dev *dev) 55811e9eae4SChaoyong He { 55911e9eae4SChaoyong He int ret; 56072d1dea6SChaoyong He uint32_t update; 56111e9eae4SChaoyong He uint32_t new_ctrl; 56272d1dea6SChaoyong He struct nfp_hw *hw; 56372d1dea6SChaoyong He struct nfp_net_hw *net_hw; 56411e9eae4SChaoyong He 565b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 56611e9eae4SChaoyong He 56772d1dea6SChaoyong He hw = &net_hw->super; 56872d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) { 56911e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Promiscuous mode not supported"); 57011e9eae4SChaoyong He return -ENOTSUP; 57111e9eae4SChaoyong He } 57211e9eae4SChaoyong He 57372d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) != 0) { 57411e9eae4SChaoyong He PMD_DRV_LOG(INFO, "Promiscuous mode already enabled"); 57511e9eae4SChaoyong He return 0; 57611e9eae4SChaoyong He } 57711e9eae4SChaoyong He 57872d1dea6SChaoyong He new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_PROMISC; 57911e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 58011e9eae4SChaoyong He 58172d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 58211e9eae4SChaoyong He if (ret != 0) 58311e9eae4SChaoyong He return ret; 58411e9eae4SChaoyong He 58572d1dea6SChaoyong He hw->ctrl = new_ctrl; 58611e9eae4SChaoyong He 58711e9eae4SChaoyong He return 0; 58811e9eae4SChaoyong He } 58911e9eae4SChaoyong He 59011e9eae4SChaoyong He int 59111e9eae4SChaoyong He nfp_net_promisc_disable(struct rte_eth_dev *dev) 59211e9eae4SChaoyong He { 59311e9eae4SChaoyong He int ret; 59472d1dea6SChaoyong He uint32_t update; 59511e9eae4SChaoyong He uint32_t new_ctrl; 59672d1dea6SChaoyong He struct nfp_hw *hw; 59772d1dea6SChaoyong He struct nfp_net_hw *net_hw; 59811e9eae4SChaoyong He 599b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 60072d1dea6SChaoyong He hw = &net_hw->super; 60111e9eae4SChaoyong He 6025ff76867SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) { 6035ff76867SChaoyong He PMD_DRV_LOG(ERR, "Promiscuous mode not supported"); 6045ff76867SChaoyong He return -ENOTSUP; 6055ff76867SChaoyong He } 6065ff76867SChaoyong He 60772d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) == 0) { 60811e9eae4SChaoyong He PMD_DRV_LOG(INFO, "Promiscuous mode already disabled"); 60911e9eae4SChaoyong He return 0; 61011e9eae4SChaoyong He } 61111e9eae4SChaoyong He 61272d1dea6SChaoyong He new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_PROMISC; 61311e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 61411e9eae4SChaoyong He 61572d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 61611e9eae4SChaoyong He if (ret != 0) 61711e9eae4SChaoyong He return ret; 61811e9eae4SChaoyong He 61972d1dea6SChaoyong He hw->ctrl = new_ctrl; 62011e9eae4SChaoyong He 62111e9eae4SChaoyong He return 0; 62211e9eae4SChaoyong He } 62311e9eae4SChaoyong He 6244a86c36bSQin Ke static int 6254a86c36bSQin Ke nfp_net_set_allmulticast_mode(struct rte_eth_dev *dev, 6264a86c36bSQin Ke bool enable) 6274a86c36bSQin Ke { 6284a86c36bSQin Ke int ret; 6294a86c36bSQin Ke uint32_t update; 6304a86c36bSQin Ke struct nfp_hw *hw; 6314a86c36bSQin Ke uint32_t cap_extend; 6324a86c36bSQin Ke uint32_t ctrl_extend; 6334a86c36bSQin Ke uint32_t new_ctrl_extend; 6344a86c36bSQin Ke struct nfp_net_hw *net_hw; 6354a86c36bSQin Ke 6364a86c36bSQin Ke net_hw = nfp_net_get_hw(dev); 6374a86c36bSQin Ke hw = &net_hw->super; 6384a86c36bSQin Ke 6394a86c36bSQin Ke cap_extend = hw->cap_ext; 6404a86c36bSQin Ke if ((cap_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0) { 6414a86c36bSQin Ke PMD_DRV_LOG(ERR, "Allmulticast mode not supported"); 6424a86c36bSQin Ke return -ENOTSUP; 6434a86c36bSQin Ke } 6444a86c36bSQin Ke 6454a86c36bSQin Ke /* 6464a86c36bSQin Ke * Allmulticast mode enabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 0. 6474a86c36bSQin Ke * Allmulticast mode disabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 1. 6484a86c36bSQin Ke */ 6494a86c36bSQin Ke ctrl_extend = hw->ctrl_ext; 6504a86c36bSQin Ke if (enable) { 6514a86c36bSQin Ke if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0) 6524a86c36bSQin Ke return 0; 6534a86c36bSQin Ke 6544a86c36bSQin Ke new_ctrl_extend = ctrl_extend & ~NFP_NET_CFG_CTRL_MCAST_FILTER; 6554a86c36bSQin Ke } else { 6564a86c36bSQin Ke if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) != 0) 6574a86c36bSQin Ke return 0; 6584a86c36bSQin Ke 6594a86c36bSQin Ke new_ctrl_extend = ctrl_extend | NFP_NET_CFG_CTRL_MCAST_FILTER; 6604a86c36bSQin Ke } 6614a86c36bSQin Ke 6624a86c36bSQin Ke update = NFP_NET_CFG_UPDATE_GEN; 6634a86c36bSQin Ke 6644a86c36bSQin Ke ret = nfp_ext_reconfig(hw, new_ctrl_extend, update); 6654a86c36bSQin Ke if (ret != 0) 6664a86c36bSQin Ke return ret; 6674a86c36bSQin Ke 6684a86c36bSQin Ke hw->ctrl_ext = new_ctrl_extend; 6694a86c36bSQin Ke return 0; 6704a86c36bSQin Ke } 6714a86c36bSQin Ke 6724a86c36bSQin Ke int 6734a86c36bSQin Ke nfp_net_allmulticast_enable(struct rte_eth_dev *dev) 6744a86c36bSQin Ke { 6754a86c36bSQin Ke return nfp_net_set_allmulticast_mode(dev, true); 6764a86c36bSQin Ke } 6774a86c36bSQin Ke 6784a86c36bSQin Ke int 6794a86c36bSQin Ke nfp_net_allmulticast_disable(struct rte_eth_dev *dev) 6804a86c36bSQin Ke { 6814a86c36bSQin Ke return nfp_net_set_allmulticast_mode(dev, false); 6824a86c36bSQin Ke } 6834a86c36bSQin Ke 6848412feedSZerun Fu static int 6858412feedSZerun Fu nfp_net_speed_aneg_update(struct rte_eth_dev *dev, 6868412feedSZerun Fu struct nfp_net_hw *hw, 6878412feedSZerun Fu struct rte_eth_link *link) 6888412feedSZerun Fu { 6898412feedSZerun Fu uint32_t i; 6908412feedSZerun Fu uint32_t speed; 6918412feedSZerun Fu struct nfp_eth_table *nfp_eth_table; 6928412feedSZerun Fu struct nfp_eth_table_port *eth_port; 6938412feedSZerun Fu 6948412feedSZerun Fu /* Compare whether the current status has changed. */ 6958412feedSZerun Fu if (dev->data->dev_link.link_status != link->link_status) { 6968412feedSZerun Fu nfp_eth_table = nfp_eth_read_ports(hw->cpp); 6978412feedSZerun Fu if (nfp_eth_table == NULL) { 6988412feedSZerun Fu PMD_DRV_LOG(DEBUG, "Error reading NFP ethernet table."); 6998412feedSZerun Fu return -EIO; 7008412feedSZerun Fu } 7018412feedSZerun Fu 7028412feedSZerun Fu hw->pf_dev->nfp_eth_table->ports[hw->idx] = nfp_eth_table->ports[hw->idx]; 7038412feedSZerun Fu free(nfp_eth_table); 7048412feedSZerun Fu } 7058412feedSZerun Fu 7068412feedSZerun Fu nfp_eth_table = hw->pf_dev->nfp_eth_table; 7078412feedSZerun Fu eth_port = &nfp_eth_table->ports[hw->idx]; 7088412feedSZerun Fu speed = eth_port->speed; 7098412feedSZerun Fu 7108412feedSZerun Fu for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) { 7118412feedSZerun Fu if (nfp_net_link_speed_nfp2rte[i] == speed) { 7128412feedSZerun Fu link->link_speed = speed; 7138412feedSZerun Fu break; 7148412feedSZerun Fu } 7158412feedSZerun Fu } 7168412feedSZerun Fu 7178412feedSZerun Fu if (dev->data->dev_conf.link_speeds == RTE_ETH_LINK_SPEED_AUTONEG && 7188412feedSZerun Fu eth_port->supp_aneg) 7198412feedSZerun Fu link->link_autoneg = RTE_ETH_LINK_AUTONEG; 7208412feedSZerun Fu 7218412feedSZerun Fu return 0; 7228412feedSZerun Fu } 7238412feedSZerun Fu 724c4de52ecSChaoyong He int 725c4de52ecSChaoyong He nfp_net_link_update_common(struct rte_eth_dev *dev, 726c4de52ecSChaoyong He struct nfp_net_hw *hw, 727c4de52ecSChaoyong He struct rte_eth_link *link, 728c4de52ecSChaoyong He uint32_t link_status) 729c4de52ecSChaoyong He { 730c4de52ecSChaoyong He int ret; 731c4de52ecSChaoyong He uint32_t nn_link_status; 732c4de52ecSChaoyong He 733c4de52ecSChaoyong He if (link->link_status == RTE_ETH_LINK_UP) { 734c4de52ecSChaoyong He if (hw->pf_dev != NULL) { 7358412feedSZerun Fu ret = nfp_net_speed_aneg_update(dev, hw, link); 7368412feedSZerun Fu if (ret != 0) { 7378412feedSZerun Fu PMD_DRV_LOG(DEBUG, "Failed to update speed and aneg."); 7388412feedSZerun Fu return ret; 739c4de52ecSChaoyong He } 740c4de52ecSChaoyong He } else { 741c4de52ecSChaoyong He /* 742c4de52ecSChaoyong He * Shift and mask nn_link_status so that it is effectively the value 743c4de52ecSChaoyong He * at offset NFP_NET_CFG_STS_NSP_LINK_RATE. 744c4de52ecSChaoyong He */ 745c4de52ecSChaoyong He nn_link_status = (link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) & 746c4de52ecSChaoyong He NFP_NET_CFG_STS_LINK_RATE_MASK; 747c4de52ecSChaoyong He if (nn_link_status < RTE_DIM(nfp_net_link_speed_nfp2rte)) 748c4de52ecSChaoyong He link->link_speed = nfp_net_link_speed_nfp2rte[nn_link_status]; 749c4de52ecSChaoyong He } 750c4de52ecSChaoyong He } 751c4de52ecSChaoyong He 752c4de52ecSChaoyong He ret = rte_eth_linkstatus_set(dev, link); 753c4de52ecSChaoyong He if (ret == 0) { 754c4de52ecSChaoyong He if (link->link_status != 0) 755c4de52ecSChaoyong He PMD_DRV_LOG(INFO, "NIC Link is Up"); 756c4de52ecSChaoyong He else 757c4de52ecSChaoyong He PMD_DRV_LOG(INFO, "NIC Link is Down"); 758c4de52ecSChaoyong He } 759c4de52ecSChaoyong He 760c4de52ecSChaoyong He return ret; 761c4de52ecSChaoyong He } 762c4de52ecSChaoyong He 76311e9eae4SChaoyong He /* 76411e9eae4SChaoyong He * Return 0 means link status changed, -1 means not changed 76511e9eae4SChaoyong He * 76611e9eae4SChaoyong He * Wait to complete is needed as it can take up to 9 seconds to get the Link 76711e9eae4SChaoyong He * status. 76811e9eae4SChaoyong He */ 76911e9eae4SChaoyong He int 77011e9eae4SChaoyong He nfp_net_link_update(struct rte_eth_dev *dev, 77111e9eae4SChaoyong He __rte_unused int wait_to_complete) 77211e9eae4SChaoyong He { 77311e9eae4SChaoyong He int ret; 77411e9eae4SChaoyong He struct nfp_net_hw *hw; 77511e9eae4SChaoyong He uint32_t nn_link_status; 77611e9eae4SChaoyong He struct rte_eth_link link; 77711e9eae4SChaoyong He 778b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 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 789c4de52ecSChaoyong He ret = nfp_net_link_update_common(dev, hw, &link, nn_link_status); 7908412feedSZerun Fu if (ret == -EIO) 7918412feedSZerun Fu return ret; 79211e9eae4SChaoyong He 79311e9eae4SChaoyong He /* 79411e9eae4SChaoyong He * Notify the port to update the speed value in the CTRL BAR from NSP. 79511e9eae4SChaoyong He * Not applicable for VFs as the associated PF is still attached to the 79611e9eae4SChaoyong He * kernel driver. 79711e9eae4SChaoyong He */ 79811e9eae4SChaoyong He if (hw->pf_dev != NULL) 79911e9eae4SChaoyong He nfp_net_notify_port_speed(hw, &link); 80011e9eae4SChaoyong He 80111e9eae4SChaoyong He return ret; 80211e9eae4SChaoyong He } 80311e9eae4SChaoyong He 80411e9eae4SChaoyong He int 80511e9eae4SChaoyong He nfp_net_stats_get(struct rte_eth_dev *dev, 80611e9eae4SChaoyong He struct rte_eth_stats *stats) 80711e9eae4SChaoyong He { 80811e9eae4SChaoyong He uint16_t i; 80911e9eae4SChaoyong He struct nfp_net_hw *hw; 81011e9eae4SChaoyong He struct rte_eth_stats nfp_dev_stats; 81111e9eae4SChaoyong He 81211e9eae4SChaoyong He if (stats == NULL) 81311e9eae4SChaoyong He return -EINVAL; 81411e9eae4SChaoyong He 815b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 81611e9eae4SChaoyong He 81711e9eae4SChaoyong He memset(&nfp_dev_stats, 0, sizeof(nfp_dev_stats)); 81811e9eae4SChaoyong He 81911e9eae4SChaoyong He /* Reading per RX ring stats */ 82011e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 82111e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 82211e9eae4SChaoyong He break; 82311e9eae4SChaoyong He 82411e9eae4SChaoyong He nfp_dev_stats.q_ipackets[i] = 825f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i)); 82611e9eae4SChaoyong He nfp_dev_stats.q_ipackets[i] -= 82711e9eae4SChaoyong He hw->eth_stats_base.q_ipackets[i]; 82811e9eae4SChaoyong He 82911e9eae4SChaoyong He nfp_dev_stats.q_ibytes[i] = 830f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8); 83111e9eae4SChaoyong He nfp_dev_stats.q_ibytes[i] -= 83211e9eae4SChaoyong He hw->eth_stats_base.q_ibytes[i]; 83311e9eae4SChaoyong He } 83411e9eae4SChaoyong He 83511e9eae4SChaoyong He /* Reading per TX ring stats */ 83611e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 83711e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 83811e9eae4SChaoyong He break; 83911e9eae4SChaoyong He 84011e9eae4SChaoyong He nfp_dev_stats.q_opackets[i] = 841f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i)); 84211e9eae4SChaoyong He nfp_dev_stats.q_opackets[i] -= hw->eth_stats_base.q_opackets[i]; 84311e9eae4SChaoyong He 84411e9eae4SChaoyong He nfp_dev_stats.q_obytes[i] = 845f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8); 84611e9eae4SChaoyong He nfp_dev_stats.q_obytes[i] -= hw->eth_stats_base.q_obytes[i]; 84711e9eae4SChaoyong He } 84811e9eae4SChaoyong He 849f58bde00SChaoyong He nfp_dev_stats.ipackets = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES); 85011e9eae4SChaoyong He nfp_dev_stats.ipackets -= hw->eth_stats_base.ipackets; 85111e9eae4SChaoyong He 852f58bde00SChaoyong He nfp_dev_stats.ibytes = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS); 85311e9eae4SChaoyong He nfp_dev_stats.ibytes -= hw->eth_stats_base.ibytes; 85411e9eae4SChaoyong He 85511e9eae4SChaoyong He nfp_dev_stats.opackets = 856f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES); 85711e9eae4SChaoyong He nfp_dev_stats.opackets -= hw->eth_stats_base.opackets; 85811e9eae4SChaoyong He 85911e9eae4SChaoyong He nfp_dev_stats.obytes = 860f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS); 86111e9eae4SChaoyong He nfp_dev_stats.obytes -= hw->eth_stats_base.obytes; 86211e9eae4SChaoyong He 86311e9eae4SChaoyong He /* Reading general device stats */ 86411e9eae4SChaoyong He nfp_dev_stats.ierrors = 865f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS); 86611e9eae4SChaoyong He nfp_dev_stats.ierrors -= hw->eth_stats_base.ierrors; 86711e9eae4SChaoyong He 86811e9eae4SChaoyong He nfp_dev_stats.oerrors = 869f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS); 87011e9eae4SChaoyong He nfp_dev_stats.oerrors -= hw->eth_stats_base.oerrors; 87111e9eae4SChaoyong He 87211e9eae4SChaoyong He /* RX ring mbuf allocation failures */ 87311e9eae4SChaoyong He nfp_dev_stats.rx_nombuf = dev->data->rx_mbuf_alloc_failed; 87411e9eae4SChaoyong He 87511e9eae4SChaoyong He nfp_dev_stats.imissed = 876f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS); 87711e9eae4SChaoyong He nfp_dev_stats.imissed -= hw->eth_stats_base.imissed; 87811e9eae4SChaoyong He 87911e9eae4SChaoyong He memcpy(stats, &nfp_dev_stats, sizeof(*stats)); 88011e9eae4SChaoyong He return 0; 88111e9eae4SChaoyong He } 88211e9eae4SChaoyong He 88311e9eae4SChaoyong He /* 88411e9eae4SChaoyong He * hw->eth_stats_base records the per counter starting point. 88511e9eae4SChaoyong He * Lets update it now. 88611e9eae4SChaoyong He */ 88711e9eae4SChaoyong He int 88811e9eae4SChaoyong He nfp_net_stats_reset(struct rte_eth_dev *dev) 88911e9eae4SChaoyong He { 89011e9eae4SChaoyong He uint16_t i; 89111e9eae4SChaoyong He struct nfp_net_hw *hw; 89211e9eae4SChaoyong He 893b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 89411e9eae4SChaoyong He 89511e9eae4SChaoyong He /* Reading per RX ring stats */ 89611e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 89711e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 89811e9eae4SChaoyong He break; 89911e9eae4SChaoyong He 90011e9eae4SChaoyong He hw->eth_stats_base.q_ipackets[i] = 901f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i)); 90211e9eae4SChaoyong He 90311e9eae4SChaoyong He hw->eth_stats_base.q_ibytes[i] = 904f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8); 90511e9eae4SChaoyong He } 90611e9eae4SChaoyong He 90711e9eae4SChaoyong He /* Reading per TX ring stats */ 90811e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 90911e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 91011e9eae4SChaoyong He break; 91111e9eae4SChaoyong He 91211e9eae4SChaoyong He hw->eth_stats_base.q_opackets[i] = 913f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i)); 91411e9eae4SChaoyong He 91511e9eae4SChaoyong He hw->eth_stats_base.q_obytes[i] = 916f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8); 91711e9eae4SChaoyong He } 91811e9eae4SChaoyong He 91911e9eae4SChaoyong He hw->eth_stats_base.ipackets = 920f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES); 92111e9eae4SChaoyong He 92211e9eae4SChaoyong He hw->eth_stats_base.ibytes = 923f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS); 92411e9eae4SChaoyong He 92511e9eae4SChaoyong He hw->eth_stats_base.opackets = 926f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES); 92711e9eae4SChaoyong He 92811e9eae4SChaoyong He hw->eth_stats_base.obytes = 929f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS); 93011e9eae4SChaoyong He 93111e9eae4SChaoyong He /* Reading general device stats */ 93211e9eae4SChaoyong He hw->eth_stats_base.ierrors = 933f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS); 93411e9eae4SChaoyong He 93511e9eae4SChaoyong He hw->eth_stats_base.oerrors = 936f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS); 93711e9eae4SChaoyong He 93811e9eae4SChaoyong He /* RX ring mbuf allocation failures */ 93911e9eae4SChaoyong He dev->data->rx_mbuf_alloc_failed = 0; 94011e9eae4SChaoyong He 94111e9eae4SChaoyong He hw->eth_stats_base.imissed = 942f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS); 94311e9eae4SChaoyong He 94411e9eae4SChaoyong He return 0; 94511e9eae4SChaoyong He } 94611e9eae4SChaoyong He 94711e9eae4SChaoyong He uint32_t 94811e9eae4SChaoyong He nfp_net_xstats_size(const struct rte_eth_dev *dev) 94911e9eae4SChaoyong He { 95011e9eae4SChaoyong He uint32_t count; 95111e9eae4SChaoyong He struct nfp_net_hw *hw; 95211e9eae4SChaoyong He const uint32_t size = RTE_DIM(nfp_net_xstats); 95311e9eae4SChaoyong He 95411e9eae4SChaoyong He /* If the device is a VF, then there will be no MAC stats */ 955b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 95611e9eae4SChaoyong He if (hw->mac_stats == NULL) { 95711e9eae4SChaoyong He for (count = 0; count < size; count++) { 95811e9eae4SChaoyong He if (nfp_net_xstats[count].group == NFP_XSTAT_GROUP_MAC) 95911e9eae4SChaoyong He break; 96011e9eae4SChaoyong He } 96111e9eae4SChaoyong He 96211e9eae4SChaoyong He return count; 96311e9eae4SChaoyong He } 96411e9eae4SChaoyong He 96511e9eae4SChaoyong He return size; 96611e9eae4SChaoyong He } 96711e9eae4SChaoyong He 96811e9eae4SChaoyong He static const struct nfp_xstat * 96911e9eae4SChaoyong He nfp_net_xstats_info(const struct rte_eth_dev *dev, 97011e9eae4SChaoyong He uint32_t index) 97111e9eae4SChaoyong He { 97211e9eae4SChaoyong He if (index >= nfp_net_xstats_size(dev)) { 97311e9eae4SChaoyong He PMD_DRV_LOG(ERR, "xstat index out of bounds"); 97411e9eae4SChaoyong He return NULL; 97511e9eae4SChaoyong He } 97611e9eae4SChaoyong He 97711e9eae4SChaoyong He return &nfp_net_xstats[index]; 97811e9eae4SChaoyong He } 97911e9eae4SChaoyong He 98011e9eae4SChaoyong He static uint64_t 98111e9eae4SChaoyong He nfp_net_xstats_value(const struct rte_eth_dev *dev, 98211e9eae4SChaoyong He uint32_t index, 98311e9eae4SChaoyong He bool raw) 98411e9eae4SChaoyong He { 98511e9eae4SChaoyong He uint64_t value; 98611e9eae4SChaoyong He struct nfp_net_hw *hw; 98711e9eae4SChaoyong He struct nfp_xstat xstat; 98811e9eae4SChaoyong He 989b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 99011e9eae4SChaoyong He xstat = nfp_net_xstats[index]; 99111e9eae4SChaoyong He 99211e9eae4SChaoyong He if (xstat.group == NFP_XSTAT_GROUP_MAC) 99311e9eae4SChaoyong He value = nn_readq(hw->mac_stats + xstat.offset); 99411e9eae4SChaoyong He else 995f58bde00SChaoyong He value = nn_cfg_readq(&hw->super, xstat.offset); 99611e9eae4SChaoyong He 99711e9eae4SChaoyong He if (raw) 99811e9eae4SChaoyong He return value; 99911e9eae4SChaoyong He 100011e9eae4SChaoyong He /* 100111e9eae4SChaoyong He * A baseline value of each statistic counter is recorded when stats are "reset". 100211e9eae4SChaoyong He * Thus, the value returned by this function need to be decremented by this 100311e9eae4SChaoyong He * baseline value. The result is the count of this statistic since the last time 100411e9eae4SChaoyong He * it was "reset". 100511e9eae4SChaoyong He */ 100611e9eae4SChaoyong He return value - hw->eth_xstats_base[index].value; 100711e9eae4SChaoyong He } 100811e9eae4SChaoyong He 100911e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */ 101011e9eae4SChaoyong He int 101111e9eae4SChaoyong He nfp_net_xstats_get_names(struct rte_eth_dev *dev, 101211e9eae4SChaoyong He struct rte_eth_xstat_name *xstats_names, 101311e9eae4SChaoyong He unsigned int size) 101411e9eae4SChaoyong He { 101511e9eae4SChaoyong He uint32_t id; 101611e9eae4SChaoyong He uint32_t nfp_size; 101711e9eae4SChaoyong He uint32_t read_size; 101811e9eae4SChaoyong He 101911e9eae4SChaoyong He nfp_size = nfp_net_xstats_size(dev); 102011e9eae4SChaoyong He 102111e9eae4SChaoyong He if (xstats_names == NULL) 102211e9eae4SChaoyong He return nfp_size; 102311e9eae4SChaoyong He 102411e9eae4SChaoyong He /* Read at most NFP xstats number of names. */ 102511e9eae4SChaoyong He read_size = RTE_MIN(size, nfp_size); 102611e9eae4SChaoyong He 102711e9eae4SChaoyong He for (id = 0; id < read_size; id++) 102811e9eae4SChaoyong He rte_strlcpy(xstats_names[id].name, nfp_net_xstats[id].name, 102911e9eae4SChaoyong He RTE_ETH_XSTATS_NAME_SIZE); 103011e9eae4SChaoyong He 103111e9eae4SChaoyong He return read_size; 103211e9eae4SChaoyong He } 103311e9eae4SChaoyong He 103411e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */ 103511e9eae4SChaoyong He int 103611e9eae4SChaoyong He nfp_net_xstats_get(struct rte_eth_dev *dev, 103711e9eae4SChaoyong He struct rte_eth_xstat *xstats, 103811e9eae4SChaoyong He unsigned int n) 103911e9eae4SChaoyong He { 104011e9eae4SChaoyong He uint32_t id; 104111e9eae4SChaoyong He uint32_t nfp_size; 104211e9eae4SChaoyong He uint32_t read_size; 104311e9eae4SChaoyong He 104411e9eae4SChaoyong He nfp_size = nfp_net_xstats_size(dev); 104511e9eae4SChaoyong He 104611e9eae4SChaoyong He if (xstats == NULL) 104711e9eae4SChaoyong He return nfp_size; 104811e9eae4SChaoyong He 104911e9eae4SChaoyong He /* Read at most NFP xstats number of values. */ 105011e9eae4SChaoyong He read_size = RTE_MIN(n, nfp_size); 105111e9eae4SChaoyong He 105211e9eae4SChaoyong He for (id = 0; id < read_size; id++) { 105311e9eae4SChaoyong He xstats[id].id = id; 105411e9eae4SChaoyong He xstats[id].value = nfp_net_xstats_value(dev, id, false); 105511e9eae4SChaoyong He } 105611e9eae4SChaoyong He 105711e9eae4SChaoyong He return read_size; 105811e9eae4SChaoyong He } 105911e9eae4SChaoyong He 106011e9eae4SChaoyong He /* 106111e9eae4SChaoyong He * NOTE: The only caller rte_eth_xstats_get_names_by_id() ensures dev, 106211e9eae4SChaoyong He * ids, xstats_names and size are valid, and non-NULL. 106311e9eae4SChaoyong He */ 106411e9eae4SChaoyong He int 106511e9eae4SChaoyong He nfp_net_xstats_get_names_by_id(struct rte_eth_dev *dev, 106611e9eae4SChaoyong He const uint64_t *ids, 106711e9eae4SChaoyong He struct rte_eth_xstat_name *xstats_names, 106811e9eae4SChaoyong He unsigned int size) 106911e9eae4SChaoyong He { 107011e9eae4SChaoyong He uint32_t i; 107111e9eae4SChaoyong He uint32_t read_size; 107211e9eae4SChaoyong He 107311e9eae4SChaoyong He /* Read at most NFP xstats number of names. */ 107411e9eae4SChaoyong He read_size = RTE_MIN(size, nfp_net_xstats_size(dev)); 107511e9eae4SChaoyong He 107611e9eae4SChaoyong He for (i = 0; i < read_size; i++) { 107711e9eae4SChaoyong He const struct nfp_xstat *xstat; 107811e9eae4SChaoyong He 107911e9eae4SChaoyong He /* Make sure ID is valid for device. */ 108011e9eae4SChaoyong He xstat = nfp_net_xstats_info(dev, ids[i]); 108111e9eae4SChaoyong He if (xstat == NULL) 108211e9eae4SChaoyong He return -EINVAL; 108311e9eae4SChaoyong He 108411e9eae4SChaoyong He rte_strlcpy(xstats_names[i].name, xstat->name, 108511e9eae4SChaoyong He RTE_ETH_XSTATS_NAME_SIZE); 108611e9eae4SChaoyong He } 108711e9eae4SChaoyong He 108811e9eae4SChaoyong He return read_size; 108911e9eae4SChaoyong He } 109011e9eae4SChaoyong He 109111e9eae4SChaoyong He /* 109211e9eae4SChaoyong He * NOTE: The only caller rte_eth_xstats_get_by_id() ensures dev, 109311e9eae4SChaoyong He * ids, values and n are valid, and non-NULL. 109411e9eae4SChaoyong He */ 109511e9eae4SChaoyong He int 109611e9eae4SChaoyong He nfp_net_xstats_get_by_id(struct rte_eth_dev *dev, 109711e9eae4SChaoyong He const uint64_t *ids, 109811e9eae4SChaoyong He uint64_t *values, 109911e9eae4SChaoyong He unsigned int n) 110011e9eae4SChaoyong He { 110111e9eae4SChaoyong He uint32_t i; 110211e9eae4SChaoyong He uint32_t read_size; 110311e9eae4SChaoyong He 110411e9eae4SChaoyong He /* Read at most NFP xstats number of values. */ 110511e9eae4SChaoyong He read_size = RTE_MIN(n, nfp_net_xstats_size(dev)); 110611e9eae4SChaoyong He 110711e9eae4SChaoyong He for (i = 0; i < read_size; i++) { 110811e9eae4SChaoyong He const struct nfp_xstat *xstat; 110911e9eae4SChaoyong He 111011e9eae4SChaoyong He /* Make sure index is valid for device. */ 111111e9eae4SChaoyong He xstat = nfp_net_xstats_info(dev, ids[i]); 111211e9eae4SChaoyong He if (xstat == NULL) 111311e9eae4SChaoyong He return -EINVAL; 111411e9eae4SChaoyong He 111511e9eae4SChaoyong He values[i] = nfp_net_xstats_value(dev, ids[i], false); 111611e9eae4SChaoyong He } 111711e9eae4SChaoyong He 111811e9eae4SChaoyong He return read_size; 111911e9eae4SChaoyong He } 112011e9eae4SChaoyong He 112111e9eae4SChaoyong He int 112211e9eae4SChaoyong He nfp_net_xstats_reset(struct rte_eth_dev *dev) 112311e9eae4SChaoyong He { 112411e9eae4SChaoyong He uint32_t id; 112511e9eae4SChaoyong He uint32_t read_size; 112611e9eae4SChaoyong He struct nfp_net_hw *hw; 112711e9eae4SChaoyong He 1128b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 112911e9eae4SChaoyong He read_size = nfp_net_xstats_size(dev); 113011e9eae4SChaoyong He 113111e9eae4SChaoyong He for (id = 0; id < read_size; id++) { 113211e9eae4SChaoyong He hw->eth_xstats_base[id].id = id; 113311e9eae4SChaoyong He hw->eth_xstats_base[id].value = nfp_net_xstats_value(dev, id, true); 113411e9eae4SChaoyong He } 113511e9eae4SChaoyong He 113611e9eae4SChaoyong He /* Successfully reset xstats, now call function to reset basic stats. */ 113711e9eae4SChaoyong He return nfp_net_stats_reset(dev); 113811e9eae4SChaoyong He } 113911e9eae4SChaoyong He 114011e9eae4SChaoyong He void 114111e9eae4SChaoyong He nfp_net_rx_desc_limits(struct nfp_net_hw *hw, 114211e9eae4SChaoyong He uint16_t *min_rx_desc, 114311e9eae4SChaoyong He uint16_t *max_rx_desc) 114411e9eae4SChaoyong He { 114511e9eae4SChaoyong He *max_rx_desc = hw->dev_info->max_qc_size; 114611e9eae4SChaoyong He *min_rx_desc = hw->dev_info->min_qc_size; 114711e9eae4SChaoyong He } 114811e9eae4SChaoyong He 114911e9eae4SChaoyong He void 115011e9eae4SChaoyong He nfp_net_tx_desc_limits(struct nfp_net_hw *hw, 115111e9eae4SChaoyong He uint16_t *min_tx_desc, 115211e9eae4SChaoyong He uint16_t *max_tx_desc) 115311e9eae4SChaoyong He { 115411e9eae4SChaoyong He uint16_t tx_dpp; 115511e9eae4SChaoyong He 115611e9eae4SChaoyong He if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 115711e9eae4SChaoyong He tx_dpp = NFD3_TX_DESC_PER_PKT; 115811e9eae4SChaoyong He else 115911e9eae4SChaoyong He tx_dpp = NFDK_TX_DESC_PER_SIMPLE_PKT; 116011e9eae4SChaoyong He 116111e9eae4SChaoyong He *max_tx_desc = hw->dev_info->max_qc_size / tx_dpp; 116211e9eae4SChaoyong He *min_tx_desc = hw->dev_info->min_qc_size / tx_dpp; 116311e9eae4SChaoyong He } 116411e9eae4SChaoyong He 116511e9eae4SChaoyong He int 116611e9eae4SChaoyong He nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 116711e9eae4SChaoyong He { 11684a9bb682SChaoyong He uint32_t cap; 116911e9eae4SChaoyong He uint32_t cap_extend; 117011e9eae4SChaoyong He uint16_t min_rx_desc; 117111e9eae4SChaoyong He uint16_t max_rx_desc; 117211e9eae4SChaoyong He uint16_t min_tx_desc; 117311e9eae4SChaoyong He uint16_t max_tx_desc; 117411e9eae4SChaoyong He struct nfp_net_hw *hw; 117511e9eae4SChaoyong He 1176b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 117711e9eae4SChaoyong He 117811e9eae4SChaoyong He nfp_net_rx_desc_limits(hw, &min_rx_desc, &max_rx_desc); 117911e9eae4SChaoyong He nfp_net_tx_desc_limits(hw, &min_tx_desc, &max_tx_desc); 118011e9eae4SChaoyong He 118111e9eae4SChaoyong He dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues; 118211e9eae4SChaoyong He dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues; 118311e9eae4SChaoyong He dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU; 11842f1bfbf4SJames Hershaw /* 11852f1bfbf4SJames Hershaw * The maximum rx packet length is set to the maximum layer 3 MTU, 11862f1bfbf4SJames Hershaw * plus layer 2, CRC and VLAN headers. 118711e9eae4SChaoyong He * The maximum layer 3 MTU (max_mtu) is read from hardware, 118811e9eae4SChaoyong He * which was set by the firmware loaded onto the card. 118911e9eae4SChaoyong He */ 11902f1bfbf4SJames Hershaw dev_info->max_rx_pktlen = hw->max_mtu + NFP_ETH_OVERHEAD; 119111e9eae4SChaoyong He dev_info->max_mtu = hw->max_mtu; 119211e9eae4SChaoyong He dev_info->min_mtu = RTE_ETHER_MIN_MTU; 119311e9eae4SChaoyong He /* Next should change when PF support is implemented */ 119411e9eae4SChaoyong He dev_info->max_mac_addrs = 1; 119511e9eae4SChaoyong He 11964a9bb682SChaoyong He cap = hw->super.cap; 11974a9bb682SChaoyong He 11984a9bb682SChaoyong He if ((cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) != 0) 119911e9eae4SChaoyong He dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 120011e9eae4SChaoyong He 12014a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0) 120211e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP; 120311e9eae4SChaoyong He 12044a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0) 120511e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | 120611e9eae4SChaoyong He RTE_ETH_RX_OFFLOAD_UDP_CKSUM | 120711e9eae4SChaoyong He RTE_ETH_RX_OFFLOAD_TCP_CKSUM; 120811e9eae4SChaoyong He 12094a9bb682SChaoyong He if ((cap & (NFP_NET_CFG_CTRL_TXVLAN | NFP_NET_CFG_CTRL_TXVLAN_V2)) != 0) 121011e9eae4SChaoyong He dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT; 121111e9eae4SChaoyong He 12124a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_TXCSUM) != 0) 121311e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | 121411e9eae4SChaoyong He RTE_ETH_TX_OFFLOAD_UDP_CKSUM | 121511e9eae4SChaoyong He RTE_ETH_TX_OFFLOAD_TCP_CKSUM; 121611e9eae4SChaoyong He 12174a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0) { 121811e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO; 1219df77f704SChaoyong He if ((cap & NFP_NET_CFG_CTRL_USO) != 0) 1220df77f704SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_UDP_TSO; 12214a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_VXLAN) != 0) 122211e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO; 122311e9eae4SChaoyong He } 122411e9eae4SChaoyong He 12254a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_GATHER) != 0) 122611e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 122711e9eae4SChaoyong He 122875a76c73SChaoyong He cap_extend = hw->super.cap_ext; 122911e9eae4SChaoyong He if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) { 123011e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY; 123111e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY; 123211e9eae4SChaoyong He } 123311e9eae4SChaoyong He 123411e9eae4SChaoyong He dev_info->default_rxconf = (struct rte_eth_rxconf) { 123511e9eae4SChaoyong He .rx_thresh = { 123611e9eae4SChaoyong He .pthresh = DEFAULT_RX_PTHRESH, 123711e9eae4SChaoyong He .hthresh = DEFAULT_RX_HTHRESH, 123811e9eae4SChaoyong He .wthresh = DEFAULT_RX_WTHRESH, 123911e9eae4SChaoyong He }, 124011e9eae4SChaoyong He .rx_free_thresh = DEFAULT_RX_FREE_THRESH, 124111e9eae4SChaoyong He .rx_drop_en = 0, 124211e9eae4SChaoyong He }; 124311e9eae4SChaoyong He 124411e9eae4SChaoyong He dev_info->default_txconf = (struct rte_eth_txconf) { 124511e9eae4SChaoyong He .tx_thresh = { 124611e9eae4SChaoyong He .pthresh = DEFAULT_TX_PTHRESH, 124711e9eae4SChaoyong He .hthresh = DEFAULT_TX_HTHRESH, 124811e9eae4SChaoyong He .wthresh = DEFAULT_TX_WTHRESH, 124911e9eae4SChaoyong He }, 125011e9eae4SChaoyong He .tx_free_thresh = DEFAULT_TX_FREE_THRESH, 125111e9eae4SChaoyong He .tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH, 125211e9eae4SChaoyong He }; 125311e9eae4SChaoyong He 125411e9eae4SChaoyong He dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 125511e9eae4SChaoyong He .nb_max = max_rx_desc, 125611e9eae4SChaoyong He .nb_min = min_rx_desc, 125711e9eae4SChaoyong He .nb_align = NFP_ALIGN_RING_DESC, 125811e9eae4SChaoyong He }; 125911e9eae4SChaoyong He 126011e9eae4SChaoyong He dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 126111e9eae4SChaoyong He .nb_max = max_tx_desc, 126211e9eae4SChaoyong He .nb_min = min_tx_desc, 126311e9eae4SChaoyong He .nb_align = NFP_ALIGN_RING_DESC, 126411e9eae4SChaoyong He .nb_seg_max = NFP_TX_MAX_SEG, 126511e9eae4SChaoyong He .nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG, 126611e9eae4SChaoyong He }; 126711e9eae4SChaoyong He 12684a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) { 126911e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 1270*b458a2a0SLong Wu dev_info->flow_type_rss_offloads = NFP_NET_RSS_CAP; 127111e9eae4SChaoyong He dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ; 127211e9eae4SChaoyong He dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ; 127311e9eae4SChaoyong He } 127411e9eae4SChaoyong He 12753110ab73SZerun Fu /* Only PF supports getting speed capability. */ 12763110ab73SZerun Fu if (hw->pf_dev != NULL) 12773110ab73SZerun Fu dev_info->speed_capa = hw->pf_dev->speed_capa; 127811e9eae4SChaoyong He 127911e9eae4SChaoyong He return 0; 128011e9eae4SChaoyong He } 128111e9eae4SChaoyong He 128211e9eae4SChaoyong He int 128311e9eae4SChaoyong He nfp_net_common_init(struct rte_pci_device *pci_dev, 128411e9eae4SChaoyong He struct nfp_net_hw *hw) 128511e9eae4SChaoyong He { 128611e9eae4SChaoyong He const int stride = 4; 128711e9eae4SChaoyong He 128811e9eae4SChaoyong He hw->device_id = pci_dev->id.device_id; 128911e9eae4SChaoyong He hw->vendor_id = pci_dev->id.vendor_id; 129011e9eae4SChaoyong He hw->subsystem_device_id = pci_dev->id.subsystem_device_id; 129111e9eae4SChaoyong He hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; 129211e9eae4SChaoyong He 1293f58bde00SChaoyong He hw->max_rx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_RXRINGS); 1294f58bde00SChaoyong He hw->max_tx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_TXRINGS); 129511e9eae4SChaoyong He if (hw->max_rx_queues == 0 || hw->max_tx_queues == 0) { 129611e9eae4SChaoyong He PMD_INIT_LOG(ERR, "Device %s can not be used, there are no valid queue " 129711e9eae4SChaoyong He "pairs for use", pci_dev->name); 129811e9eae4SChaoyong He return -ENODEV; 129911e9eae4SChaoyong He } 130011e9eae4SChaoyong He 130111e9eae4SChaoyong He nfp_net_cfg_read_version(hw); 130211e9eae4SChaoyong He if (!nfp_net_is_valid_nfd_version(hw->ver)) 130311e9eae4SChaoyong He return -EINVAL; 130411e9eae4SChaoyong He 130511e9eae4SChaoyong He if (nfp_net_check_dma_mask(hw, pci_dev->name) != 0) 130611e9eae4SChaoyong He return -ENODEV; 130711e9eae4SChaoyong He 130811e9eae4SChaoyong He /* Get some of the read-only fields from the config BAR */ 1309f58bde00SChaoyong He hw->super.cap = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP); 1310f58bde00SChaoyong He hw->super.cap_ext = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP_WORD1); 1311f58bde00SChaoyong He hw->max_mtu = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_MTU); 131211e9eae4SChaoyong He hw->flbufsz = DEFAULT_FLBUF_SIZE; 131311e9eae4SChaoyong He 131411e9eae4SChaoyong He nfp_net_init_metadata_format(hw); 131511e9eae4SChaoyong He 131611e9eae4SChaoyong He /* Read the Rx offset configured from firmware */ 131711e9eae4SChaoyong He if (hw->ver.major < 2) 131811e9eae4SChaoyong He hw->rx_offset = NFP_NET_RX_OFFSET; 131911e9eae4SChaoyong He else 132065f6915dSChaoyong He hw->rx_offset = nn_cfg_readl(&hw->super, NFP_NET_CFG_RX_OFFSET); 132111e9eae4SChaoyong He 1322b4b6988aSChaoyong He hw->super.ctrl = 0; 132311e9eae4SChaoyong He hw->stride_rx = stride; 132411e9eae4SChaoyong He hw->stride_tx = stride; 132511e9eae4SChaoyong He 132611e9eae4SChaoyong He return 0; 132711e9eae4SChaoyong He } 132811e9eae4SChaoyong He 132911e9eae4SChaoyong He const uint32_t * 1330ba6a168aSSivaramakrishnan Venkat nfp_net_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) 133111e9eae4SChaoyong He { 133211e9eae4SChaoyong He struct nfp_net_hw *net_hw; 133311e9eae4SChaoyong He static const uint32_t ptypes[] = { 133411e9eae4SChaoyong He RTE_PTYPE_L2_ETHER, 133511e9eae4SChaoyong He RTE_PTYPE_L3_IPV4, 133611e9eae4SChaoyong He RTE_PTYPE_L3_IPV4_EXT, 133711e9eae4SChaoyong He RTE_PTYPE_L3_IPV6, 133811e9eae4SChaoyong He RTE_PTYPE_L3_IPV6_EXT, 133911e9eae4SChaoyong He RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 134011e9eae4SChaoyong He RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 134111e9eae4SChaoyong He RTE_PTYPE_L4_TCP, 134211e9eae4SChaoyong He RTE_PTYPE_L4_UDP, 134311e9eae4SChaoyong He RTE_PTYPE_L4_FRAG, 134411e9eae4SChaoyong He RTE_PTYPE_L4_NONFRAG, 134511e9eae4SChaoyong He RTE_PTYPE_L4_ICMP, 134611e9eae4SChaoyong He RTE_PTYPE_L4_SCTP, 134711e9eae4SChaoyong He RTE_PTYPE_TUNNEL_VXLAN, 134811e9eae4SChaoyong He RTE_PTYPE_TUNNEL_NVGRE, 134911e9eae4SChaoyong He RTE_PTYPE_TUNNEL_GENEVE, 135011e9eae4SChaoyong He RTE_PTYPE_INNER_L2_ETHER, 135111e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4, 135211e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4_EXT, 135311e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6, 135411e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6_EXT, 135511e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 135611e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 135711e9eae4SChaoyong He RTE_PTYPE_INNER_L4_TCP, 135811e9eae4SChaoyong He RTE_PTYPE_INNER_L4_UDP, 135911e9eae4SChaoyong He RTE_PTYPE_INNER_L4_FRAG, 136011e9eae4SChaoyong He RTE_PTYPE_INNER_L4_NONFRAG, 136111e9eae4SChaoyong He RTE_PTYPE_INNER_L4_ICMP, 136211e9eae4SChaoyong He RTE_PTYPE_INNER_L4_SCTP, 136311e9eae4SChaoyong He }; 136411e9eae4SChaoyong He 136511e9eae4SChaoyong He if (dev->rx_pkt_burst != nfp_net_recv_pkts) 136611e9eae4SChaoyong He return NULL; 136711e9eae4SChaoyong He 13689d723baaSChaoyong He net_hw = dev->data->dev_private; 13699177c800SChaoyong He if ((net_hw->super.ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0) 137011e9eae4SChaoyong He return NULL; 137111e9eae4SChaoyong He 1372ba6a168aSSivaramakrishnan Venkat *no_of_elements = RTE_DIM(ptypes); 137311e9eae4SChaoyong He return ptypes; 137411e9eae4SChaoyong He } 137511e9eae4SChaoyong He 137611e9eae4SChaoyong He int 137711e9eae4SChaoyong He nfp_rx_queue_intr_enable(struct rte_eth_dev *dev, 137811e9eae4SChaoyong He uint16_t queue_id) 137911e9eae4SChaoyong He { 138011e9eae4SChaoyong He uint16_t base = 0; 138111e9eae4SChaoyong He struct nfp_net_hw *hw; 138211e9eae4SChaoyong He struct rte_pci_device *pci_dev; 138311e9eae4SChaoyong He 138411e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 138511e9eae4SChaoyong He if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO) 138611e9eae4SChaoyong He base = 1; 138711e9eae4SChaoyong He 138811e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 138911e9eae4SChaoyong He rte_wmb(); 139011e9eae4SChaoyong He 1391b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 1392f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), 139311e9eae4SChaoyong He NFP_NET_CFG_ICR_UNMASKED); 139411e9eae4SChaoyong He return 0; 139511e9eae4SChaoyong He } 139611e9eae4SChaoyong He 139711e9eae4SChaoyong He int 139811e9eae4SChaoyong He nfp_rx_queue_intr_disable(struct rte_eth_dev *dev, 139911e9eae4SChaoyong He uint16_t queue_id) 140011e9eae4SChaoyong He { 140111e9eae4SChaoyong He uint16_t base = 0; 140211e9eae4SChaoyong He struct nfp_net_hw *hw; 140311e9eae4SChaoyong He struct rte_pci_device *pci_dev; 140411e9eae4SChaoyong He 140511e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 140611e9eae4SChaoyong He if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO) 140711e9eae4SChaoyong He base = 1; 140811e9eae4SChaoyong He 140911e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 141011e9eae4SChaoyong He rte_wmb(); 141111e9eae4SChaoyong He 1412b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 1413f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), NFP_NET_CFG_ICR_RXTX); 141411e9eae4SChaoyong He 141511e9eae4SChaoyong He return 0; 141611e9eae4SChaoyong He } 141711e9eae4SChaoyong He 141811e9eae4SChaoyong He static void 141911e9eae4SChaoyong He nfp_net_dev_link_status_print(struct rte_eth_dev *dev) 142011e9eae4SChaoyong He { 142111e9eae4SChaoyong He struct rte_eth_link link; 142211e9eae4SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 142311e9eae4SChaoyong He 142411e9eae4SChaoyong He rte_eth_linkstatus_get(dev, &link); 142511e9eae4SChaoyong He if (link.link_status != 0) 142611e9eae4SChaoyong He PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s", 142711e9eae4SChaoyong He dev->data->port_id, link.link_speed, 142811e9eae4SChaoyong He link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX ? 142911e9eae4SChaoyong He "full-duplex" : "half-duplex"); 143011e9eae4SChaoyong He else 143111e9eae4SChaoyong He PMD_DRV_LOG(INFO, " Port %d: Link Down", dev->data->port_id); 143211e9eae4SChaoyong He 143311e9eae4SChaoyong He PMD_DRV_LOG(INFO, "PCI Address: " PCI_PRI_FMT, 143411e9eae4SChaoyong He pci_dev->addr.domain, pci_dev->addr.bus, 143511e9eae4SChaoyong He pci_dev->addr.devid, pci_dev->addr.function); 143611e9eae4SChaoyong He } 143711e9eae4SChaoyong He 143811e9eae4SChaoyong He /* 143911e9eae4SChaoyong He * Unmask an interrupt 144011e9eae4SChaoyong He * 144111e9eae4SChaoyong He * If MSI-X auto-masking is enabled clear the mask bit, otherwise 144211e9eae4SChaoyong He * clear the ICR for the entry. 144311e9eae4SChaoyong He */ 144494d0631aSPeng Zhang void 144511e9eae4SChaoyong He nfp_net_irq_unmask(struct rte_eth_dev *dev) 144611e9eae4SChaoyong He { 144711e9eae4SChaoyong He struct nfp_net_hw *hw; 144811e9eae4SChaoyong He struct rte_pci_device *pci_dev; 144911e9eae4SChaoyong He 1450b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 145111e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 145211e9eae4SChaoyong He 145311e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 145411e9eae4SChaoyong He rte_wmb(); 145511e9eae4SChaoyong He 1456b4b6988aSChaoyong He if ((hw->super.ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) != 0) { 145711e9eae4SChaoyong He /* If MSI-X auto-masking is used, clear the entry */ 145811e9eae4SChaoyong He rte_intr_ack(pci_dev->intr_handle); 145911e9eae4SChaoyong He } else { 1460f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(NFP_NET_IRQ_LSC_IDX), 146111e9eae4SChaoyong He NFP_NET_CFG_ICR_UNMASKED); 146211e9eae4SChaoyong He } 146311e9eae4SChaoyong He } 146411e9eae4SChaoyong He 146511e9eae4SChaoyong He /** 146611e9eae4SChaoyong He * Interrupt handler which shall be registered for alarm callback for delayed 146711e9eae4SChaoyong He * handling specific interrupt to wait for the stable nic state. As the NIC 146811e9eae4SChaoyong He * interrupt state is not stable for nfp after link is just down, it needs 146911e9eae4SChaoyong He * to wait 4 seconds to get the stable status. 147011e9eae4SChaoyong He * 147111e9eae4SChaoyong He * @param param 147211e9eae4SChaoyong He * The address of parameter (struct rte_eth_dev *) 147311e9eae4SChaoyong He */ 147411e9eae4SChaoyong He void 147511e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler(void *param) 147611e9eae4SChaoyong He { 147711e9eae4SChaoyong He struct rte_eth_dev *dev = param; 147811e9eae4SChaoyong He 147911e9eae4SChaoyong He nfp_net_link_update(dev, 0); 148011e9eae4SChaoyong He rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 148111e9eae4SChaoyong He 148211e9eae4SChaoyong He nfp_net_dev_link_status_print(dev); 148311e9eae4SChaoyong He 148411e9eae4SChaoyong He /* Unmasking */ 148511e9eae4SChaoyong He nfp_net_irq_unmask(dev); 148611e9eae4SChaoyong He } 148711e9eae4SChaoyong He 148811e9eae4SChaoyong He void 148911e9eae4SChaoyong He nfp_net_dev_interrupt_handler(void *param) 149011e9eae4SChaoyong He { 149111e9eae4SChaoyong He int64_t timeout; 149211e9eae4SChaoyong He struct rte_eth_link link; 149311e9eae4SChaoyong He struct rte_eth_dev *dev = param; 149411e9eae4SChaoyong He 149511e9eae4SChaoyong He PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!"); 149611e9eae4SChaoyong He 149711e9eae4SChaoyong He rte_eth_linkstatus_get(dev, &link); 149811e9eae4SChaoyong He 149911e9eae4SChaoyong He nfp_net_link_update(dev, 0); 150011e9eae4SChaoyong He 150111e9eae4SChaoyong He /* Likely to up */ 150211e9eae4SChaoyong He if (link.link_status == 0) { 150311e9eae4SChaoyong He /* Handle it 1 sec later, wait it being stable */ 150411e9eae4SChaoyong He timeout = NFP_NET_LINK_UP_CHECK_TIMEOUT; 150511e9eae4SChaoyong He } else { /* Likely to down */ 150611e9eae4SChaoyong He /* Handle it 4 sec later, wait it being stable */ 150711e9eae4SChaoyong He timeout = NFP_NET_LINK_DOWN_CHECK_TIMEOUT; 150811e9eae4SChaoyong He } 150911e9eae4SChaoyong He 151011e9eae4SChaoyong He if (rte_eal_alarm_set(timeout * 1000, 151111e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler, 151211e9eae4SChaoyong He (void *)dev) != 0) { 151311e9eae4SChaoyong He PMD_INIT_LOG(ERR, "Error setting alarm"); 151411e9eae4SChaoyong He /* Unmasking */ 151511e9eae4SChaoyong He nfp_net_irq_unmask(dev); 151611e9eae4SChaoyong He } 151711e9eae4SChaoyong He } 151811e9eae4SChaoyong He 151911e9eae4SChaoyong He int 152011e9eae4SChaoyong He nfp_net_dev_mtu_set(struct rte_eth_dev *dev, 152111e9eae4SChaoyong He uint16_t mtu) 152211e9eae4SChaoyong He { 152311e9eae4SChaoyong He struct nfp_net_hw *hw; 152411e9eae4SChaoyong He 1525b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 152611e9eae4SChaoyong He 152711e9eae4SChaoyong He /* MTU setting is forbidden if port is started */ 152811e9eae4SChaoyong He if (dev->data->dev_started) { 152911e9eae4SChaoyong He PMD_DRV_LOG(ERR, "port %d must be stopped before configuration", 153011e9eae4SChaoyong He dev->data->port_id); 153111e9eae4SChaoyong He return -EBUSY; 153211e9eae4SChaoyong He } 153311e9eae4SChaoyong He 153411e9eae4SChaoyong He /* MTU larger than current mbufsize not supported */ 153511e9eae4SChaoyong He if (mtu > hw->flbufsz) { 153611e9eae4SChaoyong He PMD_DRV_LOG(ERR, "MTU (%u) larger than current mbufsize (%u) not supported", 153711e9eae4SChaoyong He mtu, hw->flbufsz); 153811e9eae4SChaoyong He return -ERANGE; 153911e9eae4SChaoyong He } 154011e9eae4SChaoyong He 154111e9eae4SChaoyong He /* Writing to configuration space */ 1542f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, mtu); 154311e9eae4SChaoyong He 154411e9eae4SChaoyong He hw->mtu = mtu; 154511e9eae4SChaoyong He 154611e9eae4SChaoyong He return 0; 154711e9eae4SChaoyong He } 154811e9eae4SChaoyong He 154911e9eae4SChaoyong He int 155011e9eae4SChaoyong He nfp_net_vlan_offload_set(struct rte_eth_dev *dev, 155111e9eae4SChaoyong He int mask) 155211e9eae4SChaoyong He { 155311e9eae4SChaoyong He int ret; 155411e9eae4SChaoyong He uint32_t update; 155511e9eae4SChaoyong He uint32_t new_ctrl; 155672d1dea6SChaoyong He struct nfp_hw *hw; 155711e9eae4SChaoyong He uint64_t rx_offload; 155872d1dea6SChaoyong He struct nfp_net_hw *net_hw; 155911e9eae4SChaoyong He uint32_t rxvlan_ctrl = 0; 156011e9eae4SChaoyong He 1561b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 156272d1dea6SChaoyong He hw = &net_hw->super; 156311e9eae4SChaoyong He rx_offload = dev->data->dev_conf.rxmode.offloads; 156472d1dea6SChaoyong He new_ctrl = hw->ctrl; 156511e9eae4SChaoyong He 156611e9eae4SChaoyong He /* VLAN stripping setting */ 156711e9eae4SChaoyong He if ((mask & RTE_ETH_VLAN_STRIP_MASK) != 0) { 156872d1dea6SChaoyong He nfp_net_enable_rxvlan_cap(net_hw, &rxvlan_ctrl); 156911e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0) 157011e9eae4SChaoyong He new_ctrl |= rxvlan_ctrl; 157111e9eae4SChaoyong He else 157211e9eae4SChaoyong He new_ctrl &= ~rxvlan_ctrl; 157311e9eae4SChaoyong He } 157411e9eae4SChaoyong He 157511e9eae4SChaoyong He /* QinQ stripping setting */ 157611e9eae4SChaoyong He if ((mask & RTE_ETH_QINQ_STRIP_MASK) != 0) { 157711e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) 157811e9eae4SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ; 157911e9eae4SChaoyong He else 158011e9eae4SChaoyong He new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ; 158111e9eae4SChaoyong He } 158211e9eae4SChaoyong He 158372d1dea6SChaoyong He if (new_ctrl == hw->ctrl) 158411e9eae4SChaoyong He return 0; 158511e9eae4SChaoyong He 158611e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 158711e9eae4SChaoyong He 158872d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 158911e9eae4SChaoyong He if (ret != 0) 159011e9eae4SChaoyong He return ret; 159111e9eae4SChaoyong He 159272d1dea6SChaoyong He hw->ctrl = new_ctrl; 159311e9eae4SChaoyong He 159411e9eae4SChaoyong He return 0; 159511e9eae4SChaoyong He } 159611e9eae4SChaoyong He 159711e9eae4SChaoyong He static int 159811e9eae4SChaoyong He nfp_net_rss_reta_write(struct rte_eth_dev *dev, 159911e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 160011e9eae4SChaoyong He uint16_t reta_size) 160111e9eae4SChaoyong He { 160211e9eae4SChaoyong He uint16_t i; 160311e9eae4SChaoyong He uint16_t j; 160411e9eae4SChaoyong He uint16_t idx; 160511e9eae4SChaoyong He uint8_t mask; 160611e9eae4SChaoyong He uint32_t reta; 160711e9eae4SChaoyong He uint16_t shift; 16084a9bb682SChaoyong He struct nfp_hw *hw; 16094a9bb682SChaoyong He struct nfp_net_hw *net_hw; 161011e9eae4SChaoyong He 1611b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 16124a9bb682SChaoyong He hw = &net_hw->super; 161311e9eae4SChaoyong He 161411e9eae4SChaoyong He if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) { 161511e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%hu)" 161611e9eae4SChaoyong He " doesn't match hardware can supported (%d)", 161711e9eae4SChaoyong He reta_size, NFP_NET_CFG_RSS_ITBL_SZ); 161811e9eae4SChaoyong He return -EINVAL; 161911e9eae4SChaoyong He } 162011e9eae4SChaoyong He 162111e9eae4SChaoyong He /* 162211e9eae4SChaoyong He * Update Redirection Table. There are 128 8bit-entries which can be 162311e9eae4SChaoyong He * manage as 32 32bit-entries. 162411e9eae4SChaoyong He */ 162511e9eae4SChaoyong He for (i = 0; i < reta_size; i += 4) { 162611e9eae4SChaoyong He /* Handling 4 RSS entries per loop */ 162711e9eae4SChaoyong He idx = i / RTE_ETH_RETA_GROUP_SIZE; 162811e9eae4SChaoyong He shift = i % RTE_ETH_RETA_GROUP_SIZE; 162911e9eae4SChaoyong He mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF); 163011e9eae4SChaoyong He if (mask == 0) 163111e9eae4SChaoyong He continue; 163211e9eae4SChaoyong He 163311e9eae4SChaoyong He reta = 0; 163411e9eae4SChaoyong He 163511e9eae4SChaoyong He /* If all 4 entries were set, don't need read RETA register */ 163611e9eae4SChaoyong He if (mask != 0xF) 16374a9bb682SChaoyong He reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + i); 163811e9eae4SChaoyong He 163911e9eae4SChaoyong He for (j = 0; j < 4; j++) { 164011e9eae4SChaoyong He if ((mask & (0x1 << j)) == 0) 164111e9eae4SChaoyong He continue; 164211e9eae4SChaoyong He 164311e9eae4SChaoyong He /* Clearing the entry bits */ 164411e9eae4SChaoyong He if (mask != 0xF) 164511e9eae4SChaoyong He reta &= ~(0xFF << (8 * j)); 164611e9eae4SChaoyong He 164711e9eae4SChaoyong He reta |= reta_conf[idx].reta[shift + j] << (8 * j); 164811e9eae4SChaoyong He } 164911e9eae4SChaoyong He 16504a9bb682SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift, reta); 165111e9eae4SChaoyong He } 165211e9eae4SChaoyong He 165311e9eae4SChaoyong He return 0; 165411e9eae4SChaoyong He } 165511e9eae4SChaoyong He 165611e9eae4SChaoyong He /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */ 165711e9eae4SChaoyong He int 165811e9eae4SChaoyong He nfp_net_reta_update(struct rte_eth_dev *dev, 165911e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 166011e9eae4SChaoyong He uint16_t reta_size) 166111e9eae4SChaoyong He { 166211e9eae4SChaoyong He int ret; 166311e9eae4SChaoyong He uint32_t update; 166472d1dea6SChaoyong He struct nfp_hw *hw; 166572d1dea6SChaoyong He struct nfp_net_hw *net_hw; 166611e9eae4SChaoyong He 1667b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 166872d1dea6SChaoyong He hw = &net_hw->super; 166972d1dea6SChaoyong He 167072d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 167111e9eae4SChaoyong He return -EINVAL; 167211e9eae4SChaoyong He 167311e9eae4SChaoyong He ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size); 167411e9eae4SChaoyong He if (ret != 0) 167511e9eae4SChaoyong He return ret; 167611e9eae4SChaoyong He 167711e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_RSS; 167811e9eae4SChaoyong He 167972d1dea6SChaoyong He if (nfp_reconfig(hw, hw->ctrl, update) != 0) 168011e9eae4SChaoyong He return -EIO; 168111e9eae4SChaoyong He 168211e9eae4SChaoyong He return 0; 168311e9eae4SChaoyong He } 168411e9eae4SChaoyong He 168511e9eae4SChaoyong He /* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */ 168611e9eae4SChaoyong He int 168711e9eae4SChaoyong He nfp_net_reta_query(struct rte_eth_dev *dev, 168811e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 168911e9eae4SChaoyong He uint16_t reta_size) 169011e9eae4SChaoyong He { 169111e9eae4SChaoyong He uint16_t i; 169211e9eae4SChaoyong He uint16_t j; 169311e9eae4SChaoyong He uint16_t idx; 169411e9eae4SChaoyong He uint8_t mask; 169511e9eae4SChaoyong He uint32_t reta; 169611e9eae4SChaoyong He uint16_t shift; 16974a9bb682SChaoyong He struct nfp_hw *hw; 16984a9bb682SChaoyong He struct nfp_net_hw *net_hw; 169911e9eae4SChaoyong He 1700b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 17014a9bb682SChaoyong He hw = &net_hw->super; 17024a9bb682SChaoyong He 17034a9bb682SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 170411e9eae4SChaoyong He return -EINVAL; 170511e9eae4SChaoyong He 170611e9eae4SChaoyong He if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) { 170711e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d)" 170811e9eae4SChaoyong He " doesn't match hardware can supported (%d)", 170911e9eae4SChaoyong He reta_size, NFP_NET_CFG_RSS_ITBL_SZ); 171011e9eae4SChaoyong He return -EINVAL; 171111e9eae4SChaoyong He } 171211e9eae4SChaoyong He 171311e9eae4SChaoyong He /* 171411e9eae4SChaoyong He * Reading Redirection Table. There are 128 8bit-entries which can be 171511e9eae4SChaoyong He * manage as 32 32bit-entries. 171611e9eae4SChaoyong He */ 171711e9eae4SChaoyong He for (i = 0; i < reta_size; i += 4) { 171811e9eae4SChaoyong He /* Handling 4 RSS entries per loop */ 171911e9eae4SChaoyong He idx = i / RTE_ETH_RETA_GROUP_SIZE; 172011e9eae4SChaoyong He shift = i % RTE_ETH_RETA_GROUP_SIZE; 172111e9eae4SChaoyong He mask = (reta_conf[idx].mask >> shift) & 0xF; 172211e9eae4SChaoyong He 172311e9eae4SChaoyong He if (mask == 0) 172411e9eae4SChaoyong He continue; 172511e9eae4SChaoyong He 17264a9bb682SChaoyong He reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift); 172711e9eae4SChaoyong He for (j = 0; j < 4; j++) { 172811e9eae4SChaoyong He if ((mask & (0x1 << j)) == 0) 172911e9eae4SChaoyong He continue; 173011e9eae4SChaoyong He 173111e9eae4SChaoyong He reta_conf[idx].reta[shift + j] = 173211e9eae4SChaoyong He (uint8_t)((reta >> (8 * j)) & 0xF); 173311e9eae4SChaoyong He } 173411e9eae4SChaoyong He } 173511e9eae4SChaoyong He 173611e9eae4SChaoyong He return 0; 173711e9eae4SChaoyong He } 173811e9eae4SChaoyong He 173911e9eae4SChaoyong He static int 174011e9eae4SChaoyong He nfp_net_rss_hash_write(struct rte_eth_dev *dev, 174111e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 174211e9eae4SChaoyong He { 174311e9eae4SChaoyong He uint8_t i; 174411e9eae4SChaoyong He uint8_t key; 174511e9eae4SChaoyong He uint64_t rss_hf; 17464a9bb682SChaoyong He struct nfp_hw *hw; 17474a9bb682SChaoyong He struct nfp_net_hw *net_hw; 174811e9eae4SChaoyong He uint32_t cfg_rss_ctrl = 0; 174911e9eae4SChaoyong He 1750b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 17514a9bb682SChaoyong He hw = &net_hw->super; 175211e9eae4SChaoyong He 175311e9eae4SChaoyong He /* Writing the key byte by byte */ 175411e9eae4SChaoyong He for (i = 0; i < rss_conf->rss_key_len; i++) { 175511e9eae4SChaoyong He memcpy(&key, &rss_conf->rss_key[i], 1); 17564a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY + i, key); 175711e9eae4SChaoyong He } 175811e9eae4SChaoyong He 175911e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 176011e9eae4SChaoyong He 176111e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_IPV4) != 0) 176211e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4; 176311e9eae4SChaoyong He 176411e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0) 176511e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_TCP; 176611e9eae4SChaoyong He 176711e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0) 176811e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_UDP; 176911e9eae4SChaoyong He 177011e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) != 0) 177111e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_SCTP; 177211e9eae4SChaoyong He 177311e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_IPV6) != 0) 177411e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6; 177511e9eae4SChaoyong He 177611e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0) 177711e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_TCP; 177811e9eae4SChaoyong He 177911e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0) 178011e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_UDP; 178111e9eae4SChaoyong He 178211e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) != 0) 178311e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_SCTP; 178411e9eae4SChaoyong He 178511e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_MASK; 1786*b458a2a0SLong Wu 1787*b458a2a0SLong Wu if (rte_eth_dev_is_repr(dev)) 1788*b458a2a0SLong Wu cfg_rss_ctrl |= NFP_NET_CFG_RSS_CRC32; 1789*b458a2a0SLong Wu else 179011e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_TOEPLITZ; 179111e9eae4SChaoyong He 179211e9eae4SChaoyong He /* Configuring where to apply the RSS hash */ 17934a9bb682SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl); 179411e9eae4SChaoyong He 179511e9eae4SChaoyong He /* Writing the key size */ 17964a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len); 179711e9eae4SChaoyong He 179811e9eae4SChaoyong He return 0; 179911e9eae4SChaoyong He } 180011e9eae4SChaoyong He 180111e9eae4SChaoyong He int 180211e9eae4SChaoyong He nfp_net_rss_hash_update(struct rte_eth_dev *dev, 180311e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 180411e9eae4SChaoyong He { 180511e9eae4SChaoyong He uint32_t update; 180611e9eae4SChaoyong He uint64_t rss_hf; 180772d1dea6SChaoyong He struct nfp_hw *hw; 180872d1dea6SChaoyong He struct nfp_net_hw *net_hw; 180911e9eae4SChaoyong He 1810b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 181172d1dea6SChaoyong He hw = &net_hw->super; 181211e9eae4SChaoyong He 181311e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 181411e9eae4SChaoyong He 181511e9eae4SChaoyong He /* Checking if RSS is enabled */ 181672d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) { 181711e9eae4SChaoyong He if (rss_hf != 0) { 181811e9eae4SChaoyong He PMD_DRV_LOG(ERR, "RSS unsupported"); 181911e9eae4SChaoyong He return -EINVAL; 182011e9eae4SChaoyong He } 182111e9eae4SChaoyong He 182211e9eae4SChaoyong He return 0; /* Nothing to do */ 182311e9eae4SChaoyong He } 182411e9eae4SChaoyong He 182511e9eae4SChaoyong He if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) { 182611e9eae4SChaoyong He PMD_DRV_LOG(ERR, "RSS hash key too long"); 182711e9eae4SChaoyong He return -EINVAL; 182811e9eae4SChaoyong He } 182911e9eae4SChaoyong He 183011e9eae4SChaoyong He nfp_net_rss_hash_write(dev, rss_conf); 183111e9eae4SChaoyong He 183211e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_RSS; 183311e9eae4SChaoyong He 183472d1dea6SChaoyong He if (nfp_reconfig(hw, hw->ctrl, update) != 0) 183511e9eae4SChaoyong He return -EIO; 183611e9eae4SChaoyong He 183711e9eae4SChaoyong He return 0; 183811e9eae4SChaoyong He } 183911e9eae4SChaoyong He 184011e9eae4SChaoyong He int 184111e9eae4SChaoyong He nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev, 184211e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 184311e9eae4SChaoyong He { 184411e9eae4SChaoyong He uint8_t i; 184511e9eae4SChaoyong He uint8_t key; 184611e9eae4SChaoyong He uint64_t rss_hf; 18474a9bb682SChaoyong He struct nfp_hw *hw; 184811e9eae4SChaoyong He uint32_t cfg_rss_ctrl; 18494a9bb682SChaoyong He struct nfp_net_hw *net_hw; 185011e9eae4SChaoyong He 1851b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 18524a9bb682SChaoyong He hw = &net_hw->super; 185311e9eae4SChaoyong He 18544a9bb682SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 185511e9eae4SChaoyong He return -EINVAL; 185611e9eae4SChaoyong He 185711e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 18584a9bb682SChaoyong He cfg_rss_ctrl = nn_cfg_readl(hw, NFP_NET_CFG_RSS_CTRL); 185911e9eae4SChaoyong He 186011e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4) != 0) 186111e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_IPV4; 186211e9eae4SChaoyong He 186311e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP) != 0) 186411e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP; 186511e9eae4SChaoyong He 186611e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP) != 0) 186711e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP; 186811e9eae4SChaoyong He 186911e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP) != 0) 187011e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP; 187111e9eae4SChaoyong He 187211e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP) != 0) 187311e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP; 187411e9eae4SChaoyong He 187511e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6) != 0) 187611e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_IPV6; 187711e9eae4SChaoyong He 187811e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_SCTP) != 0) 187911e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_SCTP; 188011e9eae4SChaoyong He 188111e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_SCTP) != 0) 188211e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_SCTP; 188311e9eae4SChaoyong He 188411e9eae4SChaoyong He /* Propagate current RSS hash functions to caller */ 188511e9eae4SChaoyong He rss_conf->rss_hf = rss_hf; 188611e9eae4SChaoyong He 188711e9eae4SChaoyong He /* Reading the key size */ 18884a9bb682SChaoyong He rss_conf->rss_key_len = nn_cfg_readl(hw, NFP_NET_CFG_RSS_KEY_SZ); 188911e9eae4SChaoyong He 189011e9eae4SChaoyong He /* Reading the key byte a byte */ 189111e9eae4SChaoyong He for (i = 0; i < rss_conf->rss_key_len; i++) { 18924a9bb682SChaoyong He key = nn_cfg_readb(hw, NFP_NET_CFG_RSS_KEY + i); 189311e9eae4SChaoyong He memcpy(&rss_conf->rss_key[i], &key, 1); 189411e9eae4SChaoyong He } 189511e9eae4SChaoyong He 189611e9eae4SChaoyong He return 0; 189711e9eae4SChaoyong He } 189811e9eae4SChaoyong He 189911e9eae4SChaoyong He int 190011e9eae4SChaoyong He nfp_net_rss_config_default(struct rte_eth_dev *dev) 190111e9eae4SChaoyong He { 190211e9eae4SChaoyong He int ret; 190311e9eae4SChaoyong He uint8_t i; 190411e9eae4SChaoyong He uint8_t j; 190511e9eae4SChaoyong He uint16_t queue = 0; 190611e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 190711e9eae4SChaoyong He struct rte_eth_rss_conf rss_conf; 190811e9eae4SChaoyong He uint16_t rx_queues = dev->data->nb_rx_queues; 190911e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 nfp_reta_conf[2]; 191011e9eae4SChaoyong He 191111e9eae4SChaoyong He nfp_reta_conf[0].mask = ~0x0; 191211e9eae4SChaoyong He nfp_reta_conf[1].mask = ~0x0; 191311e9eae4SChaoyong He 191411e9eae4SChaoyong He for (i = 0; i < 0x40; i += 8) { 191511e9eae4SChaoyong He for (j = i; j < (i + 8); j++) { 191611e9eae4SChaoyong He nfp_reta_conf[0].reta[j] = queue; 191711e9eae4SChaoyong He nfp_reta_conf[1].reta[j] = queue++; 191811e9eae4SChaoyong He queue %= rx_queues; 191911e9eae4SChaoyong He } 192011e9eae4SChaoyong He } 192111e9eae4SChaoyong He 192211e9eae4SChaoyong He ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80); 192311e9eae4SChaoyong He if (ret != 0) 192411e9eae4SChaoyong He return ret; 192511e9eae4SChaoyong He 192611e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 192711e9eae4SChaoyong He if (dev_conf == NULL) { 192811e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Wrong rss conf"); 192911e9eae4SChaoyong He return -EINVAL; 193011e9eae4SChaoyong He } 193111e9eae4SChaoyong He 193211e9eae4SChaoyong He rss_conf = dev_conf->rx_adv_conf.rss_conf; 193311e9eae4SChaoyong He ret = nfp_net_rss_hash_write(dev, &rss_conf); 193411e9eae4SChaoyong He 193511e9eae4SChaoyong He return ret; 193611e9eae4SChaoyong He } 193711e9eae4SChaoyong He 193811e9eae4SChaoyong He void 193911e9eae4SChaoyong He nfp_net_stop_rx_queue(struct rte_eth_dev *dev) 194011e9eae4SChaoyong He { 194111e9eae4SChaoyong He uint16_t i; 194211e9eae4SChaoyong He struct nfp_net_rxq *this_rx_q; 194311e9eae4SChaoyong He 194411e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 194511e9eae4SChaoyong He this_rx_q = dev->data->rx_queues[i]; 194611e9eae4SChaoyong He nfp_net_reset_rx_queue(this_rx_q); 194711e9eae4SChaoyong He dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 194811e9eae4SChaoyong He } 194911e9eae4SChaoyong He } 195011e9eae4SChaoyong He 195111e9eae4SChaoyong He void 195211e9eae4SChaoyong He nfp_net_close_rx_queue(struct rte_eth_dev *dev) 195311e9eae4SChaoyong He { 195411e9eae4SChaoyong He uint16_t i; 195511e9eae4SChaoyong He struct nfp_net_rxq *this_rx_q; 195611e9eae4SChaoyong He 195711e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 195811e9eae4SChaoyong He this_rx_q = dev->data->rx_queues[i]; 195911e9eae4SChaoyong He nfp_net_reset_rx_queue(this_rx_q); 196011e9eae4SChaoyong He nfp_net_rx_queue_release(dev, i); 196111e9eae4SChaoyong He } 196211e9eae4SChaoyong He } 196311e9eae4SChaoyong He 196411e9eae4SChaoyong He void 196511e9eae4SChaoyong He nfp_net_stop_tx_queue(struct rte_eth_dev *dev) 196611e9eae4SChaoyong He { 196711e9eae4SChaoyong He uint16_t i; 196811e9eae4SChaoyong He struct nfp_net_txq *this_tx_q; 196911e9eae4SChaoyong He 197011e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 197111e9eae4SChaoyong He this_tx_q = dev->data->tx_queues[i]; 197211e9eae4SChaoyong He nfp_net_reset_tx_queue(this_tx_q); 197311e9eae4SChaoyong He dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 197411e9eae4SChaoyong He } 197511e9eae4SChaoyong He } 197611e9eae4SChaoyong He 197711e9eae4SChaoyong He void 197811e9eae4SChaoyong He nfp_net_close_tx_queue(struct rte_eth_dev *dev) 197911e9eae4SChaoyong He { 198011e9eae4SChaoyong He uint16_t i; 198111e9eae4SChaoyong He struct nfp_net_txq *this_tx_q; 198211e9eae4SChaoyong He 198311e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 198411e9eae4SChaoyong He this_tx_q = dev->data->tx_queues[i]; 198511e9eae4SChaoyong He nfp_net_reset_tx_queue(this_tx_q); 198611e9eae4SChaoyong He nfp_net_tx_queue_release(dev, i); 198711e9eae4SChaoyong He } 198811e9eae4SChaoyong He } 198911e9eae4SChaoyong He 199011e9eae4SChaoyong He int 199172d1dea6SChaoyong He nfp_net_set_vxlan_port(struct nfp_net_hw *net_hw, 199211e9eae4SChaoyong He size_t idx, 199311e9eae4SChaoyong He uint16_t port) 199411e9eae4SChaoyong He { 199511e9eae4SChaoyong He int ret; 199611e9eae4SChaoyong He uint32_t i; 199772d1dea6SChaoyong He struct nfp_hw *hw = &net_hw->super; 199811e9eae4SChaoyong He 199911e9eae4SChaoyong He if (idx >= NFP_NET_N_VXLAN_PORTS) { 200011e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The idx value is out of range."); 200111e9eae4SChaoyong He return -ERANGE; 200211e9eae4SChaoyong He } 200311e9eae4SChaoyong He 200472d1dea6SChaoyong He net_hw->vxlan_ports[idx] = port; 200511e9eae4SChaoyong He 200611e9eae4SChaoyong He for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) { 200772d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port), 200872d1dea6SChaoyong He (net_hw->vxlan_ports[i + 1] << 16) | net_hw->vxlan_ports[i]); 200911e9eae4SChaoyong He } 201011e9eae4SChaoyong He 201111e9eae4SChaoyong He rte_spinlock_lock(&hw->reconfig_lock); 201211e9eae4SChaoyong He 201372d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_VXLAN); 201411e9eae4SChaoyong He rte_wmb(); 201511e9eae4SChaoyong He 201672d1dea6SChaoyong He ret = nfp_reconfig_real(hw, NFP_NET_CFG_UPDATE_VXLAN); 201711e9eae4SChaoyong He 201811e9eae4SChaoyong He rte_spinlock_unlock(&hw->reconfig_lock); 201911e9eae4SChaoyong He 202011e9eae4SChaoyong He return ret; 202111e9eae4SChaoyong He } 202211e9eae4SChaoyong He 202311e9eae4SChaoyong He /* 202411e9eae4SChaoyong He * The firmware with NFD3 can not handle DMA address requiring more 202511e9eae4SChaoyong He * than 40 bits. 202611e9eae4SChaoyong He */ 202711e9eae4SChaoyong He int 202811e9eae4SChaoyong He nfp_net_check_dma_mask(struct nfp_net_hw *hw, 202911e9eae4SChaoyong He char *name) 203011e9eae4SChaoyong He { 203111e9eae4SChaoyong He if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3 && 203211e9eae4SChaoyong He rte_mem_check_dma_mask(40) != 0) { 203311e9eae4SChaoyong He PMD_DRV_LOG(ERR, "Device %s can't be used: restricted dma mask to 40 bits!", 203411e9eae4SChaoyong He name); 203511e9eae4SChaoyong He return -ENODEV; 203611e9eae4SChaoyong He } 203711e9eae4SChaoyong He 203811e9eae4SChaoyong He return 0; 203911e9eae4SChaoyong He } 204011e9eae4SChaoyong He 204111e9eae4SChaoyong He void 204211e9eae4SChaoyong He nfp_net_init_metadata_format(struct nfp_net_hw *hw) 204311e9eae4SChaoyong He { 204411e9eae4SChaoyong He /* 204511e9eae4SChaoyong He * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of 204611e9eae4SChaoyong He * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2) 204711e9eae4SChaoyong He * also indicate that we are using chained metadata. 204811e9eae4SChaoyong He */ 204911e9eae4SChaoyong He if (hw->ver.major == 4) { 205011e9eae4SChaoyong He hw->meta_format = NFP_NET_METAFORMAT_CHAINED; 205175a76c73SChaoyong He } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) { 205211e9eae4SChaoyong He hw->meta_format = NFP_NET_METAFORMAT_CHAINED; 205311e9eae4SChaoyong He /* 205475a76c73SChaoyong He * RSS is incompatible with chained metadata. hw->super.cap just represents 205511e9eae4SChaoyong He * firmware's ability rather than the firmware's configuration. We decide 205675a76c73SChaoyong He * to reduce the confusion to allow us can use hw->super.cap to identify RSS later. 205711e9eae4SChaoyong He */ 205875a76c73SChaoyong He hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS; 205911e9eae4SChaoyong He } else { 206011e9eae4SChaoyong He hw->meta_format = NFP_NET_METAFORMAT_SINGLE; 206111e9eae4SChaoyong He } 206211e9eae4SChaoyong He } 206311e9eae4SChaoyong He 206411e9eae4SChaoyong He void 206511e9eae4SChaoyong He nfp_net_cfg_read_version(struct nfp_net_hw *hw) 206611e9eae4SChaoyong He { 206711e9eae4SChaoyong He union { 206811e9eae4SChaoyong He uint32_t whole; 206911e9eae4SChaoyong He struct nfp_net_fw_ver split; 207011e9eae4SChaoyong He } version; 207111e9eae4SChaoyong He 2072f58bde00SChaoyong He version.whole = nn_cfg_readl(&hw->super, NFP_NET_CFG_VERSION); 207311e9eae4SChaoyong He hw->ver = version.split; 207411e9eae4SChaoyong He } 207511e9eae4SChaoyong He 207611e9eae4SChaoyong He static void 207711e9eae4SChaoyong He nfp_net_get_nsp_info(struct nfp_net_hw *hw, 207811e9eae4SChaoyong He char *nsp_version) 207911e9eae4SChaoyong He { 208011e9eae4SChaoyong He struct nfp_nsp *nsp; 208111e9eae4SChaoyong He 208211e9eae4SChaoyong He nsp = nfp_nsp_open(hw->cpp); 208311e9eae4SChaoyong He if (nsp == NULL) 208411e9eae4SChaoyong He return; 208511e9eae4SChaoyong He 208611e9eae4SChaoyong He snprintf(nsp_version, FW_VER_LEN, "%hu.%hu", 208711e9eae4SChaoyong He nfp_nsp_get_abi_ver_major(nsp), 208811e9eae4SChaoyong He nfp_nsp_get_abi_ver_minor(nsp)); 208911e9eae4SChaoyong He 209011e9eae4SChaoyong He nfp_nsp_close(nsp); 209111e9eae4SChaoyong He } 209211e9eae4SChaoyong He 209311e9eae4SChaoyong He static void 209411e9eae4SChaoyong He nfp_net_get_mip_name(struct nfp_net_hw *hw, 209511e9eae4SChaoyong He char *mip_name) 209611e9eae4SChaoyong He { 209711e9eae4SChaoyong He struct nfp_mip *mip; 209811e9eae4SChaoyong He 209911e9eae4SChaoyong He mip = nfp_mip_open(hw->cpp); 210011e9eae4SChaoyong He if (mip == NULL) 210111e9eae4SChaoyong He return; 210211e9eae4SChaoyong He 210311e9eae4SChaoyong He snprintf(mip_name, FW_VER_LEN, "%s", nfp_mip_name(mip)); 210411e9eae4SChaoyong He 210511e9eae4SChaoyong He nfp_mip_close(mip); 210611e9eae4SChaoyong He } 210711e9eae4SChaoyong He 210811e9eae4SChaoyong He static void 210911e9eae4SChaoyong He nfp_net_get_app_name(struct nfp_net_hw *hw, 211011e9eae4SChaoyong He char *app_name) 211111e9eae4SChaoyong He { 211211e9eae4SChaoyong He switch (hw->pf_dev->app_fw_id) { 211311e9eae4SChaoyong He case NFP_APP_FW_CORE_NIC: 211411e9eae4SChaoyong He snprintf(app_name, FW_VER_LEN, "%s", "nic"); 211511e9eae4SChaoyong He break; 211611e9eae4SChaoyong He case NFP_APP_FW_FLOWER_NIC: 211711e9eae4SChaoyong He snprintf(app_name, FW_VER_LEN, "%s", "flower"); 211811e9eae4SChaoyong He break; 211911e9eae4SChaoyong He default: 212011e9eae4SChaoyong He snprintf(app_name, FW_VER_LEN, "%s", "unknown"); 212111e9eae4SChaoyong He break; 212211e9eae4SChaoyong He } 212311e9eae4SChaoyong He } 212411e9eae4SChaoyong He 212511e9eae4SChaoyong He int 212611e9eae4SChaoyong He nfp_net_firmware_version_get(struct rte_eth_dev *dev, 212711e9eae4SChaoyong He char *fw_version, 212811e9eae4SChaoyong He size_t fw_size) 212911e9eae4SChaoyong He { 213011e9eae4SChaoyong He struct nfp_net_hw *hw; 213111e9eae4SChaoyong He char mip_name[FW_VER_LEN]; 213211e9eae4SChaoyong He char app_name[FW_VER_LEN]; 213311e9eae4SChaoyong He char nsp_version[FW_VER_LEN]; 213411e9eae4SChaoyong He char vnic_version[FW_VER_LEN]; 213511e9eae4SChaoyong He 213611e9eae4SChaoyong He if (fw_size < FW_VER_LEN) 213711e9eae4SChaoyong He return FW_VER_LEN; 213811e9eae4SChaoyong He 2139c4de52ecSChaoyong He hw = nfp_net_get_hw(dev); 214011e9eae4SChaoyong He 2141c99e1db8SLong Wu if (rte_eth_dev_is_repr(dev)) { 214211e9eae4SChaoyong He snprintf(vnic_version, FW_VER_LEN, "%d.%d.%d.%d", 214311e9eae4SChaoyong He hw->ver.extend, hw->ver.class, 214411e9eae4SChaoyong He hw->ver.major, hw->ver.minor); 2145c4de52ecSChaoyong He } else { 2146c4de52ecSChaoyong He snprintf(vnic_version, FW_VER_LEN, "*"); 2147c4de52ecSChaoyong He } 214811e9eae4SChaoyong He 214911e9eae4SChaoyong He nfp_net_get_nsp_info(hw, nsp_version); 215011e9eae4SChaoyong He nfp_net_get_mip_name(hw, mip_name); 215111e9eae4SChaoyong He nfp_net_get_app_name(hw, app_name); 215211e9eae4SChaoyong He 215311e9eae4SChaoyong He snprintf(fw_version, FW_VER_LEN, "%s %s %s %s", 215411e9eae4SChaoyong He vnic_version, nsp_version, mip_name, app_name); 215511e9eae4SChaoyong He 215611e9eae4SChaoyong He return 0; 215711e9eae4SChaoyong He } 215811e9eae4SChaoyong He 215911e9eae4SChaoyong He bool 216011e9eae4SChaoyong He nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version) 216111e9eae4SChaoyong He { 216211e9eae4SChaoyong He uint8_t nfd_version = version.extend; 216311e9eae4SChaoyong He 216411e9eae4SChaoyong He if (nfd_version == NFP_NET_CFG_VERSION_DP_NFD3) 216511e9eae4SChaoyong He return true; 216611e9eae4SChaoyong He 216711e9eae4SChaoyong He if (nfd_version == NFP_NET_CFG_VERSION_DP_NFDK) { 216811e9eae4SChaoyong He if (version.major < 5) { 216911e9eae4SChaoyong He PMD_INIT_LOG(ERR, "NFDK must use ABI 5 or newer, found: %d", 217011e9eae4SChaoyong He version.major); 217111e9eae4SChaoyong He return false; 217211e9eae4SChaoyong He } 217311e9eae4SChaoyong He 217411e9eae4SChaoyong He return true; 217511e9eae4SChaoyong He } 217611e9eae4SChaoyong He 217711e9eae4SChaoyong He return false; 217811e9eae4SChaoyong He } 2179c4de52ecSChaoyong He 2180c4de52ecSChaoyong He /* Disable rx and tx functions to allow for reconfiguring. */ 2181c4de52ecSChaoyong He int 2182c4de52ecSChaoyong He nfp_net_stop(struct rte_eth_dev *dev) 2183c4de52ecSChaoyong He { 2184acb6bebfSChaoyong He struct nfp_cpp *cpp; 2185c4de52ecSChaoyong He struct nfp_net_hw *hw; 2186c4de52ecSChaoyong He 2187c4de52ecSChaoyong He hw = nfp_net_get_hw(dev); 2188c4de52ecSChaoyong He 2189c4de52ecSChaoyong He nfp_net_disable_queues(dev); 2190c4de52ecSChaoyong He 2191c4de52ecSChaoyong He /* Clear queues */ 2192c4de52ecSChaoyong He nfp_net_stop_tx_queue(dev); 2193c4de52ecSChaoyong He nfp_net_stop_rx_queue(dev); 2194c4de52ecSChaoyong He 2195c4de52ecSChaoyong He if (rte_eal_process_type() == RTE_PROC_PRIMARY) 2196acb6bebfSChaoyong He cpp = hw->cpp; 2197c4de52ecSChaoyong He else 2198acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 2199acb6bebfSChaoyong He 2200acb6bebfSChaoyong He nfp_eth_set_configured(cpp, hw->nfp_idx, 0); 2201c4de52ecSChaoyong He 2202c4de52ecSChaoyong He return 0; 2203c4de52ecSChaoyong He } 220451d15e82SZerun Fu 220551d15e82SZerun Fu static enum rte_eth_fc_mode 220651d15e82SZerun Fu nfp_net_get_pause_mode(struct nfp_eth_table_port *eth_port) 220751d15e82SZerun Fu { 220851d15e82SZerun Fu enum rte_eth_fc_mode mode; 220951d15e82SZerun Fu 221051d15e82SZerun Fu if (eth_port->rx_pause_enabled) { 221151d15e82SZerun Fu if (eth_port->tx_pause_enabled) 221251d15e82SZerun Fu mode = RTE_ETH_FC_FULL; 221351d15e82SZerun Fu else 221451d15e82SZerun Fu mode = RTE_ETH_FC_RX_PAUSE; 221551d15e82SZerun Fu } else { 221651d15e82SZerun Fu if (eth_port->tx_pause_enabled) 221751d15e82SZerun Fu mode = RTE_ETH_FC_TX_PAUSE; 221851d15e82SZerun Fu else 221951d15e82SZerun Fu mode = RTE_ETH_FC_NONE; 222051d15e82SZerun Fu } 222151d15e82SZerun Fu 222251d15e82SZerun Fu return mode; 222351d15e82SZerun Fu } 222451d15e82SZerun Fu 222551d15e82SZerun Fu int 222651d15e82SZerun Fu nfp_net_flow_ctrl_get(struct rte_eth_dev *dev, 222751d15e82SZerun Fu struct rte_eth_fc_conf *fc_conf) 222851d15e82SZerun Fu { 222951d15e82SZerun Fu struct nfp_net_hw *net_hw; 223051d15e82SZerun Fu struct nfp_eth_table *nfp_eth_table; 223151d15e82SZerun Fu struct nfp_eth_table_port *eth_port; 223251d15e82SZerun Fu 223351d15e82SZerun Fu net_hw = nfp_net_get_hw(dev); 223451d15e82SZerun Fu if (net_hw->pf_dev == NULL) 223551d15e82SZerun Fu return -EINVAL; 223651d15e82SZerun Fu 223751d15e82SZerun Fu nfp_eth_table = net_hw->pf_dev->nfp_eth_table; 223851d15e82SZerun Fu eth_port = &nfp_eth_table->ports[dev->data->port_id]; 223951d15e82SZerun Fu 224051d15e82SZerun Fu /* Currently only RX/TX switch are supported */ 224151d15e82SZerun Fu fc_conf->mode = nfp_net_get_pause_mode(eth_port); 224251d15e82SZerun Fu 224351d15e82SZerun Fu return 0; 224451d15e82SZerun Fu } 224568aa3537SZerun Fu 224668aa3537SZerun Fu static int 224768aa3537SZerun Fu nfp_net_pause_frame_set(struct nfp_net_hw *net_hw, 224868aa3537SZerun Fu struct nfp_eth_table_port *eth_port, 224968aa3537SZerun Fu enum rte_eth_fc_mode mode) 225068aa3537SZerun Fu { 225168aa3537SZerun Fu int err; 225268aa3537SZerun Fu bool flag; 225368aa3537SZerun Fu struct nfp_nsp *nsp; 225468aa3537SZerun Fu 225568aa3537SZerun Fu nsp = nfp_eth_config_start(net_hw->cpp, eth_port->index); 225668aa3537SZerun Fu if (nsp == NULL) { 225768aa3537SZerun Fu PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle."); 225868aa3537SZerun Fu return -EIO; 225968aa3537SZerun Fu } 226068aa3537SZerun Fu 226168aa3537SZerun Fu flag = (mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true; 226268aa3537SZerun Fu err = nfp_eth_set_tx_pause(nsp, flag); 226368aa3537SZerun Fu if (err != 0) { 226468aa3537SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure TX pause frame."); 226568aa3537SZerun Fu nfp_eth_config_cleanup_end(nsp); 226668aa3537SZerun Fu return err; 226768aa3537SZerun Fu } 226868aa3537SZerun Fu 226968aa3537SZerun Fu flag = (mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true; 227068aa3537SZerun Fu err = nfp_eth_set_rx_pause(nsp, flag); 227168aa3537SZerun Fu if (err != 0) { 227268aa3537SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure RX pause frame."); 227368aa3537SZerun Fu nfp_eth_config_cleanup_end(nsp); 227468aa3537SZerun Fu return err; 227568aa3537SZerun Fu } 227668aa3537SZerun Fu 227768aa3537SZerun Fu err = nfp_eth_config_commit_end(nsp); 227868aa3537SZerun Fu if (err != 0) { 227968aa3537SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure pause frame."); 228068aa3537SZerun Fu return err; 228168aa3537SZerun Fu } 228268aa3537SZerun Fu 228368aa3537SZerun Fu return 0; 228468aa3537SZerun Fu } 228568aa3537SZerun Fu 228668aa3537SZerun Fu int 228768aa3537SZerun Fu nfp_net_flow_ctrl_set(struct rte_eth_dev *dev, 228868aa3537SZerun Fu struct rte_eth_fc_conf *fc_conf) 228968aa3537SZerun Fu { 229068aa3537SZerun Fu int ret; 229168aa3537SZerun Fu struct nfp_net_hw *net_hw; 229268aa3537SZerun Fu enum rte_eth_fc_mode set_mode; 229368aa3537SZerun Fu enum rte_eth_fc_mode original_mode; 229468aa3537SZerun Fu struct nfp_eth_table *nfp_eth_table; 229568aa3537SZerun Fu struct nfp_eth_table_port *eth_port; 229668aa3537SZerun Fu 229768aa3537SZerun Fu net_hw = nfp_net_get_hw(dev); 229868aa3537SZerun Fu if (net_hw->pf_dev == NULL) 229968aa3537SZerun Fu return -EINVAL; 230068aa3537SZerun Fu 230168aa3537SZerun Fu nfp_eth_table = net_hw->pf_dev->nfp_eth_table; 230268aa3537SZerun Fu eth_port = &nfp_eth_table->ports[net_hw->idx]; 230368aa3537SZerun Fu 230468aa3537SZerun Fu original_mode = nfp_net_get_pause_mode(eth_port); 230568aa3537SZerun Fu set_mode = fc_conf->mode; 230668aa3537SZerun Fu 230768aa3537SZerun Fu if (set_mode == original_mode) 230868aa3537SZerun Fu return 0; 230968aa3537SZerun Fu 231068aa3537SZerun Fu ret = nfp_net_pause_frame_set(net_hw, eth_port, set_mode); 231168aa3537SZerun Fu if (ret != 0) 231268aa3537SZerun Fu return ret; 231368aa3537SZerun Fu 231468aa3537SZerun Fu /* Update eth_table after modifying RX/TX pause frame mode. */ 231568aa3537SZerun Fu eth_port->tx_pause_enabled = (set_mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true; 231668aa3537SZerun Fu eth_port->rx_pause_enabled = (set_mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true; 231768aa3537SZerun Fu 231868aa3537SZerun Fu return 0; 231968aa3537SZerun Fu } 23200786add9SZerun Fu 23210786add9SZerun Fu int 23220786add9SZerun Fu nfp_net_fec_get_capability(struct rte_eth_dev *dev, 23230786add9SZerun Fu struct rte_eth_fec_capa *speed_fec_capa, 23240786add9SZerun Fu __rte_unused unsigned int num) 23250786add9SZerun Fu { 23260786add9SZerun Fu uint16_t speed; 23270786add9SZerun Fu struct nfp_net_hw *hw; 23280786add9SZerun Fu uint32_t supported_fec; 23290786add9SZerun Fu struct nfp_eth_table *nfp_eth_table; 23300786add9SZerun Fu struct nfp_eth_table_port *eth_port; 23310786add9SZerun Fu 23320786add9SZerun Fu hw = nfp_net_get_hw(dev); 23330786add9SZerun Fu if (hw->pf_dev == NULL) 23340786add9SZerun Fu return -EINVAL; 23350786add9SZerun Fu 23360786add9SZerun Fu nfp_eth_table = hw->pf_dev->nfp_eth_table; 23370786add9SZerun Fu eth_port = &nfp_eth_table->ports[hw->idx]; 23380786add9SZerun Fu 23390786add9SZerun Fu speed = eth_port->speed; 23400786add9SZerun Fu supported_fec = nfp_eth_supported_fec_modes(eth_port); 23410786add9SZerun Fu if (speed == 0 || supported_fec == 0) { 23420786add9SZerun Fu PMD_DRV_LOG(ERR, "FEC modes supported or Speed is invalid."); 23430786add9SZerun Fu return -EINVAL; 23440786add9SZerun Fu } 23450786add9SZerun Fu 23460786add9SZerun Fu if (speed_fec_capa == NULL) 23470786add9SZerun Fu return NFP_FEC_CAPA_ENTRY_NUM; 23480786add9SZerun Fu 23490786add9SZerun Fu speed_fec_capa->speed = speed; 23500786add9SZerun Fu 23510786add9SZerun Fu if ((supported_fec & NFP_FEC_AUTO) != 0) 23520786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(AUTO); 23530786add9SZerun Fu if ((supported_fec & NFP_FEC_BASER) != 0) 23540786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(BASER); 23550786add9SZerun Fu if ((supported_fec & NFP_FEC_REED_SOLOMON) != 0) 23560786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(RS); 23570786add9SZerun Fu if ((supported_fec & NFP_FEC_DISABLED) != 0) 23580786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC); 23590786add9SZerun Fu 23600786add9SZerun Fu return NFP_FEC_CAPA_ENTRY_NUM; 23610786add9SZerun Fu } 2362c6835a32SZerun Fu 2363c6835a32SZerun Fu static uint32_t 2364c6835a32SZerun Fu nfp_net_fec_nfp_to_rte(enum nfp_eth_fec fec) 2365c6835a32SZerun Fu { 2366c6835a32SZerun Fu switch (fec) { 2367c6835a32SZerun Fu case NFP_FEC_AUTO_BIT: 2368c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(AUTO); 2369c6835a32SZerun Fu case NFP_FEC_BASER_BIT: 2370c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(BASER); 2371c6835a32SZerun Fu case NFP_FEC_REED_SOLOMON_BIT: 2372c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(RS); 2373c6835a32SZerun Fu case NFP_FEC_DISABLED_BIT: 2374c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC); 2375c6835a32SZerun Fu default: 2376c6835a32SZerun Fu PMD_DRV_LOG(ERR, "FEC mode is invalid."); 2377c6835a32SZerun Fu return 0; 2378c6835a32SZerun Fu } 2379c6835a32SZerun Fu } 2380c6835a32SZerun Fu 2381c6835a32SZerun Fu int 2382c6835a32SZerun Fu nfp_net_fec_get(struct rte_eth_dev *dev, 2383c6835a32SZerun Fu uint32_t *fec_capa) 2384c6835a32SZerun Fu { 2385c6835a32SZerun Fu struct nfp_net_hw *hw; 2386c6835a32SZerun Fu struct nfp_eth_table *nfp_eth_table; 2387c6835a32SZerun Fu struct nfp_eth_table_port *eth_port; 2388c6835a32SZerun Fu 2389c6835a32SZerun Fu hw = nfp_net_get_hw(dev); 2390c6835a32SZerun Fu if (hw->pf_dev == NULL) 2391c6835a32SZerun Fu return -EINVAL; 2392c6835a32SZerun Fu 2393c6835a32SZerun Fu if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN) { 2394c6835a32SZerun Fu nfp_eth_table = nfp_eth_read_ports(hw->cpp); 2395c6835a32SZerun Fu hw->pf_dev->nfp_eth_table->ports[hw->idx] = nfp_eth_table->ports[hw->idx]; 2396c6835a32SZerun Fu free(nfp_eth_table); 2397c6835a32SZerun Fu } 2398c6835a32SZerun Fu 2399c6835a32SZerun Fu nfp_eth_table = hw->pf_dev->nfp_eth_table; 2400c6835a32SZerun Fu eth_port = &nfp_eth_table->ports[hw->idx]; 2401c6835a32SZerun Fu 2402c6835a32SZerun Fu if (!nfp_eth_can_support_fec(eth_port)) { 2403c6835a32SZerun Fu PMD_DRV_LOG(ERR, "NFP can not support FEC."); 2404c6835a32SZerun Fu return -ENOTSUP; 2405c6835a32SZerun Fu } 2406c6835a32SZerun Fu 2407c6835a32SZerun Fu /* 2408c6835a32SZerun Fu * If link is down and AUTO is enabled, AUTO is returned, otherwise, 2409c6835a32SZerun Fu * configured FEC mode is returned. 2410c6835a32SZerun Fu * If link is up, current FEC mode is returned. 2411c6835a32SZerun Fu */ 2412c6835a32SZerun Fu if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN) 2413c6835a32SZerun Fu *fec_capa = nfp_net_fec_nfp_to_rte(eth_port->fec); 2414c6835a32SZerun Fu else 2415c6835a32SZerun Fu *fec_capa = nfp_net_fec_nfp_to_rte(eth_port->act_fec); 2416c6835a32SZerun Fu 2417c6835a32SZerun Fu if (*fec_capa == 0) 2418c6835a32SZerun Fu return -EINVAL; 2419c6835a32SZerun Fu 2420c6835a32SZerun Fu return 0; 2421c6835a32SZerun Fu } 242237bd1b84SZerun Fu 242337bd1b84SZerun Fu static enum nfp_eth_fec 242437bd1b84SZerun Fu nfp_net_fec_rte_to_nfp(uint32_t fec) 242537bd1b84SZerun Fu { 242637bd1b84SZerun Fu switch (fec) { 242737bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_AUTO): 242837bd1b84SZerun Fu return NFP_FEC_AUTO_BIT; 242937bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_NOFEC): 243037bd1b84SZerun Fu return NFP_FEC_DISABLED_BIT; 243137bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_RS): 243237bd1b84SZerun Fu return NFP_FEC_REED_SOLOMON_BIT; 243337bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_BASER): 243437bd1b84SZerun Fu return NFP_FEC_BASER_BIT; 243537bd1b84SZerun Fu default: 243637bd1b84SZerun Fu return NFP_FEC_INVALID_BIT; 243737bd1b84SZerun Fu } 243837bd1b84SZerun Fu } 243937bd1b84SZerun Fu 244037bd1b84SZerun Fu int 244137bd1b84SZerun Fu nfp_net_fec_set(struct rte_eth_dev *dev, 244237bd1b84SZerun Fu uint32_t fec_capa) 244337bd1b84SZerun Fu { 244437bd1b84SZerun Fu enum nfp_eth_fec fec; 244537bd1b84SZerun Fu struct nfp_net_hw *hw; 244637bd1b84SZerun Fu uint32_t supported_fec; 244737bd1b84SZerun Fu struct nfp_eth_table *nfp_eth_table; 244837bd1b84SZerun Fu struct nfp_eth_table_port *eth_port; 244937bd1b84SZerun Fu 245037bd1b84SZerun Fu hw = nfp_net_get_hw(dev); 245137bd1b84SZerun Fu if (hw->pf_dev == NULL) 245237bd1b84SZerun Fu return -EINVAL; 245337bd1b84SZerun Fu 245437bd1b84SZerun Fu nfp_eth_table = hw->pf_dev->nfp_eth_table; 245537bd1b84SZerun Fu eth_port = &nfp_eth_table->ports[hw->idx]; 245637bd1b84SZerun Fu 245737bd1b84SZerun Fu supported_fec = nfp_eth_supported_fec_modes(eth_port); 245837bd1b84SZerun Fu if (supported_fec == 0) { 245937bd1b84SZerun Fu PMD_DRV_LOG(ERR, "NFP can not support FEC."); 246037bd1b84SZerun Fu return -ENOTSUP; 246137bd1b84SZerun Fu } 246237bd1b84SZerun Fu 246337bd1b84SZerun Fu fec = nfp_net_fec_rte_to_nfp(fec_capa); 246437bd1b84SZerun Fu if (fec == NFP_FEC_INVALID_BIT) { 246537bd1b84SZerun Fu PMD_DRV_LOG(ERR, "FEC modes is invalid."); 246637bd1b84SZerun Fu return -EINVAL; 246737bd1b84SZerun Fu } 246837bd1b84SZerun Fu 246937bd1b84SZerun Fu if ((RTE_BIT32(fec) & supported_fec) == 0) { 247037bd1b84SZerun Fu PMD_DRV_LOG(ERR, "Unsupported FEC mode is set."); 247137bd1b84SZerun Fu return -EIO; 247237bd1b84SZerun Fu } 247337bd1b84SZerun Fu 247437bd1b84SZerun Fu return nfp_eth_set_fec(hw->cpp, eth_port->index, fec); 247537bd1b84SZerun Fu } 2476