1a9643ea8Slogwang /* 2a9643ea8Slogwang * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. 3a9643ea8Slogwang * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4a9643ea8Slogwang * 5a9643ea8Slogwang * Copyright (c) 2014, Cisco Systems, Inc. 6a9643ea8Slogwang * All rights reserved. 7a9643ea8Slogwang * 8a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 9a9643ea8Slogwang * modification, are permitted provided that the following conditions 10a9643ea8Slogwang * are met: 11a9643ea8Slogwang * 12a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright 13a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 14a9643ea8Slogwang * 15a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright 16a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in 17a9643ea8Slogwang * the documentation and/or other materials provided with the 18a9643ea8Slogwang * distribution. 19a9643ea8Slogwang * 20a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21a9643ea8Slogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22a9643ea8Slogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23a9643ea8Slogwang * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24a9643ea8Slogwang * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25a9643ea8Slogwang * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26a9643ea8Slogwang * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27a9643ea8Slogwang * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28a9643ea8Slogwang * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30a9643ea8Slogwang * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31a9643ea8Slogwang * POSSIBILITY OF SUCH DAMAGE. 32a9643ea8Slogwang * 33a9643ea8Slogwang */ 34a9643ea8Slogwang 35a9643ea8Slogwang #include <stdio.h> 36a9643ea8Slogwang #include <stdint.h> 37a9643ea8Slogwang 38a9643ea8Slogwang #include <rte_dev.h> 39a9643ea8Slogwang #include <rte_pci.h> 402bfe3f2eSlogwang #include <rte_bus_pci.h> 41a9643ea8Slogwang #include <rte_ethdev.h> 422bfe3f2eSlogwang #include <rte_ethdev_pci.h> 43*579bf1e2Sjfb8856606 #include <rte_kvargs.h> 44a9643ea8Slogwang #include <rte_string_fns.h> 45a9643ea8Slogwang 46a9643ea8Slogwang #include "vnic_intr.h" 47a9643ea8Slogwang #include "vnic_cq.h" 48a9643ea8Slogwang #include "vnic_wq.h" 49a9643ea8Slogwang #include "vnic_rq.h" 50a9643ea8Slogwang #include "vnic_enet.h" 51a9643ea8Slogwang #include "enic.h" 52a9643ea8Slogwang 53a9643ea8Slogwang #ifdef RTE_LIBRTE_ENIC_DEBUG 54a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() \ 55a9643ea8Slogwang RTE_LOG(DEBUG, PMD, "ENICPMD trace: %s\n", __func__) 56a9643ea8Slogwang #else 57a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() (void)0 58a9643ea8Slogwang #endif 59a9643ea8Slogwang 60a9643ea8Slogwang /* 61a9643ea8Slogwang * The set of PCI devices this driver supports 62a9643ea8Slogwang */ 63a9643ea8Slogwang #define CISCO_PCI_VENDOR_ID 0x1137 64a9643ea8Slogwang static const struct rte_pci_id pci_id_enic_map[] = { 65a9643ea8Slogwang { RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET) }, 66a9643ea8Slogwang { RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) }, 67a9643ea8Slogwang {.vendor_id = 0, /* sentinel */}, 68a9643ea8Slogwang }; 69a9643ea8Slogwang 70*579bf1e2Sjfb8856606 #define ENIC_DEVARG_IG_VLAN_REWRITE "ig-vlan-rewrite" 71*579bf1e2Sjfb8856606 72a9643ea8Slogwang static int 73a9643ea8Slogwang enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev, 74a9643ea8Slogwang enum rte_filter_op filter_op, void *arg) 75a9643ea8Slogwang { 76a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 77a9643ea8Slogwang int ret = 0; 78a9643ea8Slogwang 79a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 80a9643ea8Slogwang if (filter_op == RTE_ETH_FILTER_NOP) 81a9643ea8Slogwang return 0; 82a9643ea8Slogwang 83a9643ea8Slogwang if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) 84a9643ea8Slogwang return -EINVAL; 85a9643ea8Slogwang 86a9643ea8Slogwang switch (filter_op) { 87a9643ea8Slogwang case RTE_ETH_FILTER_ADD: 88a9643ea8Slogwang case RTE_ETH_FILTER_UPDATE: 89a9643ea8Slogwang ret = enic_fdir_add_fltr(enic, 90a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 91a9643ea8Slogwang break; 92a9643ea8Slogwang 93a9643ea8Slogwang case RTE_ETH_FILTER_DELETE: 94a9643ea8Slogwang ret = enic_fdir_del_fltr(enic, 95a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 96a9643ea8Slogwang break; 97a9643ea8Slogwang 98a9643ea8Slogwang case RTE_ETH_FILTER_STATS: 99a9643ea8Slogwang enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg); 100a9643ea8Slogwang break; 101a9643ea8Slogwang 102a9643ea8Slogwang case RTE_ETH_FILTER_FLUSH: 103a9643ea8Slogwang dev_warning(enic, "unsupported operation %u", filter_op); 104a9643ea8Slogwang ret = -ENOTSUP; 105a9643ea8Slogwang break; 1062bfe3f2eSlogwang case RTE_ETH_FILTER_INFO: 1072bfe3f2eSlogwang enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg); 1082bfe3f2eSlogwang break; 109a9643ea8Slogwang default: 110a9643ea8Slogwang dev_err(enic, "unknown operation %u", filter_op); 111a9643ea8Slogwang ret = -EINVAL; 112a9643ea8Slogwang break; 113a9643ea8Slogwang } 114a9643ea8Slogwang return ret; 115a9643ea8Slogwang } 116a9643ea8Slogwang 117a9643ea8Slogwang static int 118a9643ea8Slogwang enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev, 119a9643ea8Slogwang enum rte_filter_type filter_type, 120a9643ea8Slogwang enum rte_filter_op filter_op, 121a9643ea8Slogwang void *arg) 122a9643ea8Slogwang { 1232bfe3f2eSlogwang int ret = 0; 124a9643ea8Slogwang 1252bfe3f2eSlogwang ENICPMD_FUNC_TRACE(); 1262bfe3f2eSlogwang 1272bfe3f2eSlogwang switch (filter_type) { 1282bfe3f2eSlogwang case RTE_ETH_FILTER_GENERIC: 1292bfe3f2eSlogwang if (filter_op != RTE_ETH_FILTER_GET) 1302bfe3f2eSlogwang return -EINVAL; 1312bfe3f2eSlogwang *(const void **)arg = &enic_flow_ops; 1322bfe3f2eSlogwang break; 1332bfe3f2eSlogwang case RTE_ETH_FILTER_FDIR: 134a9643ea8Slogwang ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg); 1352bfe3f2eSlogwang break; 1362bfe3f2eSlogwang default: 137a9643ea8Slogwang dev_warning(enic, "Filter type (%d) not supported", 138a9643ea8Slogwang filter_type); 1392bfe3f2eSlogwang ret = -EINVAL; 1402bfe3f2eSlogwang break; 1412bfe3f2eSlogwang } 142a9643ea8Slogwang 143a9643ea8Slogwang return ret; 144a9643ea8Slogwang } 145a9643ea8Slogwang 146a9643ea8Slogwang static void enicpmd_dev_tx_queue_release(void *txq) 147a9643ea8Slogwang { 148a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 1492bfe3f2eSlogwang 1502bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 1512bfe3f2eSlogwang return; 1522bfe3f2eSlogwang 153a9643ea8Slogwang enic_free_wq(txq); 154a9643ea8Slogwang } 155a9643ea8Slogwang 156a9643ea8Slogwang static int enicpmd_dev_setup_intr(struct enic *enic) 157a9643ea8Slogwang { 158a9643ea8Slogwang int ret; 159a9643ea8Slogwang unsigned int index; 160a9643ea8Slogwang 161a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 162a9643ea8Slogwang 163a9643ea8Slogwang /* Are we done with the init of all the queues? */ 164a9643ea8Slogwang for (index = 0; index < enic->cq_count; index++) { 165a9643ea8Slogwang if (!enic->cq[index].ctrl) 166a9643ea8Slogwang break; 167a9643ea8Slogwang } 168a9643ea8Slogwang if (enic->cq_count != index) 169a9643ea8Slogwang return 0; 170a9643ea8Slogwang for (index = 0; index < enic->wq_count; index++) { 171a9643ea8Slogwang if (!enic->wq[index].ctrl) 172a9643ea8Slogwang break; 173a9643ea8Slogwang } 174a9643ea8Slogwang if (enic->wq_count != index) 175a9643ea8Slogwang return 0; 176a9643ea8Slogwang /* check start of packet (SOP) RQs only in case scatter is disabled. */ 177a9643ea8Slogwang for (index = 0; index < enic->rq_count; index++) { 1782bfe3f2eSlogwang if (!enic->rq[enic_rte_rq_idx_to_sop_idx(index)].ctrl) 179a9643ea8Slogwang break; 180a9643ea8Slogwang } 181a9643ea8Slogwang if (enic->rq_count != index) 182a9643ea8Slogwang return 0; 183a9643ea8Slogwang 184a9643ea8Slogwang ret = enic_alloc_intr_resources(enic); 185a9643ea8Slogwang if (ret) { 186a9643ea8Slogwang dev_err(enic, "alloc intr failed\n"); 187a9643ea8Slogwang return ret; 188a9643ea8Slogwang } 189a9643ea8Slogwang enic_init_vnic_resources(enic); 190a9643ea8Slogwang 191a9643ea8Slogwang ret = enic_setup_finish(enic); 192a9643ea8Slogwang if (ret) 193a9643ea8Slogwang dev_err(enic, "setup could not be finished\n"); 194a9643ea8Slogwang 195a9643ea8Slogwang return ret; 196a9643ea8Slogwang } 197a9643ea8Slogwang 198a9643ea8Slogwang static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 199a9643ea8Slogwang uint16_t queue_idx, 200a9643ea8Slogwang uint16_t nb_desc, 201a9643ea8Slogwang unsigned int socket_id, 202a9643ea8Slogwang __rte_unused const struct rte_eth_txconf *tx_conf) 203a9643ea8Slogwang { 204a9643ea8Slogwang int ret; 205a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 206a9643ea8Slogwang 2072bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 2082bfe3f2eSlogwang return -E_RTE_SECONDARY; 209a9643ea8Slogwang 2102bfe3f2eSlogwang ENICPMD_FUNC_TRACE(); 2112bfe3f2eSlogwang RTE_ASSERT(queue_idx < enic->conf_wq_count); 212a9643ea8Slogwang eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx]; 213a9643ea8Slogwang 214a9643ea8Slogwang ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc); 215a9643ea8Slogwang if (ret) { 216a9643ea8Slogwang dev_err(enic, "error in allocating wq\n"); 217a9643ea8Slogwang return ret; 218a9643ea8Slogwang } 219a9643ea8Slogwang 220a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 221a9643ea8Slogwang } 222a9643ea8Slogwang 223a9643ea8Slogwang static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev, 224a9643ea8Slogwang uint16_t queue_idx) 225a9643ea8Slogwang { 226a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 227a9643ea8Slogwang 228a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 229a9643ea8Slogwang 230a9643ea8Slogwang enic_start_wq(enic, queue_idx); 231a9643ea8Slogwang 232a9643ea8Slogwang return 0; 233a9643ea8Slogwang } 234a9643ea8Slogwang 235a9643ea8Slogwang static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, 236a9643ea8Slogwang uint16_t queue_idx) 237a9643ea8Slogwang { 238a9643ea8Slogwang int ret; 239a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 240a9643ea8Slogwang 241a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 242a9643ea8Slogwang 243a9643ea8Slogwang ret = enic_stop_wq(enic, queue_idx); 244a9643ea8Slogwang if (ret) 245a9643ea8Slogwang dev_err(enic, "error in stopping wq %d\n", queue_idx); 246a9643ea8Slogwang 247a9643ea8Slogwang return ret; 248a9643ea8Slogwang } 249a9643ea8Slogwang 250a9643ea8Slogwang static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev, 251a9643ea8Slogwang uint16_t queue_idx) 252a9643ea8Slogwang { 253a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 254a9643ea8Slogwang 255a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 256a9643ea8Slogwang 257a9643ea8Slogwang enic_start_rq(enic, queue_idx); 258a9643ea8Slogwang 259a9643ea8Slogwang return 0; 260a9643ea8Slogwang } 261a9643ea8Slogwang 262a9643ea8Slogwang static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, 263a9643ea8Slogwang uint16_t queue_idx) 264a9643ea8Slogwang { 265a9643ea8Slogwang int ret; 266a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 267a9643ea8Slogwang 268a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 269a9643ea8Slogwang 270a9643ea8Slogwang ret = enic_stop_rq(enic, queue_idx); 271a9643ea8Slogwang if (ret) 272a9643ea8Slogwang dev_err(enic, "error in stopping rq %d\n", queue_idx); 273a9643ea8Slogwang 274a9643ea8Slogwang return ret; 275a9643ea8Slogwang } 276a9643ea8Slogwang 277a9643ea8Slogwang static void enicpmd_dev_rx_queue_release(void *rxq) 278a9643ea8Slogwang { 279a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 2802bfe3f2eSlogwang 2812bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 2822bfe3f2eSlogwang return; 2832bfe3f2eSlogwang 284a9643ea8Slogwang enic_free_rq(rxq); 285a9643ea8Slogwang } 286a9643ea8Slogwang 2872bfe3f2eSlogwang static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev, 2882bfe3f2eSlogwang uint16_t rx_queue_id) 2892bfe3f2eSlogwang { 2902bfe3f2eSlogwang struct enic *enic = pmd_priv(dev); 2912bfe3f2eSlogwang uint32_t queue_count = 0; 2922bfe3f2eSlogwang struct vnic_cq *cq; 2932bfe3f2eSlogwang uint32_t cq_tail; 2942bfe3f2eSlogwang uint16_t cq_idx; 2952bfe3f2eSlogwang int rq_num; 2962bfe3f2eSlogwang 2972bfe3f2eSlogwang rq_num = enic_rte_rq_idx_to_sop_idx(rx_queue_id); 2982bfe3f2eSlogwang cq = &enic->cq[enic_cq_rq(enic, rq_num)]; 2992bfe3f2eSlogwang cq_idx = cq->to_clean; 3002bfe3f2eSlogwang 3012bfe3f2eSlogwang cq_tail = ioread32(&cq->ctrl->cq_tail); 3022bfe3f2eSlogwang 3032bfe3f2eSlogwang if (cq_tail < cq_idx) 3042bfe3f2eSlogwang cq_tail += cq->ring.desc_count; 3052bfe3f2eSlogwang 3062bfe3f2eSlogwang queue_count = cq_tail - cq_idx; 3072bfe3f2eSlogwang 3082bfe3f2eSlogwang return queue_count; 3092bfe3f2eSlogwang } 3102bfe3f2eSlogwang 311a9643ea8Slogwang static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 312a9643ea8Slogwang uint16_t queue_idx, 313a9643ea8Slogwang uint16_t nb_desc, 314a9643ea8Slogwang unsigned int socket_id, 315a9643ea8Slogwang const struct rte_eth_rxconf *rx_conf, 316a9643ea8Slogwang struct rte_mempool *mp) 317a9643ea8Slogwang { 318a9643ea8Slogwang int ret; 319a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 320a9643ea8Slogwang 321a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 322a9643ea8Slogwang 3232bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 3242bfe3f2eSlogwang return -E_RTE_SECONDARY; 3252bfe3f2eSlogwang RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(queue_idx) < enic->conf_rq_count); 326a9643ea8Slogwang eth_dev->data->rx_queues[queue_idx] = 3272bfe3f2eSlogwang (void *)&enic->rq[enic_rte_rq_idx_to_sop_idx(queue_idx)]; 328a9643ea8Slogwang 329a9643ea8Slogwang ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc, 330a9643ea8Slogwang rx_conf->rx_free_thresh); 331a9643ea8Slogwang if (ret) { 332a9643ea8Slogwang dev_err(enic, "error in allocating rq\n"); 333a9643ea8Slogwang return ret; 334a9643ea8Slogwang } 335a9643ea8Slogwang 336a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 337a9643ea8Slogwang } 338a9643ea8Slogwang 339a9643ea8Slogwang static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev, 340a9643ea8Slogwang uint16_t vlan_id, int on) 341a9643ea8Slogwang { 342a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 343a9643ea8Slogwang int err; 344a9643ea8Slogwang 345a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 346a9643ea8Slogwang if (on) 347a9643ea8Slogwang err = enic_add_vlan(enic, vlan_id); 348a9643ea8Slogwang else 349a9643ea8Slogwang err = enic_del_vlan(enic, vlan_id); 350a9643ea8Slogwang return err; 351a9643ea8Slogwang } 352a9643ea8Slogwang 3532bfe3f2eSlogwang static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 354a9643ea8Slogwang { 355a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 356a9643ea8Slogwang 357a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 358a9643ea8Slogwang 359a9643ea8Slogwang if (mask & ETH_VLAN_STRIP_MASK) { 360a9643ea8Slogwang if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) 361a9643ea8Slogwang enic->ig_vlan_strip_en = 1; 362a9643ea8Slogwang else 363a9643ea8Slogwang enic->ig_vlan_strip_en = 0; 364a9643ea8Slogwang } 365a9643ea8Slogwang enic_set_rss_nic_cfg(enic); 366a9643ea8Slogwang 367a9643ea8Slogwang 368a9643ea8Slogwang if (mask & ETH_VLAN_FILTER_MASK) { 369a9643ea8Slogwang dev_warning(enic, 370a9643ea8Slogwang "Configuration of VLAN filter is not supported\n"); 371a9643ea8Slogwang } 372a9643ea8Slogwang 373a9643ea8Slogwang if (mask & ETH_VLAN_EXTEND_MASK) { 374a9643ea8Slogwang dev_warning(enic, 375a9643ea8Slogwang "Configuration of extended VLAN is not supported\n"); 376a9643ea8Slogwang } 3772bfe3f2eSlogwang 3782bfe3f2eSlogwang return 0; 379a9643ea8Slogwang } 380a9643ea8Slogwang 381a9643ea8Slogwang static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev) 382a9643ea8Slogwang { 383a9643ea8Slogwang int ret; 384a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 385a9643ea8Slogwang 3862bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 3872bfe3f2eSlogwang return -E_RTE_SECONDARY; 3882bfe3f2eSlogwang 389a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 390a9643ea8Slogwang ret = enic_set_vnic_res(enic); 391a9643ea8Slogwang if (ret) { 392a9643ea8Slogwang dev_err(enic, "Set vNIC resource num failed, aborting\n"); 393a9643ea8Slogwang return ret; 394a9643ea8Slogwang } 395a9643ea8Slogwang 396a9643ea8Slogwang if (eth_dev->data->dev_conf.rxmode.split_hdr_size && 397a9643ea8Slogwang eth_dev->data->dev_conf.rxmode.header_split) { 398a9643ea8Slogwang /* Enable header-data-split */ 399a9643ea8Slogwang enic_set_hdr_split_size(enic, 400a9643ea8Slogwang eth_dev->data->dev_conf.rxmode.split_hdr_size); 401a9643ea8Slogwang } 402a9643ea8Slogwang 403a9643ea8Slogwang enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum; 4042bfe3f2eSlogwang ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK); 4052bfe3f2eSlogwang 4062bfe3f2eSlogwang return ret; 407a9643ea8Slogwang } 408a9643ea8Slogwang 409a9643ea8Slogwang /* Start the device. 410a9643ea8Slogwang * It returns 0 on success. 411a9643ea8Slogwang */ 412a9643ea8Slogwang static int enicpmd_dev_start(struct rte_eth_dev *eth_dev) 413a9643ea8Slogwang { 414a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 415a9643ea8Slogwang 4162bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 4172bfe3f2eSlogwang return -E_RTE_SECONDARY; 4182bfe3f2eSlogwang 419a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 420a9643ea8Slogwang return enic_enable(enic); 421a9643ea8Slogwang } 422a9643ea8Slogwang 423a9643ea8Slogwang /* 424a9643ea8Slogwang * Stop device: disable rx and tx functions to allow for reconfiguring. 425a9643ea8Slogwang */ 426a9643ea8Slogwang static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev) 427a9643ea8Slogwang { 428a9643ea8Slogwang struct rte_eth_link link; 429a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 430a9643ea8Slogwang 4312bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 4322bfe3f2eSlogwang return; 4332bfe3f2eSlogwang 434a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 435a9643ea8Slogwang enic_disable(enic); 436a9643ea8Slogwang memset(&link, 0, sizeof(link)); 437a9643ea8Slogwang rte_atomic64_cmpset((uint64_t *)ð_dev->data->dev_link, 438a9643ea8Slogwang *(uint64_t *)ð_dev->data->dev_link, 439a9643ea8Slogwang *(uint64_t *)&link); 440a9643ea8Slogwang } 441a9643ea8Slogwang 442a9643ea8Slogwang /* 443a9643ea8Slogwang * Stop device. 444a9643ea8Slogwang */ 445a9643ea8Slogwang static void enicpmd_dev_close(struct rte_eth_dev *eth_dev) 446a9643ea8Slogwang { 447a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 448a9643ea8Slogwang 449a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 450a9643ea8Slogwang enic_remove(enic); 451a9643ea8Slogwang } 452a9643ea8Slogwang 453a9643ea8Slogwang static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev, 454a9643ea8Slogwang __rte_unused int wait_to_complete) 455a9643ea8Slogwang { 456a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 457a9643ea8Slogwang 458a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 4592bfe3f2eSlogwang return enic_link_update(enic); 460a9643ea8Slogwang } 461a9643ea8Slogwang 4622bfe3f2eSlogwang static int enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev, 463a9643ea8Slogwang struct rte_eth_stats *stats) 464a9643ea8Slogwang { 465a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 466a9643ea8Slogwang 467a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 4682bfe3f2eSlogwang return enic_dev_stats_get(enic, stats); 469a9643ea8Slogwang } 470a9643ea8Slogwang 471a9643ea8Slogwang static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev) 472a9643ea8Slogwang { 473a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 474a9643ea8Slogwang 475a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 476a9643ea8Slogwang enic_dev_stats_clear(enic); 477a9643ea8Slogwang } 478a9643ea8Slogwang 479a9643ea8Slogwang static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, 480a9643ea8Slogwang struct rte_eth_dev_info *device_info) 481a9643ea8Slogwang { 482a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 483a9643ea8Slogwang 484a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 4852bfe3f2eSlogwang device_info->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 486a9643ea8Slogwang /* Scattered Rx uses two receive queues per rx queue exposed to dpdk */ 487a9643ea8Slogwang device_info->max_rx_queues = enic->conf_rq_count / 2; 488a9643ea8Slogwang device_info->max_tx_queues = enic->conf_wq_count; 489a9643ea8Slogwang device_info->min_rx_bufsize = ENIC_MIN_MTU; 490a9643ea8Slogwang device_info->max_rx_pktlen = enic->max_mtu + ETHER_HDR_LEN + 4; 4912bfe3f2eSlogwang device_info->max_mac_addrs = ENIC_MAX_MAC_ADDR; 492a9643ea8Slogwang device_info->rx_offload_capa = 493a9643ea8Slogwang DEV_RX_OFFLOAD_VLAN_STRIP | 494a9643ea8Slogwang DEV_RX_OFFLOAD_IPV4_CKSUM | 495a9643ea8Slogwang DEV_RX_OFFLOAD_UDP_CKSUM | 496a9643ea8Slogwang DEV_RX_OFFLOAD_TCP_CKSUM; 497a9643ea8Slogwang device_info->tx_offload_capa = 498a9643ea8Slogwang DEV_TX_OFFLOAD_VLAN_INSERT | 499a9643ea8Slogwang DEV_TX_OFFLOAD_IPV4_CKSUM | 500a9643ea8Slogwang DEV_TX_OFFLOAD_UDP_CKSUM | 5012bfe3f2eSlogwang DEV_TX_OFFLOAD_TCP_CKSUM | 5022bfe3f2eSlogwang DEV_TX_OFFLOAD_TCP_TSO; 503a9643ea8Slogwang device_info->default_rxconf = (struct rte_eth_rxconf) { 504a9643ea8Slogwang .rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH 505a9643ea8Slogwang }; 506a9643ea8Slogwang } 507a9643ea8Slogwang 508a9643ea8Slogwang static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev) 509a9643ea8Slogwang { 510a9643ea8Slogwang static const uint32_t ptypes[] = { 5112bfe3f2eSlogwang RTE_PTYPE_L2_ETHER, 5122bfe3f2eSlogwang RTE_PTYPE_L2_ETHER_VLAN, 513a9643ea8Slogwang RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 514a9643ea8Slogwang RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 515a9643ea8Slogwang RTE_PTYPE_L4_TCP, 516a9643ea8Slogwang RTE_PTYPE_L4_UDP, 517a9643ea8Slogwang RTE_PTYPE_L4_FRAG, 518a9643ea8Slogwang RTE_PTYPE_L4_NONFRAG, 519a9643ea8Slogwang RTE_PTYPE_UNKNOWN 520a9643ea8Slogwang }; 521a9643ea8Slogwang 522a9643ea8Slogwang if (dev->rx_pkt_burst == enic_recv_pkts) 523a9643ea8Slogwang return ptypes; 524a9643ea8Slogwang return NULL; 525a9643ea8Slogwang } 526a9643ea8Slogwang 527a9643ea8Slogwang static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 528a9643ea8Slogwang { 529a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 530a9643ea8Slogwang 5312bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 5322bfe3f2eSlogwang return; 5332bfe3f2eSlogwang 534a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 5352bfe3f2eSlogwang 536a9643ea8Slogwang enic->promisc = 1; 537a9643ea8Slogwang enic_add_packet_filter(enic); 538a9643ea8Slogwang } 539a9643ea8Slogwang 540a9643ea8Slogwang static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 541a9643ea8Slogwang { 542a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 543a9643ea8Slogwang 5442bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 5452bfe3f2eSlogwang return; 5462bfe3f2eSlogwang 547a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 548a9643ea8Slogwang enic->promisc = 0; 549a9643ea8Slogwang enic_add_packet_filter(enic); 550a9643ea8Slogwang } 551a9643ea8Slogwang 552a9643ea8Slogwang static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 553a9643ea8Slogwang { 554a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 555a9643ea8Slogwang 5562bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 5572bfe3f2eSlogwang return; 5582bfe3f2eSlogwang 559a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 560a9643ea8Slogwang enic->allmulti = 1; 561a9643ea8Slogwang enic_add_packet_filter(enic); 562a9643ea8Slogwang } 563a9643ea8Slogwang 564a9643ea8Slogwang static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 565a9643ea8Slogwang { 566a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 567a9643ea8Slogwang 5682bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 5692bfe3f2eSlogwang return; 5702bfe3f2eSlogwang 571a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 572a9643ea8Slogwang enic->allmulti = 0; 573a9643ea8Slogwang enic_add_packet_filter(enic); 574a9643ea8Slogwang } 575a9643ea8Slogwang 5762bfe3f2eSlogwang static int enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev, 577a9643ea8Slogwang struct ether_addr *mac_addr, 578a9643ea8Slogwang __rte_unused uint32_t index, __rte_unused uint32_t pool) 579a9643ea8Slogwang { 580a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 581a9643ea8Slogwang 5822bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 5832bfe3f2eSlogwang return -E_RTE_SECONDARY; 5842bfe3f2eSlogwang 585a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 5862bfe3f2eSlogwang return enic_set_mac_address(enic, mac_addr->addr_bytes); 587a9643ea8Slogwang } 588a9643ea8Slogwang 5892bfe3f2eSlogwang static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, uint32_t index) 590a9643ea8Slogwang { 591a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 592a9643ea8Slogwang 5932bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 5942bfe3f2eSlogwang return; 5952bfe3f2eSlogwang 596a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 5972bfe3f2eSlogwang enic_del_mac_address(enic, index); 598a9643ea8Slogwang } 599a9643ea8Slogwang 600a9643ea8Slogwang static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) 601a9643ea8Slogwang { 602a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 603a9643ea8Slogwang 604a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 605a9643ea8Slogwang return enic_set_mtu(enic, mtu); 606a9643ea8Slogwang } 607a9643ea8Slogwang 608a9643ea8Slogwang static const struct eth_dev_ops enicpmd_eth_dev_ops = { 609a9643ea8Slogwang .dev_configure = enicpmd_dev_configure, 610a9643ea8Slogwang .dev_start = enicpmd_dev_start, 611a9643ea8Slogwang .dev_stop = enicpmd_dev_stop, 612a9643ea8Slogwang .dev_set_link_up = NULL, 613a9643ea8Slogwang .dev_set_link_down = NULL, 614a9643ea8Slogwang .dev_close = enicpmd_dev_close, 615a9643ea8Slogwang .promiscuous_enable = enicpmd_dev_promiscuous_enable, 616a9643ea8Slogwang .promiscuous_disable = enicpmd_dev_promiscuous_disable, 617a9643ea8Slogwang .allmulticast_enable = enicpmd_dev_allmulticast_enable, 618a9643ea8Slogwang .allmulticast_disable = enicpmd_dev_allmulticast_disable, 619a9643ea8Slogwang .link_update = enicpmd_dev_link_update, 620a9643ea8Slogwang .stats_get = enicpmd_dev_stats_get, 621a9643ea8Slogwang .stats_reset = enicpmd_dev_stats_reset, 622a9643ea8Slogwang .queue_stats_mapping_set = NULL, 623a9643ea8Slogwang .dev_infos_get = enicpmd_dev_info_get, 624a9643ea8Slogwang .dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get, 625a9643ea8Slogwang .mtu_set = enicpmd_mtu_set, 626a9643ea8Slogwang .vlan_filter_set = enicpmd_vlan_filter_set, 627a9643ea8Slogwang .vlan_tpid_set = NULL, 628a9643ea8Slogwang .vlan_offload_set = enicpmd_vlan_offload_set, 629a9643ea8Slogwang .vlan_strip_queue_set = NULL, 630a9643ea8Slogwang .rx_queue_start = enicpmd_dev_rx_queue_start, 631a9643ea8Slogwang .rx_queue_stop = enicpmd_dev_rx_queue_stop, 632a9643ea8Slogwang .tx_queue_start = enicpmd_dev_tx_queue_start, 633a9643ea8Slogwang .tx_queue_stop = enicpmd_dev_tx_queue_stop, 634a9643ea8Slogwang .rx_queue_setup = enicpmd_dev_rx_queue_setup, 635a9643ea8Slogwang .rx_queue_release = enicpmd_dev_rx_queue_release, 6362bfe3f2eSlogwang .rx_queue_count = enicpmd_dev_rx_queue_count, 637a9643ea8Slogwang .rx_descriptor_done = NULL, 638a9643ea8Slogwang .tx_queue_setup = enicpmd_dev_tx_queue_setup, 639a9643ea8Slogwang .tx_queue_release = enicpmd_dev_tx_queue_release, 640a9643ea8Slogwang .dev_led_on = NULL, 641a9643ea8Slogwang .dev_led_off = NULL, 642a9643ea8Slogwang .flow_ctrl_get = NULL, 643a9643ea8Slogwang .flow_ctrl_set = NULL, 644a9643ea8Slogwang .priority_flow_ctrl_set = NULL, 645a9643ea8Slogwang .mac_addr_add = enicpmd_add_mac_addr, 646a9643ea8Slogwang .mac_addr_remove = enicpmd_remove_mac_addr, 647a9643ea8Slogwang .filter_ctrl = enicpmd_dev_filter_ctrl, 648a9643ea8Slogwang }; 649a9643ea8Slogwang 650*579bf1e2Sjfb8856606 static int enic_parse_ig_vlan_rewrite(__rte_unused const char *key, 651*579bf1e2Sjfb8856606 const char *value, 652*579bf1e2Sjfb8856606 void *opaque) 653*579bf1e2Sjfb8856606 { 654*579bf1e2Sjfb8856606 struct enic *enic; 655*579bf1e2Sjfb8856606 656*579bf1e2Sjfb8856606 enic = (struct enic *)opaque; 657*579bf1e2Sjfb8856606 if (strcmp(value, "trunk") == 0) { 658*579bf1e2Sjfb8856606 /* Trunk mode: always tag */ 659*579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK; 660*579bf1e2Sjfb8856606 } else if (strcmp(value, "untag") == 0) { 661*579bf1e2Sjfb8856606 /* Untag default VLAN mode: untag if VLAN = default VLAN */ 662*579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = 663*579bf1e2Sjfb8856606 IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN; 664*579bf1e2Sjfb8856606 } else if (strcmp(value, "priority") == 0) { 665*579bf1e2Sjfb8856606 /* 666*579bf1e2Sjfb8856606 * Priority-tag default VLAN mode: priority tag (VLAN header 667*579bf1e2Sjfb8856606 * with ID=0) if VLAN = default 668*579bf1e2Sjfb8856606 */ 669*579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = 670*579bf1e2Sjfb8856606 IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN; 671*579bf1e2Sjfb8856606 } else if (strcmp(value, "pass") == 0) { 672*579bf1e2Sjfb8856606 /* Pass through mode: do not touch tags */ 673*579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU; 674*579bf1e2Sjfb8856606 } else { 675*579bf1e2Sjfb8856606 dev_err(enic, "Invalid value for " ENIC_DEVARG_IG_VLAN_REWRITE 676*579bf1e2Sjfb8856606 ": expected=trunk|untag|priority|pass given=%s\n", 677*579bf1e2Sjfb8856606 value); 678*579bf1e2Sjfb8856606 return -EINVAL; 679*579bf1e2Sjfb8856606 } 680*579bf1e2Sjfb8856606 return 0; 681*579bf1e2Sjfb8856606 } 682*579bf1e2Sjfb8856606 683*579bf1e2Sjfb8856606 static int enic_check_devargs(struct rte_eth_dev *dev) 684*579bf1e2Sjfb8856606 { 685*579bf1e2Sjfb8856606 static const char *const valid_keys[] = { 686*579bf1e2Sjfb8856606 ENIC_DEVARG_IG_VLAN_REWRITE, 687*579bf1e2Sjfb8856606 NULL}; 688*579bf1e2Sjfb8856606 struct enic *enic = pmd_priv(dev); 689*579bf1e2Sjfb8856606 struct rte_kvargs *kvlist; 690*579bf1e2Sjfb8856606 691*579bf1e2Sjfb8856606 ENICPMD_FUNC_TRACE(); 692*579bf1e2Sjfb8856606 693*579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU; 694*579bf1e2Sjfb8856606 if (!dev->device->devargs) 695*579bf1e2Sjfb8856606 return 0; 696*579bf1e2Sjfb8856606 kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys); 697*579bf1e2Sjfb8856606 if (!kvlist) 698*579bf1e2Sjfb8856606 return -EINVAL; 699*579bf1e2Sjfb8856606 if (rte_kvargs_process(kvlist, ENIC_DEVARG_IG_VLAN_REWRITE, 700*579bf1e2Sjfb8856606 enic_parse_ig_vlan_rewrite, enic) < 0) { 701*579bf1e2Sjfb8856606 rte_kvargs_free(kvlist); 702*579bf1e2Sjfb8856606 return -EINVAL; 703*579bf1e2Sjfb8856606 } 704*579bf1e2Sjfb8856606 rte_kvargs_free(kvlist); 705*579bf1e2Sjfb8856606 return 0; 706*579bf1e2Sjfb8856606 } 707*579bf1e2Sjfb8856606 708a9643ea8Slogwang struct enic *enicpmd_list_head = NULL; 709a9643ea8Slogwang /* Initialize the driver 710a9643ea8Slogwang * It returns 0 on success. 711a9643ea8Slogwang */ 712a9643ea8Slogwang static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev) 713a9643ea8Slogwang { 714a9643ea8Slogwang struct rte_pci_device *pdev; 715a9643ea8Slogwang struct rte_pci_addr *addr; 716a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 717*579bf1e2Sjfb8856606 int err; 718a9643ea8Slogwang 719a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 720a9643ea8Slogwang 721a9643ea8Slogwang enic->port_id = eth_dev->data->port_id; 722a9643ea8Slogwang enic->rte_dev = eth_dev; 723a9643ea8Slogwang eth_dev->dev_ops = &enicpmd_eth_dev_ops; 724a9643ea8Slogwang eth_dev->rx_pkt_burst = &enic_recv_pkts; 725a9643ea8Slogwang eth_dev->tx_pkt_burst = &enic_xmit_pkts; 726a9643ea8Slogwang 7272bfe3f2eSlogwang pdev = RTE_ETH_DEV_TO_PCI(eth_dev); 728a9643ea8Slogwang rte_eth_copy_pci_info(eth_dev, pdev); 729a9643ea8Slogwang enic->pdev = pdev; 730a9643ea8Slogwang addr = &pdev->addr; 731a9643ea8Slogwang 732a9643ea8Slogwang snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x", 733a9643ea8Slogwang addr->domain, addr->bus, addr->devid, addr->function); 734a9643ea8Slogwang 735*579bf1e2Sjfb8856606 err = enic_check_devargs(eth_dev); 736*579bf1e2Sjfb8856606 if (err) 737*579bf1e2Sjfb8856606 return err; 738a9643ea8Slogwang return enic_probe(enic); 739a9643ea8Slogwang } 740a9643ea8Slogwang 7412bfe3f2eSlogwang static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 7422bfe3f2eSlogwang struct rte_pci_device *pci_dev) 743a9643ea8Slogwang { 7442bfe3f2eSlogwang return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct enic), 7452bfe3f2eSlogwang eth_enicpmd_dev_init); 746a9643ea8Slogwang } 747a9643ea8Slogwang 7482bfe3f2eSlogwang static int eth_enic_pci_remove(struct rte_pci_device *pci_dev) 7492bfe3f2eSlogwang { 7502bfe3f2eSlogwang return rte_eth_dev_pci_generic_remove(pci_dev, NULL); 7512bfe3f2eSlogwang } 7522bfe3f2eSlogwang 7532bfe3f2eSlogwang static struct rte_pci_driver rte_enic_pmd = { 7542bfe3f2eSlogwang .id_table = pci_id_enic_map, 7552bfe3f2eSlogwang .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 7562bfe3f2eSlogwang .probe = eth_enic_pci_probe, 7572bfe3f2eSlogwang .remove = eth_enic_pci_remove, 758a9643ea8Slogwang }; 759a9643ea8Slogwang 7602bfe3f2eSlogwang RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd); 7612bfe3f2eSlogwang RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map); 7622bfe3f2eSlogwang RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci"); 763*579bf1e2Sjfb8856606 RTE_PMD_REGISTER_PARAM_STRING(net_enic, 764*579bf1e2Sjfb8856606 ENIC_DEVARG_IG_VLAN_REWRITE "=trunk|untag|priority|pass"); 765