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 2631c80e4fdSJerin Jacob static const uint32_t * 2641c80e4fdSJerin Jacob nicvf_dev_supported_ptypes_get(struct rte_eth_dev *dev) 2651c80e4fdSJerin Jacob { 2661c80e4fdSJerin Jacob size_t copied; 2671c80e4fdSJerin Jacob static uint32_t ptypes[32]; 2681c80e4fdSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 2691c80e4fdSJerin Jacob static const uint32_t ptypes_pass1[] = { 2701c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV4, 2711c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV4_EXT, 2721c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV6, 2731c80e4fdSJerin Jacob RTE_PTYPE_L3_IPV6_EXT, 2741c80e4fdSJerin Jacob RTE_PTYPE_L4_TCP, 2751c80e4fdSJerin Jacob RTE_PTYPE_L4_UDP, 2761c80e4fdSJerin Jacob RTE_PTYPE_L4_FRAG, 2771c80e4fdSJerin Jacob }; 2781c80e4fdSJerin Jacob static const uint32_t ptypes_pass2[] = { 2791c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_GRE, 2801c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_GENEVE, 2811c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_VXLAN, 2821c80e4fdSJerin Jacob RTE_PTYPE_TUNNEL_NVGRE, 2831c80e4fdSJerin Jacob }; 2841c80e4fdSJerin Jacob static const uint32_t ptypes_end = RTE_PTYPE_UNKNOWN; 2851c80e4fdSJerin Jacob 2861c80e4fdSJerin Jacob copied = sizeof(ptypes_pass1); 2871c80e4fdSJerin Jacob memcpy(ptypes, ptypes_pass1, copied); 2881c80e4fdSJerin Jacob if (nicvf_hw_version(nic) == NICVF_PASS2) { 2891c80e4fdSJerin Jacob memcpy((char *)ptypes + copied, ptypes_pass2, 2901c80e4fdSJerin Jacob sizeof(ptypes_pass2)); 2911c80e4fdSJerin Jacob copied += sizeof(ptypes_pass2); 2921c80e4fdSJerin Jacob } 2931c80e4fdSJerin Jacob 2941c80e4fdSJerin Jacob memcpy((char *)ptypes + copied, &ptypes_end, sizeof(ptypes_end)); 2951c80e4fdSJerin Jacob if (dev->rx_pkt_burst == nicvf_recv_pkts || 2961c80e4fdSJerin Jacob dev->rx_pkt_burst == nicvf_recv_pkts_multiseg) 2971c80e4fdSJerin Jacob return ptypes; 2981c80e4fdSJerin Jacob 2991c80e4fdSJerin Jacob return NULL; 3001c80e4fdSJerin Jacob } 3011c80e4fdSJerin 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 565*fc1f6c62SJerin Jacob static inline int 566*fc1f6c62SJerin Jacob nicvf_start_tx_queue(struct rte_eth_dev *dev, uint16_t qidx) 567*fc1f6c62SJerin Jacob { 568*fc1f6c62SJerin Jacob struct nicvf_txq *txq; 569*fc1f6c62SJerin Jacob int ret; 570*fc1f6c62SJerin Jacob 571*fc1f6c62SJerin Jacob if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) 572*fc1f6c62SJerin Jacob return 0; 573*fc1f6c62SJerin Jacob 574*fc1f6c62SJerin Jacob txq = dev->data->tx_queues[qidx]; 575*fc1f6c62SJerin Jacob txq->pool = NULL; 576*fc1f6c62SJerin Jacob ret = nicvf_qset_sq_config(nicvf_pmd_priv(dev), qidx, txq); 577*fc1f6c62SJerin Jacob if (ret) { 578*fc1f6c62SJerin Jacob PMD_INIT_LOG(ERR, "Failed to configure sq %d %d", qidx, ret); 579*fc1f6c62SJerin Jacob goto config_sq_error; 580*fc1f6c62SJerin Jacob } 581*fc1f6c62SJerin Jacob 582*fc1f6c62SJerin Jacob dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED; 583*fc1f6c62SJerin Jacob return ret; 584*fc1f6c62SJerin Jacob 585*fc1f6c62SJerin Jacob config_sq_error: 586*fc1f6c62SJerin Jacob nicvf_qset_sq_reclaim(nicvf_pmd_priv(dev), qidx); 587*fc1f6c62SJerin Jacob return ret; 588*fc1f6c62SJerin Jacob } 589*fc1f6c62SJerin Jacob 590*fc1f6c62SJerin Jacob static inline int 591*fc1f6c62SJerin Jacob nicvf_stop_tx_queue(struct rte_eth_dev *dev, uint16_t qidx) 592*fc1f6c62SJerin Jacob { 593*fc1f6c62SJerin Jacob struct nicvf_txq *txq; 594*fc1f6c62SJerin Jacob int ret; 595*fc1f6c62SJerin Jacob 596*fc1f6c62SJerin Jacob if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) 597*fc1f6c62SJerin Jacob return 0; 598*fc1f6c62SJerin Jacob 599*fc1f6c62SJerin Jacob ret = nicvf_qset_sq_reclaim(nicvf_pmd_priv(dev), qidx); 600*fc1f6c62SJerin Jacob if (ret) 601*fc1f6c62SJerin Jacob PMD_INIT_LOG(ERR, "Failed to reclaim sq %d %d", qidx, ret); 602*fc1f6c62SJerin Jacob 603*fc1f6c62SJerin Jacob txq = dev->data->tx_queues[qidx]; 604*fc1f6c62SJerin Jacob nicvf_tx_queue_release_mbufs(txq); 605*fc1f6c62SJerin Jacob nicvf_tx_queue_reset(txq); 606*fc1f6c62SJerin Jacob 607*fc1f6c62SJerin Jacob dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 608*fc1f6c62SJerin Jacob return ret; 609*fc1f6c62SJerin Jacob } 61086b4eb42SJerin Jacob 61186b4eb42SJerin Jacob static inline int 61286b4eb42SJerin Jacob nicvf_configure_cpi(struct rte_eth_dev *dev) 61386b4eb42SJerin Jacob { 61486b4eb42SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 61586b4eb42SJerin Jacob uint16_t qidx, qcnt; 61686b4eb42SJerin Jacob int ret; 61786b4eb42SJerin Jacob 61886b4eb42SJerin Jacob /* Count started rx queues */ 61986b4eb42SJerin Jacob for (qidx = qcnt = 0; qidx < nic->eth_dev->data->nb_rx_queues; qidx++) 62086b4eb42SJerin Jacob if (dev->data->rx_queue_state[qidx] == 62186b4eb42SJerin Jacob RTE_ETH_QUEUE_STATE_STARTED) 62286b4eb42SJerin Jacob qcnt++; 62386b4eb42SJerin Jacob 62486b4eb42SJerin Jacob nic->cpi_alg = CPI_ALG_NONE; 62586b4eb42SJerin Jacob ret = nicvf_mbox_config_cpi(nic, qcnt); 62686b4eb42SJerin Jacob if (ret) 62786b4eb42SJerin Jacob PMD_INIT_LOG(ERR, "Failed to configure CPI %d", ret); 62886b4eb42SJerin Jacob 62986b4eb42SJerin Jacob return ret; 63086b4eb42SJerin Jacob } 63186b4eb42SJerin Jacob 63286b4eb42SJerin Jacob static int 63386b4eb42SJerin Jacob nicvf_configure_rss_reta(struct rte_eth_dev *dev) 63486b4eb42SJerin Jacob { 63586b4eb42SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 63686b4eb42SJerin Jacob unsigned int idx, qmap_size; 63786b4eb42SJerin Jacob uint8_t qmap[RTE_MAX_QUEUES_PER_PORT]; 63886b4eb42SJerin Jacob uint8_t default_reta[NIC_MAX_RSS_IDR_TBL_SIZE]; 63986b4eb42SJerin Jacob 64086b4eb42SJerin Jacob if (nic->cpi_alg != CPI_ALG_NONE) 64186b4eb42SJerin Jacob return -EINVAL; 64286b4eb42SJerin Jacob 64386b4eb42SJerin Jacob /* Prepare queue map */ 64486b4eb42SJerin Jacob for (idx = 0, qmap_size = 0; idx < dev->data->nb_rx_queues; idx++) { 64586b4eb42SJerin Jacob if (dev->data->rx_queue_state[idx] == 64686b4eb42SJerin Jacob RTE_ETH_QUEUE_STATE_STARTED) 64786b4eb42SJerin Jacob qmap[qmap_size++] = idx; 64886b4eb42SJerin Jacob } 64986b4eb42SJerin Jacob 65086b4eb42SJerin Jacob /* Update default RSS RETA */ 65186b4eb42SJerin Jacob for (idx = 0; idx < NIC_MAX_RSS_IDR_TBL_SIZE; idx++) 65286b4eb42SJerin Jacob default_reta[idx] = qmap[idx % qmap_size]; 65386b4eb42SJerin Jacob 65486b4eb42SJerin Jacob return nicvf_rss_reta_update(nic, default_reta, 65586b4eb42SJerin Jacob NIC_MAX_RSS_IDR_TBL_SIZE); 65686b4eb42SJerin Jacob } 65786b4eb42SJerin Jacob 6583f3c6f97SJerin Jacob static void 6593f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(void *sq) 6603f3c6f97SJerin Jacob { 6613f3c6f97SJerin Jacob struct nicvf_txq *txq; 6623f3c6f97SJerin Jacob 6633f3c6f97SJerin Jacob PMD_INIT_FUNC_TRACE(); 6643f3c6f97SJerin Jacob 6653f3c6f97SJerin Jacob txq = (struct nicvf_txq *)sq; 6663f3c6f97SJerin Jacob if (txq) { 6673f3c6f97SJerin Jacob if (txq->txbuffs != NULL) { 6683f3c6f97SJerin Jacob nicvf_tx_queue_release_mbufs(txq); 6693f3c6f97SJerin Jacob rte_free(txq->txbuffs); 6703f3c6f97SJerin Jacob txq->txbuffs = NULL; 6713f3c6f97SJerin Jacob } 6723f3c6f97SJerin Jacob rte_free(txq); 6733f3c6f97SJerin Jacob } 6743f3c6f97SJerin Jacob } 6753f3c6f97SJerin Jacob 6763f3c6f97SJerin Jacob static int 6773f3c6f97SJerin Jacob nicvf_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, 6783f3c6f97SJerin Jacob uint16_t nb_desc, unsigned int socket_id, 6793f3c6f97SJerin Jacob const struct rte_eth_txconf *tx_conf) 6803f3c6f97SJerin Jacob { 6813f3c6f97SJerin Jacob uint16_t tx_free_thresh; 6823f3c6f97SJerin Jacob uint8_t is_single_pool; 6833f3c6f97SJerin Jacob struct nicvf_txq *txq; 6843f3c6f97SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 6853f3c6f97SJerin Jacob 6863f3c6f97SJerin Jacob PMD_INIT_FUNC_TRACE(); 6873f3c6f97SJerin Jacob 6883f3c6f97SJerin Jacob /* Socket id check */ 6893f3c6f97SJerin Jacob if (socket_id != (unsigned int)SOCKET_ID_ANY && socket_id != nic->node) 6903f3c6f97SJerin Jacob PMD_DRV_LOG(WARNING, "socket_id expected %d, configured %d", 6913f3c6f97SJerin Jacob socket_id, nic->node); 6923f3c6f97SJerin Jacob 6933f3c6f97SJerin Jacob /* Tx deferred start is not supported */ 6943f3c6f97SJerin Jacob if (tx_conf->tx_deferred_start) { 6953f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Tx deferred start not supported"); 6963f3c6f97SJerin Jacob return -EINVAL; 6973f3c6f97SJerin Jacob } 6983f3c6f97SJerin Jacob 6993f3c6f97SJerin Jacob /* Roundup nb_desc to available qsize and validate max number of desc */ 7003f3c6f97SJerin Jacob nb_desc = nicvf_qsize_sq_roundup(nb_desc); 7013f3c6f97SJerin Jacob if (nb_desc == 0) { 7023f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Value of nb_desc beyond available sq qsize"); 7033f3c6f97SJerin Jacob return -EINVAL; 7043f3c6f97SJerin Jacob } 7053f3c6f97SJerin Jacob 7063f3c6f97SJerin Jacob /* Validate tx_free_thresh */ 7073f3c6f97SJerin Jacob tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? 7083f3c6f97SJerin Jacob tx_conf->tx_free_thresh : 7093f3c6f97SJerin Jacob NICVF_DEFAULT_TX_FREE_THRESH); 7103f3c6f97SJerin Jacob 7113f3c6f97SJerin Jacob if (tx_free_thresh > (nb_desc) || 7123f3c6f97SJerin Jacob tx_free_thresh > NICVF_MAX_TX_FREE_THRESH) { 7133f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, 7143f3c6f97SJerin Jacob "tx_free_thresh must be less than the number of TX " 7153f3c6f97SJerin Jacob "descriptors. (tx_free_thresh=%u port=%d " 7163f3c6f97SJerin Jacob "queue=%d)", (unsigned int)tx_free_thresh, 7173f3c6f97SJerin Jacob (int)dev->data->port_id, (int)qidx); 7183f3c6f97SJerin Jacob return -EINVAL; 7193f3c6f97SJerin Jacob } 7203f3c6f97SJerin Jacob 7213f3c6f97SJerin Jacob /* Free memory prior to re-allocation if needed. */ 7223f3c6f97SJerin Jacob if (dev->data->tx_queues[qidx] != NULL) { 7233f3c6f97SJerin Jacob PMD_TX_LOG(DEBUG, "Freeing memory prior to re-allocation %d", 7243f3c6f97SJerin Jacob qidx); 7253f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(dev->data->tx_queues[qidx]); 7263f3c6f97SJerin Jacob dev->data->tx_queues[qidx] = NULL; 7273f3c6f97SJerin Jacob } 7283f3c6f97SJerin Jacob 7293f3c6f97SJerin Jacob /* Allocating tx queue data structure */ 7303f3c6f97SJerin Jacob txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct nicvf_txq), 7313f3c6f97SJerin Jacob RTE_CACHE_LINE_SIZE, nic->node); 7323f3c6f97SJerin Jacob if (txq == NULL) { 7333f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate txq=%d", qidx); 7343f3c6f97SJerin Jacob return -ENOMEM; 7353f3c6f97SJerin Jacob } 7363f3c6f97SJerin Jacob 7373f3c6f97SJerin Jacob txq->nic = nic; 7383f3c6f97SJerin Jacob txq->queue_id = qidx; 7393f3c6f97SJerin Jacob txq->tx_free_thresh = tx_free_thresh; 7403f3c6f97SJerin Jacob txq->txq_flags = tx_conf->txq_flags; 7413f3c6f97SJerin Jacob txq->sq_head = nicvf_qset_base(nic, qidx) + NIC_QSET_SQ_0_7_HEAD; 7423f3c6f97SJerin Jacob txq->sq_door = nicvf_qset_base(nic, qidx) + NIC_QSET_SQ_0_7_DOOR; 7433f3c6f97SJerin Jacob is_single_pool = (txq->txq_flags & ETH_TXQ_FLAGS_NOREFCOUNT && 7443f3c6f97SJerin Jacob txq->txq_flags & ETH_TXQ_FLAGS_NOMULTMEMP); 7453f3c6f97SJerin Jacob 7463f3c6f97SJerin Jacob /* Choose optimum free threshold value for multipool case */ 7473f3c6f97SJerin Jacob if (!is_single_pool) { 7483f3c6f97SJerin Jacob txq->tx_free_thresh = (uint16_t) 7493f3c6f97SJerin Jacob (tx_conf->tx_free_thresh == NICVF_DEFAULT_TX_FREE_THRESH ? 7503f3c6f97SJerin Jacob NICVF_TX_FREE_MPOOL_THRESH : 7513f3c6f97SJerin Jacob tx_conf->tx_free_thresh); 7521c421f18SJerin Jacob txq->pool_free = nicvf_multi_pool_free_xmited_buffers; 7531c421f18SJerin Jacob } else { 7541c421f18SJerin Jacob txq->pool_free = nicvf_single_pool_free_xmited_buffers; 7553f3c6f97SJerin Jacob } 7563f3c6f97SJerin Jacob 7573f3c6f97SJerin Jacob /* Allocate software ring */ 7583f3c6f97SJerin Jacob txq->txbuffs = rte_zmalloc_socket("txq->txbuffs", 7593f3c6f97SJerin Jacob nb_desc * sizeof(struct rte_mbuf *), 7603f3c6f97SJerin Jacob RTE_CACHE_LINE_SIZE, nic->node); 7613f3c6f97SJerin Jacob 7623f3c6f97SJerin Jacob if (txq->txbuffs == NULL) { 7633f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(txq); 7643f3c6f97SJerin Jacob return -ENOMEM; 7653f3c6f97SJerin Jacob } 7663f3c6f97SJerin Jacob 7673f3c6f97SJerin Jacob if (nicvf_qset_sq_alloc(nic, txq, qidx, nb_desc)) { 7683f3c6f97SJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate mem for sq %d", qidx); 7693f3c6f97SJerin Jacob nicvf_dev_tx_queue_release(txq); 7703f3c6f97SJerin Jacob return -ENOMEM; 7713f3c6f97SJerin Jacob } 7723f3c6f97SJerin Jacob 7733f3c6f97SJerin Jacob nicvf_tx_queue_reset(txq); 7743f3c6f97SJerin Jacob 7753f3c6f97SJerin Jacob PMD_TX_LOG(DEBUG, "[%d] txq=%p nb_desc=%d desc=%p phys=0x%" PRIx64, 7763f3c6f97SJerin Jacob qidx, txq, nb_desc, txq->desc, txq->phys); 7773f3c6f97SJerin Jacob 7783f3c6f97SJerin Jacob dev->data->tx_queues[qidx] = txq; 7793f3c6f97SJerin Jacob dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 7803f3c6f97SJerin Jacob return 0; 7813f3c6f97SJerin Jacob } 7823f3c6f97SJerin Jacob 78386b4eb42SJerin Jacob static inline void 78486b4eb42SJerin Jacob nicvf_rx_queue_release_mbufs(struct nicvf_rxq *rxq) 78586b4eb42SJerin Jacob { 78686b4eb42SJerin Jacob uint32_t rxq_cnt; 78786b4eb42SJerin Jacob uint32_t nb_pkts, released_pkts = 0; 78886b4eb42SJerin Jacob uint32_t refill_cnt = 0; 78986b4eb42SJerin Jacob struct rte_eth_dev *dev = rxq->nic->eth_dev; 79086b4eb42SJerin Jacob struct rte_mbuf *rx_pkts[NICVF_MAX_RX_FREE_THRESH]; 79186b4eb42SJerin Jacob 79286b4eb42SJerin Jacob if (dev->rx_pkt_burst == NULL) 79386b4eb42SJerin Jacob return; 79486b4eb42SJerin Jacob 79586b4eb42SJerin Jacob while ((rxq_cnt = nicvf_dev_rx_queue_count(dev, rxq->queue_id))) { 79686b4eb42SJerin Jacob nb_pkts = dev->rx_pkt_burst(rxq, rx_pkts, 79786b4eb42SJerin Jacob NICVF_MAX_RX_FREE_THRESH); 79886b4eb42SJerin Jacob PMD_DRV_LOG(INFO, "nb_pkts=%d rxq_cnt=%d", nb_pkts, rxq_cnt); 79986b4eb42SJerin Jacob while (nb_pkts) { 80086b4eb42SJerin Jacob rte_pktmbuf_free_seg(rx_pkts[--nb_pkts]); 80186b4eb42SJerin Jacob released_pkts++; 80286b4eb42SJerin Jacob } 80386b4eb42SJerin Jacob } 80486b4eb42SJerin Jacob 80586b4eb42SJerin Jacob refill_cnt += nicvf_dev_rbdr_refill(dev, rxq->queue_id); 80686b4eb42SJerin Jacob PMD_DRV_LOG(INFO, "free_cnt=%d refill_cnt=%d", 80786b4eb42SJerin Jacob released_pkts, refill_cnt); 80886b4eb42SJerin Jacob } 80986b4eb42SJerin Jacob 810aa0d976eSJerin Jacob static void 811aa0d976eSJerin Jacob nicvf_rx_queue_reset(struct nicvf_rxq *rxq) 812aa0d976eSJerin Jacob { 813aa0d976eSJerin Jacob rxq->head = 0; 814aa0d976eSJerin Jacob rxq->available_space = 0; 815aa0d976eSJerin Jacob rxq->recv_buffers = 0; 816aa0d976eSJerin Jacob } 817aa0d976eSJerin Jacob 81886b4eb42SJerin Jacob static inline int 81986b4eb42SJerin Jacob nicvf_start_rx_queue(struct rte_eth_dev *dev, uint16_t qidx) 82086b4eb42SJerin Jacob { 82186b4eb42SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 82286b4eb42SJerin Jacob struct nicvf_rxq *rxq; 82386b4eb42SJerin Jacob int ret; 82486b4eb42SJerin Jacob 82586b4eb42SJerin Jacob if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) 82686b4eb42SJerin Jacob return 0; 82786b4eb42SJerin Jacob 82886b4eb42SJerin Jacob /* Update rbdr pointer to all rxq */ 82986b4eb42SJerin Jacob rxq = dev->data->rx_queues[qidx]; 83086b4eb42SJerin Jacob rxq->shared_rbdr = nic->rbdr; 83186b4eb42SJerin Jacob 83286b4eb42SJerin Jacob ret = nicvf_qset_rq_config(nic, qidx, rxq); 83386b4eb42SJerin Jacob if (ret) { 83486b4eb42SJerin Jacob PMD_INIT_LOG(ERR, "Failed to configure rq %d %d", qidx, ret); 83586b4eb42SJerin Jacob goto config_rq_error; 83686b4eb42SJerin Jacob } 83786b4eb42SJerin Jacob ret = nicvf_qset_cq_config(nic, qidx, rxq); 83886b4eb42SJerin Jacob if (ret) { 83986b4eb42SJerin Jacob PMD_INIT_LOG(ERR, "Failed to configure cq %d %d", qidx, ret); 84086b4eb42SJerin Jacob goto config_cq_error; 84186b4eb42SJerin Jacob } 84286b4eb42SJerin Jacob 84386b4eb42SJerin Jacob dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED; 84486b4eb42SJerin Jacob return 0; 84586b4eb42SJerin Jacob 84686b4eb42SJerin Jacob config_cq_error: 84786b4eb42SJerin Jacob nicvf_qset_cq_reclaim(nic, qidx); 84886b4eb42SJerin Jacob config_rq_error: 84986b4eb42SJerin Jacob nicvf_qset_rq_reclaim(nic, qidx); 85086b4eb42SJerin Jacob return ret; 85186b4eb42SJerin Jacob } 85286b4eb42SJerin Jacob 85386b4eb42SJerin Jacob static inline int 85486b4eb42SJerin Jacob nicvf_stop_rx_queue(struct rte_eth_dev *dev, uint16_t qidx) 85586b4eb42SJerin Jacob { 85686b4eb42SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 85786b4eb42SJerin Jacob struct nicvf_rxq *rxq; 85886b4eb42SJerin Jacob int ret, other_error; 85986b4eb42SJerin Jacob 86086b4eb42SJerin Jacob if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) 86186b4eb42SJerin Jacob return 0; 86286b4eb42SJerin Jacob 86386b4eb42SJerin Jacob ret = nicvf_qset_rq_reclaim(nic, qidx); 86486b4eb42SJerin Jacob if (ret) 86586b4eb42SJerin Jacob PMD_INIT_LOG(ERR, "Failed to reclaim rq %d %d", qidx, ret); 86686b4eb42SJerin Jacob 86786b4eb42SJerin Jacob other_error = ret; 86886b4eb42SJerin Jacob rxq = dev->data->rx_queues[qidx]; 86986b4eb42SJerin Jacob nicvf_rx_queue_release_mbufs(rxq); 87086b4eb42SJerin Jacob nicvf_rx_queue_reset(rxq); 87186b4eb42SJerin Jacob 87286b4eb42SJerin Jacob ret = nicvf_qset_cq_reclaim(nic, qidx); 87386b4eb42SJerin Jacob if (ret) 87486b4eb42SJerin Jacob PMD_INIT_LOG(ERR, "Failed to reclaim cq %d %d", qidx, ret); 87586b4eb42SJerin Jacob 87686b4eb42SJerin Jacob other_error |= ret; 87786b4eb42SJerin Jacob dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 87886b4eb42SJerin Jacob return other_error; 87986b4eb42SJerin Jacob } 88086b4eb42SJerin Jacob 881aa0d976eSJerin Jacob static void 882aa0d976eSJerin Jacob nicvf_dev_rx_queue_release(void *rx_queue) 883aa0d976eSJerin Jacob { 884aa0d976eSJerin Jacob struct nicvf_rxq *rxq = rx_queue; 885aa0d976eSJerin Jacob 886aa0d976eSJerin Jacob PMD_INIT_FUNC_TRACE(); 887aa0d976eSJerin Jacob 888aa0d976eSJerin Jacob if (rxq) 889aa0d976eSJerin Jacob rte_free(rxq); 890aa0d976eSJerin Jacob } 891aa0d976eSJerin Jacob 892aa0d976eSJerin Jacob static int 89386b4eb42SJerin Jacob nicvf_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx) 89486b4eb42SJerin Jacob { 89586b4eb42SJerin Jacob int ret; 89686b4eb42SJerin Jacob 89786b4eb42SJerin Jacob ret = nicvf_start_rx_queue(dev, qidx); 89886b4eb42SJerin Jacob if (ret) 89986b4eb42SJerin Jacob return ret; 90086b4eb42SJerin Jacob 90186b4eb42SJerin Jacob ret = nicvf_configure_cpi(dev); 90286b4eb42SJerin Jacob if (ret) 90386b4eb42SJerin Jacob return ret; 90486b4eb42SJerin Jacob 90586b4eb42SJerin Jacob return nicvf_configure_rss_reta(dev); 90686b4eb42SJerin Jacob } 90786b4eb42SJerin Jacob 90886b4eb42SJerin Jacob static int 90986b4eb42SJerin Jacob nicvf_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx) 91086b4eb42SJerin Jacob { 91186b4eb42SJerin Jacob int ret; 91286b4eb42SJerin Jacob 91386b4eb42SJerin Jacob ret = nicvf_stop_rx_queue(dev, qidx); 91486b4eb42SJerin Jacob ret |= nicvf_configure_cpi(dev); 91586b4eb42SJerin Jacob ret |= nicvf_configure_rss_reta(dev); 91686b4eb42SJerin Jacob return ret; 91786b4eb42SJerin Jacob } 91886b4eb42SJerin Jacob 91986b4eb42SJerin Jacob static int 920*fc1f6c62SJerin Jacob nicvf_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx) 921*fc1f6c62SJerin Jacob { 922*fc1f6c62SJerin Jacob return nicvf_start_tx_queue(dev, qidx); 923*fc1f6c62SJerin Jacob } 924*fc1f6c62SJerin Jacob 925*fc1f6c62SJerin Jacob static int 926*fc1f6c62SJerin Jacob nicvf_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx) 927*fc1f6c62SJerin Jacob { 928*fc1f6c62SJerin Jacob return nicvf_stop_tx_queue(dev, qidx); 929*fc1f6c62SJerin Jacob } 930*fc1f6c62SJerin Jacob 931*fc1f6c62SJerin Jacob static int 932aa0d976eSJerin Jacob nicvf_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, 933aa0d976eSJerin Jacob uint16_t nb_desc, unsigned int socket_id, 934aa0d976eSJerin Jacob const struct rte_eth_rxconf *rx_conf, 935aa0d976eSJerin Jacob struct rte_mempool *mp) 936aa0d976eSJerin Jacob { 937aa0d976eSJerin Jacob uint16_t rx_free_thresh; 938aa0d976eSJerin Jacob struct nicvf_rxq *rxq; 939aa0d976eSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 940aa0d976eSJerin Jacob 941aa0d976eSJerin Jacob PMD_INIT_FUNC_TRACE(); 942aa0d976eSJerin Jacob 943aa0d976eSJerin Jacob /* Socket id check */ 944aa0d976eSJerin Jacob if (socket_id != (unsigned int)SOCKET_ID_ANY && socket_id != nic->node) 945aa0d976eSJerin Jacob PMD_DRV_LOG(WARNING, "socket_id expected %d, configured %d", 946aa0d976eSJerin Jacob socket_id, nic->node); 947aa0d976eSJerin Jacob 948aa0d976eSJerin Jacob /* Mempool memory should be contiguous */ 949aa0d976eSJerin Jacob if (mp->nb_mem_chunks != 1) { 950aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Non contiguous mempool, check huge page sz"); 951aa0d976eSJerin Jacob return -EINVAL; 952aa0d976eSJerin Jacob } 953aa0d976eSJerin Jacob 954aa0d976eSJerin Jacob /* Rx deferred start is not supported */ 955aa0d976eSJerin Jacob if (rx_conf->rx_deferred_start) { 956aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Rx deferred start not supported"); 957aa0d976eSJerin Jacob return -EINVAL; 958aa0d976eSJerin Jacob } 959aa0d976eSJerin Jacob 960aa0d976eSJerin Jacob /* Roundup nb_desc to available qsize and validate max number of desc */ 961aa0d976eSJerin Jacob nb_desc = nicvf_qsize_cq_roundup(nb_desc); 962aa0d976eSJerin Jacob if (nb_desc == 0) { 963aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Value nb_desc beyond available hw cq qsize"); 964aa0d976eSJerin Jacob return -EINVAL; 965aa0d976eSJerin Jacob } 966aa0d976eSJerin Jacob 967aa0d976eSJerin Jacob /* Check rx_free_thresh upper bound */ 968aa0d976eSJerin Jacob rx_free_thresh = (uint16_t)((rx_conf->rx_free_thresh) ? 969aa0d976eSJerin Jacob rx_conf->rx_free_thresh : 970aa0d976eSJerin Jacob NICVF_DEFAULT_RX_FREE_THRESH); 971aa0d976eSJerin Jacob if (rx_free_thresh > NICVF_MAX_RX_FREE_THRESH || 972aa0d976eSJerin Jacob rx_free_thresh >= nb_desc * .75) { 973aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "rx_free_thresh greater than expected %d", 974aa0d976eSJerin Jacob rx_free_thresh); 975aa0d976eSJerin Jacob return -EINVAL; 976aa0d976eSJerin Jacob } 977aa0d976eSJerin Jacob 978aa0d976eSJerin Jacob /* Free memory prior to re-allocation if needed */ 979aa0d976eSJerin Jacob if (dev->data->rx_queues[qidx] != NULL) { 980aa0d976eSJerin Jacob PMD_RX_LOG(DEBUG, "Freeing memory prior to re-allocation %d", 981aa0d976eSJerin Jacob qidx); 982aa0d976eSJerin Jacob nicvf_dev_rx_queue_release(dev->data->rx_queues[qidx]); 983aa0d976eSJerin Jacob dev->data->rx_queues[qidx] = NULL; 984aa0d976eSJerin Jacob } 985aa0d976eSJerin Jacob 986aa0d976eSJerin Jacob /* Allocate rxq memory */ 987aa0d976eSJerin Jacob rxq = rte_zmalloc_socket("ethdev rx queue", sizeof(struct nicvf_rxq), 988aa0d976eSJerin Jacob RTE_CACHE_LINE_SIZE, nic->node); 989aa0d976eSJerin Jacob if (rxq == NULL) { 990aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate rxq=%d", qidx); 991aa0d976eSJerin Jacob return -ENOMEM; 992aa0d976eSJerin Jacob } 993aa0d976eSJerin Jacob 994aa0d976eSJerin Jacob rxq->nic = nic; 995aa0d976eSJerin Jacob rxq->pool = mp; 996aa0d976eSJerin Jacob rxq->queue_id = qidx; 997aa0d976eSJerin Jacob rxq->port_id = dev->data->port_id; 998aa0d976eSJerin Jacob rxq->rx_free_thresh = rx_free_thresh; 999aa0d976eSJerin Jacob rxq->rx_drop_en = rx_conf->rx_drop_en; 1000aa0d976eSJerin Jacob rxq->cq_status = nicvf_qset_base(nic, qidx) + NIC_QSET_CQ_0_7_STATUS; 1001aa0d976eSJerin Jacob rxq->cq_door = nicvf_qset_base(nic, qidx) + NIC_QSET_CQ_0_7_DOOR; 1002aa0d976eSJerin Jacob rxq->precharge_cnt = 0; 1003aa0d976eSJerin Jacob rxq->rbptr_offset = NICVF_CQE_RBPTR_WORD; 1004aa0d976eSJerin Jacob 1005aa0d976eSJerin Jacob /* Alloc completion queue */ 1006aa0d976eSJerin Jacob if (nicvf_qset_cq_alloc(nic, rxq, rxq->queue_id, nb_desc)) { 1007aa0d976eSJerin Jacob PMD_INIT_LOG(ERR, "failed to allocate cq %u", rxq->queue_id); 1008aa0d976eSJerin Jacob nicvf_dev_rx_queue_release(rxq); 1009aa0d976eSJerin Jacob return -ENOMEM; 1010aa0d976eSJerin Jacob } 1011aa0d976eSJerin Jacob 1012aa0d976eSJerin Jacob nicvf_rx_queue_reset(rxq); 1013aa0d976eSJerin Jacob 1014aa0d976eSJerin Jacob PMD_RX_LOG(DEBUG, "[%d] rxq=%p pool=%s nb_desc=(%d/%d) phy=%" PRIx64, 1015aa0d976eSJerin Jacob qidx, rxq, mp->name, nb_desc, 1016aa0d976eSJerin Jacob rte_mempool_count(mp), rxq->phys); 1017aa0d976eSJerin Jacob 1018aa0d976eSJerin Jacob dev->data->rx_queues[qidx] = rxq; 1019aa0d976eSJerin Jacob dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 1020aa0d976eSJerin Jacob return 0; 1021aa0d976eSJerin Jacob } 1022aa0d976eSJerin Jacob 1023dcd7b1e1SJerin Jacob static void 1024dcd7b1e1SJerin Jacob nicvf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 1025dcd7b1e1SJerin Jacob { 1026dcd7b1e1SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 1027dcd7b1e1SJerin Jacob 1028dcd7b1e1SJerin Jacob PMD_INIT_FUNC_TRACE(); 1029dcd7b1e1SJerin Jacob 1030dcd7b1e1SJerin Jacob dev_info->min_rx_bufsize = ETHER_MIN_MTU; 1031dcd7b1e1SJerin Jacob dev_info->max_rx_pktlen = NIC_HW_MAX_FRS; 1032dcd7b1e1SJerin Jacob dev_info->max_rx_queues = (uint16_t)MAX_RCV_QUEUES_PER_QS; 1033dcd7b1e1SJerin Jacob dev_info->max_tx_queues = (uint16_t)MAX_SND_QUEUES_PER_QS; 1034dcd7b1e1SJerin Jacob dev_info->max_mac_addrs = 1; 1035dcd7b1e1SJerin Jacob dev_info->max_vfs = dev->pci_dev->max_vfs; 1036dcd7b1e1SJerin Jacob 1037dcd7b1e1SJerin Jacob dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP; 1038dcd7b1e1SJerin Jacob dev_info->tx_offload_capa = 1039dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_IPV4_CKSUM | 1040dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_UDP_CKSUM | 1041dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_TCP_CKSUM | 1042dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_TCP_TSO | 1043dcd7b1e1SJerin Jacob DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; 1044dcd7b1e1SJerin Jacob 1045dcd7b1e1SJerin Jacob dev_info->reta_size = nic->rss_info.rss_size; 1046dcd7b1e1SJerin Jacob dev_info->hash_key_size = RSS_HASH_KEY_BYTE_SIZE; 1047dcd7b1e1SJerin Jacob dev_info->flow_type_rss_offloads = NICVF_RSS_OFFLOAD_PASS1; 1048dcd7b1e1SJerin Jacob if (nicvf_hw_cap(nic) & NICVF_CAP_TUNNEL_PARSING) 1049dcd7b1e1SJerin Jacob dev_info->flow_type_rss_offloads |= NICVF_RSS_OFFLOAD_TUNNEL; 1050dcd7b1e1SJerin Jacob 1051dcd7b1e1SJerin Jacob dev_info->default_rxconf = (struct rte_eth_rxconf) { 1052dcd7b1e1SJerin Jacob .rx_free_thresh = NICVF_DEFAULT_RX_FREE_THRESH, 1053dcd7b1e1SJerin Jacob .rx_drop_en = 0, 1054dcd7b1e1SJerin Jacob }; 1055dcd7b1e1SJerin Jacob 1056dcd7b1e1SJerin Jacob dev_info->default_txconf = (struct rte_eth_txconf) { 1057dcd7b1e1SJerin Jacob .tx_free_thresh = NICVF_DEFAULT_TX_FREE_THRESH, 1058dcd7b1e1SJerin Jacob .txq_flags = 1059dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOMULTSEGS | 1060dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOREFCOUNT | 1061dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOMULTMEMP | 1062dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOVLANOFFL | 1063dcd7b1e1SJerin Jacob ETH_TXQ_FLAGS_NOXSUMSCTP, 1064dcd7b1e1SJerin Jacob }; 1065dcd7b1e1SJerin Jacob } 1066dcd7b1e1SJerin Jacob 1067bc79615aSJerin Jacob static int 1068bc79615aSJerin Jacob nicvf_dev_configure(struct rte_eth_dev *dev) 1069bc79615aSJerin Jacob { 1070bc79615aSJerin Jacob struct rte_eth_conf *conf = &dev->data->dev_conf; 1071bc79615aSJerin Jacob struct rte_eth_rxmode *rxmode = &conf->rxmode; 1072bc79615aSJerin Jacob struct rte_eth_txmode *txmode = &conf->txmode; 1073bc79615aSJerin Jacob struct nicvf *nic = nicvf_pmd_priv(dev); 1074bc79615aSJerin Jacob 1075bc79615aSJerin Jacob PMD_INIT_FUNC_TRACE(); 1076bc79615aSJerin Jacob 1077bc79615aSJerin Jacob if (!rte_eal_has_hugepages()) { 1078bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Huge page is not configured"); 1079bc79615aSJerin Jacob return -EINVAL; 1080bc79615aSJerin Jacob } 1081bc79615aSJerin Jacob 1082bc79615aSJerin Jacob if (txmode->mq_mode) { 1083bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Tx mq_mode DCB or VMDq not supported"); 1084bc79615aSJerin Jacob return -EINVAL; 1085bc79615aSJerin Jacob } 1086bc79615aSJerin Jacob 1087bc79615aSJerin Jacob if (rxmode->mq_mode != ETH_MQ_RX_NONE && 1088bc79615aSJerin Jacob rxmode->mq_mode != ETH_MQ_RX_RSS) { 1089bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Unsupported rx qmode %d", rxmode->mq_mode); 1090bc79615aSJerin Jacob return -EINVAL; 1091bc79615aSJerin Jacob } 1092bc79615aSJerin Jacob 1093bc79615aSJerin Jacob if (!rxmode->hw_strip_crc) { 1094bc79615aSJerin Jacob PMD_INIT_LOG(NOTICE, "Can't disable hw crc strip"); 1095bc79615aSJerin Jacob rxmode->hw_strip_crc = 1; 1096bc79615aSJerin Jacob } 1097bc79615aSJerin Jacob 1098bc79615aSJerin Jacob if (rxmode->hw_ip_checksum) { 1099bc79615aSJerin Jacob PMD_INIT_LOG(NOTICE, "Rxcksum not supported"); 1100bc79615aSJerin Jacob rxmode->hw_ip_checksum = 0; 1101bc79615aSJerin Jacob } 1102bc79615aSJerin Jacob 1103bc79615aSJerin Jacob if (rxmode->split_hdr_size) { 1104bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Rxmode does not support split header"); 1105bc79615aSJerin Jacob return -EINVAL; 1106bc79615aSJerin Jacob } 1107bc79615aSJerin Jacob 1108bc79615aSJerin Jacob if (rxmode->hw_vlan_filter) { 1109bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "VLAN filter not supported"); 1110bc79615aSJerin Jacob return -EINVAL; 1111bc79615aSJerin Jacob } 1112bc79615aSJerin Jacob 1113bc79615aSJerin Jacob if (rxmode->hw_vlan_extend) { 1114bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "VLAN extended not supported"); 1115bc79615aSJerin Jacob return -EINVAL; 1116bc79615aSJerin Jacob } 1117bc79615aSJerin Jacob 1118bc79615aSJerin Jacob if (rxmode->enable_lro) { 1119bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "LRO not supported"); 1120bc79615aSJerin Jacob return -EINVAL; 1121bc79615aSJerin Jacob } 1122bc79615aSJerin Jacob 1123bc79615aSJerin Jacob if (conf->link_speeds & ETH_LINK_SPEED_FIXED) { 1124bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Setting link speed/duplex not supported"); 1125bc79615aSJerin Jacob return -EINVAL; 1126bc79615aSJerin Jacob } 1127bc79615aSJerin Jacob 1128bc79615aSJerin Jacob if (conf->dcb_capability_en) { 1129bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "DCB enable not supported"); 1130bc79615aSJerin Jacob return -EINVAL; 1131bc79615aSJerin Jacob } 1132bc79615aSJerin Jacob 1133bc79615aSJerin Jacob if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) { 1134bc79615aSJerin Jacob PMD_INIT_LOG(INFO, "Flow director not supported"); 1135bc79615aSJerin Jacob return -EINVAL; 1136bc79615aSJerin Jacob } 1137bc79615aSJerin Jacob 1138bc79615aSJerin Jacob PMD_INIT_LOG(DEBUG, "Configured ethdev port%d hwcap=0x%" PRIx64, 1139bc79615aSJerin Jacob dev->data->port_id, nicvf_hw_cap(nic)); 1140bc79615aSJerin Jacob 1141bc79615aSJerin Jacob return 0; 1142bc79615aSJerin Jacob } 1143bc79615aSJerin Jacob 1144e4387966SJerin Jacob /* Initialize and register driver with DPDK Application */ 1145e4387966SJerin Jacob static const struct eth_dev_ops nicvf_eth_dev_ops = { 1146bc79615aSJerin Jacob .dev_configure = nicvf_dev_configure, 11478fc70464SJerin Jacob .link_update = nicvf_dev_link_update, 1148684fa771SJerin Jacob .stats_get = nicvf_dev_stats_get, 1149684fa771SJerin Jacob .stats_reset = nicvf_dev_stats_reset, 11506eae36eaSJerin Jacob .promiscuous_enable = nicvf_dev_promisc_enable, 1151dcd7b1e1SJerin Jacob .dev_infos_get = nicvf_dev_info_get, 11521c80e4fdSJerin Jacob .dev_supported_ptypes_get = nicvf_dev_supported_ptypes_get, 115365d9804eSJerin Jacob .mtu_set = nicvf_dev_set_mtu, 115443362c6aSJerin Jacob .reta_update = nicvf_dev_reta_update, 115543362c6aSJerin Jacob .reta_query = nicvf_dev_reta_query, 115643362c6aSJerin Jacob .rss_hash_update = nicvf_dev_rss_hash_update, 115743362c6aSJerin Jacob .rss_hash_conf_get = nicvf_dev_rss_hash_conf_get, 115886b4eb42SJerin Jacob .rx_queue_start = nicvf_dev_rx_queue_start, 115986b4eb42SJerin Jacob .rx_queue_stop = nicvf_dev_rx_queue_stop, 1160*fc1f6c62SJerin Jacob .tx_queue_start = nicvf_dev_tx_queue_start, 1161*fc1f6c62SJerin Jacob .tx_queue_stop = nicvf_dev_tx_queue_stop, 1162aa0d976eSJerin Jacob .rx_queue_setup = nicvf_dev_rx_queue_setup, 1163aa0d976eSJerin Jacob .rx_queue_release = nicvf_dev_rx_queue_release, 1164da14e00cSJerin Jacob .rx_queue_count = nicvf_dev_rx_queue_count, 11653f3c6f97SJerin Jacob .tx_queue_setup = nicvf_dev_tx_queue_setup, 11663f3c6f97SJerin Jacob .tx_queue_release = nicvf_dev_tx_queue_release, 1167606ee746SJerin Jacob .get_reg_length = nicvf_dev_get_reg_length, 1168606ee746SJerin Jacob .get_reg = nicvf_dev_get_regs, 1169e4387966SJerin Jacob }; 1170e4387966SJerin Jacob 1171e4387966SJerin Jacob static int 1172e4387966SJerin Jacob nicvf_eth_dev_init(struct rte_eth_dev *eth_dev) 1173e4387966SJerin Jacob { 1174e4387966SJerin Jacob int ret; 1175e4387966SJerin Jacob struct rte_pci_device *pci_dev; 1176e4387966SJerin Jacob struct nicvf *nic = nicvf_pmd_priv(eth_dev); 1177e4387966SJerin Jacob 1178e4387966SJerin Jacob PMD_INIT_FUNC_TRACE(); 1179e4387966SJerin Jacob 1180e4387966SJerin Jacob eth_dev->dev_ops = &nicvf_eth_dev_ops; 1181e4387966SJerin Jacob 1182e4387966SJerin Jacob pci_dev = eth_dev->pci_dev; 1183e4387966SJerin Jacob rte_eth_copy_pci_info(eth_dev, pci_dev); 1184e4387966SJerin Jacob 1185e4387966SJerin Jacob nic->device_id = pci_dev->id.device_id; 1186e4387966SJerin Jacob nic->vendor_id = pci_dev->id.vendor_id; 1187e4387966SJerin Jacob nic->subsystem_device_id = pci_dev->id.subsystem_device_id; 1188e4387966SJerin Jacob nic->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; 1189e4387966SJerin Jacob nic->eth_dev = eth_dev; 1190e4387966SJerin Jacob 1191e4387966SJerin Jacob PMD_INIT_LOG(DEBUG, "nicvf: device (%x:%x) %u:%u:%u:%u", 1192e4387966SJerin Jacob pci_dev->id.vendor_id, pci_dev->id.device_id, 1193e4387966SJerin Jacob pci_dev->addr.domain, pci_dev->addr.bus, 1194e4387966SJerin Jacob pci_dev->addr.devid, pci_dev->addr.function); 1195e4387966SJerin Jacob 1196e4387966SJerin Jacob nic->reg_base = (uintptr_t)pci_dev->mem_resource[0].addr; 1197e4387966SJerin Jacob if (!nic->reg_base) { 1198e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to map BAR0"); 1199e4387966SJerin Jacob ret = -ENODEV; 1200e4387966SJerin Jacob goto fail; 1201e4387966SJerin Jacob } 1202e4387966SJerin Jacob 1203e4387966SJerin Jacob nicvf_disable_all_interrupts(nic); 1204e4387966SJerin Jacob 1205e4387966SJerin Jacob ret = nicvf_periodic_alarm_start(nic); 1206e4387966SJerin Jacob if (ret) { 1207e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to start period alarm"); 1208e4387966SJerin Jacob goto fail; 1209e4387966SJerin Jacob } 1210e4387966SJerin Jacob 1211e4387966SJerin Jacob ret = nicvf_mbox_check_pf_ready(nic); 1212e4387966SJerin Jacob if (ret) { 1213e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to get ready message from PF"); 1214e4387966SJerin Jacob goto alarm_fail; 1215e4387966SJerin Jacob } else { 1216e4387966SJerin Jacob PMD_INIT_LOG(INFO, 1217e4387966SJerin Jacob "node=%d vf=%d mode=%s sqs=%s loopback_supported=%s", 1218e4387966SJerin Jacob nic->node, nic->vf_id, 1219e4387966SJerin Jacob nic->tns_mode == NIC_TNS_MODE ? "tns" : "tns-bypass", 1220e4387966SJerin Jacob nic->sqs_mode ? "true" : "false", 1221e4387966SJerin Jacob nic->loopback_supported ? "true" : "false" 1222e4387966SJerin Jacob ); 1223e4387966SJerin Jacob } 1224e4387966SJerin Jacob 1225e4387966SJerin Jacob if (nic->sqs_mode) { 1226e4387966SJerin Jacob PMD_INIT_LOG(INFO, "Unsupported SQS VF detected, Detaching..."); 1227e4387966SJerin Jacob /* Detach port by returning Positive error number */ 1228e4387966SJerin Jacob ret = ENOTSUP; 1229e4387966SJerin Jacob goto alarm_fail; 1230e4387966SJerin Jacob } 1231e4387966SJerin Jacob 1232e4387966SJerin Jacob eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", ETHER_ADDR_LEN, 0); 1233e4387966SJerin Jacob if (eth_dev->data->mac_addrs == NULL) { 1234e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to allocate memory for mac addr"); 1235e4387966SJerin Jacob ret = -ENOMEM; 1236e4387966SJerin Jacob goto alarm_fail; 1237e4387966SJerin Jacob } 1238e4387966SJerin Jacob if (is_zero_ether_addr((struct ether_addr *)nic->mac_addr)) 1239e4387966SJerin Jacob eth_random_addr(&nic->mac_addr[0]); 1240e4387966SJerin Jacob 1241e4387966SJerin Jacob ether_addr_copy((struct ether_addr *)nic->mac_addr, 1242e4387966SJerin Jacob ð_dev->data->mac_addrs[0]); 1243e4387966SJerin Jacob 1244e4387966SJerin Jacob ret = nicvf_mbox_set_mac_addr(nic, nic->mac_addr); 1245e4387966SJerin Jacob if (ret) { 1246e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to set mac addr"); 1247e4387966SJerin Jacob goto malloc_fail; 1248e4387966SJerin Jacob } 1249e4387966SJerin Jacob 1250e4387966SJerin Jacob ret = nicvf_base_init(nic); 1251e4387966SJerin Jacob if (ret) { 1252e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to execute nicvf_base_init"); 1253e4387966SJerin Jacob goto malloc_fail; 1254e4387966SJerin Jacob } 1255e4387966SJerin Jacob 1256e4387966SJerin Jacob ret = nicvf_mbox_get_rss_size(nic); 1257e4387966SJerin Jacob if (ret) { 1258e4387966SJerin Jacob PMD_INIT_LOG(ERR, "Failed to get rss table size"); 1259e4387966SJerin Jacob goto malloc_fail; 1260e4387966SJerin Jacob } 1261e4387966SJerin Jacob 1262e4387966SJerin Jacob PMD_INIT_LOG(INFO, "Port %d (%x:%x) mac=%02x:%02x:%02x:%02x:%02x:%02x", 1263e4387966SJerin Jacob eth_dev->data->port_id, nic->vendor_id, nic->device_id, 1264e4387966SJerin Jacob nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2], 1265e4387966SJerin Jacob nic->mac_addr[3], nic->mac_addr[4], nic->mac_addr[5]); 1266e4387966SJerin Jacob 1267e4387966SJerin Jacob return 0; 1268e4387966SJerin Jacob 1269e4387966SJerin Jacob malloc_fail: 1270e4387966SJerin Jacob rte_free(eth_dev->data->mac_addrs); 1271e4387966SJerin Jacob alarm_fail: 1272e4387966SJerin Jacob nicvf_periodic_alarm_stop(nic); 1273e4387966SJerin Jacob fail: 1274e4387966SJerin Jacob return ret; 1275e4387966SJerin Jacob } 1276e4387966SJerin Jacob 1277e4387966SJerin Jacob static const struct rte_pci_id pci_id_nicvf_map[] = { 1278e4387966SJerin Jacob { 1279e4387966SJerin Jacob .class_id = RTE_CLASS_ANY_ID, 1280e4387966SJerin Jacob .vendor_id = PCI_VENDOR_ID_CAVIUM, 1281e4387966SJerin Jacob .device_id = PCI_DEVICE_ID_THUNDERX_PASS1_NICVF, 1282e4387966SJerin Jacob .subsystem_vendor_id = PCI_VENDOR_ID_CAVIUM, 1283e4387966SJerin Jacob .subsystem_device_id = PCI_SUB_DEVICE_ID_THUNDERX_PASS1_NICVF, 1284e4387966SJerin Jacob }, 1285e4387966SJerin Jacob { 1286e4387966SJerin Jacob .class_id = RTE_CLASS_ANY_ID, 1287e4387966SJerin Jacob .vendor_id = PCI_VENDOR_ID_CAVIUM, 1288e4387966SJerin Jacob .device_id = PCI_DEVICE_ID_THUNDERX_PASS2_NICVF, 1289e4387966SJerin Jacob .subsystem_vendor_id = PCI_VENDOR_ID_CAVIUM, 1290e4387966SJerin Jacob .subsystem_device_id = PCI_SUB_DEVICE_ID_THUNDERX_PASS2_NICVF, 1291e4387966SJerin Jacob }, 1292e4387966SJerin Jacob { 1293e4387966SJerin Jacob .vendor_id = 0, 1294e4387966SJerin Jacob }, 1295e4387966SJerin Jacob }; 1296e4387966SJerin Jacob 1297e4387966SJerin Jacob static struct eth_driver rte_nicvf_pmd = { 1298e4387966SJerin Jacob .pci_drv = { 1299e4387966SJerin Jacob .name = "rte_nicvf_pmd", 1300e4387966SJerin Jacob .id_table = pci_id_nicvf_map, 1301e4387966SJerin Jacob .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 1302e4387966SJerin Jacob }, 1303e4387966SJerin Jacob .eth_dev_init = nicvf_eth_dev_init, 1304e4387966SJerin Jacob .dev_private_size = sizeof(struct nicvf), 1305e4387966SJerin Jacob }; 1306e4387966SJerin Jacob 1307e4387966SJerin Jacob static int 1308e4387966SJerin Jacob rte_nicvf_pmd_init(const char *name __rte_unused, const char *para __rte_unused) 1309e4387966SJerin Jacob { 1310e4387966SJerin Jacob PMD_INIT_FUNC_TRACE(); 1311e4387966SJerin Jacob PMD_INIT_LOG(INFO, "librte_pmd_thunderx nicvf version %s", 1312e4387966SJerin Jacob THUNDERX_NICVF_PMD_VERSION); 1313e4387966SJerin Jacob 1314e4387966SJerin Jacob rte_eth_driver_register(&rte_nicvf_pmd); 1315e4387966SJerin Jacob return 0; 1316e4387966SJerin Jacob } 1317e4387966SJerin Jacob 1318e4387966SJerin Jacob static struct rte_driver rte_nicvf_driver = { 1319e4387966SJerin Jacob .name = "nicvf_driver", 1320e4387966SJerin Jacob .type = PMD_PDEV, 1321e4387966SJerin Jacob .init = rte_nicvf_pmd_init, 1322e4387966SJerin Jacob }; 1323e4387966SJerin Jacob 1324e4387966SJerin Jacob PMD_REGISTER_DRIVER(rte_nicvf_driver); 1325