1e4387966SJerin Jacob /* 2e4387966SJerin Jacob * BSD LICENSE 3e4387966SJerin Jacob * 4e4387966SJerin Jacob * Copyright (C) Cavium networks Ltd. 2016. 5e4387966SJerin Jacob * 6e4387966SJerin Jacob * Redistribution and use in source and binary forms, with or without 7e4387966SJerin Jacob * modification, are permitted provided that the following conditions 8e4387966SJerin Jacob * are met: 9e4387966SJerin Jacob * 10e4387966SJerin Jacob * * Redistributions of source code must retain the above copyright 11e4387966SJerin Jacob * notice, this list of conditions and the following disclaimer. 12e4387966SJerin Jacob * * Redistributions in binary form must reproduce the above copyright 13e4387966SJerin Jacob * notice, this list of conditions and the following disclaimer in 14e4387966SJerin Jacob * the documentation and/or other materials provided with the 15e4387966SJerin Jacob * distribution. 16e4387966SJerin Jacob * * Neither the name of Cavium networks nor the names of its 17e4387966SJerin Jacob * contributors may be used to endorse or promote products derived 18e4387966SJerin Jacob * from this software without specific prior written permission. 19e4387966SJerin Jacob * 20e4387966SJerin Jacob * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21e4387966SJerin Jacob * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22e4387966SJerin Jacob * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23e4387966SJerin Jacob * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24e4387966SJerin Jacob * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25e4387966SJerin Jacob * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26e4387966SJerin Jacob * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27e4387966SJerin Jacob * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28e4387966SJerin Jacob * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29e4387966SJerin Jacob * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30e4387966SJerin Jacob * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31e4387966SJerin Jacob */ 32e4387966SJerin Jacob 33e4387966SJerin Jacob #include <assert.h> 34e4387966SJerin Jacob #include <stdio.h> 35e4387966SJerin Jacob #include <stdbool.h> 36e4387966SJerin Jacob #include <errno.h> 37e4387966SJerin Jacob #include <stdint.h> 38e4387966SJerin Jacob #include <string.h> 39e4387966SJerin Jacob #include <unistd.h> 40e4387966SJerin Jacob #include <stdarg.h> 41e4387966SJerin Jacob #include <inttypes.h> 42e4387966SJerin Jacob #include <netinet/in.h> 43e4387966SJerin Jacob #include <sys/queue.h> 44e4387966SJerin Jacob #include <sys/timerfd.h> 45e4387966SJerin Jacob 46e4387966SJerin Jacob #include <rte_alarm.h> 47e4387966SJerin Jacob #include <rte_atomic.h> 48e4387966SJerin Jacob #include <rte_branch_prediction.h> 49e4387966SJerin Jacob #include <rte_byteorder.h> 50e4387966SJerin Jacob #include <rte_common.h> 51e4387966SJerin Jacob #include <rte_cycles.h> 52e4387966SJerin Jacob #include <rte_debug.h> 53e4387966SJerin Jacob #include <rte_dev.h> 54e4387966SJerin Jacob #include <rte_eal.h> 55e4387966SJerin Jacob #include <rte_ether.h> 56e4387966SJerin Jacob #include <rte_ethdev.h> 57e4387966SJerin Jacob #include <rte_interrupts.h> 58e4387966SJerin Jacob #include <rte_log.h> 59e4387966SJerin Jacob #include <rte_memory.h> 60e4387966SJerin Jacob #include <rte_memzone.h> 61e4387966SJerin Jacob #include <rte_malloc.h> 62e4387966SJerin Jacob #include <rte_random.h> 63e4387966SJerin Jacob #include <rte_pci.h> 64e4387966SJerin Jacob #include <rte_tailq.h> 65e4387966SJerin Jacob 66e4387966SJerin Jacob #include "base/nicvf_plat.h" 67e4387966SJerin Jacob 68e4387966SJerin Jacob #include "nicvf_ethdev.h" 691c421f18SJerin Jacob #include "nicvf_rxtx.h" 70e4387966SJerin Jacob #include "nicvf_logs.h" 71e4387966SJerin Jacob 728fc70464SJerin Jacob static inline int 738fc70464SJerin Jacob nicvf_atomic_write_link_status(struct rte_eth_dev *dev, 748fc70464SJerin Jacob struct rte_eth_link *link) 758fc70464SJerin Jacob { 768fc70464SJerin Jacob struct rte_eth_link *dst = &dev->data->dev_link; 778fc70464SJerin Jacob struct rte_eth_link *src = link; 788fc70464SJerin Jacob 798fc70464SJerin Jacob if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, 808fc70464SJerin Jacob *(uint64_t *)src) == 0) 818fc70464SJerin Jacob return -1; 828fc70464SJerin Jacob 838fc70464SJerin Jacob return 0; 848fc70464SJerin Jacob } 858fc70464SJerin Jacob 868fc70464SJerin Jacob static inline void 878fc70464SJerin Jacob nicvf_set_eth_link_status(struct nicvf *nic, struct rte_eth_link *link) 888fc70464SJerin Jacob { 898fc70464SJerin Jacob link->link_status = nic->link_up; 908fc70464SJerin Jacob link->link_duplex = ETH_LINK_AUTONEG; 918fc70464SJerin Jacob if (nic->duplex == NICVF_HALF_DUPLEX) 928fc70464SJerin Jacob link->link_duplex = ETH_LINK_HALF_DUPLEX; 938fc70464SJerin Jacob else if (nic->duplex == NICVF_FULL_DUPLEX) 948fc70464SJerin Jacob link->link_duplex = ETH_LINK_FULL_DUPLEX; 958fc70464SJerin Jacob link->link_speed = nic->speed; 968fc70464SJerin Jacob link->link_autoneg = ETH_LINK_SPEED_AUTONEG; 978fc70464SJerin Jacob } 988fc70464SJerin Jacob 99e4387966SJerin Jacob static void 100e4387966SJerin Jacob nicvf_interrupt(void *arg) 101e4387966SJerin Jacob { 102e4387966SJerin Jacob struct nicvf *nic = arg; 103e4387966SJerin Jacob 1048fc70464SJerin Jacob if (nicvf_reg_poll_interrupts(nic) == NIC_MBOX_MSG_BGX_LINK_CHANGE) { 1058fc70464SJerin Jacob if (nic->eth_dev->data->dev_conf.intr_conf.lsc) 1068fc70464SJerin Jacob nicvf_set_eth_link_status(nic, 1078fc70464SJerin Jacob &nic->eth_dev->data->dev_link); 1088fc70464SJerin Jacob _rte_eth_dev_callback_process(nic->eth_dev, 1098fc70464SJerin Jacob RTE_ETH_EVENT_INTR_LSC); 1108fc70464SJerin Jacob } 111e4387966SJerin Jacob 112e4387966SJerin Jacob rte_eal_alarm_set(NICVF_INTR_POLL_INTERVAL_MS * 1000, 113e4387966SJerin Jacob nicvf_interrupt, nic); 114e4387966SJerin Jacob } 115e4387966SJerin Jacob 116e4387966SJerin Jacob static int 117e4387966SJerin Jacob nicvf_periodic_alarm_start(struct nicvf *nic) 118e4387966SJerin Jacob { 119e4387966SJerin Jacob return rte_eal_alarm_set(NICVF_INTR_POLL_INTERVAL_MS * 1000, 120e4387966SJerin Jacob nicvf_interrupt, nic); 121e4387966SJerin Jacob } 122e4387966SJerin Jacob 123e4387966SJerin Jacob static int 124e4387966SJerin Jacob nicvf_periodic_alarm_stop(struct nicvf *nic) 125e4387966SJerin Jacob { 126e4387966SJerin Jacob return rte_eal_alarm_cancel(nicvf_interrupt, nic); 127e4387966SJerin Jacob } 128e4387966SJerin Jacob 1298fc70464SJerin Jacob /* 1308fc70464SJerin Jacob * Return 0 means link status changed, -1 means not changed 1318fc70464SJerin Jacob */ 1328fc70464SJerin Jacob static int 1338fc70464SJerin Jacob nicvf_dev_link_update(struct rte_eth_dev *dev, 1348fc70464SJerin Jacob int wait_to_complete __rte_unused) 1358fc70464SJerin Jacob { 1368fc70464SJerin Jacob struct rte_eth_link link; 1378fc70464SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 1388fc70464SJerin Jacob 1398fc70464SJerin Jacob PMD_INIT_FUNC_TRACE(); 1408fc70464SJerin Jacob 1418fc70464SJerin Jacob memset(&link, 0, sizeof(link)); 1428fc70464SJerin Jacob nicvf_set_eth_link_status(nic, &link); 1438fc70464SJerin Jacob return nicvf_atomic_write_link_status(dev, &link); 1448fc70464SJerin Jacob } 1458fc70464SJerin Jacob 146606ee746SJerin Jacob static int 14765d9804eSJerin Jacob nicvf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 14865d9804eSJerin Jacob { 14965d9804eSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 15065d9804eSJerin Jacob uint32_t buffsz, frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 15165d9804eSJerin Jacob 15265d9804eSJerin Jacob PMD_INIT_FUNC_TRACE(); 15365d9804eSJerin Jacob 15465d9804eSJerin Jacob if (frame_size > NIC_HW_MAX_FRS) 15565d9804eSJerin Jacob return -EINVAL; 15665d9804eSJerin Jacob 15765d9804eSJerin Jacob if (frame_size < NIC_HW_MIN_FRS) 15865d9804eSJerin Jacob return -EINVAL; 15965d9804eSJerin Jacob 16065d9804eSJerin Jacob buffsz = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM; 16165d9804eSJerin Jacob 16265d9804eSJerin Jacob /* 16365d9804eSJerin Jacob * Refuse mtu that requires the support of scattered packets 16465d9804eSJerin Jacob * when this feature has not been enabled before. 16565d9804eSJerin Jacob */ 16665d9804eSJerin Jacob if (!dev->data->scattered_rx && 16765d9804eSJerin Jacob (frame_size + 2 * VLAN_TAG_SIZE > buffsz)) 16865d9804eSJerin Jacob return -EINVAL; 16965d9804eSJerin Jacob 17065d9804eSJerin Jacob /* check <seg size> * <max_seg> >= max_frame */ 17165d9804eSJerin Jacob if (dev->data->scattered_rx && 17265d9804eSJerin Jacob (frame_size + 2 * VLAN_TAG_SIZE > buffsz * NIC_HW_MAX_SEGS)) 17365d9804eSJerin Jacob return -EINVAL; 17465d9804eSJerin Jacob 17565d9804eSJerin Jacob if (frame_size > ETHER_MAX_LEN) 17665d9804eSJerin Jacob dev->data->dev_conf.rxmode.jumbo_frame = 1; 17765d9804eSJerin Jacob else 17865d9804eSJerin Jacob dev->data->dev_conf.rxmode.jumbo_frame = 0; 17965d9804eSJerin Jacob 18065d9804eSJerin Jacob if (nicvf_mbox_update_hw_max_frs(nic, frame_size)) 18165d9804eSJerin Jacob return -EINVAL; 18265d9804eSJerin Jacob 18365d9804eSJerin Jacob /* Update max frame size */ 18465d9804eSJerin Jacob dev->data->dev_conf.rxmode.max_rx_pkt_len = (uint32_t)frame_size; 18565d9804eSJerin Jacob nic->mtu = mtu; 18665d9804eSJerin Jacob return 0; 18765d9804eSJerin Jacob } 18865d9804eSJerin Jacob 18965d9804eSJerin Jacob static int 190606ee746SJerin Jacob nicvf_dev_get_reg_length(struct rte_eth_dev *dev __rte_unused) 191606ee746SJerin Jacob { 192606ee746SJerin Jacob return nicvf_reg_get_count(); 193606ee746SJerin Jacob } 194606ee746SJerin Jacob 195606ee746SJerin Jacob static int 196606ee746SJerin Jacob nicvf_dev_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs) 197606ee746SJerin Jacob { 198606ee746SJerin Jacob uint64_t *data = regs->data; 199606ee746SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 200606ee746SJerin Jacob 201606ee746SJerin Jacob if (data == NULL) 202606ee746SJerin Jacob return -EINVAL; 203606ee746SJerin Jacob 204606ee746SJerin Jacob /* Support only full register dump */ 205606ee746SJerin Jacob if ((regs->length == 0) || 206606ee746SJerin Jacob (regs->length == (uint32_t)nicvf_reg_get_count())) { 207606ee746SJerin Jacob regs->version = nic->vendor_id << 16 | nic->device_id; 208606ee746SJerin Jacob nicvf_reg_dump(nic, data); 209606ee746SJerin Jacob return 0; 210606ee746SJerin Jacob } 211606ee746SJerin Jacob return -ENOTSUP; 212606ee746SJerin Jacob } 213606ee746SJerin Jacob 214684fa771SJerin Jacob static void 215684fa771SJerin Jacob nicvf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 216684fa771SJerin Jacob { 217684fa771SJerin Jacob uint16_t qidx; 218684fa771SJerin Jacob struct nicvf_hw_rx_qstats rx_qstats; 219684fa771SJerin Jacob struct nicvf_hw_tx_qstats tx_qstats; 220684fa771SJerin Jacob struct nicvf_hw_stats port_stats; 221684fa771SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 222684fa771SJerin Jacob 223684fa771SJerin Jacob /* Reading per RX ring stats */ 224684fa771SJerin Jacob for (qidx = 0; qidx < dev->data->nb_rx_queues; qidx++) { 225684fa771SJerin Jacob if (qidx == RTE_ETHDEV_QUEUE_STAT_CNTRS) 226684fa771SJerin Jacob break; 227684fa771SJerin Jacob 228684fa771SJerin Jacob nicvf_hw_get_rx_qstats(nic, &rx_qstats, qidx); 229684fa771SJerin Jacob stats->q_ibytes[qidx] = rx_qstats.q_rx_bytes; 230684fa771SJerin Jacob stats->q_ipackets[qidx] = rx_qstats.q_rx_packets; 231684fa771SJerin Jacob } 232684fa771SJerin Jacob 233684fa771SJerin Jacob /* Reading per TX ring stats */ 234684fa771SJerin Jacob for (qidx = 0; qidx < dev->data->nb_tx_queues; qidx++) { 235684fa771SJerin Jacob if (qidx == RTE_ETHDEV_QUEUE_STAT_CNTRS) 236684fa771SJerin Jacob break; 237684fa771SJerin Jacob 238684fa771SJerin Jacob nicvf_hw_get_tx_qstats(nic, &tx_qstats, qidx); 239684fa771SJerin Jacob stats->q_obytes[qidx] = tx_qstats.q_tx_bytes; 240684fa771SJerin Jacob stats->q_opackets[qidx] = tx_qstats.q_tx_packets; 241684fa771SJerin Jacob } 242684fa771SJerin Jacob 243684fa771SJerin Jacob nicvf_hw_get_stats(nic, &port_stats); 244684fa771SJerin Jacob stats->ibytes = port_stats.rx_bytes; 245684fa771SJerin Jacob stats->ipackets = port_stats.rx_ucast_frames; 246684fa771SJerin Jacob stats->ipackets += port_stats.rx_bcast_frames; 247684fa771SJerin Jacob stats->ipackets += port_stats.rx_mcast_frames; 248684fa771SJerin Jacob stats->ierrors = port_stats.rx_l2_errors; 249684fa771SJerin Jacob stats->imissed = port_stats.rx_drop_red; 250684fa771SJerin Jacob stats->imissed += port_stats.rx_drop_overrun; 251684fa771SJerin Jacob stats->imissed += port_stats.rx_drop_bcast; 252684fa771SJerin Jacob stats->imissed += port_stats.rx_drop_mcast; 253684fa771SJerin Jacob stats->imissed += port_stats.rx_drop_l3_bcast; 254684fa771SJerin Jacob stats->imissed += port_stats.rx_drop_l3_mcast; 255684fa771SJerin Jacob 256684fa771SJerin Jacob stats->obytes = port_stats.tx_bytes_ok; 257684fa771SJerin Jacob stats->opackets = port_stats.tx_ucast_frames_ok; 258684fa771SJerin Jacob stats->opackets += port_stats.tx_bcast_frames_ok; 259684fa771SJerin Jacob stats->opackets += port_stats.tx_mcast_frames_ok; 260684fa771SJerin Jacob stats->oerrors = port_stats.tx_drops; 261684fa771SJerin Jacob } 262684fa771SJerin Jacob 263*1c80e4fdSJerin Jacob static const uint32_t * 264*1c80e4fdSJerin Jacob nicvf_dev_supported_ptypes_get(struct rte_eth_dev *dev) 265*1c80e4fdSJerin Jacob { 266*1c80e4fdSJerin Jacob size_t copied; 267*1c80e4fdSJerin Jacob static uint32_t ptypes[32]; 268*1c80e4fdSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 269*1c80e4fdSJerin Jacob static const uint32_t ptypes_pass1[] = { 270*1c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV4, 271*1c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV4_EXT, 272*1c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV6, 273*1c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV6_EXT, 274*1c80e4fdSJerin Jacob RTE_PTYPE_L4_TCP, 275*1c80e4fdSJerin Jacob RTE_PTYPE_L4_UDP, 276*1c80e4fdSJerin Jacob RTE_PTYPE_L4_FRAG, 277*1c80e4fdSJerin Jacob }; 278*1c80e4fdSJerin Jacob static const uint32_t ptypes_pass2[] = { 279*1c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_GRE, 280*1c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_GENEVE, 281*1c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_VXLAN, 282*1c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_NVGRE, 283*1c80e4fdSJerin Jacob }; 284*1c80e4fdSJerin Jacob static const uint32_t ptypes_end = RTE_PTYPE_UNKNOWN; 285*1c80e4fdSJerin Jacob 286*1c80e4fdSJerin Jacob copied = sizeof(ptypes_pass1); 287*1c80e4fdSJerin Jacob memcpy(ptypes, ptypes_pass1, copied); 288*1c80e4fdSJerin Jacob if (nicvf_hw_version(nic) == NICVF_PASS2) { 289*1c80e4fdSJerin Jacob memcpy((char *)ptypes + copied, ptypes_pass2, 290*1c80e4fdSJerin Jacob sizeof(ptypes_pass2)); 291*1c80e4fdSJerin Jacob copied += sizeof(ptypes_pass2); 292*1c80e4fdSJerin Jacob } 293*1c80e4fdSJerin Jacob 294*1c80e4fdSJerin Jacob memcpy((char *)ptypes + copied, &ptypes_end, sizeof(ptypes_end)); 295*1c80e4fdSJerin Jacob if (dev->rx_pkt_burst == nicvf_recv_pkts || 296*1c80e4fdSJerin Jacob dev->rx_pkt_burst == nicvf_recv_pkts_multiseg) 297*1c80e4fdSJerin Jacob return ptypes; 298*1c80e4fdSJerin Jacob 299*1c80e4fdSJerin Jacob return NULL; 300*1c80e4fdSJerin Jacob } 301*1c80e4fdSJerin Jacob 302684fa771SJerin Jacob static void 303684fa771SJerin Jacob nicvf_dev_stats_reset(struct rte_eth_dev *dev) 304684fa771SJerin Jacob { 305684fa771SJerin Jacob int i; 306684fa771SJerin Jacob uint16_t rxqs = 0, txqs = 0; 307684fa771SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 308684fa771SJerin Jacob 309684fa771SJerin Jacob for (i = 0; i < dev->data->nb_rx_queues; i++) 310684fa771SJerin Jacob rxqs |= (0x3 << (i * 2)); 311684fa771SJerin Jacob for (i = 0; i < dev->data->nb_tx_queues; i++) 312684fa771SJerin Jacob txqs |= (0x3 << (i * 2)); 313684fa771SJerin Jacob 314684fa771SJerin Jacob nicvf_mbox_reset_stat_counters(nic, 0x3FFF, 0x1F, rxqs, txqs); 315684fa771SJerin Jacob } 316684fa771SJerin Jacob 3176eae36eaSJerin Jacob /* Promiscuous mode enabled by default in LMAC to VF 1:1 map configuration */ 3186eae36eaSJerin Jacob static void 3196eae36eaSJerin Jacob nicvf_dev_promisc_enable(struct rte_eth_dev *dev __rte_unused) 3206eae36eaSJerin Jacob { 3216eae36eaSJerin Jacob } 3226eae36eaSJerin Jacob 32343362c6aSJerin Jacob static inline uint64_t 32443362c6aSJerin Jacob nicvf_rss_ethdev_to_nic(struct nicvf *nic, uint64_t ethdev_rss) 32543362c6aSJerin Jacob { 32643362c6aSJerin Jacob uint64_t nic_rss = 0; 32743362c6aSJerin Jacob 32843362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_IPV4) 32943362c6aSJerin Jacob nic_rss |= RSS_IP_ENA; 33043362c6aSJerin Jacob 33143362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_IPV6) 33243362c6aSJerin Jacob nic_rss |= RSS_IP_ENA; 33343362c6aSJerin Jacob 33443362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_NONFRAG_IPV4_UDP) 33543362c6aSJerin Jacob nic_rss |= (RSS_IP_ENA | RSS_UDP_ENA); 33643362c6aSJerin Jacob 33743362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_NONFRAG_IPV4_TCP) 33843362c6aSJerin Jacob nic_rss |= (RSS_IP_ENA | RSS_TCP_ENA); 33943362c6aSJerin Jacob 34043362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_NONFRAG_IPV6_UDP) 34143362c6aSJerin Jacob nic_rss |= (RSS_IP_ENA | RSS_UDP_ENA); 34243362c6aSJerin Jacob 34343362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_NONFRAG_IPV6_TCP) 34443362c6aSJerin Jacob nic_rss |= (RSS_IP_ENA | RSS_TCP_ENA); 34543362c6aSJerin Jacob 34643362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_PORT) 34743362c6aSJerin Jacob nic_rss |= RSS_L2_EXTENDED_HASH_ENA; 34843362c6aSJerin Jacob 34943362c6aSJerin Jacob if (nicvf_hw_cap(nic) & NICVF_CAP_TUNNEL_PARSING) { 35043362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_VXLAN) 35143362c6aSJerin Jacob nic_rss |= RSS_TUN_VXLAN_ENA; 35243362c6aSJerin Jacob 35343362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_GENEVE) 35443362c6aSJerin Jacob nic_rss |= RSS_TUN_GENEVE_ENA; 35543362c6aSJerin Jacob 35643362c6aSJerin Jacob if (ethdev_rss & ETH_RSS_NVGRE) 35743362c6aSJerin Jacob nic_rss |= RSS_TUN_NVGRE_ENA; 35843362c6aSJerin Jacob } 35943362c6aSJerin Jacob 36043362c6aSJerin Jacob return nic_rss; 36143362c6aSJerin Jacob } 36243362c6aSJerin Jacob 36343362c6aSJerin Jacob static inline uint64_t 36443362c6aSJerin Jacob nicvf_rss_nic_to_ethdev(struct nicvf *nic, uint64_t nic_rss) 36543362c6aSJerin Jacob { 36643362c6aSJerin Jacob uint64_t ethdev_rss = 0; 36743362c6aSJerin Jacob 36843362c6aSJerin Jacob if (nic_rss & RSS_IP_ENA) 36943362c6aSJerin Jacob ethdev_rss |= (ETH_RSS_IPV4 | ETH_RSS_IPV6); 37043362c6aSJerin Jacob 37143362c6aSJerin Jacob if ((nic_rss & RSS_IP_ENA) && (nic_rss & RSS_TCP_ENA)) 37243362c6aSJerin Jacob ethdev_rss |= (ETH_RSS_NONFRAG_IPV4_TCP | 37343362c6aSJerin Jacob ETH_RSS_NONFRAG_IPV6_TCP); 37443362c6aSJerin Jacob 37543362c6aSJerin Jacob if ((nic_rss & RSS_IP_ENA) && (nic_rss & RSS_UDP_ENA)) 37643362c6aSJerin Jacob ethdev_rss |= (ETH_RSS_NONFRAG_IPV4_UDP | 37743362c6aSJerin Jacob ETH_RSS_NONFRAG_IPV6_UDP); 37843362c6aSJerin Jacob 37943362c6aSJerin Jacob if (nic_rss & RSS_L2_EXTENDED_HASH_ENA) 38043362c6aSJerin Jacob ethdev_rss |= ETH_RSS_PORT; 38143362c6aSJerin Jacob 38243362c6aSJerin Jacob if (nicvf_hw_cap(nic) & NICVF_CAP_TUNNEL_PARSING) { 38343362c6aSJerin Jacob if (nic_rss & RSS_TUN_VXLAN_ENA) 38443362c6aSJerin Jacob ethdev_rss |= ETH_RSS_VXLAN; 38543362c6aSJerin Jacob 38643362c6aSJerin Jacob if (nic_rss & RSS_TUN_GENEVE_ENA) 38743362c6aSJerin Jacob ethdev_rss |= ETH_RSS_GENEVE; 38843362c6aSJerin Jacob 38943362c6aSJerin Jacob if (nic_rss & RSS_TUN_NVGRE_ENA) 39043362c6aSJerin Jacob ethdev_rss |= ETH_RSS_NVGRE; 39143362c6aSJerin Jacob } 39243362c6aSJerin Jacob return ethdev_rss; 39343362c6aSJerin Jacob } 39443362c6aSJerin Jacob 39543362c6aSJerin Jacob static int 39643362c6aSJerin Jacob nicvf_dev_reta_query(struct rte_eth_dev *dev, 39743362c6aSJerin Jacob struct rte_eth_rss_reta_entry64 *reta_conf, 39843362c6aSJerin Jacob uint16_t reta_size) 39943362c6aSJerin Jacob { 40043362c6aSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 40143362c6aSJerin Jacob uint8_t tbl[NIC_MAX_RSS_IDR_TBL_SIZE]; 40243362c6aSJerin Jacob int ret, i, j; 40343362c6aSJerin Jacob 40443362c6aSJerin Jacob if (reta_size != NIC_MAX_RSS_IDR_TBL_SIZE) { 40543362c6aSJerin Jacob RTE_LOG(ERR, PMD, "The size of hash lookup table configured " 40643362c6aSJerin Jacob "(%d) doesn't match the number hardware can supported " 40743362c6aSJerin Jacob "(%d)", reta_size, NIC_MAX_RSS_IDR_TBL_SIZE); 40843362c6aSJerin Jacob return -EINVAL; 40943362c6aSJerin Jacob } 41043362c6aSJerin Jacob 41143362c6aSJerin Jacob ret = nicvf_rss_reta_query(nic, tbl, NIC_MAX_RSS_IDR_TBL_SIZE); 41243362c6aSJerin Jacob if (ret) 41343362c6aSJerin Jacob return ret; 41443362c6aSJerin Jacob 41543362c6aSJerin Jacob /* Copy RETA table */ 41643362c6aSJerin Jacob for (i = 0; i < (NIC_MAX_RSS_IDR_TBL_SIZE / RTE_RETA_GROUP_SIZE); i++) { 41743362c6aSJerin Jacob for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) 41843362c6aSJerin Jacob if ((reta_conf[i].mask >> j) & 0x01) 41943362c6aSJerin Jacob reta_conf[i].reta[j] = tbl[j]; 42043362c6aSJerin Jacob } 42143362c6aSJerin Jacob 42243362c6aSJerin Jacob return 0; 42343362c6aSJerin Jacob } 42443362c6aSJerin Jacob 42543362c6aSJerin Jacob static int 42643362c6aSJerin Jacob nicvf_dev_reta_update(struct rte_eth_dev *dev, 42743362c6aSJerin Jacob struct rte_eth_rss_reta_entry64 *reta_conf, 42843362c6aSJerin Jacob uint16_t reta_size) 42943362c6aSJerin Jacob { 43043362c6aSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 43143362c6aSJerin Jacob uint8_t tbl[NIC_MAX_RSS_IDR_TBL_SIZE]; 43243362c6aSJerin Jacob int ret, i, j; 43343362c6aSJerin Jacob 43443362c6aSJerin Jacob if (reta_size != NIC_MAX_RSS_IDR_TBL_SIZE) { 43543362c6aSJerin Jacob RTE_LOG(ERR, PMD, "The size of hash lookup table configured " 43643362c6aSJerin Jacob "(%d) doesn't match the number hardware can supported " 43743362c6aSJerin Jacob "(%d)", reta_size, NIC_MAX_RSS_IDR_TBL_SIZE); 43843362c6aSJerin Jacob return -EINVAL; 43943362c6aSJerin Jacob } 44043362c6aSJerin Jacob 44143362c6aSJerin Jacob ret = nicvf_rss_reta_query(nic, tbl, NIC_MAX_RSS_IDR_TBL_SIZE); 44243362c6aSJerin Jacob if (ret) 44343362c6aSJerin Jacob return ret; 44443362c6aSJerin Jacob 44543362c6aSJerin Jacob /* Copy RETA table */ 44643362c6aSJerin Jacob for (i = 0; i < (NIC_MAX_RSS_IDR_TBL_SIZE / RTE_RETA_GROUP_SIZE); i++) { 44743362c6aSJerin Jacob for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) 44843362c6aSJerin Jacob if ((reta_conf[i].mask >> j) & 0x01) 44943362c6aSJerin Jacob tbl[j] = reta_conf[i].reta[j]; 45043362c6aSJerin Jacob } 45143362c6aSJerin Jacob 45243362c6aSJerin Jacob return nicvf_rss_reta_update(nic, tbl, NIC_MAX_RSS_IDR_TBL_SIZE); 45343362c6aSJerin Jacob } 45443362c6aSJerin Jacob 45543362c6aSJerin Jacob static int 45643362c6aSJerin Jacob nicvf_dev_rss_hash_conf_get(struct rte_eth_dev *dev, 45743362c6aSJerin Jacob struct rte_eth_rss_conf *rss_conf) 45843362c6aSJerin Jacob { 45943362c6aSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 46043362c6aSJerin Jacob 46143362c6aSJerin Jacob if (rss_conf->rss_key) 46243362c6aSJerin Jacob nicvf_rss_get_key(nic, rss_conf->rss_key); 46343362c6aSJerin Jacob 46443362c6aSJerin Jacob rss_conf->rss_key_len = RSS_HASH_KEY_BYTE_SIZE; 46543362c6aSJerin Jacob rss_conf->rss_hf = nicvf_rss_nic_to_ethdev(nic, nicvf_rss_get_cfg(nic)); 46643362c6aSJerin Jacob return 0; 46743362c6aSJerin Jacob } 46843362c6aSJerin Jacob 46943362c6aSJerin Jacob static int 47043362c6aSJerin Jacob nicvf_dev_rss_hash_update(struct rte_eth_dev *dev, 47143362c6aSJerin Jacob struct rte_eth_rss_conf *rss_conf) 47243362c6aSJerin Jacob { 47343362c6aSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 47443362c6aSJerin Jacob uint64_t nic_rss; 47543362c6aSJerin Jacob 47643362c6aSJerin Jacob if (rss_conf->rss_key && 47743362c6aSJerin Jacob rss_conf->rss_key_len != RSS_HASH_KEY_BYTE_SIZE) { 47843362c6aSJerin Jacob RTE_LOG(ERR, PMD, "Hash key size mismatch %d", 47943362c6aSJerin Jacob rss_conf->rss_key_len); 48043362c6aSJerin Jacob return -EINVAL; 48143362c6aSJerin Jacob } 48243362c6aSJerin Jacob 48343362c6aSJerin Jacob if (rss_conf->rss_key) 48443362c6aSJerin Jacob nicvf_rss_set_key(nic, rss_conf->rss_key); 48543362c6aSJerin Jacob 48643362c6aSJerin Jacob nic_rss = nicvf_rss_ethdev_to_nic(nic, rss_conf->rss_hf); 48743362c6aSJerin Jacob nicvf_rss_set_cfg(nic, nic_rss); 48843362c6aSJerin Jacob return 0; 48943362c6aSJerin Jacob } 49043362c6aSJerin Jacob 491aa0d976eSJerin Jacob static int 492aa0d976eSJerin Jacob nicvf_qset_cq_alloc(struct nicvf *nic, struct nicvf_rxq *rxq, uint16_t qidx, 493aa0d976eSJerin Jacob uint32_t desc_cnt) 494aa0d976eSJerin Jacob { 495aa0d976eSJerin Jacob const struct rte_memzone *rz; 496aa0d976eSJerin Jacob uint32_t ring_size = desc_cnt * sizeof(union cq_entry_t); 497aa0d976eSJerin Jacob 498aa0d976eSJerin Jacob rz = rte_eth_dma_zone_reserve(nic->eth_dev, "cq_ring", qidx, ring_size, 499aa0d976eSJerin Jacob NICVF_CQ_BASE_ALIGN_BYTES, nic->node); 500aa0d976eSJerin Jacob if (rz == NULL) { 501aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate mem for cq hw ring"); 502aa0d976eSJerin Jacob return -ENOMEM; 503aa0d976eSJerin Jacob } 504aa0d976eSJerin Jacob 505aa0d976eSJerin Jacob memset(rz->addr, 0, ring_size); 506aa0d976eSJerin Jacob 507aa0d976eSJerin Jacob rxq->phys = rz->phys_addr; 508aa0d976eSJerin Jacob rxq->desc = rz->addr; 509aa0d976eSJerin Jacob rxq->qlen_mask = desc_cnt - 1; 510aa0d976eSJerin Jacob 511aa0d976eSJerin Jacob return 0; 512aa0d976eSJerin Jacob } 513aa0d976eSJerin Jacob 5143f3c6f97SJerin Jacob static int 5153f3c6f97SJerin Jacob nicvf_qset_sq_alloc(struct nicvf *nic, struct nicvf_txq *sq, uint16_t qidx, 5163f3c6f97SJerin Jacob uint32_t desc_cnt) 5173f3c6f97SJerin Jacob { 5183f3c6f97SJerin Jacob const struct rte_memzone *rz; 5193f3c6f97SJerin Jacob uint32_t ring_size = desc_cnt * sizeof(union sq_entry_t); 5203f3c6f97SJerin Jacob 5213f3c6f97SJerin Jacob rz = rte_eth_dma_zone_reserve(nic->eth_dev, "sq", qidx, ring_size, 5223f3c6f97SJerin Jacob NICVF_SQ_BASE_ALIGN_BYTES, nic->node); 5233f3c6f97SJerin Jacob if (rz == NULL) { 5243f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Failed allocate mem for sq hw ring"); 5253f3c6f97SJerin Jacob return -ENOMEM; 5263f3c6f97SJerin Jacob } 5273f3c6f97SJerin Jacob 5283f3c6f97SJerin Jacob memset(rz->addr, 0, ring_size); 5293f3c6f97SJerin Jacob 5303f3c6f97SJerin Jacob sq->phys = rz->phys_addr; 5313f3c6f97SJerin Jacob sq->desc = rz->addr; 5323f3c6f97SJerin Jacob sq->qlen_mask = desc_cnt - 1; 5333f3c6f97SJerin Jacob 5343f3c6f97SJerin Jacob return 0; 5353f3c6f97SJerin Jacob } 5363f3c6f97SJerin Jacob 5373f3c6f97SJerin Jacob static inline void 5383f3c6f97SJerin Jacob nicvf_tx_queue_release_mbufs(struct nicvf_txq *txq) 5393f3c6f97SJerin Jacob { 5403f3c6f97SJerin Jacob uint32_t head; 5413f3c6f97SJerin Jacob 5423f3c6f97SJerin Jacob head = txq->head; 5433f3c6f97SJerin Jacob while (head != txq->tail) { 5443f3c6f97SJerin Jacob if (txq->txbuffs[head]) { 5453f3c6f97SJerin Jacob rte_pktmbuf_free_seg(txq->txbuffs[head]); 5463f3c6f97SJerin Jacob txq->txbuffs[head] = NULL; 5473f3c6f97SJerin Jacob } 5483f3c6f97SJerin Jacob head++; 5493f3c6f97SJerin Jacob head = head & txq->qlen_mask; 5503f3c6f97SJerin Jacob } 5513f3c6f97SJerin Jacob } 5523f3c6f97SJerin Jacob 5533f3c6f97SJerin Jacob static void 5543f3c6f97SJerin Jacob nicvf_tx_queue_reset(struct nicvf_txq *txq) 5553f3c6f97SJerin Jacob { 5563f3c6f97SJerin Jacob uint32_t txq_desc_cnt = txq->qlen_mask + 1; 5573f3c6f97SJerin Jacob 5583f3c6f97SJerin Jacob memset(txq->desc, 0, sizeof(union sq_entry_t) * txq_desc_cnt); 5593f3c6f97SJerin Jacob memset(txq->txbuffs, 0, sizeof(struct rte_mbuf *) * txq_desc_cnt); 5603f3c6f97SJerin Jacob txq->tail = 0; 5613f3c6f97SJerin Jacob txq->head = 0; 5623f3c6f97SJerin Jacob txq->xmit_bufs = 0; 5633f3c6f97SJerin Jacob } 5643f3c6f97SJerin Jacob 5653f3c6f97SJerin Jacob static void 5663f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(void *sq) 5673f3c6f97SJerin Jacob { 5683f3c6f97SJerin Jacob struct nicvf_txq *txq; 5693f3c6f97SJerin Jacob 5703f3c6f97SJerin Jacob PMD_INIT_FUNC_TRACE(); 5713f3c6f97SJerin Jacob 5723f3c6f97SJerin Jacob txq = (struct nicvf_txq *)sq; 5733f3c6f97SJerin Jacob if (txq) { 5743f3c6f97SJerin Jacob if (txq->txbuffs != NULL) { 5753f3c6f97SJerin Jacob nicvf_tx_queue_release_mbufs(txq); 5763f3c6f97SJerin Jacob rte_free(txq->txbuffs); 5773f3c6f97SJerin Jacob txq->txbuffs = NULL; 5783f3c6f97SJerin Jacob } 5793f3c6f97SJerin Jacob rte_free(txq); 5803f3c6f97SJerin Jacob } 5813f3c6f97SJerin Jacob } 5823f3c6f97SJerin Jacob 5833f3c6f97SJerin Jacob static int 5843f3c6f97SJerin Jacob nicvf_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, 5853f3c6f97SJerin Jacob uint16_t nb_desc, unsigned int socket_id, 5863f3c6f97SJerin Jacob const struct rte_eth_txconf *tx_conf) 5873f3c6f97SJerin Jacob { 5883f3c6f97SJerin Jacob uint16_t tx_free_thresh; 5893f3c6f97SJerin Jacob uint8_t is_single_pool; 5903f3c6f97SJerin Jacob struct nicvf_txq *txq; 5913f3c6f97SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 5923f3c6f97SJerin Jacob 5933f3c6f97SJerin Jacob PMD_INIT_FUNC_TRACE(); 5943f3c6f97SJerin Jacob 5953f3c6f97SJerin Jacob /* Socket id check */ 5963f3c6f97SJerin Jacob if (socket_id != (unsigned int)SOCKET_ID_ANY && socket_id != nic->node) 5973f3c6f97SJerin Jacob PMD_DRV_LOG(WARNING, "socket_id expected %d, configured %d", 5983f3c6f97SJerin Jacob socket_id, nic->node); 5993f3c6f97SJerin Jacob 6003f3c6f97SJerin Jacob /* Tx deferred start is not supported */ 6013f3c6f97SJerin Jacob if (tx_conf->tx_deferred_start) { 6023f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Tx deferred start not supported"); 6033f3c6f97SJerin Jacob return -EINVAL; 6043f3c6f97SJerin Jacob } 6053f3c6f97SJerin Jacob 6063f3c6f97SJerin Jacob /* Roundup nb_desc to available qsize and validate max number of desc */ 6073f3c6f97SJerin Jacob nb_desc = nicvf_qsize_sq_roundup(nb_desc); 6083f3c6f97SJerin Jacob if (nb_desc == 0) { 6093f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Value of nb_desc beyond available sq qsize"); 6103f3c6f97SJerin Jacob return -EINVAL; 6113f3c6f97SJerin Jacob } 6123f3c6f97SJerin Jacob 6133f3c6f97SJerin Jacob /* Validate tx_free_thresh */ 6143f3c6f97SJerin Jacob tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? 6153f3c6f97SJerin Jacob tx_conf->tx_free_thresh : 6163f3c6f97SJerin Jacob NICVF_DEFAULT_TX_FREE_THRESH); 6173f3c6f97SJerin Jacob 6183f3c6f97SJerin Jacob if (tx_free_thresh > (nb_desc) || 6193f3c6f97SJerin Jacob tx_free_thresh > NICVF_MAX_TX_FREE_THRESH) { 6203f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, 6213f3c6f97SJerin Jacob "tx_free_thresh must be less than the number of TX " 6223f3c6f97SJerin Jacob "descriptors. (tx_free_thresh=%u port=%d " 6233f3c6f97SJerin Jacob "queue=%d)", (unsigned int)tx_free_thresh, 6243f3c6f97SJerin Jacob (int)dev->data->port_id, (int)qidx); 6253f3c6f97SJerin Jacob return -EINVAL; 6263f3c6f97SJerin Jacob } 6273f3c6f97SJerin Jacob 6283f3c6f97SJerin Jacob /* Free memory prior to re-allocation if needed. */ 6293f3c6f97SJerin Jacob if (dev->data->tx_queues[qidx] != NULL) { 6303f3c6f97SJerin Jacob PMD_TX_LOG(DEBUG, "Freeing memory prior to re-allocation %d", 6313f3c6f97SJerin Jacob qidx); 6323f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(dev->data->tx_queues[qidx]); 6333f3c6f97SJerin Jacob dev->data->tx_queues[qidx] = NULL; 6343f3c6f97SJerin Jacob } 6353f3c6f97SJerin Jacob 6363f3c6f97SJerin Jacob /* Allocating tx queue data structure */ 6373f3c6f97SJerin Jacob txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct nicvf_txq), 6383f3c6f97SJerin Jacob RTE_CACHE_LINE_SIZE, nic->node); 6393f3c6f97SJerin Jacob if (txq == NULL) { 6403f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate txq=%d", qidx); 6413f3c6f97SJerin Jacob return -ENOMEM; 6423f3c6f97SJerin Jacob } 6433f3c6f97SJerin Jacob 6443f3c6f97SJerin Jacob txq->nic = nic; 6453f3c6f97SJerin Jacob txq->queue_id = qidx; 6463f3c6f97SJerin Jacob txq->tx_free_thresh = tx_free_thresh; 6473f3c6f97SJerin Jacob txq->txq_flags = tx_conf->txq_flags; 6483f3c6f97SJerin Jacob txq->sq_head = nicvf_qset_base(nic, qidx) + NIC_QSET_SQ_0_7_HEAD; 6493f3c6f97SJerin Jacob txq->sq_door = nicvf_qset_base(nic, qidx) + NIC_QSET_SQ_0_7_DOOR; 6503f3c6f97SJerin Jacob is_single_pool = (txq->txq_flags & ETH_TXQ_FLAGS_NOREFCOUNT && 6513f3c6f97SJerin Jacob txq->txq_flags & ETH_TXQ_FLAGS_NOMULTMEMP); 6523f3c6f97SJerin Jacob 6533f3c6f97SJerin Jacob /* Choose optimum free threshold value for multipool case */ 6543f3c6f97SJerin Jacob if (!is_single_pool) { 6553f3c6f97SJerin Jacob txq->tx_free_thresh = (uint16_t) 6563f3c6f97SJerin Jacob (tx_conf->tx_free_thresh == NICVF_DEFAULT_TX_FREE_THRESH ? 6573f3c6f97SJerin Jacob NICVF_TX_FREE_MPOOL_THRESH : 6583f3c6f97SJerin Jacob tx_conf->tx_free_thresh); 6591c421f18SJerin Jacob txq->pool_free = nicvf_multi_pool_free_xmited_buffers; 6601c421f18SJerin Jacob } else { 6611c421f18SJerin Jacob txq->pool_free = nicvf_single_pool_free_xmited_buffers; 6623f3c6f97SJerin Jacob } 6633f3c6f97SJerin Jacob 6643f3c6f97SJerin Jacob /* Allocate software ring */ 6653f3c6f97SJerin Jacob txq->txbuffs = rte_zmalloc_socket("txq->txbuffs", 6663f3c6f97SJerin Jacob nb_desc * sizeof(struct rte_mbuf *), 6673f3c6f97SJerin Jacob RTE_CACHE_LINE_SIZE, nic->node); 6683f3c6f97SJerin Jacob 6693f3c6f97SJerin Jacob if (txq->txbuffs == NULL) { 6703f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(txq); 6713f3c6f97SJerin Jacob return -ENOMEM; 6723f3c6f97SJerin Jacob } 6733f3c6f97SJerin Jacob 6743f3c6f97SJerin Jacob if (nicvf_qset_sq_alloc(nic, txq, qidx, nb_desc)) { 6753f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate mem for sq %d", qidx); 6763f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(txq); 6773f3c6f97SJerin Jacob return -ENOMEM; 6783f3c6f97SJerin Jacob } 6793f3c6f97SJerin Jacob 6803f3c6f97SJerin Jacob nicvf_tx_queue_reset(txq); 6813f3c6f97SJerin Jacob 6823f3c6f97SJerin Jacob PMD_TX_LOG(DEBUG, "[%d] txq=%p nb_desc=%d desc=%p phys=0x%" PRIx64, 6833f3c6f97SJerin Jacob qidx, txq, nb_desc, txq->desc, txq->phys); 6843f3c6f97SJerin Jacob 6853f3c6f97SJerin Jacob dev->data->tx_queues[qidx] = txq; 6863f3c6f97SJerin Jacob dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 6873f3c6f97SJerin Jacob return 0; 6883f3c6f97SJerin Jacob } 6893f3c6f97SJerin Jacob 690aa0d976eSJerin Jacob static void 691aa0d976eSJerin Jacob nicvf_rx_queue_reset(struct nicvf_rxq *rxq) 692aa0d976eSJerin Jacob { 693aa0d976eSJerin Jacob rxq->head = 0; 694aa0d976eSJerin Jacob rxq->available_space = 0; 695aa0d976eSJerin Jacob rxq->recv_buffers = 0; 696aa0d976eSJerin Jacob } 697aa0d976eSJerin Jacob 698aa0d976eSJerin Jacob static void 699aa0d976eSJerin Jacob nicvf_dev_rx_queue_release(void *rx_queue) 700aa0d976eSJerin Jacob { 701aa0d976eSJerin Jacob struct nicvf_rxq *rxq = rx_queue; 702aa0d976eSJerin Jacob 703aa0d976eSJerin Jacob PMD_INIT_FUNC_TRACE(); 704aa0d976eSJerin Jacob 705aa0d976eSJerin Jacob if (rxq) 706aa0d976eSJerin Jacob rte_free(rxq); 707aa0d976eSJerin Jacob } 708aa0d976eSJerin Jacob 709aa0d976eSJerin Jacob static int 710aa0d976eSJerin Jacob nicvf_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, 711aa0d976eSJerin Jacob uint16_t nb_desc, unsigned int socket_id, 712aa0d976eSJerin Jacob const struct rte_eth_rxconf *rx_conf, 713aa0d976eSJerin Jacob struct rte_mempool *mp) 714aa0d976eSJerin Jacob { 715aa0d976eSJerin Jacob uint16_t rx_free_thresh; 716aa0d976eSJerin Jacob struct nicvf_rxq *rxq; 717aa0d976eSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 718aa0d976eSJerin Jacob 719aa0d976eSJerin Jacob PMD_INIT_FUNC_TRACE(); 720aa0d976eSJerin Jacob 721aa0d976eSJerin Jacob /* Socket id check */ 722aa0d976eSJerin Jacob if (socket_id != (unsigned int)SOCKET_ID_ANY && socket_id != nic->node) 723aa0d976eSJerin Jacob PMD_DRV_LOG(WARNING, "socket_id expected %d, configured %d", 724aa0d976eSJerin Jacob socket_id, nic->node); 725aa0d976eSJerin Jacob 726aa0d976eSJerin Jacob /* Mempool memory should be contiguous */ 727aa0d976eSJerin Jacob if (mp->nb_mem_chunks != 1) { 728aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Non contiguous mempool, check huge page sz"); 729aa0d976eSJerin Jacob return -EINVAL; 730aa0d976eSJerin Jacob } 731aa0d976eSJerin Jacob 732aa0d976eSJerin Jacob /* Rx deferred start is not supported */ 733aa0d976eSJerin Jacob if (rx_conf->rx_deferred_start) { 734aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Rx deferred start not supported"); 735aa0d976eSJerin Jacob return -EINVAL; 736aa0d976eSJerin Jacob } 737aa0d976eSJerin Jacob 738aa0d976eSJerin Jacob /* Roundup nb_desc to available qsize and validate max number of desc */ 739aa0d976eSJerin Jacob nb_desc = nicvf_qsize_cq_roundup(nb_desc); 740aa0d976eSJerin Jacob if (nb_desc == 0) { 741aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Value nb_desc beyond available hw cq qsize"); 742aa0d976eSJerin Jacob return -EINVAL; 743aa0d976eSJerin Jacob } 744aa0d976eSJerin Jacob 745aa0d976eSJerin Jacob /* Check rx_free_thresh upper bound */ 746aa0d976eSJerin Jacob rx_free_thresh = (uint16_t)((rx_conf->rx_free_thresh) ? 747aa0d976eSJerin Jacob rx_conf->rx_free_thresh : 748aa0d976eSJerin Jacob NICVF_DEFAULT_RX_FREE_THRESH); 749aa0d976eSJerin Jacob if (rx_free_thresh > NICVF_MAX_RX_FREE_THRESH || 750aa0d976eSJerin Jacob rx_free_thresh >= nb_desc * .75) { 751aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "rx_free_thresh greater than expected %d", 752aa0d976eSJerin Jacob rx_free_thresh); 753aa0d976eSJerin Jacob return -EINVAL; 754aa0d976eSJerin Jacob } 755aa0d976eSJerin Jacob 756aa0d976eSJerin Jacob /* Free memory prior to re-allocation if needed */ 757aa0d976eSJerin Jacob if (dev->data->rx_queues[qidx] != NULL) { 758aa0d976eSJerin Jacob PMD_RX_LOG(DEBUG, "Freeing memory prior to re-allocation %d", 759aa0d976eSJerin Jacob qidx); 760aa0d976eSJerin Jacob nicvf_dev_rx_queue_release(dev->data->rx_queues[qidx]); 761aa0d976eSJerin Jacob dev->data->rx_queues[qidx] = NULL; 762aa0d976eSJerin Jacob } 763aa0d976eSJerin Jacob 764aa0d976eSJerin Jacob /* Allocate rxq memory */ 765aa0d976eSJerin Jacob rxq = rte_zmalloc_socket("ethdev rx queue", sizeof(struct nicvf_rxq), 766aa0d976eSJerin Jacob RTE_CACHE_LINE_SIZE, nic->node); 767aa0d976eSJerin Jacob if (rxq == NULL) { 768aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate rxq=%d", qidx); 769aa0d976eSJerin Jacob return -ENOMEM; 770aa0d976eSJerin Jacob } 771aa0d976eSJerin Jacob 772aa0d976eSJerin Jacob rxq->nic = nic; 773aa0d976eSJerin Jacob rxq->pool = mp; 774aa0d976eSJerin Jacob rxq->queue_id = qidx; 775aa0d976eSJerin Jacob rxq->port_id = dev->data->port_id; 776aa0d976eSJerin Jacob rxq->rx_free_thresh = rx_free_thresh; 777aa0d976eSJerin Jacob rxq->rx_drop_en = rx_conf->rx_drop_en; 778aa0d976eSJerin Jacob rxq->cq_status = nicvf_qset_base(nic, qidx) + NIC_QSET_CQ_0_7_STATUS; 779aa0d976eSJerin Jacob rxq->cq_door = nicvf_qset_base(nic, qidx) + NIC_QSET_CQ_0_7_DOOR; 780aa0d976eSJerin Jacob rxq->precharge_cnt = 0; 781aa0d976eSJerin Jacob rxq->rbptr_offset = NICVF_CQE_RBPTR_WORD; 782aa0d976eSJerin Jacob 783aa0d976eSJerin Jacob /* Alloc completion queue */ 784aa0d976eSJerin Jacob if (nicvf_qset_cq_alloc(nic, rxq, rxq->queue_id, nb_desc)) { 785aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "failed to allocate cq %u", rxq->queue_id); 786aa0d976eSJerin Jacob nicvf_dev_rx_queue_release(rxq); 787aa0d976eSJerin Jacob return -ENOMEM; 788aa0d976eSJerin Jacob } 789aa0d976eSJerin Jacob 790aa0d976eSJerin Jacob nicvf_rx_queue_reset(rxq); 791aa0d976eSJerin Jacob 792aa0d976eSJerin Jacob PMD_RX_LOG(DEBUG, "[%d] rxq=%p pool=%s nb_desc=(%d/%d) phy=%" PRIx64, 793aa0d976eSJerin Jacob qidx, rxq, mp->name, nb_desc, 794aa0d976eSJerin Jacob rte_mempool_count(mp), rxq->phys); 795aa0d976eSJerin Jacob 796aa0d976eSJerin Jacob dev->data->rx_queues[qidx] = rxq; 797aa0d976eSJerin Jacob dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 798aa0d976eSJerin Jacob return 0; 799aa0d976eSJerin Jacob } 800aa0d976eSJerin Jacob 801dcd7b1e1SJerin Jacob static void 802dcd7b1e1SJerin Jacob nicvf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 803dcd7b1e1SJerin Jacob { 804dcd7b1e1SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 805dcd7b1e1SJerin Jacob 806dcd7b1e1SJerin Jacob PMD_INIT_FUNC_TRACE(); 807dcd7b1e1SJerin Jacob 808dcd7b1e1SJerin Jacob dev_info->min_rx_bufsize = ETHER_MIN_MTU; 809dcd7b1e1SJerin Jacob dev_info->max_rx_pktlen = NIC_HW_MAX_FRS; 810dcd7b1e1SJerin Jacob dev_info->max_rx_queues = (uint16_t)MAX_RCV_QUEUES_PER_QS; 811dcd7b1e1SJerin Jacob dev_info->max_tx_queues = (uint16_t)MAX_SND_QUEUES_PER_QS; 812dcd7b1e1SJerin Jacob dev_info->max_mac_addrs = 1; 813dcd7b1e1SJerin Jacob dev_info->max_vfs = dev->pci_dev->max_vfs; 814dcd7b1e1SJerin Jacob 815dcd7b1e1SJerin Jacob dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP; 816dcd7b1e1SJerin Jacob dev_info->tx_offload_capa = 817dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_IPV4_CKSUM | 818dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_UDP_CKSUM | 819dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_TCP_CKSUM | 820dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_TCP_TSO | 821dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; 822dcd7b1e1SJerin Jacob 823dcd7b1e1SJerin Jacob dev_info->reta_size = nic->rss_info.rss_size; 824dcd7b1e1SJerin Jacob dev_info->hash_key_size = RSS_HASH_KEY_BYTE_SIZE; 825dcd7b1e1SJerin Jacob dev_info->flow_type_rss_offloads = NICVF_RSS_OFFLOAD_PASS1; 826dcd7b1e1SJerin Jacob if (nicvf_hw_cap(nic) & NICVF_CAP_TUNNEL_PARSING) 827dcd7b1e1SJerin Jacob dev_info->flow_type_rss_offloads |= NICVF_RSS_OFFLOAD_TUNNEL; 828dcd7b1e1SJerin Jacob 829dcd7b1e1SJerin Jacob dev_info->default_rxconf = (struct rte_eth_rxconf) { 830dcd7b1e1SJerin Jacob .rx_free_thresh = NICVF_DEFAULT_RX_FREE_THRESH, 831dcd7b1e1SJerin Jacob .rx_drop_en = 0, 832dcd7b1e1SJerin Jacob }; 833dcd7b1e1SJerin Jacob 834dcd7b1e1SJerin Jacob dev_info->default_txconf = (struct rte_eth_txconf) { 835dcd7b1e1SJerin Jacob .tx_free_thresh = NICVF_DEFAULT_TX_FREE_THRESH, 836dcd7b1e1SJerin Jacob .txq_flags = 837dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOMULTSEGS | 838dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOREFCOUNT | 839dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOMULTMEMP | 840dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOVLANOFFL | 841dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOXSUMSCTP, 842dcd7b1e1SJerin Jacob }; 843dcd7b1e1SJerin Jacob } 844dcd7b1e1SJerin Jacob 845bc79615aSJerin Jacob static int 846bc79615aSJerin Jacob nicvf_dev_configure(struct rte_eth_dev *dev) 847bc79615aSJerin Jacob { 848bc79615aSJerin Jacob struct rte_eth_conf *conf = &dev->data->dev_conf; 849bc79615aSJerin Jacob struct rte_eth_rxmode *rxmode = &conf->rxmode; 850bc79615aSJerin Jacob struct rte_eth_txmode *txmode = &conf->txmode; 851bc79615aSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 852bc79615aSJerin Jacob 853bc79615aSJerin Jacob PMD_INIT_FUNC_TRACE(); 854bc79615aSJerin Jacob 855bc79615aSJerin Jacob if (!rte_eal_has_hugepages()) { 856bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Huge page is not configured"); 857bc79615aSJerin Jacob return -EINVAL; 858bc79615aSJerin Jacob } 859bc79615aSJerin Jacob 860bc79615aSJerin Jacob if (txmode->mq_mode) { 861bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Tx mq_mode DCB or VMDq not supported"); 862bc79615aSJerin Jacob return -EINVAL; 863bc79615aSJerin Jacob } 864bc79615aSJerin Jacob 865bc79615aSJerin Jacob if (rxmode->mq_mode != ETH_MQ_RX_NONE && 866bc79615aSJerin Jacob rxmode->mq_mode != ETH_MQ_RX_RSS) { 867bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Unsupported rx qmode %d", rxmode->mq_mode); 868bc79615aSJerin Jacob return -EINVAL; 869bc79615aSJerin Jacob } 870bc79615aSJerin Jacob 871bc79615aSJerin Jacob if (!rxmode->hw_strip_crc) { 872bc79615aSJerin Jacob PMD_INIT_LOG(NOTICE, "Can't disable hw crc strip"); 873bc79615aSJerin Jacob rxmode->hw_strip_crc = 1; 874bc79615aSJerin Jacob } 875bc79615aSJerin Jacob 876bc79615aSJerin Jacob if (rxmode->hw_ip_checksum) { 877bc79615aSJerin Jacob PMD_INIT_LOG(NOTICE, "Rxcksum not supported"); 878bc79615aSJerin Jacob rxmode->hw_ip_checksum = 0; 879bc79615aSJerin Jacob } 880bc79615aSJerin Jacob 881bc79615aSJerin Jacob if (rxmode->split_hdr_size) { 882bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Rxmode does not support split header"); 883bc79615aSJerin Jacob return -EINVAL; 884bc79615aSJerin Jacob } 885bc79615aSJerin Jacob 886bc79615aSJerin Jacob if (rxmode->hw_vlan_filter) { 887bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "VLAN filter not supported"); 888bc79615aSJerin Jacob return -EINVAL; 889bc79615aSJerin Jacob } 890bc79615aSJerin Jacob 891bc79615aSJerin Jacob if (rxmode->hw_vlan_extend) { 892bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "VLAN extended not supported"); 893bc79615aSJerin Jacob return -EINVAL; 894bc79615aSJerin Jacob } 895bc79615aSJerin Jacob 896bc79615aSJerin Jacob if (rxmode->enable_lro) { 897bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "LRO not supported"); 898bc79615aSJerin Jacob return -EINVAL; 899bc79615aSJerin Jacob } 900bc79615aSJerin Jacob 901bc79615aSJerin Jacob if (conf->link_speeds & ETH_LINK_SPEED_FIXED) { 902bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Setting link speed/duplex not supported"); 903bc79615aSJerin Jacob return -EINVAL; 904bc79615aSJerin Jacob } 905bc79615aSJerin Jacob 906bc79615aSJerin Jacob if (conf->dcb_capability_en) { 907bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "DCB enable not supported"); 908bc79615aSJerin Jacob return -EINVAL; 909bc79615aSJerin Jacob } 910bc79615aSJerin Jacob 911bc79615aSJerin Jacob if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) { 912bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Flow director not supported"); 913bc79615aSJerin Jacob return -EINVAL; 914bc79615aSJerin Jacob } 915bc79615aSJerin Jacob 916bc79615aSJerin Jacob PMD_INIT_LOG(DEBUG, "Configured ethdev port%d hwcap=0x%" PRIx64, 917bc79615aSJerin Jacob dev->data->port_id, nicvf_hw_cap(nic)); 918bc79615aSJerin Jacob 919bc79615aSJerin Jacob return 0; 920bc79615aSJerin Jacob } 921bc79615aSJerin Jacob 922e4387966SJerin Jacob /* Initialize and register driver with DPDK Application */ 923e4387966SJerin Jacob static const struct eth_dev_ops nicvf_eth_dev_ops = { 924bc79615aSJerin Jacob .dev_configure = nicvf_dev_configure, 9258fc70464SJerin Jacob .link_update = nicvf_dev_link_update, 926684fa771SJerin Jacob .stats_get = nicvf_dev_stats_get, 927684fa771SJerin Jacob .stats_reset = nicvf_dev_stats_reset, 9286eae36eaSJerin Jacob .promiscuous_enable = nicvf_dev_promisc_enable, 929dcd7b1e1SJerin Jacob .dev_infos_get = nicvf_dev_info_get, 930*1c80e4fdSJerin Jacob .dev_supported_ptypes_get = nicvf_dev_supported_ptypes_get, 93165d9804eSJerin Jacob .mtu_set = nicvf_dev_set_mtu, 93243362c6aSJerin Jacob .reta_update = nicvf_dev_reta_update, 93343362c6aSJerin Jacob .reta_query = nicvf_dev_reta_query, 93443362c6aSJerin Jacob .rss_hash_update = nicvf_dev_rss_hash_update, 93543362c6aSJerin Jacob .rss_hash_conf_get = nicvf_dev_rss_hash_conf_get, 936aa0d976eSJerin Jacob .rx_queue_setup = nicvf_dev_rx_queue_setup, 937aa0d976eSJerin Jacob .rx_queue_release = nicvf_dev_rx_queue_release, 9383f3c6f97SJerin Jacob .tx_queue_setup = nicvf_dev_tx_queue_setup, 9393f3c6f97SJerin Jacob .tx_queue_release = nicvf_dev_tx_queue_release, 940606ee746SJerin Jacob .get_reg_length = nicvf_dev_get_reg_length, 941606ee746SJerin Jacob .get_reg = nicvf_dev_get_regs, 942e4387966SJerin Jacob }; 943e4387966SJerin Jacob 944e4387966SJerin Jacob static int 945e4387966SJerin Jacob nicvf_eth_dev_init(struct rte_eth_dev *eth_dev) 946e4387966SJerin Jacob { 947e4387966SJerin Jacob int ret; 948e4387966SJerin Jacob struct rte_pci_device *pci_dev; 949e4387966SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(eth_dev); 950e4387966SJerin Jacob 951e4387966SJerin Jacob PMD_INIT_FUNC_TRACE(); 952e4387966SJerin Jacob 953e4387966SJerin Jacob eth_dev->dev_ops = &nicvf_eth_dev_ops; 954e4387966SJerin Jacob 955e4387966SJerin Jacob pci_dev = eth_dev->pci_dev; 956e4387966SJerin Jacob rte_eth_copy_pci_info(eth_dev, pci_dev); 957e4387966SJerin Jacob 958e4387966SJerin Jacob nic->device_id = pci_dev->id.device_id; 959e4387966SJerin Jacob nic->vendor_id = pci_dev->id.vendor_id; 960e4387966SJerin Jacob nic->subsystem_device_id = pci_dev->id.subsystem_device_id; 961e4387966SJerin Jacob nic->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; 962e4387966SJerin Jacob nic->eth_dev = eth_dev; 963e4387966SJerin Jacob 964e4387966SJerin Jacob PMD_INIT_LOG(DEBUG, "nicvf: device (%x:%x) %u:%u:%u:%u", 965e4387966SJerin Jacob pci_dev->id.vendor_id, pci_dev->id.device_id, 966e4387966SJerin Jacob pci_dev->addr.domain, pci_dev->addr.bus, 967e4387966SJerin Jacob pci_dev->addr.devid, pci_dev->addr.function); 968e4387966SJerin Jacob 969e4387966SJerin Jacob nic->reg_base = (uintptr_t)pci_dev->mem_resource[0].addr; 970e4387966SJerin Jacob if (!nic->reg_base) { 971e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to map BAR0"); 972e4387966SJerin Jacob ret = -ENODEV; 973e4387966SJerin Jacob goto fail; 974e4387966SJerin Jacob } 975e4387966SJerin Jacob 976e4387966SJerin Jacob nicvf_disable_all_interrupts(nic); 977e4387966SJerin Jacob 978e4387966SJerin Jacob ret = nicvf_periodic_alarm_start(nic); 979e4387966SJerin Jacob if (ret) { 980e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to start period alarm"); 981e4387966SJerin Jacob goto fail; 982e4387966SJerin Jacob } 983e4387966SJerin Jacob 984e4387966SJerin Jacob ret = nicvf_mbox_check_pf_ready(nic); 985e4387966SJerin Jacob if (ret) { 986e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to get ready message from PF"); 987e4387966SJerin Jacob goto alarm_fail; 988e4387966SJerin Jacob } else { 989e4387966SJerin Jacob PMD_INIT_LOG(INFO, 990e4387966SJerin Jacob "node=%d vf=%d mode=%s sqs=%s loopback_supported=%s", 991e4387966SJerin Jacob nic->node, nic->vf_id, 992e4387966SJerin Jacob nic->tns_mode == NIC_TNS_MODE ? "tns" : "tns-bypass", 993e4387966SJerin Jacob nic->sqs_mode ? "true" : "false", 994e4387966SJerin Jacob nic->loopback_supported ? "true" : "false" 995e4387966SJerin Jacob ); 996e4387966SJerin Jacob } 997e4387966SJerin Jacob 998e4387966SJerin Jacob if (nic->sqs_mode) { 999e4387966SJerin Jacob PMD_INIT_LOG(INFO, "Unsupported SQS VF detected, Detaching..."); 1000e4387966SJerin Jacob /* Detach port by returning Positive error number */ 1001e4387966SJerin Jacob ret = ENOTSUP; 1002e4387966SJerin Jacob goto alarm_fail; 1003e4387966SJerin Jacob } 1004e4387966SJerin Jacob 1005e4387966SJerin Jacob eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", ETHER_ADDR_LEN, 0); 1006e4387966SJerin Jacob if (eth_dev->data->mac_addrs == NULL) { 1007e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate memory for mac addr"); 1008e4387966SJerin Jacob ret = -ENOMEM; 1009e4387966SJerin Jacob goto alarm_fail; 1010e4387966SJerin Jacob } 1011e4387966SJerin Jacob if (is_zero_ether_addr((struct ether_addr *)nic->mac_addr)) 1012e4387966SJerin Jacob eth_random_addr(&nic->mac_addr[0]); 1013e4387966SJerin Jacob 1014e4387966SJerin Jacob ether_addr_copy((struct ether_addr *)nic->mac_addr, 1015e4387966SJerin Jacob ð_dev->data->mac_addrs[0]); 1016e4387966SJerin Jacob 1017e4387966SJerin Jacob ret = nicvf_mbox_set_mac_addr(nic, nic->mac_addr); 1018e4387966SJerin Jacob if (ret) { 1019e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to set mac addr"); 1020e4387966SJerin Jacob goto malloc_fail; 1021e4387966SJerin Jacob } 1022e4387966SJerin Jacob 1023e4387966SJerin Jacob ret = nicvf_base_init(nic); 1024e4387966SJerin Jacob if (ret) { 1025e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to execute nicvf_base_init"); 1026e4387966SJerin Jacob goto malloc_fail; 1027e4387966SJerin Jacob } 1028e4387966SJerin Jacob 1029e4387966SJerin Jacob ret = nicvf_mbox_get_rss_size(nic); 1030e4387966SJerin Jacob if (ret) { 1031e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to get rss table size"); 1032e4387966SJerin Jacob goto malloc_fail; 1033e4387966SJerin Jacob } 1034e4387966SJerin Jacob 1035e4387966SJerin Jacob PMD_INIT_LOG(INFO, "Port %d (%x:%x) mac=%02x:%02x:%02x:%02x:%02x:%02x", 1036e4387966SJerin Jacob eth_dev->data->port_id, nic->vendor_id, nic->device_id, 1037e4387966SJerin Jacob nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2], 1038e4387966SJerin Jacob nic->mac_addr[3], nic->mac_addr[4], nic->mac_addr[5]); 1039e4387966SJerin Jacob 1040e4387966SJerin Jacob return 0; 1041e4387966SJerin Jacob 1042e4387966SJerin Jacob malloc_fail: 1043e4387966SJerin Jacob rte_free(eth_dev->data->mac_addrs); 1044e4387966SJerin Jacob alarm_fail: 1045e4387966SJerin Jacob nicvf_periodic_alarm_stop(nic); 1046e4387966SJerin Jacob fail: 1047e4387966SJerin Jacob return ret; 1048e4387966SJerin Jacob } 1049e4387966SJerin Jacob 1050e4387966SJerin Jacob static const struct rte_pci_id pci_id_nicvf_map[] = { 1051e4387966SJerin Jacob { 1052e4387966SJerin Jacob .class_id = RTE_CLASS_ANY_ID, 1053e4387966SJerin Jacob .vendor_id = PCI_VENDOR_ID_CAVIUM, 1054e4387966SJerin Jacob .device_id = PCI_DEVICE_ID_THUNDERX_PASS1_NICVF, 1055e4387966SJerin Jacob .subsystem_vendor_id = PCI_VENDOR_ID_CAVIUM, 1056e4387966SJerin Jacob .subsystem_device_id = PCI_SUB_DEVICE_ID_THUNDERX_PASS1_NICVF, 1057e4387966SJerin Jacob }, 1058e4387966SJerin Jacob { 1059e4387966SJerin Jacob .class_id = RTE_CLASS_ANY_ID, 1060e4387966SJerin Jacob .vendor_id = PCI_VENDOR_ID_CAVIUM, 1061e4387966SJerin Jacob .device_id = PCI_DEVICE_ID_THUNDERX_PASS2_NICVF, 1062e4387966SJerin Jacob .subsystem_vendor_id = PCI_VENDOR_ID_CAVIUM, 1063e4387966SJerin Jacob .subsystem_device_id = PCI_SUB_DEVICE_ID_THUNDERX_PASS2_NICVF, 1064e4387966SJerin Jacob }, 1065e4387966SJerin Jacob { 1066e4387966SJerin Jacob .vendor_id = 0, 1067e4387966SJerin Jacob }, 1068e4387966SJerin Jacob }; 1069e4387966SJerin Jacob 1070e4387966SJerin Jacob static struct eth_driver rte_nicvf_pmd = { 1071e4387966SJerin Jacob .pci_drv = { 1072e4387966SJerin Jacob .name = "rte_nicvf_pmd", 1073e4387966SJerin Jacob .id_table = pci_id_nicvf_map, 1074e4387966SJerin Jacob .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 1075e4387966SJerin Jacob }, 1076e4387966SJerin Jacob .eth_dev_init = nicvf_eth_dev_init, 1077e4387966SJerin Jacob .dev_private_size = sizeof(struct nicvf), 1078e4387966SJerin Jacob }; 1079e4387966SJerin Jacob 1080e4387966SJerin Jacob static int 1081e4387966SJerin Jacob rte_nicvf_pmd_init(const char *name __rte_unused, const char *para __rte_unused) 1082e4387966SJerin Jacob { 1083e4387966SJerin Jacob PMD_INIT_FUNC_TRACE(); 1084e4387966SJerin Jacob PMD_INIT_LOG(INFO, "librte_pmd_thunderx nicvf version %s", 1085e4387966SJerin Jacob THUNDERX_NICVF_PMD_VERSION); 1086e4387966SJerin Jacob 1087e4387966SJerin Jacob rte_eth_driver_register(&rte_nicvf_pmd); 1088e4387966SJerin Jacob return 0; 1089e4387966SJerin Jacob } 1090e4387966SJerin Jacob 1091e4387966SJerin Jacob static struct rte_driver rte_nicvf_driver = { 1092e4387966SJerin Jacob .name = "nicvf_driver", 1093e4387966SJerin Jacob .type = PMD_PDEV, 1094e4387966SJerin Jacob .init = rte_nicvf_pmd_init, 1095e4387966SJerin Jacob }; 1096e4387966SJerin Jacob 1097e4387966SJerin Jacob PMD_REGISTER_DRIVER(rte_nicvf_driver); 1098