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 12636e133eSPeng Zhang #include "flower/nfp_flower_cmsg.h" 1311e9eae4SChaoyong He #include "flower/nfp_flower_representor.h" 1411e9eae4SChaoyong He #include "nfd3/nfp_nfd3.h" 1511e9eae4SChaoyong He #include "nfdk/nfp_nfdk.h" 1611e9eae4SChaoyong He #include "nfpcore/nfp_mip.h" 1711e9eae4SChaoyong He #include "nfpcore/nfp_nsp.h" 18eac7eda4SChaoyong He #include "nfpcore/nfp_rtsym.h" 1911e9eae4SChaoyong He #include "nfp_logs.h" 20ddcd598fSLong Wu #include "nfp_net_meta.h" 2111e9eae4SChaoyong He 2211e9eae4SChaoyong He #define NFP_TX_MAX_SEG UINT8_MAX 2311e9eae4SChaoyong He #define NFP_TX_MAX_MTU_SEG 8 2411e9eae4SChaoyong He 2511e9eae4SChaoyong He #define NFP_NET_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */ 2611e9eae4SChaoyong He #define NFP_NET_LINK_UP_CHECK_TIMEOUT 1000 /* ms */ 2711e9eae4SChaoyong He 2811e9eae4SChaoyong He #define DEFAULT_FLBUF_SIZE 9216 292f1bfbf4SJames Hershaw #define NFP_ETH_OVERHEAD \ 302f1bfbf4SJames Hershaw (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + RTE_VLAN_HLEN * 2) 3111e9eae4SChaoyong He 320786add9SZerun Fu /* Only show FEC capability supported by the current speed. */ 330786add9SZerun Fu #define NFP_FEC_CAPA_ENTRY_NUM 1 340786add9SZerun Fu 3511e9eae4SChaoyong He enum nfp_xstat_group { 3611e9eae4SChaoyong He NFP_XSTAT_GROUP_NET, 3711e9eae4SChaoyong He NFP_XSTAT_GROUP_MAC 3811e9eae4SChaoyong He }; 3911e9eae4SChaoyong He 4011e9eae4SChaoyong He struct nfp_xstat { 4111e9eae4SChaoyong He char name[RTE_ETH_XSTATS_NAME_SIZE]; 4211e9eae4SChaoyong He int offset; 4311e9eae4SChaoyong He enum nfp_xstat_group group; 4411e9eae4SChaoyong He }; 4511e9eae4SChaoyong He 4611e9eae4SChaoyong He #define NFP_XSTAT_NET(_name, _offset) { \ 4711e9eae4SChaoyong He .name = _name, \ 4811e9eae4SChaoyong He .offset = NFP_NET_CFG_STATS_##_offset, \ 4911e9eae4SChaoyong He .group = NFP_XSTAT_GROUP_NET, \ 5011e9eae4SChaoyong He } 5111e9eae4SChaoyong He 5211e9eae4SChaoyong He #define NFP_XSTAT_MAC(_name, _offset) { \ 5311e9eae4SChaoyong He .name = _name, \ 5411e9eae4SChaoyong He .offset = NFP_MAC_STATS_##_offset, \ 5511e9eae4SChaoyong He .group = NFP_XSTAT_GROUP_MAC, \ 5611e9eae4SChaoyong He } 5711e9eae4SChaoyong He 5811e9eae4SChaoyong He static const struct nfp_xstat nfp_net_xstats[] = { 5911e9eae4SChaoyong He /* 6011e9eae4SChaoyong He * Basic xstats available on both VF and PF. 6111e9eae4SChaoyong He * Note that in case new statistics of group NFP_XSTAT_GROUP_NET 6211e9eae4SChaoyong He * are added to this array, they must appear before any statistics 6311e9eae4SChaoyong He * of group NFP_XSTAT_GROUP_MAC. 6411e9eae4SChaoyong He */ 6511e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_packets_mc", RX_MC_FRAMES), 6611e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_packets_mc", TX_MC_FRAMES), 6711e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_packets_bc", RX_BC_FRAMES), 6811e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_packets_bc", TX_BC_FRAMES), 6911e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_uc", RX_UC_OCTETS), 7011e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_uc", TX_UC_OCTETS), 7111e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_mc", RX_MC_OCTETS), 7211e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_mc", TX_MC_OCTETS), 7311e9eae4SChaoyong He NFP_XSTAT_NET("rx_good_bytes_bc", RX_BC_OCTETS), 7411e9eae4SChaoyong He NFP_XSTAT_NET("tx_good_bytes_bc", TX_BC_OCTETS), 7511e9eae4SChaoyong He NFP_XSTAT_NET("tx_missed_erros", TX_DISCARDS), 7611e9eae4SChaoyong He NFP_XSTAT_NET("bpf_pass_pkts", APP0_FRAMES), 7711e9eae4SChaoyong He NFP_XSTAT_NET("bpf_pass_bytes", APP0_BYTES), 7811e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app1_pkts", APP1_FRAMES), 7911e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app1_bytes", APP1_BYTES), 8011e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app2_pkts", APP2_FRAMES), 8111e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app2_bytes", APP2_BYTES), 8211e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app3_pkts", APP3_FRAMES), 8311e9eae4SChaoyong He NFP_XSTAT_NET("bpf_app3_bytes", APP3_BYTES), 8411e9eae4SChaoyong He /* 8511e9eae4SChaoyong He * MAC xstats available only on PF. These statistics are not available for VFs as the 8611e9eae4SChaoyong He * PF is not initialized when the VF is initialized as it is still bound to the kernel 8711e9eae4SChaoyong He * driver. As such, the PMD cannot obtain a CPP handle and access the rtsym_table in order 8811e9eae4SChaoyong He * to get the pointer to the start of the MAC statistics counters. 8911e9eae4SChaoyong He */ 9011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_octets", RX_IN_OCTS), 9111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frame_too_long_errors", RX_FRAME_TOO_LONG_ERRORS), 9211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_range_length_errors", RX_RANGE_LENGTH_ERRORS), 9311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_vlan_received_ok", RX_VLAN_RECEIVED_OK), 9411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_errors", RX_IN_ERRORS), 9511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_broadcast_pkts", RX_IN_BROADCAST_PKTS), 9611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_drop_events", RX_DROP_EVENTS), 9711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_alignment_errors", RX_ALIGNMENT_ERRORS), 9811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_mac_ctrl_frames", RX_PAUSE_MAC_CTRL_FRAMES), 9911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frames_received_ok", RX_FRAMES_RECEIVED_OK), 10011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_frame_check_sequence_errors", RX_FRAME_CHECK_SEQ_ERRORS), 10111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_unicast_pkts", RX_UNICAST_PKTS), 10211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_multicast_pkts", RX_MULTICAST_PKTS), 10311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts", RX_PKTS), 10411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_undersize_pkts", RX_UNDERSIZE_PKTS), 10511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_64_octets", RX_PKTS_64_OCTS), 10611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_65_to_127_octets", RX_PKTS_65_TO_127_OCTS), 10711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_128_to_255_octets", RX_PKTS_128_TO_255_OCTS), 10811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_256_to_511_octets", RX_PKTS_256_TO_511_OCTS), 10911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_512_to_1023_octets", RX_PKTS_512_TO_1023_OCTS), 11011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_1024_to_1518_octets", RX_PKTS_1024_TO_1518_OCTS), 11111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pkts_1519_to_max_octets", RX_PKTS_1519_TO_MAX_OCTS), 11211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_jabbers", RX_JABBERS), 11311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_fragments", RX_FRAGMENTS), 11411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_oversize_pkts", RX_OVERSIZE_PKTS), 11511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class0", RX_PAUSE_FRAMES_CLASS0), 11611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class1", RX_PAUSE_FRAMES_CLASS1), 11711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class2", RX_PAUSE_FRAMES_CLASS2), 11811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class3", RX_PAUSE_FRAMES_CLASS3), 11911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class4", RX_PAUSE_FRAMES_CLASS4), 12011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class5", RX_PAUSE_FRAMES_CLASS5), 12111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class6", RX_PAUSE_FRAMES_CLASS6), 12211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_pause_frames_class7", RX_PAUSE_FRAMES_CLASS7), 12311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_mac_ctrl_frames_received", RX_MAC_CTRL_FRAMES_REC), 12411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.rx_mac_head_drop", RX_MAC_HEAD_DROP), 12511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_queue_drop", TX_QUEUE_DROP), 12611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_octets", TX_OUT_OCTS), 12711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_vlan_transmitted_ok", TX_VLAN_TRANSMITTED_OK), 12811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_errors", TX_OUT_ERRORS), 12911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_broadcast_pkts", TX_BROADCAST_PKTS), 13011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_mac_ctrl_frames", TX_PAUSE_MAC_CTRL_FRAMES), 13111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_frames_transmitted_ok", TX_FRAMES_TRANSMITTED_OK), 13211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_unicast_pkts", TX_UNICAST_PKTS), 13311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_multicast_pkts", TX_MULTICAST_PKTS), 13411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_64_octets", TX_PKTS_64_OCTS), 13511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_65_to_127_octets", TX_PKTS_65_TO_127_OCTS), 13611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_128_to_255_octets", TX_PKTS_128_TO_255_OCTS), 13711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_256_to_511_octets", TX_PKTS_256_TO_511_OCTS), 13811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_512_to_1023_octets", TX_PKTS_512_TO_1023_OCTS), 13911e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_1024_to_1518_octets", TX_PKTS_1024_TO_1518_OCTS), 14011e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pkts_1519_to_max_octets", TX_PKTS_1519_TO_MAX_OCTS), 14111e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class0", TX_PAUSE_FRAMES_CLASS0), 14211e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class1", TX_PAUSE_FRAMES_CLASS1), 14311e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class2", TX_PAUSE_FRAMES_CLASS2), 14411e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class3", TX_PAUSE_FRAMES_CLASS3), 14511e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class4", TX_PAUSE_FRAMES_CLASS4), 14611e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class5", TX_PAUSE_FRAMES_CLASS5), 14711e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class6", TX_PAUSE_FRAMES_CLASS6), 14811e9eae4SChaoyong He NFP_XSTAT_MAC("mac.tx_pause_frames_class7", TX_PAUSE_FRAMES_CLASS7), 14911e9eae4SChaoyong He }; 15011e9eae4SChaoyong He 15111e9eae4SChaoyong He static const uint32_t nfp_net_link_speed_nfp2rte[] = { 15211e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = RTE_ETH_SPEED_NUM_NONE, 15311e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = RTE_ETH_SPEED_NUM_NONE, 15411e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_1G] = RTE_ETH_SPEED_NUM_1G, 15511e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_10G] = RTE_ETH_SPEED_NUM_10G, 15611e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_25G] = RTE_ETH_SPEED_NUM_25G, 15711e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_40G] = RTE_ETH_SPEED_NUM_40G, 15811e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_50G] = RTE_ETH_SPEED_NUM_50G, 15911e9eae4SChaoyong He [NFP_NET_CFG_STS_LINK_RATE_100G] = RTE_ETH_SPEED_NUM_100G, 16011e9eae4SChaoyong He }; 16111e9eae4SChaoyong He 162*c43d2aabSLong Wu static bool 163*c43d2aabSLong Wu nfp_net_is_pf(struct rte_eth_dev *dev) 164*c43d2aabSLong Wu { 165*c43d2aabSLong Wu if (rte_eth_dev_is_repr(dev)) 166*c43d2aabSLong Wu return nfp_flower_repr_is_pf(dev); 167*c43d2aabSLong Wu 168*c43d2aabSLong Wu return ((struct nfp_net_hw_priv *)dev->process_private)->is_pf; 169*c43d2aabSLong Wu } 170*c43d2aabSLong Wu 17193ebb1e5SQin Ke static size_t 17293ebb1e5SQin Ke nfp_net_link_speed_rte2nfp(uint32_t speed) 17311e9eae4SChaoyong He { 17493ebb1e5SQin Ke size_t i; 17511e9eae4SChaoyong He 17611e9eae4SChaoyong He for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) { 17711e9eae4SChaoyong He if (speed == nfp_net_link_speed_nfp2rte[i]) 17811e9eae4SChaoyong He return i; 17911e9eae4SChaoyong He } 18011e9eae4SChaoyong He 18111e9eae4SChaoyong He return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN; 18211e9eae4SChaoyong He } 18311e9eae4SChaoyong He 18448de6254SQin Ke static uint32_t 18548de6254SQin Ke nfp_net_link_speed_nfp2rte_check(uint32_t speed) 18648de6254SQin Ke { 18748de6254SQin Ke size_t i; 18848de6254SQin Ke 18948de6254SQin Ke for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) { 19048de6254SQin Ke if (speed == nfp_net_link_speed_nfp2rte[i]) 19148de6254SQin Ke return nfp_net_link_speed_nfp2rte[i]; 19248de6254SQin Ke } 19348de6254SQin Ke 19448de6254SQin Ke return RTE_ETH_SPEED_NUM_NONE; 19548de6254SQin Ke } 19648de6254SQin Ke 19722548137SZerun Fu void 19811e9eae4SChaoyong He nfp_net_notify_port_speed(struct nfp_net_hw *hw, 19911e9eae4SChaoyong He struct rte_eth_link *link) 20011e9eae4SChaoyong He { 20111e9eae4SChaoyong He /* 20211e9eae4SChaoyong He * Read the link status from NFP_NET_CFG_STS. If the link is down 20311e9eae4SChaoyong He * then write the link speed NFP_NET_CFG_STS_LINK_RATE_UNKNOWN to 20411e9eae4SChaoyong He * NFP_NET_CFG_STS_NSP_LINK_RATE. 20511e9eae4SChaoyong He */ 20611e9eae4SChaoyong He if (link->link_status == RTE_ETH_LINK_DOWN) { 207f58bde00SChaoyong He nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE, 208f58bde00SChaoyong He NFP_NET_CFG_STS_LINK_RATE_UNKNOWN); 20911e9eae4SChaoyong He return; 21011e9eae4SChaoyong He } 21111e9eae4SChaoyong He 21211e9eae4SChaoyong He /* 21311e9eae4SChaoyong He * Link is up so write the link speed from the eth_table to 21411e9eae4SChaoyong He * NFP_NET_CFG_STS_NSP_LINK_RATE. 21511e9eae4SChaoyong He */ 216f58bde00SChaoyong He nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE, 21711e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(link->link_speed)); 21811e9eae4SChaoyong He } 21911e9eae4SChaoyong He 22011e9eae4SChaoyong He /** 22187abbaf9SPeng Zhang * Reconfigure the firmware of VF configure 22287abbaf9SPeng Zhang * 22387abbaf9SPeng Zhang * @param net_hw 22487abbaf9SPeng Zhang * Device to reconfigure 22587abbaf9SPeng Zhang * @param pf_dev 22687abbaf9SPeng Zhang * Get the Device info 22787abbaf9SPeng Zhang * @param update 22887abbaf9SPeng Zhang * The value for the mailbox VF command 22987abbaf9SPeng Zhang * @param value 23087abbaf9SPeng Zhang * The value of update 23187abbaf9SPeng Zhang * @param offset 23287abbaf9SPeng Zhang * The offset in the VF configure table 23387abbaf9SPeng Zhang * 23487abbaf9SPeng Zhang * @return 23587abbaf9SPeng Zhang * - (0) if OK to reconfigure vf configure. 23687abbaf9SPeng Zhang * - (-EIO) if I/O err and fail to configure the vf configure 23787abbaf9SPeng Zhang */ 23887abbaf9SPeng Zhang static int 23987abbaf9SPeng Zhang nfp_net_vf_reconfig(struct nfp_net_hw *net_hw, 24087abbaf9SPeng Zhang struct nfp_pf_dev *pf_dev, 24187abbaf9SPeng Zhang uint16_t update, 24287abbaf9SPeng Zhang uint8_t value, 24387abbaf9SPeng Zhang uint32_t offset) 24487abbaf9SPeng Zhang { 24587abbaf9SPeng Zhang int ret; 24687abbaf9SPeng Zhang struct nfp_hw *hw; 24787abbaf9SPeng Zhang 24887abbaf9SPeng Zhang hw = &net_hw->super; 24987abbaf9SPeng Zhang rte_spinlock_lock(&hw->reconfig_lock); 25087abbaf9SPeng Zhang 25187abbaf9SPeng Zhang /* Write update info to mailbox in VF config symbol */ 25287abbaf9SPeng Zhang nn_writeb(value, pf_dev->vf_cfg_tbl_bar + offset); 25387abbaf9SPeng Zhang nn_writew(update, pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_UPD); 25487abbaf9SPeng Zhang nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_VF); 25587abbaf9SPeng Zhang 25687abbaf9SPeng Zhang rte_wmb(); 25787abbaf9SPeng Zhang 25887abbaf9SPeng Zhang ret = nfp_reconfig_real(hw, NFP_NET_CFG_UPDATE_VF); 25987abbaf9SPeng Zhang 26087abbaf9SPeng Zhang rte_spinlock_unlock(&hw->reconfig_lock); 26187abbaf9SPeng Zhang 26287abbaf9SPeng Zhang if (ret != 0) 26387abbaf9SPeng Zhang return -EIO; 26487abbaf9SPeng Zhang 26587abbaf9SPeng Zhang return nn_readw(pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_RET); 26687abbaf9SPeng Zhang } 26787abbaf9SPeng Zhang 26887abbaf9SPeng Zhang /** 26911e9eae4SChaoyong He * Reconfigure the firmware via the mailbox 27011e9eae4SChaoyong He * 2714a9bb682SChaoyong He * @param net_hw 27211e9eae4SChaoyong He * Device to reconfigure 27311e9eae4SChaoyong He * @param mbox_cmd 27411e9eae4SChaoyong He * The value for the mailbox command 27511e9eae4SChaoyong He * 27611e9eae4SChaoyong He * @return 27711e9eae4SChaoyong He * - (0) if OK to reconfigure by the mailbox. 27811e9eae4SChaoyong He * - (-EIO) if I/O err and fail to reconfigure by the mailbox 27911e9eae4SChaoyong He */ 28011e9eae4SChaoyong He int 2814a9bb682SChaoyong He nfp_net_mbox_reconfig(struct nfp_net_hw *net_hw, 28211e9eae4SChaoyong He uint32_t mbox_cmd) 28311e9eae4SChaoyong He { 28411e9eae4SChaoyong He int ret; 28511e9eae4SChaoyong He uint32_t mbox; 28611e9eae4SChaoyong He 2874a9bb682SChaoyong He mbox = net_hw->tlv_caps.mbox_off; 28811e9eae4SChaoyong He 2894a9bb682SChaoyong He rte_spinlock_lock(&net_hw->super.reconfig_lock); 29011e9eae4SChaoyong He 2914a9bb682SChaoyong He nn_cfg_writeq(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd); 2924a9bb682SChaoyong He nn_cfg_writel(&net_hw->super, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX); 29311e9eae4SChaoyong He 29411e9eae4SChaoyong He rte_wmb(); 29511e9eae4SChaoyong He 2964a9bb682SChaoyong He ret = nfp_reconfig_real(&net_hw->super, NFP_NET_CFG_UPDATE_MBOX); 29711e9eae4SChaoyong He 2984a9bb682SChaoyong He rte_spinlock_unlock(&net_hw->super.reconfig_lock); 29911e9eae4SChaoyong He 30011e9eae4SChaoyong He if (ret != 0) { 301b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x.", 30211e9eae4SChaoyong He mbox_cmd, NFP_NET_CFG_UPDATE_MBOX); 30311e9eae4SChaoyong He return -EIO; 30411e9eae4SChaoyong He } 30511e9eae4SChaoyong He 3064a9bb682SChaoyong He return nn_cfg_readl(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET); 30711e9eae4SChaoyong He } 30811e9eae4SChaoyong He 309b12d2b2eSChaoyong He struct nfp_net_hw * 310b12d2b2eSChaoyong He nfp_net_get_hw(const struct rte_eth_dev *dev) 311b12d2b2eSChaoyong He { 312b12d2b2eSChaoyong He struct nfp_net_hw *hw; 313b12d2b2eSChaoyong He 314c99e1db8SLong Wu if (rte_eth_dev_is_repr(dev)) { 315b12d2b2eSChaoyong He struct nfp_flower_representor *repr; 316b12d2b2eSChaoyong He repr = dev->data->dev_private; 317b12d2b2eSChaoyong He hw = repr->app_fw_flower->pf_hw; 318b12d2b2eSChaoyong He } else { 319b12d2b2eSChaoyong He hw = dev->data->dev_private; 320b12d2b2eSChaoyong He } 321b12d2b2eSChaoyong He 322b12d2b2eSChaoyong He return hw; 323b12d2b2eSChaoyong He } 324b12d2b2eSChaoyong He 325441839f1SQin Ke uint8_t 326441839f1SQin Ke nfp_net_get_idx(const struct rte_eth_dev *dev) 327441839f1SQin Ke { 328441839f1SQin Ke uint8_t idx; 329441839f1SQin Ke 330441839f1SQin Ke if (rte_eth_dev_is_repr(dev)) { 331441839f1SQin Ke struct nfp_flower_representor *repr; 332441839f1SQin Ke repr = dev->data->dev_private; 333441839f1SQin Ke idx = repr->idx; 334441839f1SQin Ke } else { 335441839f1SQin Ke struct nfp_net_hw *hw; 336441839f1SQin Ke hw = dev->data->dev_private; 337441839f1SQin Ke idx = hw->idx; 338441839f1SQin Ke } 339441839f1SQin Ke 340441839f1SQin Ke return idx; 341441839f1SQin Ke } 342441839f1SQin Ke 34311e9eae4SChaoyong He /* 34411e9eae4SChaoyong He * Configure an Ethernet device. 34511e9eae4SChaoyong He * 34611e9eae4SChaoyong He * This function must be invoked first before any other function in the Ethernet API. 34711e9eae4SChaoyong He * This function can also be re-invoked when a device is in the stopped state. 34811e9eae4SChaoyong He * 34911e9eae4SChaoyong He * A DPDK app sends info about how many queues to use and how those queues 35011e9eae4SChaoyong He * need to be configured. This is used by the DPDK core and it makes sure no 35111e9eae4SChaoyong He * more queues than those advertised by the driver are requested. 35211e9eae4SChaoyong He * This function is called after that internal process. 35311e9eae4SChaoyong He */ 35411e9eae4SChaoyong He int 35511e9eae4SChaoyong He nfp_net_configure(struct rte_eth_dev *dev) 35611e9eae4SChaoyong He { 35711e9eae4SChaoyong He struct nfp_net_hw *hw; 35811e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 35911e9eae4SChaoyong He struct rte_eth_rxmode *rxmode; 36011e9eae4SChaoyong He struct rte_eth_txmode *txmode; 36111e9eae4SChaoyong He 362b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 36311e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 36411e9eae4SChaoyong He rxmode = &dev_conf->rxmode; 36511e9eae4SChaoyong He txmode = &dev_conf->txmode; 36611e9eae4SChaoyong He 36711e9eae4SChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0) 36811e9eae4SChaoyong He rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 36911e9eae4SChaoyong He 37011e9eae4SChaoyong He /* Checking TX mode */ 37111e9eae4SChaoyong He if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) { 372b6de4353SZerun Fu PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported."); 37311e9eae4SChaoyong He return -EINVAL; 37411e9eae4SChaoyong He } 37511e9eae4SChaoyong He 37611e9eae4SChaoyong He /* Checking RX mode */ 37711e9eae4SChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 && 37875a76c73SChaoyong He (hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) { 379b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RSS not supported."); 38011e9eae4SChaoyong He return -EINVAL; 38111e9eae4SChaoyong He } 38211e9eae4SChaoyong He 38311e9eae4SChaoyong He /* Checking MTU set */ 3842f1bfbf4SJames Hershaw if (rxmode->mtu > hw->max_mtu + NFP_ETH_OVERHEAD) { 385b6de4353SZerun Fu PMD_DRV_LOG(ERR, "MTU (%u) larger than the maximum possible frame size (%u).", 3862f1bfbf4SJames Hershaw rxmode->mtu, hw->max_mtu + NFP_ETH_OVERHEAD); 38711e9eae4SChaoyong He return -ERANGE; 38811e9eae4SChaoyong He } 38911e9eae4SChaoyong He 39011e9eae4SChaoyong He return 0; 39111e9eae4SChaoyong He } 39211e9eae4SChaoyong He 39311e9eae4SChaoyong He void 394000feb4cSChaoyong He nfp_net_log_device_information(const struct nfp_net_hw *hw, 395000feb4cSChaoyong He struct nfp_pf_dev *pf_dev) 39611e9eae4SChaoyong He { 39775a76c73SChaoyong He uint32_t cap = hw->super.cap; 398cbf062e9SChaoyong He uint32_t cap_ext = hw->super.cap_ext; 39975a76c73SChaoyong He 400b6de4353SZerun Fu PMD_INIT_LOG(INFO, "VER: %u.%u, Maximum supported MTU: %d.", 401000feb4cSChaoyong He pf_dev->ver.major, pf_dev->ver.minor, hw->max_mtu); 40211e9eae4SChaoyong He 403b6de4353SZerun Fu PMD_INIT_LOG(INFO, "CAP: %#x.", cap); 404df77f704SChaoyong 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", 405cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_ENABLE ? "ENABLE " : "", 40675a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "", 40775a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "", 40875a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_L2MC ? "L2MCFILT " : "", 40975a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXCSUM ? "RXCSUM " : "", 41075a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXCSUM ? "TXCSUM " : "", 41175a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RXVLAN ? "RXVLAN " : "", 41275a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_TXVLAN ? "TXVLAN " : "", 41375a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_SCATTER ? "SCATTER " : "", 41475a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_GATHER ? "GATHER " : "", 41575a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_LSO ? "TSO " : "", 416cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RXQINQ ? "RXQINQ " : "", 417cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ? "RXVLANv2 " : "", 418cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RINGCFG ? "RINGCFG " : "", 41975a76c73SChaoyong He cap & NFP_NET_CFG_CTRL_RSS ? "RSS " : "", 420cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_IRQMOD ? "IRQMOD " : "", 421cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RINGPRIO ? "RINGPRIO " : "", 422cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_MSIXAUTO ? "MSIXAUTO " : "", 423cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_TXRWB ? "TXRWB " : "", 424cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_L2SWITCH ? "L2SWITCH " : "", 425cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_TXVLAN_V2 ? "TXVLANv2 " : "", 426cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_VXLAN ? "VXLAN " : "", 427cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_NVGRE ? "NVGRE " : "", 428cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_MSIX_TX_OFF ? "MSIX_TX_OFF " : "", 429cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_LSO2 ? "TSOv2 " : "", 430cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_RSS2 ? "RSSv2 " : "", 431cbf062e9SChaoyong He cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ? "CSUM " : "", 432df77f704SChaoyong He cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "", 433df77f704SChaoyong He cap & NFP_NET_CFG_CTRL_USO ? "USO" : ""); 434cbf062e9SChaoyong He 435b6de4353SZerun Fu PMD_INIT_LOG(INFO, "CAP_WORD1: %#x.", cap_ext); 436cbf062e9SChaoyong He PMD_INIT_LOG(INFO, "%s%s%s%s%s%s%s", 437cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE ? "PKT_TYPE " : "", 438cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IPSEC ? "IPSEC " : "", 439cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP ? "IPSEC_SM " : "", 440cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP ? "IPSEC_LM " : "", 441cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_MULTI_PF ? "MULTI_PF " : "", 442cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER ? "FLOW_STEER " : "", 443cbf062e9SChaoyong He cap_ext & NFP_NET_CFG_CTRL_IN_ORDER ? "VIRTIO_IN_ORDER " : ""); 44411e9eae4SChaoyong He 445b6de4353SZerun Fu PMD_INIT_LOG(INFO, "The max_rx_queues: %u, max_tx_queues: %u.", 44611e9eae4SChaoyong He hw->max_rx_queues, hw->max_tx_queues); 44711e9eae4SChaoyong He } 44811e9eae4SChaoyong He 44911e9eae4SChaoyong He static inline void 45011e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(struct nfp_net_hw *hw, 45111e9eae4SChaoyong He uint32_t *ctrl) 45211e9eae4SChaoyong He { 45375a76c73SChaoyong He if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) 45411e9eae4SChaoyong He *ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2; 45575a76c73SChaoyong He else if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN) != 0) 45611e9eae4SChaoyong He *ctrl |= NFP_NET_CFG_CTRL_RXVLAN; 45711e9eae4SChaoyong He } 45811e9eae4SChaoyong He 45911e9eae4SChaoyong He void 46011e9eae4SChaoyong He nfp_net_enable_queues(struct rte_eth_dev *dev) 46111e9eae4SChaoyong He { 46211e9eae4SChaoyong He struct nfp_net_hw *hw; 46311e9eae4SChaoyong He 464b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 46511e9eae4SChaoyong He 46687f5b35bSChaoyong He nfp_enable_queues(&hw->super, dev->data->nb_rx_queues, 46787f5b35bSChaoyong He dev->data->nb_tx_queues); 46811e9eae4SChaoyong He } 46911e9eae4SChaoyong He 47011e9eae4SChaoyong He void 47111e9eae4SChaoyong He nfp_net_disable_queues(struct rte_eth_dev *dev) 47211e9eae4SChaoyong He { 47372d1dea6SChaoyong He struct nfp_net_hw *net_hw; 47411e9eae4SChaoyong He 475b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 47611e9eae4SChaoyong He 47787f5b35bSChaoyong He nfp_disable_queues(&net_hw->super); 47811e9eae4SChaoyong He } 47911e9eae4SChaoyong He 48011e9eae4SChaoyong He void 48111e9eae4SChaoyong He nfp_net_params_setup(struct nfp_net_hw *hw) 48211e9eae4SChaoyong He { 483f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, hw->mtu); 484f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_FLBUFSZ, hw->flbufsz); 48511e9eae4SChaoyong He } 48611e9eae4SChaoyong He 48711e9eae4SChaoyong He void 48811e9eae4SChaoyong He nfp_net_cfg_queue_setup(struct nfp_net_hw *hw) 48911e9eae4SChaoyong He { 490464a535bSChaoyong He hw->super.qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ; 49111e9eae4SChaoyong He } 49211e9eae4SChaoyong He 49311e9eae4SChaoyong He int 49411e9eae4SChaoyong He nfp_net_set_mac_addr(struct rte_eth_dev *dev, 49511e9eae4SChaoyong He struct rte_ether_addr *mac_addr) 49611e9eae4SChaoyong He { 49711e9eae4SChaoyong He uint32_t update; 498d6702227SChaoyong He uint32_t new_ctrl; 49972d1dea6SChaoyong He struct nfp_hw *hw; 50072d1dea6SChaoyong He struct nfp_net_hw *net_hw; 50111e9eae4SChaoyong He 502b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 50372d1dea6SChaoyong He hw = &net_hw->super; 50472d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 && 50572d1dea6SChaoyong He (hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) { 506b6de4353SZerun Fu PMD_DRV_LOG(ERR, "MAC address unable to change when port enabled."); 50711e9eae4SChaoyong He return -EBUSY; 50811e9eae4SChaoyong He } 50911e9eae4SChaoyong He 510edbb4e1cSChaoyong He if (rte_is_valid_assigned_ether_addr(mac_addr) == 0) { 511b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Invalid MAC address."); 512edbb4e1cSChaoyong He return -EINVAL; 513edbb4e1cSChaoyong He } 514edbb4e1cSChaoyong He 51511e9eae4SChaoyong He /* Writing new MAC to the specific port BAR address */ 516503ac807SChaoyong He nfp_write_mac(hw, (uint8_t *)mac_addr); 51711e9eae4SChaoyong He 51811e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_MACADDR; 519d6702227SChaoyong He new_ctrl = hw->ctrl; 52072d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 && 52172d1dea6SChaoyong He (hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) != 0) 522d6702227SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_LIVE_ADDR; 52311e9eae4SChaoyong He 52411e9eae4SChaoyong He /* Signal the NIC about the change */ 525d6702227SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) { 526b6de4353SZerun Fu PMD_DRV_LOG(ERR, "MAC address update failed."); 52711e9eae4SChaoyong He return -EIO; 52811e9eae4SChaoyong He } 52911e9eae4SChaoyong He 530d6702227SChaoyong He hw->ctrl = new_ctrl; 531d6702227SChaoyong He 53211e9eae4SChaoyong He return 0; 53311e9eae4SChaoyong He } 53411e9eae4SChaoyong He 53511e9eae4SChaoyong He int 53611e9eae4SChaoyong He nfp_configure_rx_interrupt(struct rte_eth_dev *dev, 53711e9eae4SChaoyong He struct rte_intr_handle *intr_handle) 53811e9eae4SChaoyong He { 53911e9eae4SChaoyong He uint16_t i; 54011e9eae4SChaoyong He struct nfp_net_hw *hw; 54111e9eae4SChaoyong He 54211e9eae4SChaoyong He if (rte_intr_vec_list_alloc(intr_handle, "intr_vec", 54311e9eae4SChaoyong He dev->data->nb_rx_queues) != 0) { 544b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues intr_vec.", 54511e9eae4SChaoyong He dev->data->nb_rx_queues); 54611e9eae4SChaoyong He return -ENOMEM; 54711e9eae4SChaoyong He } 54811e9eae4SChaoyong He 549b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 55011e9eae4SChaoyong He 55111e9eae4SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 552b6de4353SZerun Fu PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with UIO."); 55311e9eae4SChaoyong He /* UIO just supports one queue and no LSC */ 554f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(0), 0); 55511e9eae4SChaoyong He if (rte_intr_vec_list_index_set(intr_handle, 0, 0) != 0) 55611e9eae4SChaoyong He return -1; 55711e9eae4SChaoyong He } else { 558b6de4353SZerun Fu PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with VFIO."); 55911e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 56011e9eae4SChaoyong He /* 56111e9eae4SChaoyong He * The first msix vector is reserved for non 56211e9eae4SChaoyong He * efd interrupts. 56311e9eae4SChaoyong He */ 564f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(i), i + 1); 56511e9eae4SChaoyong He if (rte_intr_vec_list_index_set(intr_handle, i, i + 1) != 0) 56611e9eae4SChaoyong He return -1; 56711e9eae4SChaoyong He } 56811e9eae4SChaoyong He } 56911e9eae4SChaoyong He 57011e9eae4SChaoyong He /* Avoiding TX interrupts */ 571b4b6988aSChaoyong He hw->super.ctrl |= NFP_NET_CFG_CTRL_MSIX_TX_OFF; 57211e9eae4SChaoyong He return 0; 57311e9eae4SChaoyong He } 57411e9eae4SChaoyong He 57511e9eae4SChaoyong He uint32_t 57611e9eae4SChaoyong He nfp_check_offloads(struct rte_eth_dev *dev) 57711e9eae4SChaoyong He { 5784a9bb682SChaoyong He uint32_t cap; 57911e9eae4SChaoyong He uint32_t ctrl = 0; 58011e9eae4SChaoyong He uint64_t rx_offload; 58111e9eae4SChaoyong He uint64_t tx_offload; 58211e9eae4SChaoyong He struct nfp_net_hw *hw; 58311e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 58411e9eae4SChaoyong He 585b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 5864a9bb682SChaoyong He cap = hw->super.cap; 58711e9eae4SChaoyong He 58811e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 58911e9eae4SChaoyong He rx_offload = dev_conf->rxmode.offloads; 59011e9eae4SChaoyong He tx_offload = dev_conf->txmode.offloads; 59111e9eae4SChaoyong He 59211e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0) { 5934a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0) 59411e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_RXCSUM; 59511e9eae4SChaoyong He } 59611e9eae4SChaoyong He 59711e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0) 59811e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(hw, &ctrl); 59911e9eae4SChaoyong He 60011e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) { 6014a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0) 60211e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_RXQINQ; 60311e9eae4SChaoyong He } 60411e9eae4SChaoyong He 60511e9eae4SChaoyong He hw->mtu = dev->data->mtu; 60611e9eae4SChaoyong He 60711e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) != 0) { 6084a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) 60911e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXVLAN_V2; 6104a9bb682SChaoyong He else if ((cap & NFP_NET_CFG_CTRL_TXVLAN) != 0) 61111e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXVLAN; 61211e9eae4SChaoyong He } 61311e9eae4SChaoyong He 61411e9eae4SChaoyong He /* L2 broadcast */ 6154a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_L2BC) != 0) 61611e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_L2BC; 61711e9eae4SChaoyong He 61811e9eae4SChaoyong He /* L2 multicast */ 6194a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_L2MC) != 0) 62011e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_L2MC; 62111e9eae4SChaoyong He 62211e9eae4SChaoyong He /* TX checksum offload */ 62311e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0 || 62411e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0 || 62511e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0) 62611e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_TXCSUM; 62711e9eae4SChaoyong He 62811e9eae4SChaoyong He /* LSO offload */ 62911e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0 || 630df77f704SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_UDP_TSO) != 0 || 63111e9eae4SChaoyong He (tx_offload & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) != 0) { 6324a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_LSO) != 0) 63311e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LSO; 634afa83796SChaoyong He else if ((cap & NFP_NET_CFG_CTRL_LSO2) != 0) 63511e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_LSO2; 63611e9eae4SChaoyong He } 63711e9eae4SChaoyong He 63811e9eae4SChaoyong He /* RX gather */ 63911e9eae4SChaoyong He if ((tx_offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0) 64011e9eae4SChaoyong He ctrl |= NFP_NET_CFG_CTRL_GATHER; 64111e9eae4SChaoyong He 64211e9eae4SChaoyong He return ctrl; 64311e9eae4SChaoyong He } 64411e9eae4SChaoyong He 64511e9eae4SChaoyong He int 64611e9eae4SChaoyong He nfp_net_promisc_enable(struct rte_eth_dev *dev) 64711e9eae4SChaoyong He { 64811e9eae4SChaoyong He int ret; 64972d1dea6SChaoyong He uint32_t update; 65011e9eae4SChaoyong He uint32_t new_ctrl; 65172d1dea6SChaoyong He struct nfp_hw *hw; 65272d1dea6SChaoyong He struct nfp_net_hw *net_hw; 65311e9eae4SChaoyong He 654b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 65511e9eae4SChaoyong He 65672d1dea6SChaoyong He hw = &net_hw->super; 65772d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) { 658b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Promiscuous mode not supported."); 65911e9eae4SChaoyong He return -ENOTSUP; 66011e9eae4SChaoyong He } 66111e9eae4SChaoyong He 66272d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) != 0) { 663b6de4353SZerun Fu PMD_DRV_LOG(INFO, "Promiscuous mode already enabled."); 66411e9eae4SChaoyong He return 0; 66511e9eae4SChaoyong He } 66611e9eae4SChaoyong He 66772d1dea6SChaoyong He new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_PROMISC; 66811e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 66911e9eae4SChaoyong He 67072d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 67111e9eae4SChaoyong He if (ret != 0) 67211e9eae4SChaoyong He return ret; 67311e9eae4SChaoyong He 67472d1dea6SChaoyong He hw->ctrl = new_ctrl; 67511e9eae4SChaoyong He 67611e9eae4SChaoyong He return 0; 67711e9eae4SChaoyong He } 67811e9eae4SChaoyong He 67911e9eae4SChaoyong He int 68011e9eae4SChaoyong He nfp_net_promisc_disable(struct rte_eth_dev *dev) 68111e9eae4SChaoyong He { 68211e9eae4SChaoyong He int ret; 68372d1dea6SChaoyong He uint32_t update; 68411e9eae4SChaoyong He uint32_t new_ctrl; 68572d1dea6SChaoyong He struct nfp_hw *hw; 68672d1dea6SChaoyong He struct nfp_net_hw *net_hw; 68711e9eae4SChaoyong He 688b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 68972d1dea6SChaoyong He hw = &net_hw->super; 69011e9eae4SChaoyong He 6915ff76867SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) { 692b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Promiscuous mode not supported."); 6935ff76867SChaoyong He return -ENOTSUP; 6945ff76867SChaoyong He } 6955ff76867SChaoyong He 69672d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) == 0) { 697b6de4353SZerun Fu PMD_DRV_LOG(INFO, "Promiscuous mode already disabled."); 69811e9eae4SChaoyong He return 0; 69911e9eae4SChaoyong He } 70011e9eae4SChaoyong He 70172d1dea6SChaoyong He new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_PROMISC; 70211e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 70311e9eae4SChaoyong He 70472d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 70511e9eae4SChaoyong He if (ret != 0) 70611e9eae4SChaoyong He return ret; 70711e9eae4SChaoyong He 70872d1dea6SChaoyong He hw->ctrl = new_ctrl; 70911e9eae4SChaoyong He 71011e9eae4SChaoyong He return 0; 71111e9eae4SChaoyong He } 71211e9eae4SChaoyong He 7134a86c36bSQin Ke static int 7144a86c36bSQin Ke nfp_net_set_allmulticast_mode(struct rte_eth_dev *dev, 7154a86c36bSQin Ke bool enable) 7164a86c36bSQin Ke { 7174a86c36bSQin Ke int ret; 7184a86c36bSQin Ke uint32_t update; 7194a86c36bSQin Ke struct nfp_hw *hw; 7204a86c36bSQin Ke uint32_t cap_extend; 7214a86c36bSQin Ke uint32_t ctrl_extend; 7224a86c36bSQin Ke uint32_t new_ctrl_extend; 7234a86c36bSQin Ke struct nfp_net_hw *net_hw; 7244a86c36bSQin Ke 7254a86c36bSQin Ke net_hw = nfp_net_get_hw(dev); 7264a86c36bSQin Ke hw = &net_hw->super; 7274a86c36bSQin Ke 7284a86c36bSQin Ke cap_extend = hw->cap_ext; 7294a86c36bSQin Ke if ((cap_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0) { 730b6de4353SZerun Fu PMD_DRV_LOG(DEBUG, "Allmulticast mode not supported."); 7314a86c36bSQin Ke return -ENOTSUP; 7324a86c36bSQin Ke } 7334a86c36bSQin Ke 7344a86c36bSQin Ke /* 7354a86c36bSQin Ke * Allmulticast mode enabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 0. 7364a86c36bSQin Ke * Allmulticast mode disabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 1. 7374a86c36bSQin Ke */ 7384a86c36bSQin Ke ctrl_extend = hw->ctrl_ext; 7394a86c36bSQin Ke if (enable) { 7404a86c36bSQin Ke if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0) 7414a86c36bSQin Ke return 0; 7424a86c36bSQin Ke 7434a86c36bSQin Ke new_ctrl_extend = ctrl_extend & ~NFP_NET_CFG_CTRL_MCAST_FILTER; 7444a86c36bSQin Ke } else { 7454a86c36bSQin Ke if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) != 0) 7464a86c36bSQin Ke return 0; 7474a86c36bSQin Ke 7484a86c36bSQin Ke new_ctrl_extend = ctrl_extend | NFP_NET_CFG_CTRL_MCAST_FILTER; 7494a86c36bSQin Ke } 7504a86c36bSQin Ke 7514a86c36bSQin Ke update = NFP_NET_CFG_UPDATE_GEN; 7524a86c36bSQin Ke 7534a86c36bSQin Ke ret = nfp_ext_reconfig(hw, new_ctrl_extend, update); 7544a86c36bSQin Ke if (ret != 0) 7554a86c36bSQin Ke return ret; 7564a86c36bSQin Ke 7574a86c36bSQin Ke hw->ctrl_ext = new_ctrl_extend; 7584a86c36bSQin Ke return 0; 7594a86c36bSQin Ke } 7604a86c36bSQin Ke 7614a86c36bSQin Ke int 7624a86c36bSQin Ke nfp_net_allmulticast_enable(struct rte_eth_dev *dev) 7634a86c36bSQin Ke { 7644a86c36bSQin Ke return nfp_net_set_allmulticast_mode(dev, true); 7654a86c36bSQin Ke } 7664a86c36bSQin Ke 7674a86c36bSQin Ke int 7684a86c36bSQin Ke nfp_net_allmulticast_disable(struct rte_eth_dev *dev) 7694a86c36bSQin Ke { 7704a86c36bSQin Ke return nfp_net_set_allmulticast_mode(dev, false); 7714a86c36bSQin Ke } 7724a86c36bSQin Ke 773a476ccaeSZerun Fu static void 7741b3b12c4SQin Ke nfp_net_pf_speed_update(struct rte_eth_dev *dev, 775ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv, 7768412feedSZerun Fu struct rte_eth_link *link) 7778412feedSZerun Fu { 778441839f1SQin Ke uint8_t idx; 779aaa57548SZerun Fu enum nfp_eth_aneg aneg; 780aaa57548SZerun Fu struct nfp_pf_dev *pf_dev; 7818412feedSZerun Fu struct nfp_eth_table *nfp_eth_table; 7828412feedSZerun Fu struct nfp_eth_table_port *eth_port; 7838412feedSZerun Fu 784aaa57548SZerun Fu pf_dev = hw_priv->pf_dev; 785441839f1SQin Ke idx = nfp_net_get_idx(dev); 786441839f1SQin Ke aneg = pf_dev->nfp_eth_table->ports[idx].aneg; 787aaa57548SZerun Fu 7888412feedSZerun Fu /* Compare whether the current status has changed. */ 789aaa57548SZerun Fu if (pf_dev->speed_updated || aneg == NFP_ANEG_AUTO) { 790aaa57548SZerun Fu nfp_eth_table = nfp_eth_read_ports(pf_dev->cpp); 7918412feedSZerun Fu if (nfp_eth_table == NULL) { 79217d6720eSZerun Fu PMD_DRV_LOG(DEBUG, "Failed to get nfp_eth_table."); 793aaa57548SZerun Fu } else { 794441839f1SQin Ke pf_dev->nfp_eth_table->ports[idx] = nfp_eth_table->ports[idx]; 7958412feedSZerun Fu free(nfp_eth_table); 796aaa57548SZerun Fu pf_dev->speed_updated = false; 797aaa57548SZerun Fu } 7988412feedSZerun Fu } 7998412feedSZerun Fu 800aaa57548SZerun Fu nfp_eth_table = pf_dev->nfp_eth_table; 801441839f1SQin Ke eth_port = &nfp_eth_table->ports[idx]; 8028412feedSZerun Fu 80348de6254SQin Ke link->link_speed = nfp_net_link_speed_nfp2rte_check(eth_port->speed); 8048412feedSZerun Fu 8058412feedSZerun Fu if (dev->data->dev_conf.link_speeds == RTE_ETH_LINK_SPEED_AUTONEG && 8068412feedSZerun Fu eth_port->supp_aneg) 8078412feedSZerun Fu link->link_autoneg = RTE_ETH_LINK_AUTONEG; 8088412feedSZerun Fu } 8098412feedSZerun Fu 8102e3ad187SQin Ke static void 8112e3ad187SQin Ke nfp_net_vf_speed_update(struct rte_eth_link *link, 8122e3ad187SQin Ke uint32_t link_status) 8132e3ad187SQin Ke { 8142e3ad187SQin Ke size_t link_rate_index; 8152e3ad187SQin Ke 8162e3ad187SQin Ke /* 8172e3ad187SQin Ke * Shift and mask link_status so that it is effectively the value 8182e3ad187SQin Ke * at offset NFP_NET_CFG_STS_NSP_LINK_RATE. 8192e3ad187SQin Ke */ 8202e3ad187SQin Ke link_rate_index = (link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) & 8212e3ad187SQin Ke NFP_NET_CFG_STS_LINK_RATE_MASK; 8222e3ad187SQin Ke if (link_rate_index < RTE_DIM(nfp_net_link_speed_nfp2rte)) 8232e3ad187SQin Ke link->link_speed = nfp_net_link_speed_nfp2rte[link_rate_index]; 8242e3ad187SQin Ke else 8252e3ad187SQin Ke link->link_speed = RTE_ETH_SPEED_NUM_NONE; 8262e3ad187SQin Ke } 8272e3ad187SQin Ke 828c4de52ecSChaoyong He int 829c4de52ecSChaoyong He nfp_net_link_update_common(struct rte_eth_dev *dev, 830c4de52ecSChaoyong He struct rte_eth_link *link, 831c4de52ecSChaoyong He uint32_t link_status) 832c4de52ecSChaoyong He { 833c4de52ecSChaoyong He int ret; 834ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 835c4de52ecSChaoyong He 836ff9f5a56SChaoyong He hw_priv = dev->process_private; 837c4de52ecSChaoyong He if (link->link_status == RTE_ETH_LINK_UP) { 838*c43d2aabSLong Wu if (nfp_net_is_pf(dev)) 839441839f1SQin Ke nfp_net_pf_speed_update(dev, hw_priv, link); 8402e3ad187SQin Ke else 8412e3ad187SQin Ke nfp_net_vf_speed_update(link, link_status); 842c4de52ecSChaoyong He } 843c4de52ecSChaoyong He 844c4de52ecSChaoyong He ret = rte_eth_linkstatus_set(dev, link); 845c4de52ecSChaoyong He if (ret == 0) { 8461b3b12c4SQin Ke if (link->link_status == RTE_ETH_LINK_UP) 847b6de4353SZerun Fu PMD_DRV_LOG(INFO, "NIC Link is Up."); 848c4de52ecSChaoyong He else 849b6de4353SZerun Fu PMD_DRV_LOG(INFO, "NIC Link is Down."); 850c4de52ecSChaoyong He } 851c4de52ecSChaoyong He 852c4de52ecSChaoyong He return ret; 853c4de52ecSChaoyong He } 854c4de52ecSChaoyong He 85511e9eae4SChaoyong He /* 85611e9eae4SChaoyong He * Return 0 means link status changed, -1 means not changed 85711e9eae4SChaoyong He * 85811e9eae4SChaoyong He * Wait to complete is needed as it can take up to 9 seconds to get the Link 85911e9eae4SChaoyong He * status. 86011e9eae4SChaoyong He */ 86111e9eae4SChaoyong He int 86211e9eae4SChaoyong He nfp_net_link_update(struct rte_eth_dev *dev, 86311e9eae4SChaoyong He __rte_unused int wait_to_complete) 86411e9eae4SChaoyong He { 86511e9eae4SChaoyong He int ret; 86611e9eae4SChaoyong He struct nfp_net_hw *hw; 86711e9eae4SChaoyong He uint32_t nn_link_status; 86811e9eae4SChaoyong He struct rte_eth_link link; 869ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 87011e9eae4SChaoyong He 871b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 872ff9f5a56SChaoyong He hw_priv = dev->process_private; 87311e9eae4SChaoyong He 87411e9eae4SChaoyong He memset(&link, 0, sizeof(struct rte_eth_link)); 87511e9eae4SChaoyong He 87611e9eae4SChaoyong He /* Read link status */ 877f58bde00SChaoyong He nn_link_status = nn_cfg_readw(&hw->super, NFP_NET_CFG_STS); 87811e9eae4SChaoyong He if ((nn_link_status & NFP_NET_CFG_STS_LINK) != 0) 87911e9eae4SChaoyong He link.link_status = RTE_ETH_LINK_UP; 88011e9eae4SChaoyong He 88111e9eae4SChaoyong He link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 88211e9eae4SChaoyong He 883441839f1SQin Ke ret = nfp_net_link_update_common(dev, &link, nn_link_status); 8848412feedSZerun Fu if (ret == -EIO) 8858412feedSZerun Fu return ret; 88611e9eae4SChaoyong He 88711e9eae4SChaoyong He /* 88811e9eae4SChaoyong He * Notify the port to update the speed value in the CTRL BAR from NSP. 88911e9eae4SChaoyong He * Not applicable for VFs as the associated PF is still attached to the 89011e9eae4SChaoyong He * kernel driver. 89111e9eae4SChaoyong He */ 892c2b4f0d5SChaoyong He if (hw_priv != NULL && hw_priv->is_pf) 89311e9eae4SChaoyong He nfp_net_notify_port_speed(hw, &link); 89411e9eae4SChaoyong He 89511e9eae4SChaoyong He return ret; 89611e9eae4SChaoyong He } 89711e9eae4SChaoyong He 89811e9eae4SChaoyong He int 89911e9eae4SChaoyong He nfp_net_stats_get(struct rte_eth_dev *dev, 90011e9eae4SChaoyong He struct rte_eth_stats *stats) 90111e9eae4SChaoyong He { 90211e9eae4SChaoyong He uint16_t i; 90311e9eae4SChaoyong He struct nfp_net_hw *hw; 90411e9eae4SChaoyong He struct rte_eth_stats nfp_dev_stats; 90511e9eae4SChaoyong He 90611e9eae4SChaoyong He if (stats == NULL) 90711e9eae4SChaoyong He return -EINVAL; 90811e9eae4SChaoyong He 909b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 91011e9eae4SChaoyong He 91111e9eae4SChaoyong He memset(&nfp_dev_stats, 0, sizeof(nfp_dev_stats)); 91211e9eae4SChaoyong He 91311e9eae4SChaoyong He /* Reading per RX ring stats */ 91411e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 91511e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 91611e9eae4SChaoyong He break; 91711e9eae4SChaoyong He 91811e9eae4SChaoyong He nfp_dev_stats.q_ipackets[i] = 919f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i)); 92011e9eae4SChaoyong He nfp_dev_stats.q_ipackets[i] -= 92111e9eae4SChaoyong He hw->eth_stats_base.q_ipackets[i]; 92211e9eae4SChaoyong He 92311e9eae4SChaoyong He nfp_dev_stats.q_ibytes[i] = 924f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8); 92511e9eae4SChaoyong He nfp_dev_stats.q_ibytes[i] -= 92611e9eae4SChaoyong He hw->eth_stats_base.q_ibytes[i]; 92711e9eae4SChaoyong He } 92811e9eae4SChaoyong He 92911e9eae4SChaoyong He /* Reading per TX ring stats */ 93011e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 93111e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 93211e9eae4SChaoyong He break; 93311e9eae4SChaoyong He 93411e9eae4SChaoyong He nfp_dev_stats.q_opackets[i] = 935f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i)); 93611e9eae4SChaoyong He nfp_dev_stats.q_opackets[i] -= hw->eth_stats_base.q_opackets[i]; 93711e9eae4SChaoyong He 93811e9eae4SChaoyong He nfp_dev_stats.q_obytes[i] = 939f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8); 94011e9eae4SChaoyong He nfp_dev_stats.q_obytes[i] -= hw->eth_stats_base.q_obytes[i]; 94111e9eae4SChaoyong He } 94211e9eae4SChaoyong He 943f58bde00SChaoyong He nfp_dev_stats.ipackets = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES); 94411e9eae4SChaoyong He nfp_dev_stats.ipackets -= hw->eth_stats_base.ipackets; 94511e9eae4SChaoyong He 946f58bde00SChaoyong He nfp_dev_stats.ibytes = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS); 94711e9eae4SChaoyong He nfp_dev_stats.ibytes -= hw->eth_stats_base.ibytes; 94811e9eae4SChaoyong He 94911e9eae4SChaoyong He nfp_dev_stats.opackets = 950f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES); 95111e9eae4SChaoyong He nfp_dev_stats.opackets -= hw->eth_stats_base.opackets; 95211e9eae4SChaoyong He 95311e9eae4SChaoyong He nfp_dev_stats.obytes = 954f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS); 95511e9eae4SChaoyong He nfp_dev_stats.obytes -= hw->eth_stats_base.obytes; 95611e9eae4SChaoyong He 95711e9eae4SChaoyong He /* Reading general device stats */ 95811e9eae4SChaoyong He nfp_dev_stats.ierrors = 959f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS); 96011e9eae4SChaoyong He nfp_dev_stats.ierrors -= hw->eth_stats_base.ierrors; 96111e9eae4SChaoyong He 96211e9eae4SChaoyong He nfp_dev_stats.oerrors = 963f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS); 96411e9eae4SChaoyong He nfp_dev_stats.oerrors -= hw->eth_stats_base.oerrors; 96511e9eae4SChaoyong He 96611e9eae4SChaoyong He /* RX ring mbuf allocation failures */ 96711e9eae4SChaoyong He nfp_dev_stats.rx_nombuf = dev->data->rx_mbuf_alloc_failed; 96811e9eae4SChaoyong He 96911e9eae4SChaoyong He nfp_dev_stats.imissed = 970f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS); 97111e9eae4SChaoyong He nfp_dev_stats.imissed -= hw->eth_stats_base.imissed; 97211e9eae4SChaoyong He 97311e9eae4SChaoyong He memcpy(stats, &nfp_dev_stats, sizeof(*stats)); 97411e9eae4SChaoyong He return 0; 97511e9eae4SChaoyong He } 97611e9eae4SChaoyong He 97711e9eae4SChaoyong He /* 97811e9eae4SChaoyong He * hw->eth_stats_base records the per counter starting point. 97911e9eae4SChaoyong He * Lets update it now. 98011e9eae4SChaoyong He */ 98111e9eae4SChaoyong He int 98211e9eae4SChaoyong He nfp_net_stats_reset(struct rte_eth_dev *dev) 98311e9eae4SChaoyong He { 98411e9eae4SChaoyong He uint16_t i; 98511e9eae4SChaoyong He struct nfp_net_hw *hw; 98611e9eae4SChaoyong He 987b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 98811e9eae4SChaoyong He 98911e9eae4SChaoyong He /* Reading per RX ring stats */ 99011e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 99111e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 99211e9eae4SChaoyong He break; 99311e9eae4SChaoyong He 99411e9eae4SChaoyong He hw->eth_stats_base.q_ipackets[i] = 995f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i)); 99611e9eae4SChaoyong He 99711e9eae4SChaoyong He hw->eth_stats_base.q_ibytes[i] = 998f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8); 99911e9eae4SChaoyong He } 100011e9eae4SChaoyong He 100111e9eae4SChaoyong He /* Reading per TX ring stats */ 100211e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 100311e9eae4SChaoyong He if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS) 100411e9eae4SChaoyong He break; 100511e9eae4SChaoyong He 100611e9eae4SChaoyong He hw->eth_stats_base.q_opackets[i] = 1007f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i)); 100811e9eae4SChaoyong He 100911e9eae4SChaoyong He hw->eth_stats_base.q_obytes[i] = 1010f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8); 101111e9eae4SChaoyong He } 101211e9eae4SChaoyong He 101311e9eae4SChaoyong He hw->eth_stats_base.ipackets = 1014f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES); 101511e9eae4SChaoyong He 101611e9eae4SChaoyong He hw->eth_stats_base.ibytes = 1017f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS); 101811e9eae4SChaoyong He 101911e9eae4SChaoyong He hw->eth_stats_base.opackets = 1020f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES); 102111e9eae4SChaoyong He 102211e9eae4SChaoyong He hw->eth_stats_base.obytes = 1023f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS); 102411e9eae4SChaoyong He 102511e9eae4SChaoyong He /* Reading general device stats */ 102611e9eae4SChaoyong He hw->eth_stats_base.ierrors = 1027f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS); 102811e9eae4SChaoyong He 102911e9eae4SChaoyong He hw->eth_stats_base.oerrors = 1030f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS); 103111e9eae4SChaoyong He 103211e9eae4SChaoyong He /* RX ring mbuf allocation failures */ 103311e9eae4SChaoyong He dev->data->rx_mbuf_alloc_failed = 0; 103411e9eae4SChaoyong He 103511e9eae4SChaoyong He hw->eth_stats_base.imissed = 1036f58bde00SChaoyong He nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS); 103711e9eae4SChaoyong He 103811e9eae4SChaoyong He return 0; 103911e9eae4SChaoyong He } 104011e9eae4SChaoyong He 104111e9eae4SChaoyong He uint32_t 104211e9eae4SChaoyong He nfp_net_xstats_size(const struct rte_eth_dev *dev) 104311e9eae4SChaoyong He { 104411e9eae4SChaoyong He uint32_t count; 104582a2c286SChaoyong He bool vf_flag = false; 104611e9eae4SChaoyong He struct nfp_net_hw *hw; 104782a2c286SChaoyong He struct nfp_flower_representor *repr; 104811e9eae4SChaoyong He const uint32_t size = RTE_DIM(nfp_net_xstats); 104911e9eae4SChaoyong He 105082a2c286SChaoyong He if (rte_eth_dev_is_repr(dev)) { 105182a2c286SChaoyong He repr = dev->data->dev_private; 1052608bc946SPeng Zhang if (nfp_flower_repr_is_vf(repr)) 105382a2c286SChaoyong He vf_flag = true; 105482a2c286SChaoyong He } else { 105582a2c286SChaoyong He hw = dev->data->dev_private; 105682a2c286SChaoyong He if (hw->mac_stats == NULL) 105782a2c286SChaoyong He vf_flag = true; 105882a2c286SChaoyong He } 105982a2c286SChaoyong He 106082a2c286SChaoyong He /* If the device is a VF or VF-repr, then there will be no MAC stats */ 106182a2c286SChaoyong He if (vf_flag) { 106211e9eae4SChaoyong He for (count = 0; count < size; count++) { 106311e9eae4SChaoyong He if (nfp_net_xstats[count].group == NFP_XSTAT_GROUP_MAC) 106411e9eae4SChaoyong He break; 106511e9eae4SChaoyong He } 106611e9eae4SChaoyong He 106711e9eae4SChaoyong He return count; 106811e9eae4SChaoyong He } 106911e9eae4SChaoyong He 107011e9eae4SChaoyong He return size; 107111e9eae4SChaoyong He } 107211e9eae4SChaoyong He 107311e9eae4SChaoyong He static const struct nfp_xstat * 107411e9eae4SChaoyong He nfp_net_xstats_info(const struct rte_eth_dev *dev, 107511e9eae4SChaoyong He uint32_t index) 107611e9eae4SChaoyong He { 107711e9eae4SChaoyong He if (index >= nfp_net_xstats_size(dev)) { 1078b6de4353SZerun Fu PMD_DRV_LOG(ERR, "The xstat index out of bounds."); 107911e9eae4SChaoyong He return NULL; 108011e9eae4SChaoyong He } 108111e9eae4SChaoyong He 108211e9eae4SChaoyong He return &nfp_net_xstats[index]; 108311e9eae4SChaoyong He } 108411e9eae4SChaoyong He 108511e9eae4SChaoyong He static uint64_t 108611e9eae4SChaoyong He nfp_net_xstats_value(const struct rte_eth_dev *dev, 108711e9eae4SChaoyong He uint32_t index, 108811e9eae4SChaoyong He bool raw) 108911e9eae4SChaoyong He { 109011e9eae4SChaoyong He uint64_t value; 109182a2c286SChaoyong He uint8_t *mac_stats; 109211e9eae4SChaoyong He struct nfp_net_hw *hw; 109311e9eae4SChaoyong He struct nfp_xstat xstat; 109482a2c286SChaoyong He struct rte_eth_xstat *xstats_base; 109582a2c286SChaoyong He struct nfp_flower_representor *repr; 109611e9eae4SChaoyong He 109782a2c286SChaoyong He if (rte_eth_dev_is_repr(dev)) { 109882a2c286SChaoyong He repr = dev->data->dev_private; 109982a2c286SChaoyong He hw = repr->app_fw_flower->pf_hw; 110082a2c286SChaoyong He 110182a2c286SChaoyong He mac_stats = repr->mac_stats; 110282a2c286SChaoyong He xstats_base = repr->repr_xstats_base; 110382a2c286SChaoyong He } else { 110482a2c286SChaoyong He hw = dev->data->dev_private; 110582a2c286SChaoyong He 110682a2c286SChaoyong He mac_stats = hw->mac_stats; 110782a2c286SChaoyong He xstats_base = hw->eth_xstats_base; 110882a2c286SChaoyong He } 110982a2c286SChaoyong He 111011e9eae4SChaoyong He xstat = nfp_net_xstats[index]; 111111e9eae4SChaoyong He 111211e9eae4SChaoyong He if (xstat.group == NFP_XSTAT_GROUP_MAC) 111382a2c286SChaoyong He value = nn_readq(mac_stats + xstat.offset); 111411e9eae4SChaoyong He else 1115f58bde00SChaoyong He value = nn_cfg_readq(&hw->super, xstat.offset); 111611e9eae4SChaoyong He 111711e9eae4SChaoyong He if (raw) 111811e9eae4SChaoyong He return value; 111911e9eae4SChaoyong He 112011e9eae4SChaoyong He /* 112111e9eae4SChaoyong He * A baseline value of each statistic counter is recorded when stats are "reset". 112211e9eae4SChaoyong He * Thus, the value returned by this function need to be decremented by this 112311e9eae4SChaoyong He * baseline value. The result is the count of this statistic since the last time 112411e9eae4SChaoyong He * it was "reset". 112511e9eae4SChaoyong He */ 112682a2c286SChaoyong He return value - xstats_base[index].value; 112711e9eae4SChaoyong He } 112811e9eae4SChaoyong He 112911e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */ 113011e9eae4SChaoyong He int 113111e9eae4SChaoyong He nfp_net_xstats_get_names(struct rte_eth_dev *dev, 113211e9eae4SChaoyong He struct rte_eth_xstat_name *xstats_names, 113311e9eae4SChaoyong He unsigned int size) 113411e9eae4SChaoyong He { 113511e9eae4SChaoyong He uint32_t id; 113611e9eae4SChaoyong He uint32_t nfp_size; 113711e9eae4SChaoyong He uint32_t read_size; 113811e9eae4SChaoyong He 113911e9eae4SChaoyong He nfp_size = nfp_net_xstats_size(dev); 114011e9eae4SChaoyong He 114111e9eae4SChaoyong He if (xstats_names == NULL) 114211e9eae4SChaoyong He return nfp_size; 114311e9eae4SChaoyong He 114411e9eae4SChaoyong He /* Read at most NFP xstats number of names. */ 114511e9eae4SChaoyong He read_size = RTE_MIN(size, nfp_size); 114611e9eae4SChaoyong He 114711e9eae4SChaoyong He for (id = 0; id < read_size; id++) 114811e9eae4SChaoyong He rte_strlcpy(xstats_names[id].name, nfp_net_xstats[id].name, 114911e9eae4SChaoyong He RTE_ETH_XSTATS_NAME_SIZE); 115011e9eae4SChaoyong He 115111e9eae4SChaoyong He return read_size; 115211e9eae4SChaoyong He } 115311e9eae4SChaoyong He 115411e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */ 115511e9eae4SChaoyong He int 115611e9eae4SChaoyong He nfp_net_xstats_get(struct rte_eth_dev *dev, 115711e9eae4SChaoyong He struct rte_eth_xstat *xstats, 115811e9eae4SChaoyong He unsigned int n) 115911e9eae4SChaoyong He { 116011e9eae4SChaoyong He uint32_t id; 116111e9eae4SChaoyong He uint32_t nfp_size; 116211e9eae4SChaoyong He uint32_t read_size; 116311e9eae4SChaoyong He 116411e9eae4SChaoyong He nfp_size = nfp_net_xstats_size(dev); 116511e9eae4SChaoyong He 116611e9eae4SChaoyong He if (xstats == NULL) 116711e9eae4SChaoyong He return nfp_size; 116811e9eae4SChaoyong He 116911e9eae4SChaoyong He /* Read at most NFP xstats number of values. */ 117011e9eae4SChaoyong He read_size = RTE_MIN(n, nfp_size); 117111e9eae4SChaoyong He 117211e9eae4SChaoyong He for (id = 0; id < read_size; id++) { 117311e9eae4SChaoyong He xstats[id].id = id; 117411e9eae4SChaoyong He xstats[id].value = nfp_net_xstats_value(dev, id, false); 117511e9eae4SChaoyong He } 117611e9eae4SChaoyong He 117711e9eae4SChaoyong He return read_size; 117811e9eae4SChaoyong He } 117911e9eae4SChaoyong He 118011e9eae4SChaoyong He /* 118111e9eae4SChaoyong He * NOTE: The only caller rte_eth_xstats_get_names_by_id() ensures dev, 118211e9eae4SChaoyong He * ids, xstats_names and size are valid, and non-NULL. 118311e9eae4SChaoyong He */ 118411e9eae4SChaoyong He int 118511e9eae4SChaoyong He nfp_net_xstats_get_names_by_id(struct rte_eth_dev *dev, 118611e9eae4SChaoyong He const uint64_t *ids, 118711e9eae4SChaoyong He struct rte_eth_xstat_name *xstats_names, 118811e9eae4SChaoyong He unsigned int size) 118911e9eae4SChaoyong He { 119011e9eae4SChaoyong He uint32_t i; 119111e9eae4SChaoyong He uint32_t read_size; 119211e9eae4SChaoyong He 119311e9eae4SChaoyong He /* Read at most NFP xstats number of names. */ 119411e9eae4SChaoyong He read_size = RTE_MIN(size, nfp_net_xstats_size(dev)); 119511e9eae4SChaoyong He 119611e9eae4SChaoyong He for (i = 0; i < read_size; i++) { 119711e9eae4SChaoyong He const struct nfp_xstat *xstat; 119811e9eae4SChaoyong He 119911e9eae4SChaoyong He /* Make sure ID is valid for device. */ 120011e9eae4SChaoyong He xstat = nfp_net_xstats_info(dev, ids[i]); 120111e9eae4SChaoyong He if (xstat == NULL) 120211e9eae4SChaoyong He return -EINVAL; 120311e9eae4SChaoyong He 120411e9eae4SChaoyong He rte_strlcpy(xstats_names[i].name, xstat->name, 120511e9eae4SChaoyong He RTE_ETH_XSTATS_NAME_SIZE); 120611e9eae4SChaoyong He } 120711e9eae4SChaoyong He 120811e9eae4SChaoyong He return read_size; 120911e9eae4SChaoyong He } 121011e9eae4SChaoyong He 121111e9eae4SChaoyong He /* 121211e9eae4SChaoyong He * NOTE: The only caller rte_eth_xstats_get_by_id() ensures dev, 121311e9eae4SChaoyong He * ids, values and n are valid, and non-NULL. 121411e9eae4SChaoyong He */ 121511e9eae4SChaoyong He int 121611e9eae4SChaoyong He nfp_net_xstats_get_by_id(struct rte_eth_dev *dev, 121711e9eae4SChaoyong He const uint64_t *ids, 121811e9eae4SChaoyong He uint64_t *values, 121911e9eae4SChaoyong He unsigned int n) 122011e9eae4SChaoyong He { 122111e9eae4SChaoyong He uint32_t i; 122211e9eae4SChaoyong He uint32_t read_size; 122311e9eae4SChaoyong He 122411e9eae4SChaoyong He /* Read at most NFP xstats number of values. */ 122511e9eae4SChaoyong He read_size = RTE_MIN(n, nfp_net_xstats_size(dev)); 122611e9eae4SChaoyong He 122711e9eae4SChaoyong He for (i = 0; i < read_size; i++) { 122811e9eae4SChaoyong He const struct nfp_xstat *xstat; 122911e9eae4SChaoyong He 123011e9eae4SChaoyong He /* Make sure index is valid for device. */ 123111e9eae4SChaoyong He xstat = nfp_net_xstats_info(dev, ids[i]); 123211e9eae4SChaoyong He if (xstat == NULL) 123311e9eae4SChaoyong He return -EINVAL; 123411e9eae4SChaoyong He 123511e9eae4SChaoyong He values[i] = nfp_net_xstats_value(dev, ids[i], false); 123611e9eae4SChaoyong He } 123711e9eae4SChaoyong He 123811e9eae4SChaoyong He return read_size; 123911e9eae4SChaoyong He } 124011e9eae4SChaoyong He 124111e9eae4SChaoyong He int 124211e9eae4SChaoyong He nfp_net_xstats_reset(struct rte_eth_dev *dev) 124311e9eae4SChaoyong He { 124411e9eae4SChaoyong He uint32_t id; 124511e9eae4SChaoyong He uint32_t read_size; 124611e9eae4SChaoyong He struct nfp_net_hw *hw; 124782a2c286SChaoyong He struct rte_eth_xstat *xstats_base; 124882a2c286SChaoyong He struct nfp_flower_representor *repr; 124911e9eae4SChaoyong He 125011e9eae4SChaoyong He read_size = nfp_net_xstats_size(dev); 125111e9eae4SChaoyong He 125282a2c286SChaoyong He if (rte_eth_dev_is_repr(dev)) { 125382a2c286SChaoyong He repr = dev->data->dev_private; 125482a2c286SChaoyong He xstats_base = repr->repr_xstats_base; 125582a2c286SChaoyong He } else { 125682a2c286SChaoyong He hw = dev->data->dev_private; 125782a2c286SChaoyong He xstats_base = hw->eth_xstats_base; 125882a2c286SChaoyong He } 125982a2c286SChaoyong He 126011e9eae4SChaoyong He for (id = 0; id < read_size; id++) { 126182a2c286SChaoyong He xstats_base[id].id = id; 126282a2c286SChaoyong He xstats_base[id].value = nfp_net_xstats_value(dev, id, true); 126311e9eae4SChaoyong He } 126411e9eae4SChaoyong He 126511e9eae4SChaoyong He /* Successfully reset xstats, now call function to reset basic stats. */ 126682a2c286SChaoyong He if (rte_eth_dev_is_repr(dev)) 126782a2c286SChaoyong He return nfp_flower_repr_stats_reset(dev); 126882a2c286SChaoyong He else 126911e9eae4SChaoyong He return nfp_net_stats_reset(dev); 127011e9eae4SChaoyong He } 127111e9eae4SChaoyong He 127211e9eae4SChaoyong He void 1273d81e2b51SChaoyong He nfp_net_rx_desc_limits(struct nfp_net_hw_priv *hw_priv, 127411e9eae4SChaoyong He uint16_t *min_rx_desc, 127511e9eae4SChaoyong He uint16_t *max_rx_desc) 127611e9eae4SChaoyong He { 1277d81e2b51SChaoyong He *max_rx_desc = hw_priv->dev_info->max_qc_size; 1278d81e2b51SChaoyong He *min_rx_desc = hw_priv->dev_info->min_qc_size; 127911e9eae4SChaoyong He } 128011e9eae4SChaoyong He 128111e9eae4SChaoyong He void 1282000feb4cSChaoyong He nfp_net_tx_desc_limits(struct nfp_net_hw_priv *hw_priv, 128311e9eae4SChaoyong He uint16_t *min_tx_desc, 128411e9eae4SChaoyong He uint16_t *max_tx_desc) 128511e9eae4SChaoyong He { 128611e9eae4SChaoyong He uint16_t tx_dpp; 128711e9eae4SChaoyong He 1288000feb4cSChaoyong He if (hw_priv->pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 128911e9eae4SChaoyong He tx_dpp = NFD3_TX_DESC_PER_PKT; 129011e9eae4SChaoyong He else 129111e9eae4SChaoyong He tx_dpp = NFDK_TX_DESC_PER_SIMPLE_PKT; 129211e9eae4SChaoyong He 1293d81e2b51SChaoyong He *max_tx_desc = hw_priv->dev_info->max_qc_size / tx_dpp; 1294d81e2b51SChaoyong He *min_tx_desc = hw_priv->dev_info->min_qc_size / tx_dpp; 129511e9eae4SChaoyong He } 129611e9eae4SChaoyong He 129711e9eae4SChaoyong He int 129811e9eae4SChaoyong He nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 129911e9eae4SChaoyong He { 13004a9bb682SChaoyong He uint32_t cap; 130111e9eae4SChaoyong He uint32_t cap_extend; 130211e9eae4SChaoyong He uint16_t min_rx_desc; 130311e9eae4SChaoyong He uint16_t max_rx_desc; 130411e9eae4SChaoyong He uint16_t min_tx_desc; 130511e9eae4SChaoyong He uint16_t max_tx_desc; 130611e9eae4SChaoyong He struct nfp_net_hw *hw; 1307ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 130811e9eae4SChaoyong He 1309b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 1310ff9f5a56SChaoyong He hw_priv = dev->process_private; 1311bcdf9151SChaoyong He if (hw_priv == NULL) 1312bcdf9151SChaoyong He return -EINVAL; 131311e9eae4SChaoyong He 1314d81e2b51SChaoyong He nfp_net_rx_desc_limits(hw_priv, &min_rx_desc, &max_rx_desc); 1315000feb4cSChaoyong He nfp_net_tx_desc_limits(hw_priv, &min_tx_desc, &max_tx_desc); 131611e9eae4SChaoyong He 131711e9eae4SChaoyong He dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues; 131811e9eae4SChaoyong He dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues; 131911e9eae4SChaoyong He dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU; 13202f1bfbf4SJames Hershaw /* 13212f1bfbf4SJames Hershaw * The maximum rx packet length is set to the maximum layer 3 MTU, 13222f1bfbf4SJames Hershaw * plus layer 2, CRC and VLAN headers. 132311e9eae4SChaoyong He * The maximum layer 3 MTU (max_mtu) is read from hardware, 132411e9eae4SChaoyong He * which was set by the firmware loaded onto the card. 132511e9eae4SChaoyong He */ 13262f1bfbf4SJames Hershaw dev_info->max_rx_pktlen = hw->max_mtu + NFP_ETH_OVERHEAD; 132711e9eae4SChaoyong He dev_info->max_mtu = hw->max_mtu; 132811e9eae4SChaoyong He dev_info->min_mtu = RTE_ETHER_MIN_MTU; 132911e9eae4SChaoyong He /* Next should change when PF support is implemented */ 133011e9eae4SChaoyong He dev_info->max_mac_addrs = 1; 133111e9eae4SChaoyong He 13324a9bb682SChaoyong He cap = hw->super.cap; 13334a9bb682SChaoyong He 13344a9bb682SChaoyong He if ((cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) != 0) 133511e9eae4SChaoyong He dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 133611e9eae4SChaoyong He 13374a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0) 133811e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP; 133911e9eae4SChaoyong He 13404a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0) 134111e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | 134211e9eae4SChaoyong He RTE_ETH_RX_OFFLOAD_UDP_CKSUM | 134311e9eae4SChaoyong He RTE_ETH_RX_OFFLOAD_TCP_CKSUM; 134411e9eae4SChaoyong He 13454a9bb682SChaoyong He if ((cap & (NFP_NET_CFG_CTRL_TXVLAN | NFP_NET_CFG_CTRL_TXVLAN_V2)) != 0) 134611e9eae4SChaoyong He dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT; 134711e9eae4SChaoyong He 13484a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_TXCSUM) != 0) 134911e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | 135011e9eae4SChaoyong He RTE_ETH_TX_OFFLOAD_UDP_CKSUM | 135111e9eae4SChaoyong He RTE_ETH_TX_OFFLOAD_TCP_CKSUM; 135211e9eae4SChaoyong He 13534a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0) { 135411e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO; 1355df77f704SChaoyong He if ((cap & NFP_NET_CFG_CTRL_USO) != 0) 1356df77f704SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_UDP_TSO; 13574a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_VXLAN) != 0) 135811e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO; 135911e9eae4SChaoyong He } 136011e9eae4SChaoyong He 13614a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_GATHER) != 0) 136211e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 136311e9eae4SChaoyong He 136475a76c73SChaoyong He cap_extend = hw->super.cap_ext; 136511e9eae4SChaoyong He if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) { 136611e9eae4SChaoyong He dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY; 136711e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY; 136811e9eae4SChaoyong He } 136911e9eae4SChaoyong He 137011e9eae4SChaoyong He dev_info->default_rxconf = (struct rte_eth_rxconf) { 137111e9eae4SChaoyong He .rx_thresh = { 137211e9eae4SChaoyong He .pthresh = DEFAULT_RX_PTHRESH, 137311e9eae4SChaoyong He .hthresh = DEFAULT_RX_HTHRESH, 137411e9eae4SChaoyong He .wthresh = DEFAULT_RX_WTHRESH, 137511e9eae4SChaoyong He }, 137611e9eae4SChaoyong He .rx_free_thresh = DEFAULT_RX_FREE_THRESH, 137711e9eae4SChaoyong He .rx_drop_en = 0, 137811e9eae4SChaoyong He }; 137911e9eae4SChaoyong He 138011e9eae4SChaoyong He dev_info->default_txconf = (struct rte_eth_txconf) { 138111e9eae4SChaoyong He .tx_thresh = { 138211e9eae4SChaoyong He .pthresh = DEFAULT_TX_PTHRESH, 138311e9eae4SChaoyong He .hthresh = DEFAULT_TX_HTHRESH, 138411e9eae4SChaoyong He .wthresh = DEFAULT_TX_WTHRESH, 138511e9eae4SChaoyong He }, 138611e9eae4SChaoyong He .tx_free_thresh = DEFAULT_TX_FREE_THRESH, 138711e9eae4SChaoyong He .tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH, 138811e9eae4SChaoyong He }; 138911e9eae4SChaoyong He 139011e9eae4SChaoyong He dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 139111e9eae4SChaoyong He .nb_max = max_rx_desc, 139211e9eae4SChaoyong He .nb_min = min_rx_desc, 139311e9eae4SChaoyong He .nb_align = NFP_ALIGN_RING_DESC, 139411e9eae4SChaoyong He }; 139511e9eae4SChaoyong He 139611e9eae4SChaoyong He dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 139711e9eae4SChaoyong He .nb_max = max_tx_desc, 139811e9eae4SChaoyong He .nb_min = min_tx_desc, 139911e9eae4SChaoyong He .nb_align = NFP_ALIGN_RING_DESC, 140011e9eae4SChaoyong He .nb_seg_max = NFP_TX_MAX_SEG, 140111e9eae4SChaoyong He .nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG, 140211e9eae4SChaoyong He }; 140311e9eae4SChaoyong He 14044a9bb682SChaoyong He if ((cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) { 140511e9eae4SChaoyong He dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 1406b458a2a0SLong Wu dev_info->flow_type_rss_offloads = NFP_NET_RSS_CAP; 140711e9eae4SChaoyong He dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ; 140811e9eae4SChaoyong He dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ; 140911e9eae4SChaoyong He } 141011e9eae4SChaoyong He 14113110ab73SZerun Fu /* Only PF supports getting speed capability. */ 1412c2b4f0d5SChaoyong He if (hw_priv->is_pf) 1413ff9f5a56SChaoyong He dev_info->speed_capa = hw_priv->pf_dev->speed_capa; 141411e9eae4SChaoyong He 141511e9eae4SChaoyong He return 0; 141611e9eae4SChaoyong He } 141711e9eae4SChaoyong He 141811e9eae4SChaoyong He int 1419000feb4cSChaoyong He nfp_net_common_init(struct nfp_pf_dev *pf_dev, 142011e9eae4SChaoyong He struct nfp_net_hw *hw) 142111e9eae4SChaoyong He { 142211e9eae4SChaoyong He const int stride = 4; 1423000feb4cSChaoyong He struct rte_pci_device *pci_dev; 142411e9eae4SChaoyong He 1425000feb4cSChaoyong He pci_dev = pf_dev->pci_dev; 142611e9eae4SChaoyong He hw->device_id = pci_dev->id.device_id; 142711e9eae4SChaoyong He hw->vendor_id = pci_dev->id.vendor_id; 142811e9eae4SChaoyong He hw->subsystem_device_id = pci_dev->id.subsystem_device_id; 142911e9eae4SChaoyong He hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; 143011e9eae4SChaoyong He 1431f58bde00SChaoyong He hw->max_rx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_RXRINGS); 1432f58bde00SChaoyong He hw->max_tx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_TXRINGS); 143311e9eae4SChaoyong He if (hw->max_rx_queues == 0 || hw->max_tx_queues == 0) { 143411e9eae4SChaoyong He PMD_INIT_LOG(ERR, "Device %s can not be used, there are no valid queue " 1435b6de4353SZerun Fu "pairs for use.", pci_dev->name); 143611e9eae4SChaoyong He return -ENODEV; 143711e9eae4SChaoyong He } 143811e9eae4SChaoyong He 1439000feb4cSChaoyong He if (nfp_net_check_dma_mask(pf_dev, pci_dev->name) != 0) 144011e9eae4SChaoyong He return -ENODEV; 144111e9eae4SChaoyong He 144211e9eae4SChaoyong He /* Get some of the read-only fields from the config BAR */ 1443f58bde00SChaoyong He hw->super.cap = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP); 1444f58bde00SChaoyong He hw->super.cap_ext = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP_WORD1); 1445f58bde00SChaoyong He hw->max_mtu = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_MTU); 144611e9eae4SChaoyong He hw->flbufsz = DEFAULT_FLBUF_SIZE; 144711e9eae4SChaoyong He 1448000feb4cSChaoyong He nfp_net_meta_init_format(hw, pf_dev); 144911e9eae4SChaoyong He 145011e9eae4SChaoyong He /* Read the Rx offset configured from firmware */ 1451000feb4cSChaoyong He if (pf_dev->ver.major < 2) 145211e9eae4SChaoyong He hw->rx_offset = NFP_NET_RX_OFFSET; 145311e9eae4SChaoyong He else 145465f6915dSChaoyong He hw->rx_offset = nn_cfg_readl(&hw->super, NFP_NET_CFG_RX_OFFSET); 145511e9eae4SChaoyong He 1456b4b6988aSChaoyong He hw->super.ctrl = 0; 145711e9eae4SChaoyong He hw->stride_rx = stride; 145811e9eae4SChaoyong He hw->stride_tx = stride; 145911e9eae4SChaoyong He 146011e9eae4SChaoyong He return 0; 146111e9eae4SChaoyong He } 146211e9eae4SChaoyong He 146311e9eae4SChaoyong He const uint32_t * 1464ba6a168aSSivaramakrishnan Venkat nfp_net_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) 146511e9eae4SChaoyong He { 146611e9eae4SChaoyong He struct nfp_net_hw *net_hw; 146711e9eae4SChaoyong He static const uint32_t ptypes[] = { 146811e9eae4SChaoyong He RTE_PTYPE_L2_ETHER, 146911e9eae4SChaoyong He RTE_PTYPE_L3_IPV4, 147011e9eae4SChaoyong He RTE_PTYPE_L3_IPV4_EXT, 147111e9eae4SChaoyong He RTE_PTYPE_L3_IPV6, 147211e9eae4SChaoyong He RTE_PTYPE_L3_IPV6_EXT, 147311e9eae4SChaoyong He RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 147411e9eae4SChaoyong He RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 147511e9eae4SChaoyong He RTE_PTYPE_L4_TCP, 147611e9eae4SChaoyong He RTE_PTYPE_L4_UDP, 147711e9eae4SChaoyong He RTE_PTYPE_L4_FRAG, 147811e9eae4SChaoyong He RTE_PTYPE_L4_NONFRAG, 147911e9eae4SChaoyong He RTE_PTYPE_L4_ICMP, 148011e9eae4SChaoyong He RTE_PTYPE_L4_SCTP, 148111e9eae4SChaoyong He RTE_PTYPE_TUNNEL_VXLAN, 148211e9eae4SChaoyong He RTE_PTYPE_TUNNEL_NVGRE, 148311e9eae4SChaoyong He RTE_PTYPE_TUNNEL_GENEVE, 148411e9eae4SChaoyong He RTE_PTYPE_INNER_L2_ETHER, 148511e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4, 148611e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4_EXT, 148711e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6, 148811e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6_EXT, 148911e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 149011e9eae4SChaoyong He RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 149111e9eae4SChaoyong He RTE_PTYPE_INNER_L4_TCP, 149211e9eae4SChaoyong He RTE_PTYPE_INNER_L4_UDP, 149311e9eae4SChaoyong He RTE_PTYPE_INNER_L4_FRAG, 149411e9eae4SChaoyong He RTE_PTYPE_INNER_L4_NONFRAG, 149511e9eae4SChaoyong He RTE_PTYPE_INNER_L4_ICMP, 149611e9eae4SChaoyong He RTE_PTYPE_INNER_L4_SCTP, 149711e9eae4SChaoyong He }; 149811e9eae4SChaoyong He 149962edcfd6SLong Wu if (dev->rx_pkt_burst == NULL) 150011e9eae4SChaoyong He return NULL; 150111e9eae4SChaoyong He 15029d723baaSChaoyong He net_hw = dev->data->dev_private; 1503a498019dSLong Wu if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0) 150411e9eae4SChaoyong He return NULL; 150511e9eae4SChaoyong He 1506ba6a168aSSivaramakrishnan Venkat *no_of_elements = RTE_DIM(ptypes); 150711e9eae4SChaoyong He return ptypes; 150811e9eae4SChaoyong He } 150911e9eae4SChaoyong He 151011e9eae4SChaoyong He int 1511a498019dSLong Wu nfp_net_ptypes_set(struct rte_eth_dev *dev, 1512a498019dSLong Wu uint32_t ptype_mask) 1513a498019dSLong Wu { 1514a498019dSLong Wu int ret; 1515a498019dSLong Wu uint32_t update; 1516a498019dSLong Wu uint32_t ctrl_ext; 1517a498019dSLong Wu struct nfp_hw *hw; 1518a498019dSLong Wu struct nfp_net_hw *net_hw; 1519a498019dSLong Wu 1520a498019dSLong Wu net_hw = dev->data->dev_private; 1521a498019dSLong Wu hw = &net_hw->super; 1522a498019dSLong Wu 1523a498019dSLong Wu if ((hw->cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0) 1524a498019dSLong Wu return -ENOTSUP; 1525a498019dSLong Wu 1526a498019dSLong Wu ctrl_ext = hw->ctrl_ext; 1527a498019dSLong Wu if (ptype_mask == 0) { 1528a498019dSLong Wu if ((ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0) 1529a498019dSLong Wu return 0; 1530a498019dSLong Wu 1531a498019dSLong Wu ctrl_ext &= ~NFP_NET_CFG_CTRL_PKT_TYPE; 1532a498019dSLong Wu } else { 1533a498019dSLong Wu if ((ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) != 0) 1534a498019dSLong Wu return 0; 1535a498019dSLong Wu 1536a498019dSLong Wu ctrl_ext |= NFP_NET_CFG_CTRL_PKT_TYPE; 1537a498019dSLong Wu } 1538a498019dSLong Wu 1539a498019dSLong Wu update = NFP_NET_CFG_UPDATE_GEN; 1540a498019dSLong Wu 1541a498019dSLong Wu ret = nfp_ext_reconfig(hw, ctrl_ext, update); 1542a498019dSLong Wu if (ret != 0) 1543a498019dSLong Wu return ret; 1544a498019dSLong Wu 1545a498019dSLong Wu hw->ctrl_ext = ctrl_ext; 1546a498019dSLong Wu 1547a498019dSLong Wu return 0; 1548a498019dSLong Wu } 1549a498019dSLong Wu 1550a498019dSLong Wu int 155111e9eae4SChaoyong He nfp_rx_queue_intr_enable(struct rte_eth_dev *dev, 155211e9eae4SChaoyong He uint16_t queue_id) 155311e9eae4SChaoyong He { 155411e9eae4SChaoyong He uint16_t base = 0; 155511e9eae4SChaoyong He struct nfp_net_hw *hw; 155611e9eae4SChaoyong He struct rte_pci_device *pci_dev; 155711e9eae4SChaoyong He 155811e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 155911e9eae4SChaoyong He if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO) 156011e9eae4SChaoyong He base = 1; 156111e9eae4SChaoyong He 156211e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 156311e9eae4SChaoyong He rte_wmb(); 156411e9eae4SChaoyong He 1565b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 1566f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), 156711e9eae4SChaoyong He NFP_NET_CFG_ICR_UNMASKED); 156811e9eae4SChaoyong He return 0; 156911e9eae4SChaoyong He } 157011e9eae4SChaoyong He 157111e9eae4SChaoyong He int 157211e9eae4SChaoyong He nfp_rx_queue_intr_disable(struct rte_eth_dev *dev, 157311e9eae4SChaoyong He uint16_t queue_id) 157411e9eae4SChaoyong He { 157511e9eae4SChaoyong He uint16_t base = 0; 157611e9eae4SChaoyong He struct nfp_net_hw *hw; 157711e9eae4SChaoyong He struct rte_pci_device *pci_dev; 157811e9eae4SChaoyong He 157911e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 158011e9eae4SChaoyong He if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO) 158111e9eae4SChaoyong He base = 1; 158211e9eae4SChaoyong He 158311e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 158411e9eae4SChaoyong He rte_wmb(); 158511e9eae4SChaoyong He 1586b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 1587f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), NFP_NET_CFG_ICR_RXTX); 158811e9eae4SChaoyong He 158911e9eae4SChaoyong He return 0; 159011e9eae4SChaoyong He } 159111e9eae4SChaoyong He 159211e9eae4SChaoyong He static void 159311e9eae4SChaoyong He nfp_net_dev_link_status_print(struct rte_eth_dev *dev) 159411e9eae4SChaoyong He { 159511e9eae4SChaoyong He struct rte_eth_link link; 159611e9eae4SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 159711e9eae4SChaoyong He 159811e9eae4SChaoyong He rte_eth_linkstatus_get(dev, &link); 159911e9eae4SChaoyong He if (link.link_status != 0) 1600b6de4353SZerun Fu PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s.", 160111e9eae4SChaoyong He dev->data->port_id, link.link_speed, 160211e9eae4SChaoyong He link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX ? 160311e9eae4SChaoyong He "full-duplex" : "half-duplex"); 160411e9eae4SChaoyong He else 1605b6de4353SZerun Fu PMD_DRV_LOG(INFO, " Port %d: Link Down.", dev->data->port_id); 160611e9eae4SChaoyong He 160711e9eae4SChaoyong He PMD_DRV_LOG(INFO, "PCI Address: " PCI_PRI_FMT, 160811e9eae4SChaoyong He pci_dev->addr.domain, pci_dev->addr.bus, 160911e9eae4SChaoyong He pci_dev->addr.devid, pci_dev->addr.function); 161011e9eae4SChaoyong He } 161111e9eae4SChaoyong He 161211e9eae4SChaoyong He /* 161311e9eae4SChaoyong He * Unmask an interrupt 161411e9eae4SChaoyong He * 161511e9eae4SChaoyong He * If MSI-X auto-masking is enabled clear the mask bit, otherwise 161611e9eae4SChaoyong He * clear the ICR for the entry. 161711e9eae4SChaoyong He */ 161894d0631aSPeng Zhang void 161911e9eae4SChaoyong He nfp_net_irq_unmask(struct rte_eth_dev *dev) 162011e9eae4SChaoyong He { 162111e9eae4SChaoyong He struct nfp_net_hw *hw; 162211e9eae4SChaoyong He struct rte_pci_device *pci_dev; 162311e9eae4SChaoyong He 1624b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 162511e9eae4SChaoyong He pci_dev = RTE_ETH_DEV_TO_PCI(dev); 162611e9eae4SChaoyong He 162711e9eae4SChaoyong He /* Make sure all updates are written before un-masking */ 162811e9eae4SChaoyong He rte_wmb(); 162911e9eae4SChaoyong He 1630b4b6988aSChaoyong He if ((hw->super.ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) != 0) { 163111e9eae4SChaoyong He /* If MSI-X auto-masking is used, clear the entry */ 163211e9eae4SChaoyong He rte_intr_ack(pci_dev->intr_handle); 163311e9eae4SChaoyong He } else { 1634f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(NFP_NET_IRQ_LSC_IDX), 163511e9eae4SChaoyong He NFP_NET_CFG_ICR_UNMASKED); 163611e9eae4SChaoyong He } 163711e9eae4SChaoyong He } 163811e9eae4SChaoyong He 163911e9eae4SChaoyong He /** 164011e9eae4SChaoyong He * Interrupt handler which shall be registered for alarm callback for delayed 164111e9eae4SChaoyong He * handling specific interrupt to wait for the stable nic state. As the NIC 164211e9eae4SChaoyong He * interrupt state is not stable for nfp after link is just down, it needs 164311e9eae4SChaoyong He * to wait 4 seconds to get the stable status. 164411e9eae4SChaoyong He * 164511e9eae4SChaoyong He * @param param 164611e9eae4SChaoyong He * The address of parameter (struct rte_eth_dev *) 164711e9eae4SChaoyong He */ 164811e9eae4SChaoyong He void 164911e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler(void *param) 165011e9eae4SChaoyong He { 165111e9eae4SChaoyong He struct rte_eth_dev *dev = param; 165211e9eae4SChaoyong He 165311e9eae4SChaoyong He nfp_net_link_update(dev, 0); 165411e9eae4SChaoyong He rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 165511e9eae4SChaoyong He 165611e9eae4SChaoyong He nfp_net_dev_link_status_print(dev); 165711e9eae4SChaoyong He 165811e9eae4SChaoyong He /* Unmasking */ 165911e9eae4SChaoyong He nfp_net_irq_unmask(dev); 166011e9eae4SChaoyong He } 166111e9eae4SChaoyong He 166211e9eae4SChaoyong He void 166311e9eae4SChaoyong He nfp_net_dev_interrupt_handler(void *param) 166411e9eae4SChaoyong He { 166511e9eae4SChaoyong He int64_t timeout; 166611e9eae4SChaoyong He struct rte_eth_link link; 166711e9eae4SChaoyong He struct rte_eth_dev *dev = param; 166811e9eae4SChaoyong He 166911e9eae4SChaoyong He PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!"); 167011e9eae4SChaoyong He 167111e9eae4SChaoyong He rte_eth_linkstatus_get(dev, &link); 167211e9eae4SChaoyong He 167311e9eae4SChaoyong He nfp_net_link_update(dev, 0); 167411e9eae4SChaoyong He 167511e9eae4SChaoyong He /* Likely to up */ 167611e9eae4SChaoyong He if (link.link_status == 0) { 167711e9eae4SChaoyong He /* Handle it 1 sec later, wait it being stable */ 167811e9eae4SChaoyong He timeout = NFP_NET_LINK_UP_CHECK_TIMEOUT; 167911e9eae4SChaoyong He } else { /* Likely to down */ 168011e9eae4SChaoyong He /* Handle it 4 sec later, wait it being stable */ 168111e9eae4SChaoyong He timeout = NFP_NET_LINK_DOWN_CHECK_TIMEOUT; 168211e9eae4SChaoyong He } 168311e9eae4SChaoyong He 168411e9eae4SChaoyong He if (rte_eal_alarm_set(timeout * 1000, 168511e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler, 168611e9eae4SChaoyong He (void *)dev) != 0) { 1687b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Error setting alarm."); 168811e9eae4SChaoyong He /* Unmasking */ 168911e9eae4SChaoyong He nfp_net_irq_unmask(dev); 169011e9eae4SChaoyong He } 169111e9eae4SChaoyong He } 169211e9eae4SChaoyong He 169311e9eae4SChaoyong He int 169411e9eae4SChaoyong He nfp_net_dev_mtu_set(struct rte_eth_dev *dev, 169511e9eae4SChaoyong He uint16_t mtu) 169611e9eae4SChaoyong He { 169711e9eae4SChaoyong He struct nfp_net_hw *hw; 169811e9eae4SChaoyong He 1699b12d2b2eSChaoyong He hw = nfp_net_get_hw(dev); 170011e9eae4SChaoyong He 170111e9eae4SChaoyong He /* MTU setting is forbidden if port is started */ 170211e9eae4SChaoyong He if (dev->data->dev_started) { 1703b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Port %d must be stopped before configuration.", 170411e9eae4SChaoyong He dev->data->port_id); 170511e9eae4SChaoyong He return -EBUSY; 170611e9eae4SChaoyong He } 170711e9eae4SChaoyong He 170811e9eae4SChaoyong He /* MTU larger than current mbufsize not supported */ 170911e9eae4SChaoyong He if (mtu > hw->flbufsz) { 1710b6de4353SZerun Fu PMD_DRV_LOG(ERR, "MTU (%u) larger than current mbufsize (%u) not supported.", 171111e9eae4SChaoyong He mtu, hw->flbufsz); 171211e9eae4SChaoyong He return -ERANGE; 171311e9eae4SChaoyong He } 171411e9eae4SChaoyong He 171511e9eae4SChaoyong He /* Writing to configuration space */ 1716f58bde00SChaoyong He nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, mtu); 171711e9eae4SChaoyong He 171811e9eae4SChaoyong He hw->mtu = mtu; 171911e9eae4SChaoyong He 172011e9eae4SChaoyong He return 0; 172111e9eae4SChaoyong He } 172211e9eae4SChaoyong He 172311e9eae4SChaoyong He int 172411e9eae4SChaoyong He nfp_net_vlan_offload_set(struct rte_eth_dev *dev, 172511e9eae4SChaoyong He int mask) 172611e9eae4SChaoyong He { 172711e9eae4SChaoyong He int ret; 172811e9eae4SChaoyong He uint32_t update; 172911e9eae4SChaoyong He uint32_t new_ctrl; 173072d1dea6SChaoyong He struct nfp_hw *hw; 173111e9eae4SChaoyong He uint64_t rx_offload; 173272d1dea6SChaoyong He struct nfp_net_hw *net_hw; 173311e9eae4SChaoyong He uint32_t rxvlan_ctrl = 0; 173411e9eae4SChaoyong He 1735b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 173672d1dea6SChaoyong He hw = &net_hw->super; 173711e9eae4SChaoyong He rx_offload = dev->data->dev_conf.rxmode.offloads; 173872d1dea6SChaoyong He new_ctrl = hw->ctrl; 173911e9eae4SChaoyong He 174011e9eae4SChaoyong He /* VLAN stripping setting */ 174111e9eae4SChaoyong He if ((mask & RTE_ETH_VLAN_STRIP_MASK) != 0) { 174272d1dea6SChaoyong He nfp_net_enable_rxvlan_cap(net_hw, &rxvlan_ctrl); 174311e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0) 174411e9eae4SChaoyong He new_ctrl |= rxvlan_ctrl; 174511e9eae4SChaoyong He else 174611e9eae4SChaoyong He new_ctrl &= ~rxvlan_ctrl; 174711e9eae4SChaoyong He } 174811e9eae4SChaoyong He 174911e9eae4SChaoyong He /* QinQ stripping setting */ 175011e9eae4SChaoyong He if ((mask & RTE_ETH_QINQ_STRIP_MASK) != 0) { 175111e9eae4SChaoyong He if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) 175211e9eae4SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ; 175311e9eae4SChaoyong He else 175411e9eae4SChaoyong He new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ; 175511e9eae4SChaoyong He } 175611e9eae4SChaoyong He 175772d1dea6SChaoyong He if (new_ctrl == hw->ctrl) 175811e9eae4SChaoyong He return 0; 175911e9eae4SChaoyong He 176011e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_GEN; 176111e9eae4SChaoyong He 176272d1dea6SChaoyong He ret = nfp_reconfig(hw, new_ctrl, update); 176311e9eae4SChaoyong He if (ret != 0) 176411e9eae4SChaoyong He return ret; 176511e9eae4SChaoyong He 176672d1dea6SChaoyong He hw->ctrl = new_ctrl; 176711e9eae4SChaoyong He 176811e9eae4SChaoyong He return 0; 176911e9eae4SChaoyong He } 177011e9eae4SChaoyong He 177111e9eae4SChaoyong He static int 177211e9eae4SChaoyong He nfp_net_rss_reta_write(struct rte_eth_dev *dev, 177311e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 177411e9eae4SChaoyong He uint16_t reta_size) 177511e9eae4SChaoyong He { 177611e9eae4SChaoyong He uint16_t i; 177711e9eae4SChaoyong He uint16_t j; 177811e9eae4SChaoyong He uint16_t idx; 177911e9eae4SChaoyong He uint8_t mask; 178011e9eae4SChaoyong He uint32_t reta; 178111e9eae4SChaoyong He uint16_t shift; 17824a9bb682SChaoyong He struct nfp_hw *hw; 17834a9bb682SChaoyong He struct nfp_net_hw *net_hw; 178411e9eae4SChaoyong He 1785b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 17864a9bb682SChaoyong He hw = &net_hw->super; 178711e9eae4SChaoyong He 178811e9eae4SChaoyong He if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) { 178911e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%hu)" 1790b6de4353SZerun Fu " does not match hardware can supported (%d).", 179111e9eae4SChaoyong He reta_size, NFP_NET_CFG_RSS_ITBL_SZ); 179211e9eae4SChaoyong He return -EINVAL; 179311e9eae4SChaoyong He } 179411e9eae4SChaoyong He 179511e9eae4SChaoyong He /* 179611e9eae4SChaoyong He * Update Redirection Table. There are 128 8bit-entries which can be 179711e9eae4SChaoyong He * manage as 32 32bit-entries. 179811e9eae4SChaoyong He */ 179911e9eae4SChaoyong He for (i = 0; i < reta_size; i += 4) { 180011e9eae4SChaoyong He /* Handling 4 RSS entries per loop */ 180111e9eae4SChaoyong He idx = i / RTE_ETH_RETA_GROUP_SIZE; 180211e9eae4SChaoyong He shift = i % RTE_ETH_RETA_GROUP_SIZE; 180311e9eae4SChaoyong He mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF); 180411e9eae4SChaoyong He if (mask == 0) 180511e9eae4SChaoyong He continue; 180611e9eae4SChaoyong He 180711e9eae4SChaoyong He reta = 0; 180811e9eae4SChaoyong He 180911e9eae4SChaoyong He /* If all 4 entries were set, don't need read RETA register */ 181011e9eae4SChaoyong He if (mask != 0xF) 18114a9bb682SChaoyong He reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + i); 181211e9eae4SChaoyong He 181311e9eae4SChaoyong He for (j = 0; j < 4; j++) { 181411e9eae4SChaoyong He if ((mask & (0x1 << j)) == 0) 181511e9eae4SChaoyong He continue; 181611e9eae4SChaoyong He 181711e9eae4SChaoyong He /* Clearing the entry bits */ 181811e9eae4SChaoyong He if (mask != 0xF) 181911e9eae4SChaoyong He reta &= ~(0xFF << (8 * j)); 182011e9eae4SChaoyong He 182111e9eae4SChaoyong He reta |= reta_conf[idx].reta[shift + j] << (8 * j); 182211e9eae4SChaoyong He } 182311e9eae4SChaoyong He 18244a9bb682SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift, reta); 182511e9eae4SChaoyong He } 182611e9eae4SChaoyong He 182711e9eae4SChaoyong He return 0; 182811e9eae4SChaoyong He } 182911e9eae4SChaoyong He 183011e9eae4SChaoyong He /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */ 183111e9eae4SChaoyong He int 183211e9eae4SChaoyong He nfp_net_reta_update(struct rte_eth_dev *dev, 183311e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 183411e9eae4SChaoyong He uint16_t reta_size) 183511e9eae4SChaoyong He { 183611e9eae4SChaoyong He int ret; 183711e9eae4SChaoyong He uint32_t update; 183872d1dea6SChaoyong He struct nfp_hw *hw; 183972d1dea6SChaoyong He struct nfp_net_hw *net_hw; 184011e9eae4SChaoyong He 1841b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 184272d1dea6SChaoyong He hw = &net_hw->super; 184372d1dea6SChaoyong He 184472d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 184511e9eae4SChaoyong He return -EINVAL; 184611e9eae4SChaoyong He 184711e9eae4SChaoyong He ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size); 184811e9eae4SChaoyong He if (ret != 0) 184911e9eae4SChaoyong He return ret; 185011e9eae4SChaoyong He 185111e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_RSS; 185211e9eae4SChaoyong He 185372d1dea6SChaoyong He if (nfp_reconfig(hw, hw->ctrl, update) != 0) 185411e9eae4SChaoyong He return -EIO; 185511e9eae4SChaoyong He 185611e9eae4SChaoyong He return 0; 185711e9eae4SChaoyong He } 185811e9eae4SChaoyong He 185911e9eae4SChaoyong He /* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */ 186011e9eae4SChaoyong He int 186111e9eae4SChaoyong He nfp_net_reta_query(struct rte_eth_dev *dev, 186211e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 *reta_conf, 186311e9eae4SChaoyong He uint16_t reta_size) 186411e9eae4SChaoyong He { 186511e9eae4SChaoyong He uint16_t i; 186611e9eae4SChaoyong He uint16_t j; 186711e9eae4SChaoyong He uint16_t idx; 186811e9eae4SChaoyong He uint8_t mask; 186911e9eae4SChaoyong He uint32_t reta; 187011e9eae4SChaoyong He uint16_t shift; 18714a9bb682SChaoyong He struct nfp_hw *hw; 18724a9bb682SChaoyong He struct nfp_net_hw *net_hw; 187311e9eae4SChaoyong He 1874b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 18754a9bb682SChaoyong He hw = &net_hw->super; 18764a9bb682SChaoyong He 18774a9bb682SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 187811e9eae4SChaoyong He return -EINVAL; 187911e9eae4SChaoyong He 188011e9eae4SChaoyong He if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) { 188111e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d)" 1882b6de4353SZerun Fu " does not match hardware can supported (%d).", 188311e9eae4SChaoyong He reta_size, NFP_NET_CFG_RSS_ITBL_SZ); 188411e9eae4SChaoyong He return -EINVAL; 188511e9eae4SChaoyong He } 188611e9eae4SChaoyong He 188711e9eae4SChaoyong He /* 188811e9eae4SChaoyong He * Reading Redirection Table. There are 128 8bit-entries which can be 188911e9eae4SChaoyong He * manage as 32 32bit-entries. 189011e9eae4SChaoyong He */ 189111e9eae4SChaoyong He for (i = 0; i < reta_size; i += 4) { 189211e9eae4SChaoyong He /* Handling 4 RSS entries per loop */ 189311e9eae4SChaoyong He idx = i / RTE_ETH_RETA_GROUP_SIZE; 189411e9eae4SChaoyong He shift = i % RTE_ETH_RETA_GROUP_SIZE; 189511e9eae4SChaoyong He mask = (reta_conf[idx].mask >> shift) & 0xF; 189611e9eae4SChaoyong He 189711e9eae4SChaoyong He if (mask == 0) 189811e9eae4SChaoyong He continue; 189911e9eae4SChaoyong He 19004a9bb682SChaoyong He reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift); 190111e9eae4SChaoyong He for (j = 0; j < 4; j++) { 190211e9eae4SChaoyong He if ((mask & (0x1 << j)) == 0) 190311e9eae4SChaoyong He continue; 190411e9eae4SChaoyong He 190511e9eae4SChaoyong He reta_conf[idx].reta[shift + j] = 190611e9eae4SChaoyong He (uint8_t)((reta >> (8 * j)) & 0xF); 190711e9eae4SChaoyong He } 190811e9eae4SChaoyong He } 190911e9eae4SChaoyong He 191011e9eae4SChaoyong He return 0; 191111e9eae4SChaoyong He } 191211e9eae4SChaoyong He 191311e9eae4SChaoyong He static int 191411e9eae4SChaoyong He nfp_net_rss_hash_write(struct rte_eth_dev *dev, 191511e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 191611e9eae4SChaoyong He { 191711e9eae4SChaoyong He uint8_t i; 191811e9eae4SChaoyong He uint8_t key; 191911e9eae4SChaoyong He uint64_t rss_hf; 19204a9bb682SChaoyong He struct nfp_hw *hw; 19214a9bb682SChaoyong He struct nfp_net_hw *net_hw; 192211e9eae4SChaoyong He uint32_t cfg_rss_ctrl = 0; 192311e9eae4SChaoyong He 1924b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 19254a9bb682SChaoyong He hw = &net_hw->super; 192611e9eae4SChaoyong He 192711e9eae4SChaoyong He /* Writing the key byte by byte */ 192811e9eae4SChaoyong He for (i = 0; i < rss_conf->rss_key_len; i++) { 192911e9eae4SChaoyong He memcpy(&key, &rss_conf->rss_key[i], 1); 19304a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY + i, key); 193111e9eae4SChaoyong He } 193211e9eae4SChaoyong He 193311e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 193411e9eae4SChaoyong He 193511e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_IPV4) != 0) 193611e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4; 193711e9eae4SChaoyong He 193811e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0) 193911e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_TCP; 194011e9eae4SChaoyong He 194111e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0) 194211e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_UDP; 194311e9eae4SChaoyong He 194411e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) != 0) 194511e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_SCTP; 194611e9eae4SChaoyong He 194711e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_IPV6) != 0) 194811e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6; 194911e9eae4SChaoyong He 195011e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0) 195111e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_TCP; 195211e9eae4SChaoyong He 195311e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0) 195411e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_UDP; 195511e9eae4SChaoyong He 195611e9eae4SChaoyong He if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) != 0) 195711e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_SCTP; 195811e9eae4SChaoyong He 195911e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_MASK; 1960b458a2a0SLong Wu 1961b458a2a0SLong Wu if (rte_eth_dev_is_repr(dev)) 1962b458a2a0SLong Wu cfg_rss_ctrl |= NFP_NET_CFG_RSS_CRC32; 1963b458a2a0SLong Wu else 196411e9eae4SChaoyong He cfg_rss_ctrl |= NFP_NET_CFG_RSS_TOEPLITZ; 196511e9eae4SChaoyong He 196611e9eae4SChaoyong He /* Configuring where to apply the RSS hash */ 19674a9bb682SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl); 196811e9eae4SChaoyong He 196911e9eae4SChaoyong He /* Writing the key size */ 19704a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len); 197111e9eae4SChaoyong He 197211e9eae4SChaoyong He return 0; 197311e9eae4SChaoyong He } 197411e9eae4SChaoyong He 197511e9eae4SChaoyong He int 197611e9eae4SChaoyong He nfp_net_rss_hash_update(struct rte_eth_dev *dev, 197711e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 197811e9eae4SChaoyong He { 197911e9eae4SChaoyong He uint32_t update; 198011e9eae4SChaoyong He uint64_t rss_hf; 198172d1dea6SChaoyong He struct nfp_hw *hw; 198272d1dea6SChaoyong He struct nfp_net_hw *net_hw; 198311e9eae4SChaoyong He 1984b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 198572d1dea6SChaoyong He hw = &net_hw->super; 198611e9eae4SChaoyong He 198711e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 198811e9eae4SChaoyong He 198911e9eae4SChaoyong He /* Checking if RSS is enabled */ 199072d1dea6SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) { 199111e9eae4SChaoyong He if (rss_hf != 0) { 1992b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RSS unsupported."); 199311e9eae4SChaoyong He return -EINVAL; 199411e9eae4SChaoyong He } 199511e9eae4SChaoyong He 199611e9eae4SChaoyong He return 0; /* Nothing to do */ 199711e9eae4SChaoyong He } 199811e9eae4SChaoyong He 199911e9eae4SChaoyong He if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) { 2000b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RSS hash key too long."); 200111e9eae4SChaoyong He return -EINVAL; 200211e9eae4SChaoyong He } 200311e9eae4SChaoyong He 200411e9eae4SChaoyong He nfp_net_rss_hash_write(dev, rss_conf); 200511e9eae4SChaoyong He 200611e9eae4SChaoyong He update = NFP_NET_CFG_UPDATE_RSS; 200711e9eae4SChaoyong He 200872d1dea6SChaoyong He if (nfp_reconfig(hw, hw->ctrl, update) != 0) 200911e9eae4SChaoyong He return -EIO; 201011e9eae4SChaoyong He 201111e9eae4SChaoyong He return 0; 201211e9eae4SChaoyong He } 201311e9eae4SChaoyong He 201411e9eae4SChaoyong He int 201511e9eae4SChaoyong He nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev, 201611e9eae4SChaoyong He struct rte_eth_rss_conf *rss_conf) 201711e9eae4SChaoyong He { 201811e9eae4SChaoyong He uint8_t i; 201911e9eae4SChaoyong He uint8_t key; 202011e9eae4SChaoyong He uint64_t rss_hf; 20214a9bb682SChaoyong He struct nfp_hw *hw; 202211e9eae4SChaoyong He uint32_t cfg_rss_ctrl; 20234a9bb682SChaoyong He struct nfp_net_hw *net_hw; 202411e9eae4SChaoyong He 2025b12d2b2eSChaoyong He net_hw = nfp_net_get_hw(dev); 20264a9bb682SChaoyong He hw = &net_hw->super; 202711e9eae4SChaoyong He 20284a9bb682SChaoyong He if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 202911e9eae4SChaoyong He return -EINVAL; 203011e9eae4SChaoyong He 203111e9eae4SChaoyong He rss_hf = rss_conf->rss_hf; 20324a9bb682SChaoyong He cfg_rss_ctrl = nn_cfg_readl(hw, NFP_NET_CFG_RSS_CTRL); 203311e9eae4SChaoyong He 203411e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4) != 0) 203511e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_IPV4; 203611e9eae4SChaoyong He 203711e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP) != 0) 203811e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP; 203911e9eae4SChaoyong He 204011e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP) != 0) 204111e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP; 204211e9eae4SChaoyong He 204311e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP) != 0) 204411e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP; 204511e9eae4SChaoyong He 204611e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP) != 0) 204711e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP; 204811e9eae4SChaoyong He 204911e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6) != 0) 205011e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_IPV6; 205111e9eae4SChaoyong He 205211e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_SCTP) != 0) 205311e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_SCTP; 205411e9eae4SChaoyong He 205511e9eae4SChaoyong He if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_SCTP) != 0) 205611e9eae4SChaoyong He rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_SCTP; 205711e9eae4SChaoyong He 205811e9eae4SChaoyong He /* Propagate current RSS hash functions to caller */ 205911e9eae4SChaoyong He rss_conf->rss_hf = rss_hf; 206011e9eae4SChaoyong He 206111e9eae4SChaoyong He /* Reading the key size */ 20624a9bb682SChaoyong He rss_conf->rss_key_len = nn_cfg_readl(hw, NFP_NET_CFG_RSS_KEY_SZ); 206311e9eae4SChaoyong He 206411e9eae4SChaoyong He /* Reading the key byte a byte */ 206511e9eae4SChaoyong He for (i = 0; i < rss_conf->rss_key_len; i++) { 20664a9bb682SChaoyong He key = nn_cfg_readb(hw, NFP_NET_CFG_RSS_KEY + i); 206711e9eae4SChaoyong He memcpy(&rss_conf->rss_key[i], &key, 1); 206811e9eae4SChaoyong He } 206911e9eae4SChaoyong He 207011e9eae4SChaoyong He return 0; 207111e9eae4SChaoyong He } 207211e9eae4SChaoyong He 207311e9eae4SChaoyong He int 207411e9eae4SChaoyong He nfp_net_rss_config_default(struct rte_eth_dev *dev) 207511e9eae4SChaoyong He { 207611e9eae4SChaoyong He int ret; 207711e9eae4SChaoyong He uint8_t i; 207811e9eae4SChaoyong He uint8_t j; 207911e9eae4SChaoyong He uint16_t queue = 0; 208011e9eae4SChaoyong He struct rte_eth_conf *dev_conf; 208111e9eae4SChaoyong He struct rte_eth_rss_conf rss_conf; 208211e9eae4SChaoyong He uint16_t rx_queues = dev->data->nb_rx_queues; 208311e9eae4SChaoyong He struct rte_eth_rss_reta_entry64 nfp_reta_conf[2]; 208411e9eae4SChaoyong He 208511e9eae4SChaoyong He nfp_reta_conf[0].mask = ~0x0; 208611e9eae4SChaoyong He nfp_reta_conf[1].mask = ~0x0; 208711e9eae4SChaoyong He 208811e9eae4SChaoyong He for (i = 0; i < 0x40; i += 8) { 208911e9eae4SChaoyong He for (j = i; j < (i + 8); j++) { 209011e9eae4SChaoyong He nfp_reta_conf[0].reta[j] = queue; 209111e9eae4SChaoyong He nfp_reta_conf[1].reta[j] = queue++; 209211e9eae4SChaoyong He queue %= rx_queues; 209311e9eae4SChaoyong He } 209411e9eae4SChaoyong He } 209511e9eae4SChaoyong He 209611e9eae4SChaoyong He ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80); 209711e9eae4SChaoyong He if (ret != 0) 209811e9eae4SChaoyong He return ret; 209911e9eae4SChaoyong He 210011e9eae4SChaoyong He dev_conf = &dev->data->dev_conf; 210111e9eae4SChaoyong He if (dev_conf == NULL) { 2102b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Wrong rss conf."); 210311e9eae4SChaoyong He return -EINVAL; 210411e9eae4SChaoyong He } 210511e9eae4SChaoyong He 210611e9eae4SChaoyong He rss_conf = dev_conf->rx_adv_conf.rss_conf; 210711e9eae4SChaoyong He ret = nfp_net_rss_hash_write(dev, &rss_conf); 210811e9eae4SChaoyong He 210911e9eae4SChaoyong He return ret; 211011e9eae4SChaoyong He } 211111e9eae4SChaoyong He 211211e9eae4SChaoyong He void 211311e9eae4SChaoyong He nfp_net_stop_rx_queue(struct rte_eth_dev *dev) 211411e9eae4SChaoyong He { 211511e9eae4SChaoyong He uint16_t i; 211611e9eae4SChaoyong He struct nfp_net_rxq *this_rx_q; 211711e9eae4SChaoyong He 211811e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 211911e9eae4SChaoyong He this_rx_q = dev->data->rx_queues[i]; 212011e9eae4SChaoyong He nfp_net_reset_rx_queue(this_rx_q); 212111e9eae4SChaoyong He dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 212211e9eae4SChaoyong He } 212311e9eae4SChaoyong He } 212411e9eae4SChaoyong He 212511e9eae4SChaoyong He void 212611e9eae4SChaoyong He nfp_net_close_rx_queue(struct rte_eth_dev *dev) 212711e9eae4SChaoyong He { 212811e9eae4SChaoyong He uint16_t i; 212911e9eae4SChaoyong He struct nfp_net_rxq *this_rx_q; 213011e9eae4SChaoyong He 213111e9eae4SChaoyong He for (i = 0; i < dev->data->nb_rx_queues; i++) { 213211e9eae4SChaoyong He this_rx_q = dev->data->rx_queues[i]; 213311e9eae4SChaoyong He nfp_net_reset_rx_queue(this_rx_q); 213411e9eae4SChaoyong He nfp_net_rx_queue_release(dev, i); 213511e9eae4SChaoyong He } 213611e9eae4SChaoyong He } 213711e9eae4SChaoyong He 213811e9eae4SChaoyong He void 213911e9eae4SChaoyong He nfp_net_stop_tx_queue(struct rte_eth_dev *dev) 214011e9eae4SChaoyong He { 214111e9eae4SChaoyong He uint16_t i; 214211e9eae4SChaoyong He struct nfp_net_txq *this_tx_q; 214311e9eae4SChaoyong He 214411e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 214511e9eae4SChaoyong He this_tx_q = dev->data->tx_queues[i]; 214611e9eae4SChaoyong He nfp_net_reset_tx_queue(this_tx_q); 214711e9eae4SChaoyong He dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 214811e9eae4SChaoyong He } 214911e9eae4SChaoyong He } 215011e9eae4SChaoyong He 215111e9eae4SChaoyong He void 215211e9eae4SChaoyong He nfp_net_close_tx_queue(struct rte_eth_dev *dev) 215311e9eae4SChaoyong He { 215411e9eae4SChaoyong He uint16_t i; 215511e9eae4SChaoyong He struct nfp_net_txq *this_tx_q; 215611e9eae4SChaoyong He 215711e9eae4SChaoyong He for (i = 0; i < dev->data->nb_tx_queues; i++) { 215811e9eae4SChaoyong He this_tx_q = dev->data->tx_queues[i]; 215911e9eae4SChaoyong He nfp_net_reset_tx_queue(this_tx_q); 216011e9eae4SChaoyong He nfp_net_tx_queue_release(dev, i); 216111e9eae4SChaoyong He } 216211e9eae4SChaoyong He } 216311e9eae4SChaoyong He 216411e9eae4SChaoyong He int 216572d1dea6SChaoyong He nfp_net_set_vxlan_port(struct nfp_net_hw *net_hw, 216611e9eae4SChaoyong He size_t idx, 21675b81c1e2SLong Wu uint16_t port, 21685b81c1e2SLong Wu uint32_t ctrl) 216911e9eae4SChaoyong He { 217011e9eae4SChaoyong He uint32_t i; 217172d1dea6SChaoyong He struct nfp_hw *hw = &net_hw->super; 217211e9eae4SChaoyong He 217311e9eae4SChaoyong He if (idx >= NFP_NET_N_VXLAN_PORTS) { 217411e9eae4SChaoyong He PMD_DRV_LOG(ERR, "The idx value is out of range."); 217511e9eae4SChaoyong He return -ERANGE; 217611e9eae4SChaoyong He } 217711e9eae4SChaoyong He 217872d1dea6SChaoyong He net_hw->vxlan_ports[idx] = port; 217911e9eae4SChaoyong He 218011e9eae4SChaoyong He for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) { 218172d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port), 218272d1dea6SChaoyong He (net_hw->vxlan_ports[i + 1] << 16) | net_hw->vxlan_ports[i]); 218311e9eae4SChaoyong He } 218411e9eae4SChaoyong He 21855b81c1e2SLong Wu return nfp_reconfig(hw, ctrl, NFP_NET_CFG_UPDATE_VXLAN); 218611e9eae4SChaoyong He } 218711e9eae4SChaoyong He 218811e9eae4SChaoyong He /* 218911e9eae4SChaoyong He * The firmware with NFD3 can not handle DMA address requiring more 219011e9eae4SChaoyong He * than 40 bits. 219111e9eae4SChaoyong He */ 219211e9eae4SChaoyong He int 2193000feb4cSChaoyong He nfp_net_check_dma_mask(struct nfp_pf_dev *pf_dev, 219411e9eae4SChaoyong He char *name) 219511e9eae4SChaoyong He { 2196000feb4cSChaoyong He if (pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3 && 219711e9eae4SChaoyong He rte_mem_check_dma_mask(40) != 0) { 2198fb86136dSZerun Fu PMD_DRV_LOG(ERR, "Device %s can not be used: restricted dma mask to 40 bits!", 219911e9eae4SChaoyong He name); 220011e9eae4SChaoyong He return -ENODEV; 220111e9eae4SChaoyong He } 220211e9eae4SChaoyong He 220311e9eae4SChaoyong He return 0; 220411e9eae4SChaoyong He } 220511e9eae4SChaoyong He 2206ff9da649SLong Wu int 2207ff9da649SLong Wu nfp_net_txrwb_alloc(struct rte_eth_dev *eth_dev) 2208ff9da649SLong Wu { 2209ff9da649SLong Wu struct nfp_net_hw *net_hw; 2210ff9da649SLong Wu char mz_name[RTE_MEMZONE_NAMESIZE]; 2211ff9da649SLong Wu 2212ff9da649SLong Wu net_hw = nfp_net_get_hw(eth_dev); 2213ff9da649SLong Wu snprintf(mz_name, sizeof(mz_name), "%s_TXRWB", eth_dev->data->name); 2214ff9da649SLong Wu net_hw->txrwb_mz = rte_memzone_reserve_aligned(mz_name, 2215ff9da649SLong Wu net_hw->max_tx_queues * sizeof(uint64_t), 2216ff9da649SLong Wu rte_socket_id(), 2217ff9da649SLong Wu RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE); 2218ff9da649SLong Wu if (net_hw->txrwb_mz == NULL) { 2219b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to alloc %s for TX ring write back.", 2220ff9da649SLong Wu mz_name); 2221ff9da649SLong Wu return -ENOMEM; 2222ff9da649SLong Wu } 2223ff9da649SLong Wu 2224ff9da649SLong Wu return 0; 2225ff9da649SLong Wu } 2226ff9da649SLong Wu 2227ff9da649SLong Wu void 2228ff9da649SLong Wu nfp_net_txrwb_free(struct rte_eth_dev *eth_dev) 2229ff9da649SLong Wu { 2230ff9da649SLong Wu struct nfp_net_hw *net_hw; 2231ff9da649SLong Wu 2232ff9da649SLong Wu net_hw = nfp_net_get_hw(eth_dev); 2233ff9da649SLong Wu if (net_hw->txrwb_mz == NULL) 2234ff9da649SLong Wu return; 2235ff9da649SLong Wu 2236ff9da649SLong Wu rte_memzone_free(net_hw->txrwb_mz); 2237ff9da649SLong Wu net_hw->txrwb_mz = NULL; 2238ff9da649SLong Wu } 2239ff9da649SLong Wu 2240000feb4cSChaoyong He static void 2241000feb4cSChaoyong He nfp_net_cfg_read_version(struct nfp_hw *hw, 2242000feb4cSChaoyong He struct nfp_pf_dev *pf_dev) 224311e9eae4SChaoyong He { 224411e9eae4SChaoyong He union { 224511e9eae4SChaoyong He uint32_t whole; 224611e9eae4SChaoyong He struct nfp_net_fw_ver split; 224711e9eae4SChaoyong He } version; 224811e9eae4SChaoyong He 2249000feb4cSChaoyong He version.whole = nn_cfg_readl(hw, NFP_NET_CFG_VERSION); 2250000feb4cSChaoyong He pf_dev->ver = version.split; 2251000feb4cSChaoyong He } 2252000feb4cSChaoyong He 2253000feb4cSChaoyong He bool 2254000feb4cSChaoyong He nfp_net_version_check(struct nfp_hw *hw, 2255000feb4cSChaoyong He struct nfp_pf_dev *pf_dev) 2256000feb4cSChaoyong He { 2257000feb4cSChaoyong He nfp_net_cfg_read_version(hw, pf_dev); 2258000feb4cSChaoyong He if (!nfp_net_is_valid_nfd_version(pf_dev->ver)) 2259000feb4cSChaoyong He return false; 2260000feb4cSChaoyong He 226119bd7cceSChaoyong He if (!nfp_net_is_valid_version_class(pf_dev->ver)) 226219bd7cceSChaoyong He return false; 226319bd7cceSChaoyong He 2264000feb4cSChaoyong He return true; 226511e9eae4SChaoyong He } 226611e9eae4SChaoyong He 226711e9eae4SChaoyong He static void 2268b3c21344SChaoyong He nfp_net_get_nsp_info(struct nfp_net_hw_priv *hw_priv, 226911e9eae4SChaoyong He char *nsp_version) 227011e9eae4SChaoyong He { 227111e9eae4SChaoyong He struct nfp_nsp *nsp; 227211e9eae4SChaoyong He 2273b3c21344SChaoyong He nsp = nfp_nsp_open(hw_priv->pf_dev->cpp); 227411e9eae4SChaoyong He if (nsp == NULL) 227511e9eae4SChaoyong He return; 227611e9eae4SChaoyong He 227711e9eae4SChaoyong He snprintf(nsp_version, FW_VER_LEN, "%hu.%hu", 227811e9eae4SChaoyong He nfp_nsp_get_abi_ver_major(nsp), 227911e9eae4SChaoyong He nfp_nsp_get_abi_ver_minor(nsp)); 228011e9eae4SChaoyong He 228111e9eae4SChaoyong He nfp_nsp_close(nsp); 228211e9eae4SChaoyong He } 228311e9eae4SChaoyong He 2284a2bc299dSPeng Zhang void 2285b3c21344SChaoyong He nfp_net_get_fw_version(struct nfp_cpp *cpp, 2286a2bc299dSPeng Zhang uint32_t *mip_version) 2287a2bc299dSPeng Zhang { 2288a2bc299dSPeng Zhang struct nfp_mip *mip; 2289a2bc299dSPeng Zhang 2290b3c21344SChaoyong He mip = nfp_mip_open(cpp); 2291a2bc299dSPeng Zhang if (mip == NULL) { 2292a2bc299dSPeng Zhang *mip_version = 0; 2293a2bc299dSPeng Zhang return; 2294a2bc299dSPeng Zhang } 2295a2bc299dSPeng Zhang 2296a2bc299dSPeng Zhang *mip_version = nfp_mip_fw_version(mip); 2297a2bc299dSPeng Zhang 2298a2bc299dSPeng Zhang nfp_mip_close(mip); 2299a2bc299dSPeng Zhang } 2300a2bc299dSPeng Zhang 230111e9eae4SChaoyong He static void 2302b3c21344SChaoyong He nfp_net_get_mip_name(struct nfp_net_hw_priv *hw_priv, 230311e9eae4SChaoyong He char *mip_name) 230411e9eae4SChaoyong He { 230511e9eae4SChaoyong He struct nfp_mip *mip; 230611e9eae4SChaoyong He 2307b3c21344SChaoyong He mip = nfp_mip_open(hw_priv->pf_dev->cpp); 230811e9eae4SChaoyong He if (mip == NULL) 230911e9eae4SChaoyong He return; 231011e9eae4SChaoyong He 2311cda9123eSChaoyong He strlcpy(mip_name, nfp_mip_name(mip), FW_VER_LEN); 231211e9eae4SChaoyong He 231311e9eae4SChaoyong He nfp_mip_close(mip); 231411e9eae4SChaoyong He } 231511e9eae4SChaoyong He 231611e9eae4SChaoyong He static void 2317ff9f5a56SChaoyong He nfp_net_get_app_name(struct nfp_net_hw_priv *hw_priv, 231811e9eae4SChaoyong He char *app_name) 231911e9eae4SChaoyong He { 2320ff9f5a56SChaoyong He switch (hw_priv->pf_dev->app_fw_id) { 232111e9eae4SChaoyong He case NFP_APP_FW_CORE_NIC: 2322cda9123eSChaoyong He strlcpy(app_name, "nic", FW_VER_LEN); 232311e9eae4SChaoyong He break; 232411e9eae4SChaoyong He case NFP_APP_FW_FLOWER_NIC: 2325cda9123eSChaoyong He strlcpy(app_name, "flower", FW_VER_LEN); 232611e9eae4SChaoyong He break; 232711e9eae4SChaoyong He default: 2328cda9123eSChaoyong He strlcpy(app_name, "unknown", FW_VER_LEN); 232911e9eae4SChaoyong He break; 233011e9eae4SChaoyong He } 233111e9eae4SChaoyong He } 233211e9eae4SChaoyong He 233311e9eae4SChaoyong He int 233411e9eae4SChaoyong He nfp_net_firmware_version_get(struct rte_eth_dev *dev, 233511e9eae4SChaoyong He char *fw_version, 233611e9eae4SChaoyong He size_t fw_size) 233711e9eae4SChaoyong He { 233811e9eae4SChaoyong He struct nfp_net_hw *hw; 2339000feb4cSChaoyong He struct nfp_pf_dev *pf_dev; 2340ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 2341b7adbb2eSZerun Fu char app_name[FW_VER_LEN] = {0}; 2342b7adbb2eSZerun Fu char mip_name[FW_VER_LEN] = {0}; 2343b7adbb2eSZerun Fu char nsp_version[FW_VER_LEN] = {0}; 2344b7adbb2eSZerun Fu char vnic_version[FW_VER_LEN] = {0}; 234511e9eae4SChaoyong He 234611e9eae4SChaoyong He if (fw_size < FW_VER_LEN) 234711e9eae4SChaoyong He return FW_VER_LEN; 234811e9eae4SChaoyong He 2349c4de52ecSChaoyong He hw = nfp_net_get_hw(dev); 2350ff9f5a56SChaoyong He hw_priv = dev->process_private; 2351000feb4cSChaoyong He pf_dev = hw_priv->pf_dev; 235211e9eae4SChaoyong He 2353b7adbb2eSZerun Fu if (hw->fw_version[0] != 0) { 2354b7adbb2eSZerun Fu snprintf(fw_version, FW_VER_LEN, "%s", hw->fw_version); 2355b7adbb2eSZerun Fu return 0; 2356b7adbb2eSZerun Fu } 2357b7adbb2eSZerun Fu 2358e72d6053SQin Ke if (!rte_eth_dev_is_repr(dev)) { 235911e9eae4SChaoyong He snprintf(vnic_version, FW_VER_LEN, "%d.%d.%d.%d", 2360000feb4cSChaoyong He pf_dev->ver.extend, pf_dev->ver.class, 2361000feb4cSChaoyong He pf_dev->ver.major, pf_dev->ver.minor); 2362c4de52ecSChaoyong He } else { 2363c4de52ecSChaoyong He snprintf(vnic_version, FW_VER_LEN, "*"); 2364c4de52ecSChaoyong He } 236511e9eae4SChaoyong He 2366b3c21344SChaoyong He nfp_net_get_nsp_info(hw_priv, nsp_version); 2367b3c21344SChaoyong He nfp_net_get_mip_name(hw_priv, mip_name); 2368ff9f5a56SChaoyong He nfp_net_get_app_name(hw_priv, app_name); 236911e9eae4SChaoyong He 2370b7adbb2eSZerun Fu if (nsp_version[0] == 0 || mip_name[0] == 0) { 237111e9eae4SChaoyong He snprintf(fw_version, FW_VER_LEN, "%s %s %s %s", 237211e9eae4SChaoyong He vnic_version, nsp_version, mip_name, app_name); 2373b7adbb2eSZerun Fu return 0; 2374b7adbb2eSZerun Fu } 2375b7adbb2eSZerun Fu 2376b7adbb2eSZerun Fu snprintf(hw->fw_version, FW_VER_LEN, "%s %s %s %s", 2377b7adbb2eSZerun Fu vnic_version, nsp_version, mip_name, app_name); 2378b7adbb2eSZerun Fu 2379b7adbb2eSZerun Fu snprintf(fw_version, FW_VER_LEN, "%s", hw->fw_version); 238011e9eae4SChaoyong He 238111e9eae4SChaoyong He return 0; 238211e9eae4SChaoyong He } 238311e9eae4SChaoyong He 238411e9eae4SChaoyong He bool 238511e9eae4SChaoyong He nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version) 238611e9eae4SChaoyong He { 238711e9eae4SChaoyong He uint8_t nfd_version = version.extend; 238811e9eae4SChaoyong He 238911e9eae4SChaoyong He if (nfd_version == NFP_NET_CFG_VERSION_DP_NFD3) 239011e9eae4SChaoyong He return true; 239111e9eae4SChaoyong He 239211e9eae4SChaoyong He if (nfd_version == NFP_NET_CFG_VERSION_DP_NFDK) { 239311e9eae4SChaoyong He if (version.major < 5) { 2394b6de4353SZerun Fu PMD_INIT_LOG(ERR, "NFDK must use ABI 5 or newer, found: %d.", 239511e9eae4SChaoyong He version.major); 239611e9eae4SChaoyong He return false; 239711e9eae4SChaoyong He } 239811e9eae4SChaoyong He 239911e9eae4SChaoyong He return true; 240011e9eae4SChaoyong He } 240111e9eae4SChaoyong He 240211e9eae4SChaoyong He return false; 240311e9eae4SChaoyong He } 2404c4de52ecSChaoyong He 240519bd7cceSChaoyong He bool 240619bd7cceSChaoyong He nfp_net_is_valid_version_class(struct nfp_net_fw_ver version) 240719bd7cceSChaoyong He { 240819bd7cceSChaoyong He switch (version.class) { 240919bd7cceSChaoyong He case NFP_NET_CFG_VERSION_CLASS_GENERIC: 241019bd7cceSChaoyong He return true; 241119bd7cceSChaoyong He case NFP_NET_CFG_VERSION_CLASS_NO_EMEM: 241219bd7cceSChaoyong He return true; 241319bd7cceSChaoyong He default: 241419bd7cceSChaoyong He return false; 241519bd7cceSChaoyong He } 241619bd7cceSChaoyong He } 241719bd7cceSChaoyong He 241819bd7cceSChaoyong He void 241919bd7cceSChaoyong He nfp_net_ctrl_bar_size_set(struct nfp_pf_dev *pf_dev) 242019bd7cceSChaoyong He { 242119bd7cceSChaoyong He if (pf_dev->ver.class == NFP_NET_CFG_VERSION_CLASS_GENERIC) 242219bd7cceSChaoyong He pf_dev->ctrl_bar_size = NFP_NET_CFG_BAR_SZ_32K; 242319bd7cceSChaoyong He else 242419bd7cceSChaoyong He pf_dev->ctrl_bar_size = NFP_NET_CFG_BAR_SZ_8K; 242519bd7cceSChaoyong He } 242619bd7cceSChaoyong He 2427c4de52ecSChaoyong He /* Disable rx and tx functions to allow for reconfiguring. */ 2428c4de52ecSChaoyong He int 2429c4de52ecSChaoyong He nfp_net_stop(struct rte_eth_dev *dev) 2430c4de52ecSChaoyong He { 24311580387eSChaoyong He int ret; 2432c4de52ecSChaoyong He struct nfp_net_hw *hw; 2433ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 2434c4de52ecSChaoyong He 2435c4de52ecSChaoyong He hw = nfp_net_get_hw(dev); 2436ff9f5a56SChaoyong He hw_priv = dev->process_private; 2437c4de52ecSChaoyong He 2438c4de52ecSChaoyong He nfp_net_disable_queues(dev); 2439c4de52ecSChaoyong He 2440c4de52ecSChaoyong He /* Clear queues */ 2441c4de52ecSChaoyong He nfp_net_stop_tx_queue(dev); 2442c4de52ecSChaoyong He nfp_net_stop_rx_queue(dev); 2443c4de52ecSChaoyong He 24441580387eSChaoyong He ret = nfp_eth_set_configured(hw_priv->pf_dev->cpp, hw->nfp_idx, 0); 24451580387eSChaoyong He if (ret < 0) 24461580387eSChaoyong He return ret; 2447c4de52ecSChaoyong He 2448c4de52ecSChaoyong He return 0; 2449c4de52ecSChaoyong He } 245051d15e82SZerun Fu 245151d15e82SZerun Fu static enum rte_eth_fc_mode 245251d15e82SZerun Fu nfp_net_get_pause_mode(struct nfp_eth_table_port *eth_port) 245351d15e82SZerun Fu { 245451d15e82SZerun Fu enum rte_eth_fc_mode mode; 245551d15e82SZerun Fu 245651d15e82SZerun Fu if (eth_port->rx_pause_enabled) { 245751d15e82SZerun Fu if (eth_port->tx_pause_enabled) 245851d15e82SZerun Fu mode = RTE_ETH_FC_FULL; 245951d15e82SZerun Fu else 246051d15e82SZerun Fu mode = RTE_ETH_FC_RX_PAUSE; 246151d15e82SZerun Fu } else { 246251d15e82SZerun Fu if (eth_port->tx_pause_enabled) 246351d15e82SZerun Fu mode = RTE_ETH_FC_TX_PAUSE; 246451d15e82SZerun Fu else 246551d15e82SZerun Fu mode = RTE_ETH_FC_NONE; 246651d15e82SZerun Fu } 246751d15e82SZerun Fu 246851d15e82SZerun Fu return mode; 246951d15e82SZerun Fu } 247051d15e82SZerun Fu 247151d15e82SZerun Fu int 247251d15e82SZerun Fu nfp_net_flow_ctrl_get(struct rte_eth_dev *dev, 247351d15e82SZerun Fu struct rte_eth_fc_conf *fc_conf) 247451d15e82SZerun Fu { 2475ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 247651d15e82SZerun Fu struct nfp_eth_table *nfp_eth_table; 247751d15e82SZerun Fu struct nfp_eth_table_port *eth_port; 247851d15e82SZerun Fu 2479ff9f5a56SChaoyong He hw_priv = dev->process_private; 2480ff9f5a56SChaoyong He if (hw_priv == NULL || hw_priv->pf_dev == NULL) 248151d15e82SZerun Fu return -EINVAL; 248251d15e82SZerun Fu 2483ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 248451d15e82SZerun Fu eth_port = &nfp_eth_table->ports[dev->data->port_id]; 248551d15e82SZerun Fu 248651d15e82SZerun Fu /* Currently only RX/TX switch are supported */ 248751d15e82SZerun Fu fc_conf->mode = nfp_net_get_pause_mode(eth_port); 248851d15e82SZerun Fu 248951d15e82SZerun Fu return 0; 249051d15e82SZerun Fu } 249168aa3537SZerun Fu 249268aa3537SZerun Fu static int 2493b3c21344SChaoyong He nfp_net_pause_frame_set(struct nfp_net_hw_priv *hw_priv, 249468aa3537SZerun Fu struct nfp_eth_table_port *eth_port, 249568aa3537SZerun Fu enum rte_eth_fc_mode mode) 249668aa3537SZerun Fu { 249768aa3537SZerun Fu int err; 249868aa3537SZerun Fu bool flag; 249968aa3537SZerun Fu struct nfp_nsp *nsp; 250068aa3537SZerun Fu 2501b3c21344SChaoyong He nsp = nfp_eth_config_start(hw_priv->pf_dev->cpp, eth_port->index); 250268aa3537SZerun Fu if (nsp == NULL) { 250368aa3537SZerun Fu PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle."); 250468aa3537SZerun Fu return -EIO; 250568aa3537SZerun Fu } 250668aa3537SZerun Fu 250768aa3537SZerun Fu flag = (mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true; 250868aa3537SZerun Fu err = nfp_eth_set_tx_pause(nsp, flag); 250968aa3537SZerun Fu if (err != 0) { 251068aa3537SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure TX pause frame."); 251168aa3537SZerun Fu nfp_eth_config_cleanup_end(nsp); 251268aa3537SZerun Fu return err; 251368aa3537SZerun Fu } 251468aa3537SZerun Fu 251568aa3537SZerun Fu flag = (mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true; 251668aa3537SZerun Fu err = nfp_eth_set_rx_pause(nsp, flag); 251768aa3537SZerun Fu if (err != 0) { 251868aa3537SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure RX pause frame."); 251968aa3537SZerun Fu nfp_eth_config_cleanup_end(nsp); 252068aa3537SZerun Fu return err; 252168aa3537SZerun Fu } 252268aa3537SZerun Fu 252368aa3537SZerun Fu err = nfp_eth_config_commit_end(nsp); 25244bb6de51SChaoyong He if (err < 0) { 252568aa3537SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure pause frame."); 252668aa3537SZerun Fu return err; 252768aa3537SZerun Fu } 252868aa3537SZerun Fu 252968aa3537SZerun Fu return 0; 253068aa3537SZerun Fu } 253168aa3537SZerun Fu 253268aa3537SZerun Fu int 253368aa3537SZerun Fu nfp_net_flow_ctrl_set(struct rte_eth_dev *dev, 253468aa3537SZerun Fu struct rte_eth_fc_conf *fc_conf) 253568aa3537SZerun Fu { 253668aa3537SZerun Fu int ret; 2537c33504deSQin Ke uint8_t idx; 253868aa3537SZerun Fu enum rte_eth_fc_mode set_mode; 2539ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 254068aa3537SZerun Fu enum rte_eth_fc_mode original_mode; 254168aa3537SZerun Fu struct nfp_eth_table *nfp_eth_table; 254268aa3537SZerun Fu struct nfp_eth_table_port *eth_port; 254368aa3537SZerun Fu 2544c33504deSQin Ke idx = nfp_net_get_idx(dev); 2545ff9f5a56SChaoyong He hw_priv = dev->process_private; 2546ff9f5a56SChaoyong He if (hw_priv == NULL || hw_priv->pf_dev == NULL) 254768aa3537SZerun Fu return -EINVAL; 254868aa3537SZerun Fu 2549ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 2550c33504deSQin Ke eth_port = &nfp_eth_table->ports[idx]; 255168aa3537SZerun Fu 255268aa3537SZerun Fu original_mode = nfp_net_get_pause_mode(eth_port); 255368aa3537SZerun Fu set_mode = fc_conf->mode; 255468aa3537SZerun Fu 255568aa3537SZerun Fu if (set_mode == original_mode) 255668aa3537SZerun Fu return 0; 255768aa3537SZerun Fu 2558b3c21344SChaoyong He ret = nfp_net_pause_frame_set(hw_priv, eth_port, set_mode); 255968aa3537SZerun Fu if (ret != 0) 256068aa3537SZerun Fu return ret; 256168aa3537SZerun Fu 256268aa3537SZerun Fu /* Update eth_table after modifying RX/TX pause frame mode. */ 256368aa3537SZerun Fu eth_port->tx_pause_enabled = (set_mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true; 256468aa3537SZerun Fu eth_port->rx_pause_enabled = (set_mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true; 256568aa3537SZerun Fu 256668aa3537SZerun Fu return 0; 256768aa3537SZerun Fu } 25680786add9SZerun Fu 25690786add9SZerun Fu int 25700786add9SZerun Fu nfp_net_fec_get_capability(struct rte_eth_dev *dev, 25710786add9SZerun Fu struct rte_eth_fec_capa *speed_fec_capa, 25720786add9SZerun Fu __rte_unused unsigned int num) 25730786add9SZerun Fu { 2574c33504deSQin Ke uint8_t idx; 25750786add9SZerun Fu uint16_t speed; 25760786add9SZerun Fu uint32_t supported_fec; 2577ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 25780786add9SZerun Fu struct nfp_eth_table *nfp_eth_table; 25790786add9SZerun Fu struct nfp_eth_table_port *eth_port; 25800786add9SZerun Fu 2581c33504deSQin Ke idx = nfp_net_get_idx(dev); 2582ff9f5a56SChaoyong He hw_priv = dev->process_private; 2583ff9f5a56SChaoyong He if (hw_priv == NULL || hw_priv->pf_dev == NULL) 25840786add9SZerun Fu return -EINVAL; 25850786add9SZerun Fu 2586ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 2587c33504deSQin Ke eth_port = &nfp_eth_table->ports[idx]; 25880786add9SZerun Fu 25890786add9SZerun Fu speed = eth_port->speed; 25900786add9SZerun Fu supported_fec = nfp_eth_supported_fec_modes(eth_port); 25910786add9SZerun Fu if (speed == 0 || supported_fec == 0) { 25920786add9SZerun Fu PMD_DRV_LOG(ERR, "FEC modes supported or Speed is invalid."); 25930786add9SZerun Fu return -EINVAL; 25940786add9SZerun Fu } 25950786add9SZerun Fu 25960786add9SZerun Fu if (speed_fec_capa == NULL) 25970786add9SZerun Fu return NFP_FEC_CAPA_ENTRY_NUM; 25980786add9SZerun Fu 25990786add9SZerun Fu speed_fec_capa->speed = speed; 26000786add9SZerun Fu 26010786add9SZerun Fu if ((supported_fec & NFP_FEC_AUTO) != 0) 26020786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(AUTO); 26030786add9SZerun Fu if ((supported_fec & NFP_FEC_BASER) != 0) 26040786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(BASER); 26050786add9SZerun Fu if ((supported_fec & NFP_FEC_REED_SOLOMON) != 0) 26060786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(RS); 26070786add9SZerun Fu if ((supported_fec & NFP_FEC_DISABLED) != 0) 26080786add9SZerun Fu speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC); 26090786add9SZerun Fu 26100786add9SZerun Fu return NFP_FEC_CAPA_ENTRY_NUM; 26110786add9SZerun Fu } 2612c6835a32SZerun Fu 2613c6835a32SZerun Fu static uint32_t 2614c6835a32SZerun Fu nfp_net_fec_nfp_to_rte(enum nfp_eth_fec fec) 2615c6835a32SZerun Fu { 2616c6835a32SZerun Fu switch (fec) { 2617c6835a32SZerun Fu case NFP_FEC_AUTO_BIT: 2618c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(AUTO); 2619c6835a32SZerun Fu case NFP_FEC_BASER_BIT: 2620c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(BASER); 2621c6835a32SZerun Fu case NFP_FEC_REED_SOLOMON_BIT: 2622c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(RS); 2623c6835a32SZerun Fu case NFP_FEC_DISABLED_BIT: 2624c6835a32SZerun Fu return RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC); 2625c6835a32SZerun Fu default: 2626c6835a32SZerun Fu PMD_DRV_LOG(ERR, "FEC mode is invalid."); 2627c6835a32SZerun Fu return 0; 2628c6835a32SZerun Fu } 2629c6835a32SZerun Fu } 2630c6835a32SZerun Fu 2631c6835a32SZerun Fu int 2632c6835a32SZerun Fu nfp_net_fec_get(struct rte_eth_dev *dev, 2633c6835a32SZerun Fu uint32_t *fec_capa) 2634c6835a32SZerun Fu { 2635c33504deSQin Ke uint8_t idx; 2636ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 2637c6835a32SZerun Fu struct nfp_eth_table *nfp_eth_table; 2638c6835a32SZerun Fu struct nfp_eth_table_port *eth_port; 2639c6835a32SZerun Fu 2640c33504deSQin Ke idx = nfp_net_get_idx(dev); 2641ff9f5a56SChaoyong He hw_priv = dev->process_private; 2642ff9f5a56SChaoyong He if (hw_priv == NULL || hw_priv->pf_dev == NULL) 2643c6835a32SZerun Fu return -EINVAL; 2644c6835a32SZerun Fu 2645c6835a32SZerun Fu if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN) { 2646b3c21344SChaoyong He nfp_eth_table = nfp_eth_read_ports(hw_priv->pf_dev->cpp); 2647c33504deSQin Ke hw_priv->pf_dev->nfp_eth_table->ports[idx] = nfp_eth_table->ports[idx]; 2648c6835a32SZerun Fu free(nfp_eth_table); 2649c6835a32SZerun Fu } 2650c6835a32SZerun Fu 2651ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 2652c33504deSQin Ke eth_port = &nfp_eth_table->ports[idx]; 2653c6835a32SZerun Fu 2654c6835a32SZerun Fu if (!nfp_eth_can_support_fec(eth_port)) { 2655c6835a32SZerun Fu PMD_DRV_LOG(ERR, "NFP can not support FEC."); 2656c6835a32SZerun Fu return -ENOTSUP; 2657c6835a32SZerun Fu } 2658c6835a32SZerun Fu 2659c6835a32SZerun Fu /* 2660c6835a32SZerun Fu * If link is down and AUTO is enabled, AUTO is returned, otherwise, 2661c6835a32SZerun Fu * configured FEC mode is returned. 2662c6835a32SZerun Fu * If link is up, current FEC mode is returned. 2663c6835a32SZerun Fu */ 2664c6835a32SZerun Fu if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN) 2665c6835a32SZerun Fu *fec_capa = nfp_net_fec_nfp_to_rte(eth_port->fec); 2666c6835a32SZerun Fu else 2667c6835a32SZerun Fu *fec_capa = nfp_net_fec_nfp_to_rte(eth_port->act_fec); 2668c6835a32SZerun Fu 2669c6835a32SZerun Fu if (*fec_capa == 0) 2670c6835a32SZerun Fu return -EINVAL; 2671c6835a32SZerun Fu 2672c6835a32SZerun Fu return 0; 2673c6835a32SZerun Fu } 267437bd1b84SZerun Fu 267537bd1b84SZerun Fu static enum nfp_eth_fec 267637bd1b84SZerun Fu nfp_net_fec_rte_to_nfp(uint32_t fec) 267737bd1b84SZerun Fu { 267837bd1b84SZerun Fu switch (fec) { 267937bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_AUTO): 268037bd1b84SZerun Fu return NFP_FEC_AUTO_BIT; 268137bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_NOFEC): 268237bd1b84SZerun Fu return NFP_FEC_DISABLED_BIT; 268337bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_RS): 268437bd1b84SZerun Fu return NFP_FEC_REED_SOLOMON_BIT; 268537bd1b84SZerun Fu case RTE_BIT32(RTE_ETH_FEC_BASER): 268637bd1b84SZerun Fu return NFP_FEC_BASER_BIT; 268737bd1b84SZerun Fu default: 268837bd1b84SZerun Fu return NFP_FEC_INVALID_BIT; 268937bd1b84SZerun Fu } 269037bd1b84SZerun Fu } 269137bd1b84SZerun Fu 269237bd1b84SZerun Fu int 269337bd1b84SZerun Fu nfp_net_fec_set(struct rte_eth_dev *dev, 269437bd1b84SZerun Fu uint32_t fec_capa) 269537bd1b84SZerun Fu { 269647fc5e4eSChaoyong He int ret; 2697c33504deSQin Ke uint8_t idx; 269837bd1b84SZerun Fu enum nfp_eth_fec fec; 269937bd1b84SZerun Fu uint32_t supported_fec; 2700ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 270137bd1b84SZerun Fu struct nfp_eth_table *nfp_eth_table; 270237bd1b84SZerun Fu struct nfp_eth_table_port *eth_port; 270337bd1b84SZerun Fu 2704c33504deSQin Ke idx = nfp_net_get_idx(dev); 2705ff9f5a56SChaoyong He hw_priv = dev->process_private; 2706ff9f5a56SChaoyong He if (hw_priv == NULL || hw_priv->pf_dev == NULL) 270737bd1b84SZerun Fu return -EINVAL; 270837bd1b84SZerun Fu 2709ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 2710c33504deSQin Ke eth_port = &nfp_eth_table->ports[idx]; 271137bd1b84SZerun Fu 271237bd1b84SZerun Fu supported_fec = nfp_eth_supported_fec_modes(eth_port); 271337bd1b84SZerun Fu if (supported_fec == 0) { 271437bd1b84SZerun Fu PMD_DRV_LOG(ERR, "NFP can not support FEC."); 271537bd1b84SZerun Fu return -ENOTSUP; 271637bd1b84SZerun Fu } 271737bd1b84SZerun Fu 271837bd1b84SZerun Fu fec = nfp_net_fec_rte_to_nfp(fec_capa); 271937bd1b84SZerun Fu if (fec == NFP_FEC_INVALID_BIT) { 272037bd1b84SZerun Fu PMD_DRV_LOG(ERR, "FEC modes is invalid."); 272137bd1b84SZerun Fu return -EINVAL; 272237bd1b84SZerun Fu } 272337bd1b84SZerun Fu 272437bd1b84SZerun Fu if ((RTE_BIT32(fec) & supported_fec) == 0) { 272537bd1b84SZerun Fu PMD_DRV_LOG(ERR, "Unsupported FEC mode is set."); 272637bd1b84SZerun Fu return -EIO; 272737bd1b84SZerun Fu } 272837bd1b84SZerun Fu 272947fc5e4eSChaoyong He ret = nfp_eth_set_fec(hw_priv->pf_dev->cpp, eth_port->index, fec); 273047fc5e4eSChaoyong He if (ret < 0) { 273147fc5e4eSChaoyong He PMD_DRV_LOG(ERR, "NFP set FEC mode failed."); 273247fc5e4eSChaoyong He return ret; 273347fc5e4eSChaoyong He } 273447fc5e4eSChaoyong He 273547fc5e4eSChaoyong He return 0; 273637bd1b84SZerun Fu } 2737bd4969abSPeng Zhang 2738bd4969abSPeng Zhang uint32_t 2739eac7eda4SChaoyong He nfp_net_get_phyports_from_nsp(struct nfp_pf_dev *pf_dev) 2740bd4969abSPeng Zhang { 2741bd4969abSPeng Zhang if (pf_dev->multi_pf.enabled) 2742bd4969abSPeng Zhang return 1; 2743bd4969abSPeng Zhang else 27446f708e52SChaoyong He return pf_dev->nfp_eth_table->count; 2745bd4969abSPeng Zhang } 2746a807bcebSPeng Zhang 2747eac7eda4SChaoyong He uint32_t 2748eac7eda4SChaoyong He nfp_net_get_phyports_from_fw(struct nfp_pf_dev *pf_dev) 2749eac7eda4SChaoyong He { 2750eac7eda4SChaoyong He int ret = 0; 2751eac7eda4SChaoyong He uint8_t total_phyports; 2752eac7eda4SChaoyong He char pf_name[RTE_ETH_NAME_MAX_LEN]; 2753eac7eda4SChaoyong He 2754eac7eda4SChaoyong He /* Read the number of vNIC's created for the PF */ 2755eac7eda4SChaoyong He snprintf(pf_name, sizeof(pf_name), "nfd_cfg_pf%u_num_ports", 2756eac7eda4SChaoyong He pf_dev->multi_pf.function_id); 2757eac7eda4SChaoyong He total_phyports = nfp_rtsym_read_le(pf_dev->sym_tbl, pf_name, &ret); 2758eac7eda4SChaoyong He if (ret != 0 || total_phyports == 0 || total_phyports > 8) { 2759eac7eda4SChaoyong He PMD_INIT_LOG(ERR, "%s symbol with wrong value", pf_name); 2760eac7eda4SChaoyong He return 0; 2761eac7eda4SChaoyong He } 2762eac7eda4SChaoyong He 2763eac7eda4SChaoyong He return total_phyports; 2764eac7eda4SChaoyong He } 2765eac7eda4SChaoyong He 2766a807bcebSPeng Zhang uint8_t 2767a807bcebSPeng Zhang nfp_function_id_get(const struct nfp_pf_dev *pf_dev, 2768a807bcebSPeng Zhang uint8_t port_id) 2769a807bcebSPeng Zhang { 2770a807bcebSPeng Zhang if (pf_dev->multi_pf.enabled) 2771a807bcebSPeng Zhang return pf_dev->multi_pf.function_id; 2772a807bcebSPeng Zhang 2773a807bcebSPeng Zhang return port_id; 2774a807bcebSPeng Zhang } 277587abbaf9SPeng Zhang 277687abbaf9SPeng Zhang static int 277787abbaf9SPeng Zhang nfp_net_sriov_check(struct nfp_pf_dev *pf_dev, 277887abbaf9SPeng Zhang uint16_t cap) 277987abbaf9SPeng Zhang { 278087abbaf9SPeng Zhang uint16_t cap_vf; 278187abbaf9SPeng Zhang 278287abbaf9SPeng Zhang cap_vf = nn_readw(pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_CAP); 278387abbaf9SPeng Zhang if ((cap_vf & cap) != cap) 278487abbaf9SPeng Zhang return -ENOTSUP; 278587abbaf9SPeng Zhang 278687abbaf9SPeng Zhang return 0; 278787abbaf9SPeng Zhang } 278887abbaf9SPeng Zhang 278987abbaf9SPeng Zhang static int 279087abbaf9SPeng Zhang nfp_net_sriov_update(struct nfp_net_hw *net_hw, 279187abbaf9SPeng Zhang struct nfp_pf_dev *pf_dev, 279287abbaf9SPeng Zhang uint16_t update) 279387abbaf9SPeng Zhang { 279487abbaf9SPeng Zhang int ret; 279587abbaf9SPeng Zhang 279687abbaf9SPeng Zhang /* Reuse NFP_NET_VF_CFG_MB_VF_NUM to pass vf_base_id to FW. */ 279787abbaf9SPeng Zhang ret = nfp_net_vf_reconfig(net_hw, pf_dev, update, pf_dev->vf_base_id, 279887abbaf9SPeng Zhang NFP_NET_VF_CFG_MB_VF_NUM); 279987abbaf9SPeng Zhang if (ret != 0) { 2800b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Error nfp VF reconfig."); 280187abbaf9SPeng Zhang return ret; 280287abbaf9SPeng Zhang } 280387abbaf9SPeng Zhang 280487abbaf9SPeng Zhang return 0; 280587abbaf9SPeng Zhang } 280687abbaf9SPeng Zhang 280787abbaf9SPeng Zhang static int 2808bb24eb38SPeng Zhang nfp_net_vf_queues_config(struct nfp_net_hw *net_hw, 2809bb24eb38SPeng Zhang struct nfp_pf_dev *pf_dev) 2810bb24eb38SPeng Zhang { 2811bb24eb38SPeng Zhang int ret; 2812bb24eb38SPeng Zhang uint32_t i; 2813bb24eb38SPeng Zhang uint32_t offset; 2814bb24eb38SPeng Zhang 2815bb24eb38SPeng Zhang ret = nfp_net_sriov_check(pf_dev, NFP_NET_VF_CFG_MB_CAP_QUEUE_CONFIG); 2816bb24eb38SPeng Zhang if (ret != 0) { 2817bb24eb38SPeng Zhang if (ret == -ENOTSUP) { 2818b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "Set VF max queue not supported."); 2819bb24eb38SPeng Zhang return 0; 2820bb24eb38SPeng Zhang } 2821bb24eb38SPeng Zhang 2822b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Set VF max queue failed."); 2823bb24eb38SPeng Zhang return ret; 2824bb24eb38SPeng Zhang } 2825bb24eb38SPeng Zhang 2826bb24eb38SPeng Zhang offset = NFP_NET_VF_CFG_MB_SZ + pf_dev->max_vfs * NFP_NET_VF_CFG_SZ; 2827bb24eb38SPeng Zhang for (i = 0; i < pf_dev->sriov_vf; i++) { 2828bb24eb38SPeng Zhang ret = nfp_net_vf_reconfig(net_hw, pf_dev, NFP_NET_VF_CFG_MB_UPD_QUEUE_CONFIG, 2829bb24eb38SPeng Zhang pf_dev->queue_per_vf, pf_dev->vf_base_id + offset + i); 2830bb24eb38SPeng Zhang if (ret != 0) { 2831b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Set VF max_queue failed."); 2832bb24eb38SPeng Zhang return ret; 2833bb24eb38SPeng Zhang } 2834bb24eb38SPeng Zhang } 2835bb24eb38SPeng Zhang 2836bb24eb38SPeng Zhang return 0; 2837bb24eb38SPeng Zhang } 2838bb24eb38SPeng Zhang 2839bb24eb38SPeng Zhang static int 284087abbaf9SPeng Zhang nfp_net_sriov_init(struct nfp_net_hw *net_hw, 284187abbaf9SPeng Zhang struct nfp_pf_dev *pf_dev) 284287abbaf9SPeng Zhang { 284387abbaf9SPeng Zhang int ret; 284487abbaf9SPeng Zhang 284587abbaf9SPeng Zhang ret = nfp_net_sriov_check(pf_dev, NFP_NET_VF_CFG_MB_CAP_SPLIT); 284687abbaf9SPeng Zhang if (ret != 0) { 284787abbaf9SPeng Zhang if (ret == -ENOTSUP) { 2848b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "Set VF split not supported."); 284987abbaf9SPeng Zhang return 0; 285087abbaf9SPeng Zhang } 285187abbaf9SPeng Zhang 2852b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Set VF split failed."); 285387abbaf9SPeng Zhang return ret; 285487abbaf9SPeng Zhang } 285587abbaf9SPeng Zhang 285687abbaf9SPeng Zhang nn_writeb(pf_dev->sriov_vf, pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_VF_CNT); 285787abbaf9SPeng Zhang 285887abbaf9SPeng Zhang ret = nfp_net_sriov_update(net_hw, pf_dev, NFP_NET_VF_CFG_MB_UPD_SPLIT); 285987abbaf9SPeng Zhang if (ret != 0) { 2860b6de4353SZerun Fu PMD_INIT_LOG(ERR, "The nfp sriov update spilt failed."); 286187abbaf9SPeng Zhang return ret; 286287abbaf9SPeng Zhang } 286387abbaf9SPeng Zhang 286487abbaf9SPeng Zhang return 0; 286587abbaf9SPeng Zhang } 286687abbaf9SPeng Zhang 286787abbaf9SPeng Zhang int 286887abbaf9SPeng Zhang nfp_net_vf_config_app_init(struct nfp_net_hw *net_hw, 286987abbaf9SPeng Zhang struct nfp_pf_dev *pf_dev) 287087abbaf9SPeng Zhang { 287187abbaf9SPeng Zhang int ret; 287287abbaf9SPeng Zhang 287387abbaf9SPeng Zhang if (pf_dev->sriov_vf == 0) 287487abbaf9SPeng Zhang return 0; 287587abbaf9SPeng Zhang 287687abbaf9SPeng Zhang ret = nfp_net_sriov_init(net_hw, pf_dev); 287787abbaf9SPeng Zhang if (ret != 0) { 2878b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to init sriov module."); 287987abbaf9SPeng Zhang return ret; 288087abbaf9SPeng Zhang } 288187abbaf9SPeng Zhang 2882bb24eb38SPeng Zhang ret = nfp_net_vf_queues_config(net_hw, pf_dev); 2883bb24eb38SPeng Zhang if (ret != 0) { 2884b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to config vf queue."); 2885bb24eb38SPeng Zhang return ret; 2886bb24eb38SPeng Zhang } 2887bb24eb38SPeng Zhang 288887abbaf9SPeng Zhang return 0; 288987abbaf9SPeng Zhang } 2890636e133eSPeng Zhang 2891636e133eSPeng Zhang static inline bool 2892636e133eSPeng Zhang nfp_net_meta_has_no_port_type(__rte_unused struct nfp_net_meta_parsed *meta) 2893636e133eSPeng Zhang { 2894636e133eSPeng Zhang return true; 2895636e133eSPeng Zhang } 2896636e133eSPeng Zhang 2897636e133eSPeng Zhang static inline bool 2898636e133eSPeng Zhang nfp_net_meta_is_not_pf_port(__rte_unused struct nfp_net_meta_parsed *meta) 2899636e133eSPeng Zhang { 2900636e133eSPeng Zhang return false; 2901636e133eSPeng Zhang } 2902636e133eSPeng Zhang 2903636e133eSPeng Zhang static inline bool 2904636e133eSPeng Zhang nfp_net_meta_is_pf_port(struct nfp_net_meta_parsed *meta) 2905636e133eSPeng Zhang { 2906636e133eSPeng Zhang return nfp_flower_port_is_phy_port(meta->port_id); 2907636e133eSPeng Zhang } 2908636e133eSPeng Zhang 2909636e133eSPeng Zhang bool 2910636e133eSPeng Zhang nfp_net_recv_pkt_meta_check_register(struct nfp_net_hw_priv *hw_priv) 2911636e133eSPeng Zhang { 2912636e133eSPeng Zhang struct nfp_pf_dev *pf_dev; 2913636e133eSPeng Zhang 2914636e133eSPeng Zhang pf_dev = hw_priv->pf_dev; 2915636e133eSPeng Zhang if (!hw_priv->is_pf) { 2916636e133eSPeng Zhang pf_dev->recv_pkt_meta_check_t = nfp_net_meta_has_no_port_type; 2917636e133eSPeng Zhang return true; 2918636e133eSPeng Zhang } 2919636e133eSPeng Zhang 2920636e133eSPeng Zhang switch (pf_dev->app_fw_id) { 2921636e133eSPeng Zhang case NFP_APP_FW_CORE_NIC: 2922636e133eSPeng Zhang pf_dev->recv_pkt_meta_check_t = nfp_net_meta_has_no_port_type; 2923636e133eSPeng Zhang break; 2924636e133eSPeng Zhang case NFP_APP_FW_FLOWER_NIC: 2925636e133eSPeng Zhang if (pf_dev->multi_pf.enabled) 2926636e133eSPeng Zhang pf_dev->recv_pkt_meta_check_t = nfp_net_meta_is_pf_port; 2927636e133eSPeng Zhang else 2928636e133eSPeng Zhang pf_dev->recv_pkt_meta_check_t = nfp_net_meta_is_not_pf_port; 2929636e133eSPeng Zhang break; 2930636e133eSPeng Zhang default: 2931636e133eSPeng Zhang PMD_INIT_LOG(ERR, "Unsupported Firmware loaded."); 2932636e133eSPeng Zhang return false; 2933636e133eSPeng Zhang } 2934636e133eSPeng Zhang 2935636e133eSPeng Zhang return true; 2936636e133eSPeng Zhang } 29377f693813SChaoyong He 29387f693813SChaoyong He static int 29397f693813SChaoyong He nfp_net_get_nfp_index(struct rte_eth_dev *dev) 29407f693813SChaoyong He { 29417f693813SChaoyong He int nfp_idx; 29427f693813SChaoyong He 29437f693813SChaoyong He if (rte_eth_dev_is_repr(dev)) { 29447f693813SChaoyong He struct nfp_flower_representor *repr; 29457f693813SChaoyong He repr = dev->data->dev_private; 29467f693813SChaoyong He nfp_idx = repr->nfp_idx; 29477f693813SChaoyong He } else { 29487f693813SChaoyong He struct nfp_net_hw *net_hw; 29497f693813SChaoyong He net_hw = dev->data->dev_private; 29507f693813SChaoyong He nfp_idx = net_hw->nfp_idx; 29517f693813SChaoyong He } 29527f693813SChaoyong He 29537f693813SChaoyong He return nfp_idx; 29547f693813SChaoyong He } 29557f693813SChaoyong He 29567f693813SChaoyong He int 29577f693813SChaoyong He nfp_net_get_eeprom_len(__rte_unused struct rte_eth_dev *dev) 29587f693813SChaoyong He { 29597f693813SChaoyong He return RTE_ETHER_ADDR_LEN; 29607f693813SChaoyong He } 29617f693813SChaoyong He 29627f693813SChaoyong He static int 29637f693813SChaoyong He nfp_net_get_port_mac_hwinfo(struct nfp_net_hw_priv *hw_priv, 29647f693813SChaoyong He uint32_t index, 29657f693813SChaoyong He struct rte_ether_addr *mac_addr) 29667f693813SChaoyong He { 29677f693813SChaoyong He int ret; 29687f693813SChaoyong He char hwinfo[32]; 29697f693813SChaoyong He struct nfp_nsp *nsp; 29707f693813SChaoyong He 29717f693813SChaoyong He snprintf(hwinfo, sizeof(hwinfo), "eth%u.mac", index); 29727f693813SChaoyong He 29737f693813SChaoyong He nsp = nfp_nsp_open(hw_priv->pf_dev->cpp); 29747f693813SChaoyong He if (nsp == NULL) 29757f693813SChaoyong He return -EOPNOTSUPP; 29767f693813SChaoyong He 29777f693813SChaoyong He ret = nfp_nsp_hwinfo_lookup(nsp, hwinfo, sizeof(hwinfo)); 29787f693813SChaoyong He nfp_nsp_close(nsp); 29797f693813SChaoyong He 29807f693813SChaoyong He if (ret != 0) { 29817f693813SChaoyong He PMD_DRV_LOG(ERR, "Read persistent MAC address failed for eth_index %u.", index); 29827f693813SChaoyong He return ret; 29837f693813SChaoyong He } 29847f693813SChaoyong He 29857f693813SChaoyong He ret = rte_ether_unformat_addr(hwinfo, mac_addr); 29867f693813SChaoyong He if (ret != 0) { 29877f693813SChaoyong He PMD_DRV_LOG(ERR, "Can not parse persistent MAC address."); 29887f693813SChaoyong He return -EOPNOTSUPP; 29897f693813SChaoyong He } 29907f693813SChaoyong He 29917f693813SChaoyong He return 0; 29927f693813SChaoyong He } 29937f693813SChaoyong He 29947f693813SChaoyong He static int 29957f693813SChaoyong He nfp_net_set_port_mac_hwinfo(struct nfp_net_hw_priv *hw_priv, 29967f693813SChaoyong He uint32_t index, 29977f693813SChaoyong He struct rte_ether_addr *mac_addr) 29987f693813SChaoyong He { 29997f693813SChaoyong He int ret; 30007f693813SChaoyong He char hwinfo_mac[32]; 30017f693813SChaoyong He struct nfp_nsp *nsp; 30027f693813SChaoyong He char buf[RTE_ETHER_ADDR_FMT_SIZE]; 30037f693813SChaoyong He 30047f693813SChaoyong He rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, mac_addr); 30057f693813SChaoyong He snprintf(hwinfo_mac, sizeof(hwinfo_mac), "eth%u.mac=%s", index, buf); 30067f693813SChaoyong He 30077f693813SChaoyong He nsp = nfp_nsp_open(hw_priv->pf_dev->cpp); 30087f693813SChaoyong He if (nsp == NULL) 30097f693813SChaoyong He return -EOPNOTSUPP; 30107f693813SChaoyong He 30117f693813SChaoyong He ret = nfp_nsp_hwinfo_set(nsp, hwinfo_mac, sizeof(hwinfo_mac)); 30127f693813SChaoyong He nfp_nsp_close(nsp); 30137f693813SChaoyong He 30147f693813SChaoyong He if (ret != 0) { 30157f693813SChaoyong He PMD_DRV_LOG(ERR, "HWinfo set failed: %d.", ret); 30167f693813SChaoyong He return ret; 30177f693813SChaoyong He } 30187f693813SChaoyong He 30197f693813SChaoyong He return 0; 30207f693813SChaoyong He } 30217f693813SChaoyong He 30227f693813SChaoyong He int 30237f693813SChaoyong He nfp_net_get_eeprom(struct rte_eth_dev *dev, 30247f693813SChaoyong He struct rte_dev_eeprom_info *eeprom) 30257f693813SChaoyong He { 30267f693813SChaoyong He int ret; 30277f693813SChaoyong He uint32_t nfp_idx; 30287f693813SChaoyong He struct nfp_net_hw *net_hw; 30297f693813SChaoyong He struct rte_ether_addr mac_addr; 30307f693813SChaoyong He struct nfp_net_hw_priv *hw_priv; 30317f693813SChaoyong He 30327f693813SChaoyong He if (eeprom->length == 0) 30337f693813SChaoyong He return -EINVAL; 30347f693813SChaoyong He 30357f693813SChaoyong He hw_priv = dev->process_private; 30367f693813SChaoyong He nfp_idx = nfp_net_get_nfp_index(dev); 30377f693813SChaoyong He 30387f693813SChaoyong He ret = nfp_net_get_port_mac_hwinfo(hw_priv, nfp_idx, &mac_addr); 30397f693813SChaoyong He if (ret != 0) 30407f693813SChaoyong He return -EOPNOTSUPP; 30417f693813SChaoyong He 30427f693813SChaoyong He net_hw = nfp_net_get_hw(dev); 30437f693813SChaoyong He eeprom->magic = net_hw->vendor_id | (net_hw->device_id << 16); 30447f693813SChaoyong He memcpy(eeprom->data, mac_addr.addr_bytes + eeprom->offset, eeprom->length); 30457f693813SChaoyong He 30467f693813SChaoyong He return 0; 30477f693813SChaoyong He } 30487f693813SChaoyong He 30497f693813SChaoyong He int 30507f693813SChaoyong He nfp_net_set_eeprom(struct rte_eth_dev *dev, 30517f693813SChaoyong He struct rte_dev_eeprom_info *eeprom) 30527f693813SChaoyong He { 30537f693813SChaoyong He int ret; 30547f693813SChaoyong He uint32_t nfp_idx; 30557f693813SChaoyong He struct nfp_net_hw *net_hw; 30567f693813SChaoyong He struct rte_ether_addr mac_addr; 30577f693813SChaoyong He struct nfp_net_hw_priv *hw_priv; 30587f693813SChaoyong He 30597f693813SChaoyong He if (eeprom->length == 0) 30607f693813SChaoyong He return -EINVAL; 30617f693813SChaoyong He 30627f693813SChaoyong He net_hw = nfp_net_get_hw(dev); 30637f693813SChaoyong He if (eeprom->magic != (uint32_t)(net_hw->vendor_id | (net_hw->device_id << 16))) 30647f693813SChaoyong He return -EINVAL; 30657f693813SChaoyong He 30667f693813SChaoyong He hw_priv = dev->process_private; 30677f693813SChaoyong He nfp_idx = nfp_net_get_nfp_index(dev); 30687f693813SChaoyong He ret = nfp_net_get_port_mac_hwinfo(hw_priv, nfp_idx, &mac_addr); 30697f693813SChaoyong He if (ret != 0) 30707f693813SChaoyong He return -EOPNOTSUPP; 30717f693813SChaoyong He 30727f693813SChaoyong He memcpy(mac_addr.addr_bytes + eeprom->offset, eeprom->data, eeprom->length); 30737f693813SChaoyong He ret = nfp_net_set_port_mac_hwinfo(hw_priv, nfp_idx, &mac_addr); 30747f693813SChaoyong He if (ret != 0) 30757f693813SChaoyong He return -EOPNOTSUPP; 30767f693813SChaoyong He 30777f693813SChaoyong He return 0; 30787f693813SChaoyong He } 30797f693813SChaoyong He 30807f693813SChaoyong He int 30817f693813SChaoyong He nfp_net_get_module_info(struct rte_eth_dev *dev, 30827f693813SChaoyong He struct rte_eth_dev_module_info *info) 30837f693813SChaoyong He { 30847f693813SChaoyong He int ret = 0; 30857f693813SChaoyong He uint8_t data; 30867f693813SChaoyong He uint32_t idx; 30877f693813SChaoyong He uint32_t read_len; 30887f693813SChaoyong He struct nfp_nsp *nsp; 30897f693813SChaoyong He struct nfp_net_hw_priv *hw_priv; 30907f693813SChaoyong He struct nfp_eth_table_port *eth_port; 30917f693813SChaoyong He 30927f693813SChaoyong He hw_priv = dev->process_private; 30937f693813SChaoyong He nsp = nfp_nsp_open(hw_priv->pf_dev->cpp); 30947f693813SChaoyong He if (nsp == NULL) { 30957f693813SChaoyong He PMD_DRV_LOG(ERR, "Unable to open NSP."); 30967f693813SChaoyong He return -EIO; 30977f693813SChaoyong He } 30987f693813SChaoyong He 30997f693813SChaoyong He if (!nfp_nsp_has_read_module_eeprom(nsp)) { 31007f693813SChaoyong He PMD_DRV_LOG(ERR, "Read module eeprom not supported. Please update flash."); 31017f693813SChaoyong He ret = -EOPNOTSUPP; 31027f693813SChaoyong He goto exit_close_nsp; 31037f693813SChaoyong He } 31047f693813SChaoyong He 31057f693813SChaoyong He idx = nfp_net_get_idx(dev); 31067f693813SChaoyong He eth_port = &hw_priv->pf_dev->nfp_eth_table->ports[idx]; 31077f693813SChaoyong He switch (eth_port->interface) { 31087f693813SChaoyong He case NFP_INTERFACE_SFP: 31097f693813SChaoyong He /* FALLTHROUGH */ 31107f693813SChaoyong He case NFP_INTERFACE_SFP28: 31117f693813SChaoyong He /* Read which revision the transceiver compiles with */ 31127f693813SChaoyong He ret = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index, 31137f693813SChaoyong He SFP_SFF8472_COMPLIANCE, &data, 1, &read_len); 31147f693813SChaoyong He if (ret != 0) 31157f693813SChaoyong He goto exit_close_nsp; 31167f693813SChaoyong He 31177f693813SChaoyong He if (data == 0) { 31187f693813SChaoyong He info->type = RTE_ETH_MODULE_SFF_8079; 31197f693813SChaoyong He info->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; 31207f693813SChaoyong He } else { 31217f693813SChaoyong He info->type = RTE_ETH_MODULE_SFF_8472; 31227f693813SChaoyong He info->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; 31237f693813SChaoyong He } 31247f693813SChaoyong He break; 31257f693813SChaoyong He case NFP_INTERFACE_QSFP: 31267f693813SChaoyong He /* Read which revision the transceiver compiles with */ 31277f693813SChaoyong He ret = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index, 31287f693813SChaoyong He SFP_SFF_REV_COMPLIANCE, &data, 1, &read_len); 31297f693813SChaoyong He if (ret != 0) 31307f693813SChaoyong He goto exit_close_nsp; 31317f693813SChaoyong He 31327f693813SChaoyong He if (data == 0) { 31337f693813SChaoyong He info->type = RTE_ETH_MODULE_SFF_8436; 31347f693813SChaoyong He info->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN; 31357f693813SChaoyong He } else { 31367f693813SChaoyong He info->type = RTE_ETH_MODULE_SFF_8636; 31377f693813SChaoyong He info->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN; 31387f693813SChaoyong He } 31397f693813SChaoyong He break; 31407f693813SChaoyong He case NFP_INTERFACE_QSFP28: 31417f693813SChaoyong He info->type = RTE_ETH_MODULE_SFF_8636; 31427f693813SChaoyong He info->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN; 31437f693813SChaoyong He break; 31447f693813SChaoyong He default: 31457f693813SChaoyong He PMD_DRV_LOG(ERR, "Unsupported module %#x detected.", 31467f693813SChaoyong He eth_port->interface); 31477f693813SChaoyong He ret = -EINVAL; 31487f693813SChaoyong He } 31497f693813SChaoyong He 31507f693813SChaoyong He exit_close_nsp: 31517f693813SChaoyong He nfp_nsp_close(nsp); 31527f693813SChaoyong He return ret; 31537f693813SChaoyong He } 31547f693813SChaoyong He 31557f693813SChaoyong He int 31567f693813SChaoyong He nfp_net_get_module_eeprom(struct rte_eth_dev *dev, 31577f693813SChaoyong He struct rte_dev_eeprom_info *info) 31587f693813SChaoyong He { 31597f693813SChaoyong He int ret = 0; 31607f693813SChaoyong He uint32_t idx; 31617f693813SChaoyong He struct nfp_nsp *nsp; 31627f693813SChaoyong He struct nfp_net_hw_priv *hw_priv; 31637f693813SChaoyong He struct nfp_eth_table_port *eth_port; 31647f693813SChaoyong He 31657f693813SChaoyong He hw_priv = dev->process_private; 31667f693813SChaoyong He nsp = nfp_nsp_open(hw_priv->pf_dev->cpp); 31677f693813SChaoyong He if (nsp == NULL) { 31687f693813SChaoyong He PMD_DRV_LOG(ERR, "Unable to open NSP."); 31697f693813SChaoyong He return -EIO; 31707f693813SChaoyong He } 31717f693813SChaoyong He 31727f693813SChaoyong He if (!nfp_nsp_has_read_module_eeprom(nsp)) { 31737f693813SChaoyong He PMD_DRV_LOG(ERR, "Read module eeprom not supported. Please update flash."); 31747f693813SChaoyong He ret = -EOPNOTSUPP; 31757f693813SChaoyong He goto exit_close_nsp; 31767f693813SChaoyong He } 31777f693813SChaoyong He 31787f693813SChaoyong He idx = nfp_net_get_idx(dev); 31797f693813SChaoyong He eth_port = &hw_priv->pf_dev->nfp_eth_table->ports[idx]; 31807f693813SChaoyong He ret = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index, info->offset, 31817f693813SChaoyong He info->data, info->length, &info->length); 31827f693813SChaoyong He if (ret != 0) { 31837f693813SChaoyong He if (info->length) 31847f693813SChaoyong He PMD_DRV_LOG(ERR, "Incomplete read from module EEPROM: %d.", ret); 31857f693813SChaoyong He else 31867f693813SChaoyong He PMD_DRV_LOG(ERR, "Read from module EEPROM failed: %d.", ret); 31877f693813SChaoyong He } 31887f693813SChaoyong He 31897f693813SChaoyong He exit_close_nsp: 31907f693813SChaoyong He nfp_nsp_close(nsp); 31917f693813SChaoyong He return ret; 31927f693813SChaoyong He } 31938bd6f540SChaoyong He 31948bd6f540SChaoyong He static int 31958bd6f540SChaoyong He nfp_net_led_control(struct rte_eth_dev *dev, 31968bd6f540SChaoyong He bool is_on) 31978bd6f540SChaoyong He { 31988bd6f540SChaoyong He int ret; 31998bd6f540SChaoyong He uint32_t nfp_idx; 32008bd6f540SChaoyong He struct nfp_net_hw_priv *hw_priv; 32018bd6f540SChaoyong He 32028bd6f540SChaoyong He hw_priv = dev->process_private; 32038bd6f540SChaoyong He nfp_idx = nfp_net_get_nfp_index(dev); 32048bd6f540SChaoyong He 32058bd6f540SChaoyong He ret = nfp_eth_set_idmode(hw_priv->pf_dev->cpp, nfp_idx, is_on); 32068bd6f540SChaoyong He if (ret < 0) { 32078bd6f540SChaoyong He PMD_DRV_LOG(ERR, "Set nfp idmode failed."); 32088bd6f540SChaoyong He return ret; 32098bd6f540SChaoyong He } 32108bd6f540SChaoyong He 32118bd6f540SChaoyong He return 0; 32128bd6f540SChaoyong He } 32138bd6f540SChaoyong He 32148bd6f540SChaoyong He int 32158bd6f540SChaoyong He nfp_net_led_on(struct rte_eth_dev *dev) 32168bd6f540SChaoyong He { 32178bd6f540SChaoyong He return nfp_net_led_control(dev, true); 32188bd6f540SChaoyong He } 32198bd6f540SChaoyong He 32208bd6f540SChaoyong He int 32218bd6f540SChaoyong He nfp_net_led_off(struct rte_eth_dev *dev) 32228bd6f540SChaoyong He { 32238bd6f540SChaoyong He return nfp_net_led_control(dev, false); 32248bd6f540SChaoyong He } 3225