1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause 2d30ea906Sjfb8856606 * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. 3a9643ea8Slogwang * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4a9643ea8Slogwang */ 5a9643ea8Slogwang 6a9643ea8Slogwang #include <stdio.h> 7a9643ea8Slogwang #include <stdint.h> 8a9643ea8Slogwang 9a9643ea8Slogwang #include <rte_dev.h> 10a9643ea8Slogwang #include <rte_pci.h> 112bfe3f2eSlogwang #include <rte_bus_pci.h> 12d30ea906Sjfb8856606 #include <rte_ethdev_driver.h> 132bfe3f2eSlogwang #include <rte_ethdev_pci.h> 14579bf1e2Sjfb8856606 #include <rte_kvargs.h> 15a9643ea8Slogwang #include <rte_string_fns.h> 16a9643ea8Slogwang 17a9643ea8Slogwang #include "vnic_intr.h" 18a9643ea8Slogwang #include "vnic_cq.h" 19a9643ea8Slogwang #include "vnic_wq.h" 20a9643ea8Slogwang #include "vnic_rq.h" 21a9643ea8Slogwang #include "vnic_enet.h" 22a9643ea8Slogwang #include "enic.h" 23a9643ea8Slogwang 24*4418919fSjohnjiang int enic_pmd_logtype; 25a9643ea8Slogwang 26a9643ea8Slogwang /* 27a9643ea8Slogwang * The set of PCI devices this driver supports 28a9643ea8Slogwang */ 29a9643ea8Slogwang #define CISCO_PCI_VENDOR_ID 0x1137 30a9643ea8Slogwang static const struct rte_pci_id pci_id_enic_map[] = { 31a9643ea8Slogwang {RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET)}, 32a9643ea8Slogwang {RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF)}, 33*4418919fSjohnjiang {RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_SN)}, 34a9643ea8Slogwang {.vendor_id = 0, /* sentinel */}, 35a9643ea8Slogwang }; 36a9643ea8Slogwang 37*4418919fSjohnjiang /* Supported link speeds of production VIC models */ 38*4418919fSjohnjiang static const struct vic_speed_capa { 39*4418919fSjohnjiang uint16_t sub_devid; 40*4418919fSjohnjiang uint32_t capa; 41*4418919fSjohnjiang } vic_speed_capa_map[] = { 42*4418919fSjohnjiang { 0x0043, ETH_LINK_SPEED_10G }, /* VIC */ 43*4418919fSjohnjiang { 0x0047, ETH_LINK_SPEED_10G }, /* P81E PCIe */ 44*4418919fSjohnjiang { 0x0048, ETH_LINK_SPEED_10G }, /* M81KR Mezz */ 45*4418919fSjohnjiang { 0x004f, ETH_LINK_SPEED_10G }, /* 1280 Mezz */ 46*4418919fSjohnjiang { 0x0084, ETH_LINK_SPEED_10G }, /* 1240 MLOM */ 47*4418919fSjohnjiang { 0x0085, ETH_LINK_SPEED_10G }, /* 1225 PCIe */ 48*4418919fSjohnjiang { 0x00cd, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G }, /* 1285 PCIe */ 49*4418919fSjohnjiang { 0x00ce, ETH_LINK_SPEED_10G }, /* 1225T PCIe */ 50*4418919fSjohnjiang { 0x012a, ETH_LINK_SPEED_40G }, /* M4308 */ 51*4418919fSjohnjiang { 0x012c, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G }, /* 1340 MLOM */ 52*4418919fSjohnjiang { 0x012e, ETH_LINK_SPEED_10G }, /* 1227 PCIe */ 53*4418919fSjohnjiang { 0x0137, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G }, /* 1380 Mezz */ 54*4418919fSjohnjiang { 0x014d, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G }, /* 1385 PCIe */ 55*4418919fSjohnjiang { 0x015d, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G }, /* 1387 MLOM */ 56*4418919fSjohnjiang { 0x0215, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_25G | 57*4418919fSjohnjiang ETH_LINK_SPEED_40G }, /* 1440 Mezz */ 58*4418919fSjohnjiang { 0x0216, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_25G | 59*4418919fSjohnjiang ETH_LINK_SPEED_40G }, /* 1480 MLOM */ 60*4418919fSjohnjiang { 0x0217, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_25G }, /* 1455 PCIe */ 61*4418919fSjohnjiang { 0x0218, ETH_LINK_SPEED_10G | ETH_LINK_SPEED_25G }, /* 1457 MLOM */ 62*4418919fSjohnjiang { 0x0219, ETH_LINK_SPEED_40G }, /* 1485 PCIe */ 63*4418919fSjohnjiang { 0x021a, ETH_LINK_SPEED_40G }, /* 1487 MLOM */ 64*4418919fSjohnjiang { 0x024a, ETH_LINK_SPEED_40G | ETH_LINK_SPEED_100G }, /* 1495 PCIe */ 65*4418919fSjohnjiang { 0x024b, ETH_LINK_SPEED_40G | ETH_LINK_SPEED_100G }, /* 1497 MLOM */ 66*4418919fSjohnjiang { 0, 0 }, /* End marker */ 67*4418919fSjohnjiang }; 68*4418919fSjohnjiang 69d30ea906Sjfb8856606 #define ENIC_DEVARG_DISABLE_OVERLAY "disable-overlay" 70d30ea906Sjfb8856606 #define ENIC_DEVARG_ENABLE_AVX2_RX "enable-avx2-rx" 71*4418919fSjohnjiang #define ENIC_DEVARG_GENEVE_OPT "geneve-opt" 72579bf1e2Sjfb8856606 #define ENIC_DEVARG_IG_VLAN_REWRITE "ig-vlan-rewrite" 73579bf1e2Sjfb8856606 74d30ea906Sjfb8856606 RTE_INIT(enicpmd_init_log) 75d30ea906Sjfb8856606 { 76*4418919fSjohnjiang enic_pmd_logtype = rte_log_register("pmd.net.enic"); 77*4418919fSjohnjiang if (enic_pmd_logtype >= 0) 78*4418919fSjohnjiang rte_log_set_level(enic_pmd_logtype, RTE_LOG_INFO); 79d30ea906Sjfb8856606 } 80d30ea906Sjfb8856606 81a9643ea8Slogwang static int 82a9643ea8Slogwang enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev, 83a9643ea8Slogwang enum rte_filter_op filter_op, void *arg) 84a9643ea8Slogwang { 85a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 86a9643ea8Slogwang int ret = 0; 87a9643ea8Slogwang 88a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 89a9643ea8Slogwang if (filter_op == RTE_ETH_FILTER_NOP) 90a9643ea8Slogwang return 0; 91a9643ea8Slogwang 92a9643ea8Slogwang if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) 93a9643ea8Slogwang return -EINVAL; 94a9643ea8Slogwang 95a9643ea8Slogwang switch (filter_op) { 96a9643ea8Slogwang case RTE_ETH_FILTER_ADD: 97a9643ea8Slogwang case RTE_ETH_FILTER_UPDATE: 98a9643ea8Slogwang ret = enic_fdir_add_fltr(enic, 99a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 100a9643ea8Slogwang break; 101a9643ea8Slogwang 102a9643ea8Slogwang case RTE_ETH_FILTER_DELETE: 103a9643ea8Slogwang ret = enic_fdir_del_fltr(enic, 104a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 105a9643ea8Slogwang break; 106a9643ea8Slogwang 107a9643ea8Slogwang case RTE_ETH_FILTER_STATS: 108a9643ea8Slogwang enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg); 109a9643ea8Slogwang break; 110a9643ea8Slogwang 111a9643ea8Slogwang case RTE_ETH_FILTER_FLUSH: 112a9643ea8Slogwang dev_warning(enic, "unsupported operation %u", filter_op); 113a9643ea8Slogwang ret = -ENOTSUP; 114a9643ea8Slogwang break; 1152bfe3f2eSlogwang case RTE_ETH_FILTER_INFO: 1162bfe3f2eSlogwang enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg); 1172bfe3f2eSlogwang break; 118a9643ea8Slogwang default: 119a9643ea8Slogwang dev_err(enic, "unknown operation %u", filter_op); 120a9643ea8Slogwang ret = -EINVAL; 121a9643ea8Slogwang break; 122a9643ea8Slogwang } 123a9643ea8Slogwang return ret; 124a9643ea8Slogwang } 125a9643ea8Slogwang 126a9643ea8Slogwang static int 127a9643ea8Slogwang enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev, 128a9643ea8Slogwang enum rte_filter_type filter_type, 129a9643ea8Slogwang enum rte_filter_op filter_op, 130a9643ea8Slogwang void *arg) 131a9643ea8Slogwang { 132*4418919fSjohnjiang struct enic *enic = pmd_priv(dev); 1332bfe3f2eSlogwang int ret = 0; 134a9643ea8Slogwang 1352bfe3f2eSlogwang ENICPMD_FUNC_TRACE(); 1362bfe3f2eSlogwang 137*4418919fSjohnjiang /* 138*4418919fSjohnjiang * Currently, when Geneve with options offload is enabled, host 139*4418919fSjohnjiang * cannot insert match-action rules. 140*4418919fSjohnjiang */ 141*4418919fSjohnjiang if (enic->geneve_opt_enabled) 142*4418919fSjohnjiang return -ENOTSUP; 1432bfe3f2eSlogwang switch (filter_type) { 1442bfe3f2eSlogwang case RTE_ETH_FILTER_GENERIC: 1452bfe3f2eSlogwang if (filter_op != RTE_ETH_FILTER_GET) 1462bfe3f2eSlogwang return -EINVAL; 147*4418919fSjohnjiang if (enic->flow_filter_mode == FILTER_FLOWMAN) 148*4418919fSjohnjiang *(const void **)arg = &enic_fm_flow_ops; 149*4418919fSjohnjiang else 1502bfe3f2eSlogwang *(const void **)arg = &enic_flow_ops; 1512bfe3f2eSlogwang break; 1522bfe3f2eSlogwang case RTE_ETH_FILTER_FDIR: 153a9643ea8Slogwang ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg); 1542bfe3f2eSlogwang break; 1552bfe3f2eSlogwang default: 156a9643ea8Slogwang dev_warning(enic, "Filter type (%d) not supported", 157a9643ea8Slogwang filter_type); 1582bfe3f2eSlogwang ret = -EINVAL; 1592bfe3f2eSlogwang break; 1602bfe3f2eSlogwang } 161a9643ea8Slogwang 162a9643ea8Slogwang return ret; 163a9643ea8Slogwang } 164a9643ea8Slogwang 165a9643ea8Slogwang static void enicpmd_dev_tx_queue_release(void *txq) 166a9643ea8Slogwang { 167a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 1682bfe3f2eSlogwang 1692bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 1702bfe3f2eSlogwang return; 1712bfe3f2eSlogwang 172a9643ea8Slogwang enic_free_wq(txq); 173a9643ea8Slogwang } 174a9643ea8Slogwang 175a9643ea8Slogwang static int enicpmd_dev_setup_intr(struct enic *enic) 176a9643ea8Slogwang { 177a9643ea8Slogwang int ret; 178a9643ea8Slogwang unsigned int index; 179a9643ea8Slogwang 180a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 181a9643ea8Slogwang 182a9643ea8Slogwang /* Are we done with the init of all the queues? */ 183a9643ea8Slogwang for (index = 0; index < enic->cq_count; index++) { 184a9643ea8Slogwang if (!enic->cq[index].ctrl) 185a9643ea8Slogwang break; 186a9643ea8Slogwang } 187a9643ea8Slogwang if (enic->cq_count != index) 188a9643ea8Slogwang return 0; 189a9643ea8Slogwang for (index = 0; index < enic->wq_count; index++) { 190a9643ea8Slogwang if (!enic->wq[index].ctrl) 191a9643ea8Slogwang break; 192a9643ea8Slogwang } 193a9643ea8Slogwang if (enic->wq_count != index) 194a9643ea8Slogwang return 0; 195a9643ea8Slogwang /* check start of packet (SOP) RQs only in case scatter is disabled. */ 196a9643ea8Slogwang for (index = 0; index < enic->rq_count; index++) { 1972bfe3f2eSlogwang if (!enic->rq[enic_rte_rq_idx_to_sop_idx(index)].ctrl) 198a9643ea8Slogwang break; 199a9643ea8Slogwang } 200a9643ea8Slogwang if (enic->rq_count != index) 201a9643ea8Slogwang return 0; 202a9643ea8Slogwang 203a9643ea8Slogwang ret = enic_alloc_intr_resources(enic); 204a9643ea8Slogwang if (ret) { 205a9643ea8Slogwang dev_err(enic, "alloc intr failed\n"); 206a9643ea8Slogwang return ret; 207a9643ea8Slogwang } 208a9643ea8Slogwang enic_init_vnic_resources(enic); 209a9643ea8Slogwang 210a9643ea8Slogwang ret = enic_setup_finish(enic); 211a9643ea8Slogwang if (ret) 212a9643ea8Slogwang dev_err(enic, "setup could not be finished\n"); 213a9643ea8Slogwang 214a9643ea8Slogwang return ret; 215a9643ea8Slogwang } 216a9643ea8Slogwang 217a9643ea8Slogwang static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 218a9643ea8Slogwang uint16_t queue_idx, 219a9643ea8Slogwang uint16_t nb_desc, 220a9643ea8Slogwang unsigned int socket_id, 221d30ea906Sjfb8856606 const struct rte_eth_txconf *tx_conf) 222a9643ea8Slogwang { 223a9643ea8Slogwang int ret; 224a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 225d30ea906Sjfb8856606 struct vnic_wq *wq; 226a9643ea8Slogwang 2272bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 2282bfe3f2eSlogwang return -E_RTE_SECONDARY; 229a9643ea8Slogwang 2302bfe3f2eSlogwang ENICPMD_FUNC_TRACE(); 2312bfe3f2eSlogwang RTE_ASSERT(queue_idx < enic->conf_wq_count); 232d30ea906Sjfb8856606 wq = &enic->wq[queue_idx]; 233d30ea906Sjfb8856606 wq->offloads = tx_conf->offloads | 234d30ea906Sjfb8856606 eth_dev->data->dev_conf.txmode.offloads; 235d30ea906Sjfb8856606 eth_dev->data->tx_queues[queue_idx] = (void *)wq; 236a9643ea8Slogwang 237a9643ea8Slogwang ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc); 238a9643ea8Slogwang if (ret) { 239a9643ea8Slogwang dev_err(enic, "error in allocating wq\n"); 240a9643ea8Slogwang return ret; 241a9643ea8Slogwang } 242a9643ea8Slogwang 243a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 244a9643ea8Slogwang } 245a9643ea8Slogwang 246a9643ea8Slogwang static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev, 247a9643ea8Slogwang uint16_t queue_idx) 248a9643ea8Slogwang { 249a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 250a9643ea8Slogwang 251a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 252a9643ea8Slogwang 253a9643ea8Slogwang enic_start_wq(enic, queue_idx); 254a9643ea8Slogwang 255a9643ea8Slogwang return 0; 256a9643ea8Slogwang } 257a9643ea8Slogwang 258a9643ea8Slogwang static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, 259a9643ea8Slogwang uint16_t queue_idx) 260a9643ea8Slogwang { 261a9643ea8Slogwang int ret; 262a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 263a9643ea8Slogwang 264a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 265a9643ea8Slogwang 266a9643ea8Slogwang ret = enic_stop_wq(enic, queue_idx); 267a9643ea8Slogwang if (ret) 268a9643ea8Slogwang dev_err(enic, "error in stopping wq %d\n", queue_idx); 269a9643ea8Slogwang 270a9643ea8Slogwang return ret; 271a9643ea8Slogwang } 272a9643ea8Slogwang 273a9643ea8Slogwang static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev, 274a9643ea8Slogwang uint16_t queue_idx) 275a9643ea8Slogwang { 276a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 277a9643ea8Slogwang 278a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 279a9643ea8Slogwang 280a9643ea8Slogwang enic_start_rq(enic, queue_idx); 281a9643ea8Slogwang 282a9643ea8Slogwang return 0; 283a9643ea8Slogwang } 284a9643ea8Slogwang 285a9643ea8Slogwang static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, 286a9643ea8Slogwang uint16_t queue_idx) 287a9643ea8Slogwang { 288a9643ea8Slogwang int ret; 289a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 290a9643ea8Slogwang 291a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 292a9643ea8Slogwang 293a9643ea8Slogwang ret = enic_stop_rq(enic, queue_idx); 294a9643ea8Slogwang if (ret) 295a9643ea8Slogwang dev_err(enic, "error in stopping rq %d\n", queue_idx); 296a9643ea8Slogwang 297a9643ea8Slogwang return ret; 298a9643ea8Slogwang } 299a9643ea8Slogwang 300a9643ea8Slogwang static void enicpmd_dev_rx_queue_release(void *rxq) 301a9643ea8Slogwang { 302a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 3032bfe3f2eSlogwang 3042bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 3052bfe3f2eSlogwang return; 3062bfe3f2eSlogwang 307a9643ea8Slogwang enic_free_rq(rxq); 308a9643ea8Slogwang } 309a9643ea8Slogwang 3102bfe3f2eSlogwang static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev, 3112bfe3f2eSlogwang uint16_t rx_queue_id) 3122bfe3f2eSlogwang { 3132bfe3f2eSlogwang struct enic *enic = pmd_priv(dev); 3142bfe3f2eSlogwang uint32_t queue_count = 0; 3152bfe3f2eSlogwang struct vnic_cq *cq; 3162bfe3f2eSlogwang uint32_t cq_tail; 3172bfe3f2eSlogwang uint16_t cq_idx; 3182bfe3f2eSlogwang int rq_num; 3192bfe3f2eSlogwang 3202bfe3f2eSlogwang rq_num = enic_rte_rq_idx_to_sop_idx(rx_queue_id); 3212bfe3f2eSlogwang cq = &enic->cq[enic_cq_rq(enic, rq_num)]; 3222bfe3f2eSlogwang cq_idx = cq->to_clean; 3232bfe3f2eSlogwang 3242bfe3f2eSlogwang cq_tail = ioread32(&cq->ctrl->cq_tail); 3252bfe3f2eSlogwang 3262bfe3f2eSlogwang if (cq_tail < cq_idx) 3272bfe3f2eSlogwang cq_tail += cq->ring.desc_count; 3282bfe3f2eSlogwang 3292bfe3f2eSlogwang queue_count = cq_tail - cq_idx; 3302bfe3f2eSlogwang 3312bfe3f2eSlogwang return queue_count; 3322bfe3f2eSlogwang } 3332bfe3f2eSlogwang 334a9643ea8Slogwang static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 335a9643ea8Slogwang uint16_t queue_idx, 336a9643ea8Slogwang uint16_t nb_desc, 337a9643ea8Slogwang unsigned int socket_id, 338a9643ea8Slogwang const struct rte_eth_rxconf *rx_conf, 339a9643ea8Slogwang struct rte_mempool *mp) 340a9643ea8Slogwang { 341a9643ea8Slogwang int ret; 342a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 343a9643ea8Slogwang 344a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 345a9643ea8Slogwang 3462bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 3472bfe3f2eSlogwang return -E_RTE_SECONDARY; 3482bfe3f2eSlogwang RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(queue_idx) < enic->conf_rq_count); 349a9643ea8Slogwang eth_dev->data->rx_queues[queue_idx] = 3502bfe3f2eSlogwang (void *)&enic->rq[enic_rte_rq_idx_to_sop_idx(queue_idx)]; 351a9643ea8Slogwang 352a9643ea8Slogwang ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc, 353a9643ea8Slogwang rx_conf->rx_free_thresh); 354a9643ea8Slogwang if (ret) { 355a9643ea8Slogwang dev_err(enic, "error in allocating rq\n"); 356a9643ea8Slogwang return ret; 357a9643ea8Slogwang } 358a9643ea8Slogwang 359a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 360a9643ea8Slogwang } 361a9643ea8Slogwang 3622bfe3f2eSlogwang static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 363a9643ea8Slogwang { 364a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 365d30ea906Sjfb8856606 uint64_t offloads; 366a9643ea8Slogwang 367a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 368a9643ea8Slogwang 369d30ea906Sjfb8856606 offloads = eth_dev->data->dev_conf.rxmode.offloads; 370a9643ea8Slogwang if (mask & ETH_VLAN_STRIP_MASK) { 371d30ea906Sjfb8856606 if (offloads & DEV_RX_OFFLOAD_VLAN_STRIP) 372a9643ea8Slogwang enic->ig_vlan_strip_en = 1; 373a9643ea8Slogwang else 374a9643ea8Slogwang enic->ig_vlan_strip_en = 0; 375a9643ea8Slogwang } 376a9643ea8Slogwang 377d30ea906Sjfb8856606 if ((mask & ETH_VLAN_FILTER_MASK) && 378d30ea906Sjfb8856606 (offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) { 379a9643ea8Slogwang dev_warning(enic, 380a9643ea8Slogwang "Configuration of VLAN filter is not supported\n"); 381a9643ea8Slogwang } 382a9643ea8Slogwang 383d30ea906Sjfb8856606 if ((mask & ETH_VLAN_EXTEND_MASK) && 384d30ea906Sjfb8856606 (offloads & DEV_RX_OFFLOAD_VLAN_EXTEND)) { 385a9643ea8Slogwang dev_warning(enic, 386a9643ea8Slogwang "Configuration of extended VLAN is not supported\n"); 387a9643ea8Slogwang } 3882bfe3f2eSlogwang 389d30ea906Sjfb8856606 return enic_set_vlan_strip(enic); 390a9643ea8Slogwang } 391a9643ea8Slogwang 392a9643ea8Slogwang static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev) 393a9643ea8Slogwang { 394a9643ea8Slogwang int ret; 395d30ea906Sjfb8856606 int mask; 396a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 397a9643ea8Slogwang 3982bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 3992bfe3f2eSlogwang return -E_RTE_SECONDARY; 4002bfe3f2eSlogwang 401a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 402a9643ea8Slogwang ret = enic_set_vnic_res(enic); 403a9643ea8Slogwang if (ret) { 404a9643ea8Slogwang dev_err(enic, "Set vNIC resource num failed, aborting\n"); 405a9643ea8Slogwang return ret; 406a9643ea8Slogwang } 407a9643ea8Slogwang 408*4418919fSjohnjiang if (eth_dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) 409*4418919fSjohnjiang eth_dev->data->dev_conf.rxmode.offloads |= 410*4418919fSjohnjiang DEV_RX_OFFLOAD_RSS_HASH; 411*4418919fSjohnjiang 412*4418919fSjohnjiang enic->mc_count = 0; 413d30ea906Sjfb8856606 enic->hw_ip_checksum = !!(eth_dev->data->dev_conf.rxmode.offloads & 414d30ea906Sjfb8856606 DEV_RX_OFFLOAD_CHECKSUM); 415d30ea906Sjfb8856606 /* All vlan offload masks to apply the current settings */ 416d30ea906Sjfb8856606 mask = ETH_VLAN_STRIP_MASK | 417d30ea906Sjfb8856606 ETH_VLAN_FILTER_MASK | 418d30ea906Sjfb8856606 ETH_VLAN_EXTEND_MASK; 419d30ea906Sjfb8856606 ret = enicpmd_vlan_offload_set(eth_dev, mask); 420d30ea906Sjfb8856606 if (ret) { 421d30ea906Sjfb8856606 dev_err(enic, "Failed to configure VLAN offloads\n"); 4225af785ecSfengbojiang(姜凤波) return ret; 42328440c50Sjfb8856606 } 424d30ea906Sjfb8856606 /* 425d30ea906Sjfb8856606 * Initialize RSS with the default reta and key. If the user key is 426d30ea906Sjfb8856606 * given (rx_adv_conf.rss_conf.rss_key), will use that instead of the 427d30ea906Sjfb8856606 * default key. 428d30ea906Sjfb8856606 */ 429d30ea906Sjfb8856606 return enic_init_rss_nic_cfg(enic); 430d30ea906Sjfb8856606 } 431a9643ea8Slogwang 432a9643ea8Slogwang /* Start the device. 433a9643ea8Slogwang * It returns 0 on success. 434a9643ea8Slogwang */ 435a9643ea8Slogwang static int enicpmd_dev_start(struct rte_eth_dev *eth_dev) 436a9643ea8Slogwang { 437a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 438a9643ea8Slogwang 4392bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 4402bfe3f2eSlogwang return -E_RTE_SECONDARY; 4412bfe3f2eSlogwang 442a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 443a9643ea8Slogwang return enic_enable(enic); 444a9643ea8Slogwang } 445a9643ea8Slogwang 446a9643ea8Slogwang /* 447a9643ea8Slogwang * Stop device: disable rx and tx functions to allow for reconfiguring. 448a9643ea8Slogwang */ 449a9643ea8Slogwang static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev) 450a9643ea8Slogwang { 451a9643ea8Slogwang struct rte_eth_link link; 452a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 453a9643ea8Slogwang 4542bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 4552bfe3f2eSlogwang return; 4562bfe3f2eSlogwang 457a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 458a9643ea8Slogwang enic_disable(enic); 459d30ea906Sjfb8856606 460a9643ea8Slogwang memset(&link, 0, sizeof(link)); 461d30ea906Sjfb8856606 rte_eth_linkstatus_set(eth_dev, &link); 462a9643ea8Slogwang } 463a9643ea8Slogwang 464a9643ea8Slogwang /* 465a9643ea8Slogwang * Stop device. 466a9643ea8Slogwang */ 467a9643ea8Slogwang static void enicpmd_dev_close(struct rte_eth_dev *eth_dev) 468a9643ea8Slogwang { 469a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 470a9643ea8Slogwang 471a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 472a9643ea8Slogwang enic_remove(enic); 473a9643ea8Slogwang } 474a9643ea8Slogwang 475a9643ea8Slogwang static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev, 476a9643ea8Slogwang __rte_unused int wait_to_complete) 477a9643ea8Slogwang { 478a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 479*4418919fSjohnjiang return enic_link_update(eth_dev); 480a9643ea8Slogwang } 481a9643ea8Slogwang 4822bfe3f2eSlogwang static int enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev, 483a9643ea8Slogwang struct rte_eth_stats *stats) 484a9643ea8Slogwang { 485a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 486a9643ea8Slogwang 487a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 4882bfe3f2eSlogwang return enic_dev_stats_get(enic, stats); 489a9643ea8Slogwang } 490a9643ea8Slogwang 491*4418919fSjohnjiang static int enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev) 492a9643ea8Slogwang { 493a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 494a9643ea8Slogwang 495a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 496*4418919fSjohnjiang return enic_dev_stats_clear(enic); 497a9643ea8Slogwang } 498a9643ea8Slogwang 499*4418919fSjohnjiang static uint32_t speed_capa_from_pci_id(struct rte_eth_dev *eth_dev) 500*4418919fSjohnjiang { 501*4418919fSjohnjiang const struct vic_speed_capa *m; 502*4418919fSjohnjiang struct rte_pci_device *pdev; 503*4418919fSjohnjiang uint16_t id; 504*4418919fSjohnjiang 505*4418919fSjohnjiang pdev = RTE_ETH_DEV_TO_PCI(eth_dev); 506*4418919fSjohnjiang id = pdev->id.subsystem_device_id; 507*4418919fSjohnjiang for (m = vic_speed_capa_map; m->sub_devid != 0; m++) { 508*4418919fSjohnjiang if (m->sub_devid == id) 509*4418919fSjohnjiang return m->capa; 510*4418919fSjohnjiang } 511*4418919fSjohnjiang /* 1300 and later models are at least 40G */ 512*4418919fSjohnjiang if (id >= 0x0100) 513*4418919fSjohnjiang return ETH_LINK_SPEED_40G; 514*4418919fSjohnjiang /* VFs have subsystem id 0, check device id */ 515*4418919fSjohnjiang if (id == 0) { 516*4418919fSjohnjiang /* Newer VF implies at least 40G model */ 517*4418919fSjohnjiang if (pdev->id.device_id == PCI_DEVICE_ID_CISCO_VIC_ENET_SN) 518*4418919fSjohnjiang return ETH_LINK_SPEED_40G; 519*4418919fSjohnjiang } 520*4418919fSjohnjiang return ETH_LINK_SPEED_10G; 521*4418919fSjohnjiang } 522*4418919fSjohnjiang 523*4418919fSjohnjiang static int enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, 524a9643ea8Slogwang struct rte_eth_dev_info *device_info) 525a9643ea8Slogwang { 526a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 527a9643ea8Slogwang 528a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 529a9643ea8Slogwang /* Scattered Rx uses two receive queues per rx queue exposed to dpdk */ 530a9643ea8Slogwang device_info->max_rx_queues = enic->conf_rq_count / 2; 531a9643ea8Slogwang device_info->max_tx_queues = enic->conf_wq_count; 532a9643ea8Slogwang device_info->min_rx_bufsize = ENIC_MIN_MTU; 533d30ea906Sjfb8856606 /* "Max" mtu is not a typo. HW receives packet sizes up to the 534d30ea906Sjfb8856606 * max mtu regardless of the current mtu (vNIC's mtu). vNIC mtu is 535d30ea906Sjfb8856606 * a hint to the driver to size receive buffers accordingly so that 536d30ea906Sjfb8856606 * larger-than-vnic-mtu packets get truncated.. For DPDK, we let 537d30ea906Sjfb8856606 * the user decide the buffer size via rxmode.max_rx_pkt_len, basically 538d30ea906Sjfb8856606 * ignoring vNIC mtu. 539d30ea906Sjfb8856606 */ 540d30ea906Sjfb8856606 device_info->max_rx_pktlen = enic_mtu_to_max_rx_pktlen(enic->max_mtu); 541*4418919fSjohnjiang device_info->max_mac_addrs = ENIC_UNICAST_PERFECT_FILTERS; 542*4418919fSjohnjiang device_info->min_mtu = ENIC_MIN_MTU; 543*4418919fSjohnjiang device_info->max_mtu = enic->max_mtu; 544d30ea906Sjfb8856606 device_info->rx_offload_capa = enic->rx_offload_capa; 545d30ea906Sjfb8856606 device_info->tx_offload_capa = enic->tx_offload_capa; 546d30ea906Sjfb8856606 device_info->tx_queue_offload_capa = enic->tx_queue_offload_capa; 547a9643ea8Slogwang device_info->default_rxconf = (struct rte_eth_rxconf) { 548a9643ea8Slogwang .rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH 549a9643ea8Slogwang }; 550d30ea906Sjfb8856606 device_info->reta_size = enic->reta_size; 551d30ea906Sjfb8856606 device_info->hash_key_size = enic->hash_key_size; 552d30ea906Sjfb8856606 device_info->flow_type_rss_offloads = enic->flow_type_rss_offloads; 553d30ea906Sjfb8856606 device_info->rx_desc_lim = (struct rte_eth_desc_lim) { 554d30ea906Sjfb8856606 .nb_max = enic->config.rq_desc_count, 555d30ea906Sjfb8856606 .nb_min = ENIC_MIN_RQ_DESCS, 556d30ea906Sjfb8856606 .nb_align = ENIC_ALIGN_DESCS, 557d30ea906Sjfb8856606 }; 558d30ea906Sjfb8856606 device_info->tx_desc_lim = (struct rte_eth_desc_lim) { 559d30ea906Sjfb8856606 .nb_max = enic->config.wq_desc_count, 560d30ea906Sjfb8856606 .nb_min = ENIC_MIN_WQ_DESCS, 561d30ea906Sjfb8856606 .nb_align = ENIC_ALIGN_DESCS, 562d30ea906Sjfb8856606 .nb_seg_max = ENIC_TX_XMIT_MAX, 563d30ea906Sjfb8856606 .nb_mtu_seg_max = ENIC_NON_TSO_MAX_DESC, 564d30ea906Sjfb8856606 }; 565d30ea906Sjfb8856606 device_info->default_rxportconf = (struct rte_eth_dev_portconf) { 566d30ea906Sjfb8856606 .burst_size = ENIC_DEFAULT_RX_BURST, 567d30ea906Sjfb8856606 .ring_size = RTE_MIN(device_info->rx_desc_lim.nb_max, 568d30ea906Sjfb8856606 ENIC_DEFAULT_RX_RING_SIZE), 569d30ea906Sjfb8856606 .nb_queues = ENIC_DEFAULT_RX_RINGS, 570d30ea906Sjfb8856606 }; 571d30ea906Sjfb8856606 device_info->default_txportconf = (struct rte_eth_dev_portconf) { 572d30ea906Sjfb8856606 .burst_size = ENIC_DEFAULT_TX_BURST, 573d30ea906Sjfb8856606 .ring_size = RTE_MIN(device_info->tx_desc_lim.nb_max, 574d30ea906Sjfb8856606 ENIC_DEFAULT_TX_RING_SIZE), 575d30ea906Sjfb8856606 .nb_queues = ENIC_DEFAULT_TX_RINGS, 576d30ea906Sjfb8856606 }; 577*4418919fSjohnjiang device_info->speed_capa = speed_capa_from_pci_id(eth_dev); 578*4418919fSjohnjiang 579*4418919fSjohnjiang return 0; 580a9643ea8Slogwang } 581a9643ea8Slogwang 582a9643ea8Slogwang static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev) 583a9643ea8Slogwang { 584a9643ea8Slogwang static const uint32_t ptypes[] = { 5852bfe3f2eSlogwang RTE_PTYPE_L2_ETHER, 5862bfe3f2eSlogwang RTE_PTYPE_L2_ETHER_VLAN, 587a9643ea8Slogwang RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 588a9643ea8Slogwang RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 589a9643ea8Slogwang RTE_PTYPE_L4_TCP, 590a9643ea8Slogwang RTE_PTYPE_L4_UDP, 591a9643ea8Slogwang RTE_PTYPE_L4_FRAG, 592a9643ea8Slogwang RTE_PTYPE_L4_NONFRAG, 593a9643ea8Slogwang RTE_PTYPE_UNKNOWN 594a9643ea8Slogwang }; 595d30ea906Sjfb8856606 static const uint32_t ptypes_overlay[] = { 596d30ea906Sjfb8856606 RTE_PTYPE_L2_ETHER, 597d30ea906Sjfb8856606 RTE_PTYPE_L2_ETHER_VLAN, 598d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 599d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 600d30ea906Sjfb8856606 RTE_PTYPE_L4_TCP, 601d30ea906Sjfb8856606 RTE_PTYPE_L4_UDP, 602d30ea906Sjfb8856606 RTE_PTYPE_L4_FRAG, 603d30ea906Sjfb8856606 RTE_PTYPE_L4_NONFRAG, 604d30ea906Sjfb8856606 RTE_PTYPE_TUNNEL_GRENAT, 605d30ea906Sjfb8856606 RTE_PTYPE_INNER_L2_ETHER, 606d30ea906Sjfb8856606 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 607d30ea906Sjfb8856606 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 608d30ea906Sjfb8856606 RTE_PTYPE_INNER_L4_TCP, 609d30ea906Sjfb8856606 RTE_PTYPE_INNER_L4_UDP, 610d30ea906Sjfb8856606 RTE_PTYPE_INNER_L4_FRAG, 611d30ea906Sjfb8856606 RTE_PTYPE_INNER_L4_NONFRAG, 612d30ea906Sjfb8856606 RTE_PTYPE_UNKNOWN 613d30ea906Sjfb8856606 }; 614a9643ea8Slogwang 615d30ea906Sjfb8856606 if (dev->rx_pkt_burst != enic_dummy_recv_pkts && 616d30ea906Sjfb8856606 dev->rx_pkt_burst != NULL) { 617d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 618d30ea906Sjfb8856606 if (enic->overlay_offload) 619d30ea906Sjfb8856606 return ptypes_overlay; 620d30ea906Sjfb8856606 else 621a9643ea8Slogwang return ptypes; 622d30ea906Sjfb8856606 } 623a9643ea8Slogwang return NULL; 624a9643ea8Slogwang } 625a9643ea8Slogwang 626*4418919fSjohnjiang static int enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 627a9643ea8Slogwang { 628a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 629*4418919fSjohnjiang int ret; 630a9643ea8Slogwang 6312bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 632*4418919fSjohnjiang return -E_RTE_SECONDARY; 6332bfe3f2eSlogwang 634a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 6352bfe3f2eSlogwang 636a9643ea8Slogwang enic->promisc = 1; 637*4418919fSjohnjiang ret = enic_add_packet_filter(enic); 638*4418919fSjohnjiang if (ret != 0) 639*4418919fSjohnjiang enic->promisc = 0; 640*4418919fSjohnjiang 641*4418919fSjohnjiang return ret; 642a9643ea8Slogwang } 643a9643ea8Slogwang 644*4418919fSjohnjiang static int enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 645a9643ea8Slogwang { 646a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 647*4418919fSjohnjiang int ret; 648a9643ea8Slogwang 6492bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 650*4418919fSjohnjiang return -E_RTE_SECONDARY; 6512bfe3f2eSlogwang 652a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 653a9643ea8Slogwang enic->promisc = 0; 654*4418919fSjohnjiang ret = enic_add_packet_filter(enic); 655*4418919fSjohnjiang if (ret != 0) 656*4418919fSjohnjiang enic->promisc = 1; 657*4418919fSjohnjiang 658*4418919fSjohnjiang return ret; 659a9643ea8Slogwang } 660a9643ea8Slogwang 661*4418919fSjohnjiang static int enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 662a9643ea8Slogwang { 663a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 664*4418919fSjohnjiang int ret; 665a9643ea8Slogwang 6662bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 667*4418919fSjohnjiang return -E_RTE_SECONDARY; 6682bfe3f2eSlogwang 669a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 670a9643ea8Slogwang enic->allmulti = 1; 671*4418919fSjohnjiang ret = enic_add_packet_filter(enic); 672*4418919fSjohnjiang if (ret != 0) 673*4418919fSjohnjiang enic->allmulti = 0; 674*4418919fSjohnjiang 675*4418919fSjohnjiang return ret; 676a9643ea8Slogwang } 677a9643ea8Slogwang 678*4418919fSjohnjiang static int enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 679a9643ea8Slogwang { 680a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 681*4418919fSjohnjiang int ret; 682a9643ea8Slogwang 6832bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 684*4418919fSjohnjiang return -E_RTE_SECONDARY; 6852bfe3f2eSlogwang 686a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 687a9643ea8Slogwang enic->allmulti = 0; 688*4418919fSjohnjiang ret = enic_add_packet_filter(enic); 689*4418919fSjohnjiang if (ret != 0) 690*4418919fSjohnjiang enic->allmulti = 1; 691*4418919fSjohnjiang 692*4418919fSjohnjiang return ret; 693a9643ea8Slogwang } 694a9643ea8Slogwang 6952bfe3f2eSlogwang static int enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev, 696*4418919fSjohnjiang struct rte_ether_addr *mac_addr, 697a9643ea8Slogwang __rte_unused uint32_t index, __rte_unused uint32_t pool) 698a9643ea8Slogwang { 699a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 700a9643ea8Slogwang 7012bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 7022bfe3f2eSlogwang return -E_RTE_SECONDARY; 7032bfe3f2eSlogwang 704a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 7052bfe3f2eSlogwang return enic_set_mac_address(enic, mac_addr->addr_bytes); 706a9643ea8Slogwang } 707a9643ea8Slogwang 7082bfe3f2eSlogwang static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, uint32_t index) 709a9643ea8Slogwang { 710a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 711a9643ea8Slogwang 7122bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 7132bfe3f2eSlogwang return; 7142bfe3f2eSlogwang 715a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 716d30ea906Sjfb8856606 if (enic_del_mac_address(enic, index)) 717d30ea906Sjfb8856606 dev_err(enic, "del mac addr failed\n"); 718d30ea906Sjfb8856606 } 719d30ea906Sjfb8856606 720d30ea906Sjfb8856606 static int enicpmd_set_mac_addr(struct rte_eth_dev *eth_dev, 721*4418919fSjohnjiang struct rte_ether_addr *addr) 722d30ea906Sjfb8856606 { 723d30ea906Sjfb8856606 struct enic *enic = pmd_priv(eth_dev); 724d30ea906Sjfb8856606 int ret; 725d30ea906Sjfb8856606 726d30ea906Sjfb8856606 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 727d30ea906Sjfb8856606 return -E_RTE_SECONDARY; 728d30ea906Sjfb8856606 729d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 730d30ea906Sjfb8856606 ret = enic_del_mac_address(enic, 0); 731d30ea906Sjfb8856606 if (ret) 732d30ea906Sjfb8856606 return ret; 733d30ea906Sjfb8856606 return enic_set_mac_address(enic, addr->addr_bytes); 734a9643ea8Slogwang } 735a9643ea8Slogwang 736*4418919fSjohnjiang static void debug_log_add_del_addr(struct rte_ether_addr *addr, bool add) 737*4418919fSjohnjiang { 738*4418919fSjohnjiang char mac_str[RTE_ETHER_ADDR_FMT_SIZE]; 739*4418919fSjohnjiang 740*4418919fSjohnjiang rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE, addr); 741*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " %s address %s\n", 742*4418919fSjohnjiang add ? "add" : "remove", mac_str); 743*4418919fSjohnjiang } 744*4418919fSjohnjiang 745*4418919fSjohnjiang static int enicpmd_set_mc_addr_list(struct rte_eth_dev *eth_dev, 746*4418919fSjohnjiang struct rte_ether_addr *mc_addr_set, 747*4418919fSjohnjiang uint32_t nb_mc_addr) 748*4418919fSjohnjiang { 749*4418919fSjohnjiang struct enic *enic = pmd_priv(eth_dev); 750*4418919fSjohnjiang char mac_str[RTE_ETHER_ADDR_FMT_SIZE]; 751*4418919fSjohnjiang struct rte_ether_addr *addr; 752*4418919fSjohnjiang uint32_t i, j; 753*4418919fSjohnjiang int ret; 754*4418919fSjohnjiang 755*4418919fSjohnjiang ENICPMD_FUNC_TRACE(); 756*4418919fSjohnjiang 757*4418919fSjohnjiang /* Validate the given addresses first */ 758*4418919fSjohnjiang for (i = 0; i < nb_mc_addr && mc_addr_set != NULL; i++) { 759*4418919fSjohnjiang addr = &mc_addr_set[i]; 760*4418919fSjohnjiang if (!rte_is_multicast_ether_addr(addr) || 761*4418919fSjohnjiang rte_is_broadcast_ether_addr(addr)) { 762*4418919fSjohnjiang rte_ether_format_addr(mac_str, 763*4418919fSjohnjiang RTE_ETHER_ADDR_FMT_SIZE, addr); 764*4418919fSjohnjiang ENICPMD_LOG(ERR, " invalid multicast address %s\n", 765*4418919fSjohnjiang mac_str); 766*4418919fSjohnjiang return -EINVAL; 767*4418919fSjohnjiang } 768*4418919fSjohnjiang } 769*4418919fSjohnjiang 770*4418919fSjohnjiang /* Flush all if requested */ 771*4418919fSjohnjiang if (nb_mc_addr == 0 || mc_addr_set == NULL) { 772*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " flush multicast addresses\n"); 773*4418919fSjohnjiang for (i = 0; i < enic->mc_count; i++) { 774*4418919fSjohnjiang addr = &enic->mc_addrs[i]; 775*4418919fSjohnjiang debug_log_add_del_addr(addr, false); 776*4418919fSjohnjiang ret = vnic_dev_del_addr(enic->vdev, addr->addr_bytes); 777*4418919fSjohnjiang if (ret) 778*4418919fSjohnjiang return ret; 779*4418919fSjohnjiang } 780*4418919fSjohnjiang enic->mc_count = 0; 781*4418919fSjohnjiang return 0; 782*4418919fSjohnjiang } 783*4418919fSjohnjiang 784*4418919fSjohnjiang if (nb_mc_addr > ENIC_MULTICAST_PERFECT_FILTERS) { 785*4418919fSjohnjiang ENICPMD_LOG(ERR, " too many multicast addresses: max=%d\n", 786*4418919fSjohnjiang ENIC_MULTICAST_PERFECT_FILTERS); 787*4418919fSjohnjiang return -ENOSPC; 788*4418919fSjohnjiang } 789*4418919fSjohnjiang /* 790*4418919fSjohnjiang * devcmd is slow, so apply the difference instead of flushing and 791*4418919fSjohnjiang * adding everything. 792*4418919fSjohnjiang * 1. Delete addresses on the NIC but not on the host 793*4418919fSjohnjiang */ 794*4418919fSjohnjiang for (i = 0; i < enic->mc_count; i++) { 795*4418919fSjohnjiang addr = &enic->mc_addrs[i]; 796*4418919fSjohnjiang for (j = 0; j < nb_mc_addr; j++) { 797*4418919fSjohnjiang if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) 798*4418919fSjohnjiang break; 799*4418919fSjohnjiang } 800*4418919fSjohnjiang if (j < nb_mc_addr) 801*4418919fSjohnjiang continue; 802*4418919fSjohnjiang debug_log_add_del_addr(addr, false); 803*4418919fSjohnjiang ret = vnic_dev_del_addr(enic->vdev, addr->addr_bytes); 804*4418919fSjohnjiang if (ret) 805*4418919fSjohnjiang return ret; 806*4418919fSjohnjiang } 807*4418919fSjohnjiang /* 2. Add addresses on the host but not on the NIC */ 808*4418919fSjohnjiang for (i = 0; i < nb_mc_addr; i++) { 809*4418919fSjohnjiang addr = &mc_addr_set[i]; 810*4418919fSjohnjiang for (j = 0; j < enic->mc_count; j++) { 811*4418919fSjohnjiang if (rte_is_same_ether_addr(addr, &enic->mc_addrs[j])) 812*4418919fSjohnjiang break; 813*4418919fSjohnjiang } 814*4418919fSjohnjiang if (j < enic->mc_count) 815*4418919fSjohnjiang continue; 816*4418919fSjohnjiang debug_log_add_del_addr(addr, true); 817*4418919fSjohnjiang ret = vnic_dev_add_addr(enic->vdev, addr->addr_bytes); 818*4418919fSjohnjiang if (ret) 819*4418919fSjohnjiang return ret; 820*4418919fSjohnjiang } 821*4418919fSjohnjiang /* Keep a copy so we can flush/apply later on.. */ 822*4418919fSjohnjiang memcpy(enic->mc_addrs, mc_addr_set, 823*4418919fSjohnjiang nb_mc_addr * sizeof(struct rte_ether_addr)); 824*4418919fSjohnjiang enic->mc_count = nb_mc_addr; 825*4418919fSjohnjiang return 0; 826*4418919fSjohnjiang } 827*4418919fSjohnjiang 828a9643ea8Slogwang static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) 829a9643ea8Slogwang { 830a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 831a9643ea8Slogwang 832a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 833a9643ea8Slogwang return enic_set_mtu(enic, mtu); 834a9643ea8Slogwang } 835a9643ea8Slogwang 836d30ea906Sjfb8856606 static int enicpmd_dev_rss_reta_query(struct rte_eth_dev *dev, 837d30ea906Sjfb8856606 struct rte_eth_rss_reta_entry64 838d30ea906Sjfb8856606 *reta_conf, 839d30ea906Sjfb8856606 uint16_t reta_size) 840d30ea906Sjfb8856606 { 841d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 842d30ea906Sjfb8856606 uint16_t i, idx, shift; 843d30ea906Sjfb8856606 844d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 845d30ea906Sjfb8856606 if (reta_size != ENIC_RSS_RETA_SIZE) { 846d30ea906Sjfb8856606 dev_err(enic, "reta_query: wrong reta_size. given=%u expected=%u\n", 847d30ea906Sjfb8856606 reta_size, ENIC_RSS_RETA_SIZE); 848d30ea906Sjfb8856606 return -EINVAL; 849d30ea906Sjfb8856606 } 850d30ea906Sjfb8856606 851d30ea906Sjfb8856606 for (i = 0; i < reta_size; i++) { 852d30ea906Sjfb8856606 idx = i / RTE_RETA_GROUP_SIZE; 853d30ea906Sjfb8856606 shift = i % RTE_RETA_GROUP_SIZE; 854d30ea906Sjfb8856606 if (reta_conf[idx].mask & (1ULL << shift)) 855d30ea906Sjfb8856606 reta_conf[idx].reta[shift] = enic_sop_rq_idx_to_rte_idx( 856d30ea906Sjfb8856606 enic->rss_cpu.cpu[i / 4].b[i % 4]); 857d30ea906Sjfb8856606 } 858d30ea906Sjfb8856606 859d30ea906Sjfb8856606 return 0; 860d30ea906Sjfb8856606 } 861d30ea906Sjfb8856606 862d30ea906Sjfb8856606 static int enicpmd_dev_rss_reta_update(struct rte_eth_dev *dev, 863d30ea906Sjfb8856606 struct rte_eth_rss_reta_entry64 864d30ea906Sjfb8856606 *reta_conf, 865d30ea906Sjfb8856606 uint16_t reta_size) 866d30ea906Sjfb8856606 { 867d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 868d30ea906Sjfb8856606 union vnic_rss_cpu rss_cpu; 869d30ea906Sjfb8856606 uint16_t i, idx, shift; 870d30ea906Sjfb8856606 871d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 872d30ea906Sjfb8856606 if (reta_size != ENIC_RSS_RETA_SIZE) { 873d30ea906Sjfb8856606 dev_err(enic, "reta_update: wrong reta_size. given=%u" 874d30ea906Sjfb8856606 " expected=%u\n", 875d30ea906Sjfb8856606 reta_size, ENIC_RSS_RETA_SIZE); 876d30ea906Sjfb8856606 return -EINVAL; 877d30ea906Sjfb8856606 } 878d30ea906Sjfb8856606 /* 879d30ea906Sjfb8856606 * Start with the current reta and modify it per reta_conf, as we 880d30ea906Sjfb8856606 * need to push the entire reta even if we only modify one entry. 881d30ea906Sjfb8856606 */ 882d30ea906Sjfb8856606 rss_cpu = enic->rss_cpu; 883d30ea906Sjfb8856606 for (i = 0; i < reta_size; i++) { 884d30ea906Sjfb8856606 idx = i / RTE_RETA_GROUP_SIZE; 885d30ea906Sjfb8856606 shift = i % RTE_RETA_GROUP_SIZE; 886d30ea906Sjfb8856606 if (reta_conf[idx].mask & (1ULL << shift)) 887d30ea906Sjfb8856606 rss_cpu.cpu[i / 4].b[i % 4] = 888d30ea906Sjfb8856606 enic_rte_rq_idx_to_sop_idx( 889d30ea906Sjfb8856606 reta_conf[idx].reta[shift]); 890d30ea906Sjfb8856606 } 891d30ea906Sjfb8856606 return enic_set_rss_reta(enic, &rss_cpu); 892d30ea906Sjfb8856606 } 893d30ea906Sjfb8856606 894d30ea906Sjfb8856606 static int enicpmd_dev_rss_hash_update(struct rte_eth_dev *dev, 895d30ea906Sjfb8856606 struct rte_eth_rss_conf *rss_conf) 896d30ea906Sjfb8856606 { 897d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 898d30ea906Sjfb8856606 899d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 900d30ea906Sjfb8856606 return enic_set_rss_conf(enic, rss_conf); 901d30ea906Sjfb8856606 } 902d30ea906Sjfb8856606 903d30ea906Sjfb8856606 static int enicpmd_dev_rss_hash_conf_get(struct rte_eth_dev *dev, 904d30ea906Sjfb8856606 struct rte_eth_rss_conf *rss_conf) 905d30ea906Sjfb8856606 { 906d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 907d30ea906Sjfb8856606 908d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 909d30ea906Sjfb8856606 if (rss_conf == NULL) 910d30ea906Sjfb8856606 return -EINVAL; 911d30ea906Sjfb8856606 if (rss_conf->rss_key != NULL && 912d30ea906Sjfb8856606 rss_conf->rss_key_len < ENIC_RSS_HASH_KEY_SIZE) { 913d30ea906Sjfb8856606 dev_err(enic, "rss_hash_conf_get: wrong rss_key_len. given=%u" 914d30ea906Sjfb8856606 " expected=%u+\n", 915d30ea906Sjfb8856606 rss_conf->rss_key_len, ENIC_RSS_HASH_KEY_SIZE); 916d30ea906Sjfb8856606 return -EINVAL; 917d30ea906Sjfb8856606 } 918d30ea906Sjfb8856606 rss_conf->rss_hf = enic->rss_hf; 919d30ea906Sjfb8856606 if (rss_conf->rss_key != NULL) { 920d30ea906Sjfb8856606 int i; 921d30ea906Sjfb8856606 for (i = 0; i < ENIC_RSS_HASH_KEY_SIZE; i++) { 922d30ea906Sjfb8856606 rss_conf->rss_key[i] = 923d30ea906Sjfb8856606 enic->rss_key.key[i / 10].b[i % 10]; 924d30ea906Sjfb8856606 } 925d30ea906Sjfb8856606 rss_conf->rss_key_len = ENIC_RSS_HASH_KEY_SIZE; 926d30ea906Sjfb8856606 } 927d30ea906Sjfb8856606 return 0; 928d30ea906Sjfb8856606 } 929d30ea906Sjfb8856606 930d30ea906Sjfb8856606 static void enicpmd_dev_rxq_info_get(struct rte_eth_dev *dev, 931d30ea906Sjfb8856606 uint16_t rx_queue_id, 932d30ea906Sjfb8856606 struct rte_eth_rxq_info *qinfo) 933d30ea906Sjfb8856606 { 934d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 935d30ea906Sjfb8856606 struct vnic_rq *rq_sop; 936d30ea906Sjfb8856606 struct vnic_rq *rq_data; 937d30ea906Sjfb8856606 struct rte_eth_rxconf *conf; 938d30ea906Sjfb8856606 uint16_t sop_queue_idx; 939d30ea906Sjfb8856606 uint16_t data_queue_idx; 940d30ea906Sjfb8856606 941d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 942d30ea906Sjfb8856606 sop_queue_idx = enic_rte_rq_idx_to_sop_idx(rx_queue_id); 943d30ea906Sjfb8856606 data_queue_idx = enic_rte_rq_idx_to_data_idx(rx_queue_id); 944d30ea906Sjfb8856606 rq_sop = &enic->rq[sop_queue_idx]; 945d30ea906Sjfb8856606 rq_data = &enic->rq[data_queue_idx]; /* valid if data_queue_enable */ 946d30ea906Sjfb8856606 qinfo->mp = rq_sop->mp; 947d30ea906Sjfb8856606 qinfo->scattered_rx = rq_sop->data_queue_enable; 948d30ea906Sjfb8856606 qinfo->nb_desc = rq_sop->ring.desc_count; 949d30ea906Sjfb8856606 if (qinfo->scattered_rx) 950d30ea906Sjfb8856606 qinfo->nb_desc += rq_data->ring.desc_count; 951d30ea906Sjfb8856606 conf = &qinfo->conf; 952d30ea906Sjfb8856606 memset(conf, 0, sizeof(*conf)); 953d30ea906Sjfb8856606 conf->rx_free_thresh = rq_sop->rx_free_thresh; 954d30ea906Sjfb8856606 conf->rx_drop_en = 1; 955d30ea906Sjfb8856606 /* 956d30ea906Sjfb8856606 * Except VLAN stripping (port setting), all the checksum offloads 957d30ea906Sjfb8856606 * are always enabled. 958d30ea906Sjfb8856606 */ 959d30ea906Sjfb8856606 conf->offloads = enic->rx_offload_capa; 960d30ea906Sjfb8856606 if (!enic->ig_vlan_strip_en) 961d30ea906Sjfb8856606 conf->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; 962d30ea906Sjfb8856606 /* rx_thresh and other fields are not applicable for enic */ 963d30ea906Sjfb8856606 } 964d30ea906Sjfb8856606 965d30ea906Sjfb8856606 static void enicpmd_dev_txq_info_get(struct rte_eth_dev *dev, 966d30ea906Sjfb8856606 uint16_t tx_queue_id, 967d30ea906Sjfb8856606 struct rte_eth_txq_info *qinfo) 968d30ea906Sjfb8856606 { 969d30ea906Sjfb8856606 struct enic *enic = pmd_priv(dev); 970d30ea906Sjfb8856606 struct vnic_wq *wq = &enic->wq[tx_queue_id]; 971d30ea906Sjfb8856606 972d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 973d30ea906Sjfb8856606 qinfo->nb_desc = wq->ring.desc_count; 974d30ea906Sjfb8856606 memset(&qinfo->conf, 0, sizeof(qinfo->conf)); 975d30ea906Sjfb8856606 qinfo->conf.offloads = wq->offloads; 976d30ea906Sjfb8856606 /* tx_thresh, and all the other fields are not applicable for enic */ 977d30ea906Sjfb8856606 } 978d30ea906Sjfb8856606 979d30ea906Sjfb8856606 static int enicpmd_dev_rx_queue_intr_enable(struct rte_eth_dev *eth_dev, 980d30ea906Sjfb8856606 uint16_t rx_queue_id) 981d30ea906Sjfb8856606 { 982d30ea906Sjfb8856606 struct enic *enic = pmd_priv(eth_dev); 983d30ea906Sjfb8856606 984d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 985d30ea906Sjfb8856606 vnic_intr_unmask(&enic->intr[rx_queue_id + ENICPMD_RXQ_INTR_OFFSET]); 986d30ea906Sjfb8856606 return 0; 987d30ea906Sjfb8856606 } 988d30ea906Sjfb8856606 989d30ea906Sjfb8856606 static int enicpmd_dev_rx_queue_intr_disable(struct rte_eth_dev *eth_dev, 990d30ea906Sjfb8856606 uint16_t rx_queue_id) 991d30ea906Sjfb8856606 { 992d30ea906Sjfb8856606 struct enic *enic = pmd_priv(eth_dev); 993d30ea906Sjfb8856606 994d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 995d30ea906Sjfb8856606 vnic_intr_mask(&enic->intr[rx_queue_id + ENICPMD_RXQ_INTR_OFFSET]); 996d30ea906Sjfb8856606 return 0; 997d30ea906Sjfb8856606 } 998d30ea906Sjfb8856606 999d30ea906Sjfb8856606 static int udp_tunnel_common_check(struct enic *enic, 1000d30ea906Sjfb8856606 struct rte_eth_udp_tunnel *tnl) 1001d30ea906Sjfb8856606 { 1002d30ea906Sjfb8856606 if (tnl->prot_type != RTE_TUNNEL_TYPE_VXLAN) 1003d30ea906Sjfb8856606 return -ENOTSUP; 1004d30ea906Sjfb8856606 if (!enic->overlay_offload) { 1005*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " vxlan (overlay offload) is not " 1006d30ea906Sjfb8856606 "supported\n"); 1007d30ea906Sjfb8856606 return -ENOTSUP; 1008d30ea906Sjfb8856606 } 1009d30ea906Sjfb8856606 return 0; 1010d30ea906Sjfb8856606 } 1011d30ea906Sjfb8856606 1012d30ea906Sjfb8856606 static int update_vxlan_port(struct enic *enic, uint16_t port) 1013d30ea906Sjfb8856606 { 1014d30ea906Sjfb8856606 if (vnic_dev_overlay_offload_cfg(enic->vdev, 1015d30ea906Sjfb8856606 OVERLAY_CFG_VXLAN_PORT_UPDATE, 1016d30ea906Sjfb8856606 port)) { 1017*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " failed to update vxlan port\n"); 1018d30ea906Sjfb8856606 return -EINVAL; 1019d30ea906Sjfb8856606 } 1020*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " updated vxlan port to %u\n", port); 1021d30ea906Sjfb8856606 enic->vxlan_port = port; 1022d30ea906Sjfb8856606 return 0; 1023d30ea906Sjfb8856606 } 1024d30ea906Sjfb8856606 1025d30ea906Sjfb8856606 static int enicpmd_dev_udp_tunnel_port_add(struct rte_eth_dev *eth_dev, 1026d30ea906Sjfb8856606 struct rte_eth_udp_tunnel *tnl) 1027d30ea906Sjfb8856606 { 1028d30ea906Sjfb8856606 struct enic *enic = pmd_priv(eth_dev); 1029d30ea906Sjfb8856606 int ret; 1030d30ea906Sjfb8856606 1031d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 1032d30ea906Sjfb8856606 ret = udp_tunnel_common_check(enic, tnl); 1033d30ea906Sjfb8856606 if (ret) 1034d30ea906Sjfb8856606 return ret; 1035d30ea906Sjfb8856606 /* 1036d30ea906Sjfb8856606 * The NIC has 1 configurable VXLAN port number. "Adding" a new port 1037d30ea906Sjfb8856606 * number replaces it. 1038d30ea906Sjfb8856606 */ 1039d30ea906Sjfb8856606 if (tnl->udp_port == enic->vxlan_port || tnl->udp_port == 0) { 1040*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " %u is already configured or invalid\n", 1041d30ea906Sjfb8856606 tnl->udp_port); 1042d30ea906Sjfb8856606 return -EINVAL; 1043d30ea906Sjfb8856606 } 1044d30ea906Sjfb8856606 return update_vxlan_port(enic, tnl->udp_port); 1045d30ea906Sjfb8856606 } 1046d30ea906Sjfb8856606 1047d30ea906Sjfb8856606 static int enicpmd_dev_udp_tunnel_port_del(struct rte_eth_dev *eth_dev, 1048d30ea906Sjfb8856606 struct rte_eth_udp_tunnel *tnl) 1049d30ea906Sjfb8856606 { 1050d30ea906Sjfb8856606 struct enic *enic = pmd_priv(eth_dev); 1051d30ea906Sjfb8856606 int ret; 1052d30ea906Sjfb8856606 1053d30ea906Sjfb8856606 ENICPMD_FUNC_TRACE(); 1054d30ea906Sjfb8856606 ret = udp_tunnel_common_check(enic, tnl); 1055d30ea906Sjfb8856606 if (ret) 1056d30ea906Sjfb8856606 return ret; 1057d30ea906Sjfb8856606 /* 1058d30ea906Sjfb8856606 * Clear the previously set port number and restore the 1059d30ea906Sjfb8856606 * hardware default port number. Some drivers disable VXLAN 1060d30ea906Sjfb8856606 * offloads when there are no configured port numbers. But 1061d30ea906Sjfb8856606 * enic does not do that as VXLAN is part of overlay offload, 1062d30ea906Sjfb8856606 * which is tied to inner RSS and TSO. 1063d30ea906Sjfb8856606 */ 1064d30ea906Sjfb8856606 if (tnl->udp_port != enic->vxlan_port) { 1065*4418919fSjohnjiang ENICPMD_LOG(DEBUG, " %u is not a configured vxlan port\n", 1066d30ea906Sjfb8856606 tnl->udp_port); 1067d30ea906Sjfb8856606 return -EINVAL; 1068d30ea906Sjfb8856606 } 1069*4418919fSjohnjiang return update_vxlan_port(enic, RTE_VXLAN_DEFAULT_PORT); 1070*4418919fSjohnjiang } 1071*4418919fSjohnjiang 1072*4418919fSjohnjiang static int enicpmd_dev_fw_version_get(struct rte_eth_dev *eth_dev, 1073*4418919fSjohnjiang char *fw_version, size_t fw_size) 1074*4418919fSjohnjiang { 1075*4418919fSjohnjiang struct vnic_devcmd_fw_info *info; 1076*4418919fSjohnjiang struct enic *enic; 1077*4418919fSjohnjiang int ret; 1078*4418919fSjohnjiang 1079*4418919fSjohnjiang ENICPMD_FUNC_TRACE(); 1080*4418919fSjohnjiang if (fw_version == NULL || fw_size <= 0) 1081*4418919fSjohnjiang return -EINVAL; 1082*4418919fSjohnjiang enic = pmd_priv(eth_dev); 1083*4418919fSjohnjiang ret = vnic_dev_fw_info(enic->vdev, &info); 1084*4418919fSjohnjiang if (ret) 1085*4418919fSjohnjiang return ret; 1086*4418919fSjohnjiang snprintf(fw_version, fw_size, "%s %s", 1087*4418919fSjohnjiang info->fw_version, info->fw_build); 1088*4418919fSjohnjiang fw_version[fw_size - 1] = '\0'; 1089*4418919fSjohnjiang return 0; 1090d30ea906Sjfb8856606 } 1091d30ea906Sjfb8856606 1092a9643ea8Slogwang static const struct eth_dev_ops enicpmd_eth_dev_ops = { 1093a9643ea8Slogwang .dev_configure = enicpmd_dev_configure, 1094a9643ea8Slogwang .dev_start = enicpmd_dev_start, 1095a9643ea8Slogwang .dev_stop = enicpmd_dev_stop, 1096a9643ea8Slogwang .dev_set_link_up = NULL, 1097a9643ea8Slogwang .dev_set_link_down = NULL, 1098a9643ea8Slogwang .dev_close = enicpmd_dev_close, 1099a9643ea8Slogwang .promiscuous_enable = enicpmd_dev_promiscuous_enable, 1100a9643ea8Slogwang .promiscuous_disable = enicpmd_dev_promiscuous_disable, 1101a9643ea8Slogwang .allmulticast_enable = enicpmd_dev_allmulticast_enable, 1102a9643ea8Slogwang .allmulticast_disable = enicpmd_dev_allmulticast_disable, 1103a9643ea8Slogwang .link_update = enicpmd_dev_link_update, 1104a9643ea8Slogwang .stats_get = enicpmd_dev_stats_get, 1105a9643ea8Slogwang .stats_reset = enicpmd_dev_stats_reset, 1106a9643ea8Slogwang .queue_stats_mapping_set = NULL, 1107a9643ea8Slogwang .dev_infos_get = enicpmd_dev_info_get, 1108a9643ea8Slogwang .dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get, 1109a9643ea8Slogwang .mtu_set = enicpmd_mtu_set, 1110d30ea906Sjfb8856606 .vlan_filter_set = NULL, 1111a9643ea8Slogwang .vlan_tpid_set = NULL, 1112a9643ea8Slogwang .vlan_offload_set = enicpmd_vlan_offload_set, 1113a9643ea8Slogwang .vlan_strip_queue_set = NULL, 1114a9643ea8Slogwang .rx_queue_start = enicpmd_dev_rx_queue_start, 1115a9643ea8Slogwang .rx_queue_stop = enicpmd_dev_rx_queue_stop, 1116a9643ea8Slogwang .tx_queue_start = enicpmd_dev_tx_queue_start, 1117a9643ea8Slogwang .tx_queue_stop = enicpmd_dev_tx_queue_stop, 1118a9643ea8Slogwang .rx_queue_setup = enicpmd_dev_rx_queue_setup, 1119a9643ea8Slogwang .rx_queue_release = enicpmd_dev_rx_queue_release, 11202bfe3f2eSlogwang .rx_queue_count = enicpmd_dev_rx_queue_count, 1121a9643ea8Slogwang .rx_descriptor_done = NULL, 1122a9643ea8Slogwang .tx_queue_setup = enicpmd_dev_tx_queue_setup, 1123a9643ea8Slogwang .tx_queue_release = enicpmd_dev_tx_queue_release, 1124d30ea906Sjfb8856606 .rx_queue_intr_enable = enicpmd_dev_rx_queue_intr_enable, 1125d30ea906Sjfb8856606 .rx_queue_intr_disable = enicpmd_dev_rx_queue_intr_disable, 1126d30ea906Sjfb8856606 .rxq_info_get = enicpmd_dev_rxq_info_get, 1127d30ea906Sjfb8856606 .txq_info_get = enicpmd_dev_txq_info_get, 1128a9643ea8Slogwang .dev_led_on = NULL, 1129a9643ea8Slogwang .dev_led_off = NULL, 1130a9643ea8Slogwang .flow_ctrl_get = NULL, 1131a9643ea8Slogwang .flow_ctrl_set = NULL, 1132a9643ea8Slogwang .priority_flow_ctrl_set = NULL, 1133a9643ea8Slogwang .mac_addr_add = enicpmd_add_mac_addr, 1134a9643ea8Slogwang .mac_addr_remove = enicpmd_remove_mac_addr, 1135d30ea906Sjfb8856606 .mac_addr_set = enicpmd_set_mac_addr, 1136*4418919fSjohnjiang .set_mc_addr_list = enicpmd_set_mc_addr_list, 1137a9643ea8Slogwang .filter_ctrl = enicpmd_dev_filter_ctrl, 1138d30ea906Sjfb8856606 .reta_query = enicpmd_dev_rss_reta_query, 1139d30ea906Sjfb8856606 .reta_update = enicpmd_dev_rss_reta_update, 1140d30ea906Sjfb8856606 .rss_hash_conf_get = enicpmd_dev_rss_hash_conf_get, 1141d30ea906Sjfb8856606 .rss_hash_update = enicpmd_dev_rss_hash_update, 1142d30ea906Sjfb8856606 .udp_tunnel_port_add = enicpmd_dev_udp_tunnel_port_add, 1143d30ea906Sjfb8856606 .udp_tunnel_port_del = enicpmd_dev_udp_tunnel_port_del, 1144*4418919fSjohnjiang .fw_version_get = enicpmd_dev_fw_version_get, 1145a9643ea8Slogwang }; 1146a9643ea8Slogwang 1147d30ea906Sjfb8856606 static int enic_parse_zero_one(const char *key, 1148d30ea906Sjfb8856606 const char *value, 1149d30ea906Sjfb8856606 void *opaque) 1150d30ea906Sjfb8856606 { 1151d30ea906Sjfb8856606 struct enic *enic; 1152d30ea906Sjfb8856606 bool b; 1153d30ea906Sjfb8856606 1154d30ea906Sjfb8856606 enic = (struct enic *)opaque; 1155d30ea906Sjfb8856606 if (strcmp(value, "0") == 0) { 1156d30ea906Sjfb8856606 b = false; 1157d30ea906Sjfb8856606 } else if (strcmp(value, "1") == 0) { 1158d30ea906Sjfb8856606 b = true; 1159d30ea906Sjfb8856606 } else { 1160d30ea906Sjfb8856606 dev_err(enic, "Invalid value for %s" 1161d30ea906Sjfb8856606 ": expected=0|1 given=%s\n", key, value); 1162d30ea906Sjfb8856606 return -EINVAL; 1163d30ea906Sjfb8856606 } 1164d30ea906Sjfb8856606 if (strcmp(key, ENIC_DEVARG_DISABLE_OVERLAY) == 0) 1165d30ea906Sjfb8856606 enic->disable_overlay = b; 1166d30ea906Sjfb8856606 if (strcmp(key, ENIC_DEVARG_ENABLE_AVX2_RX) == 0) 1167d30ea906Sjfb8856606 enic->enable_avx2_rx = b; 1168*4418919fSjohnjiang if (strcmp(key, ENIC_DEVARG_GENEVE_OPT) == 0) 1169*4418919fSjohnjiang enic->geneve_opt_request = b; 1170d30ea906Sjfb8856606 return 0; 1171d30ea906Sjfb8856606 } 1172d30ea906Sjfb8856606 1173579bf1e2Sjfb8856606 static int enic_parse_ig_vlan_rewrite(__rte_unused const char *key, 1174579bf1e2Sjfb8856606 const char *value, 1175579bf1e2Sjfb8856606 void *opaque) 1176579bf1e2Sjfb8856606 { 1177579bf1e2Sjfb8856606 struct enic *enic; 1178579bf1e2Sjfb8856606 1179579bf1e2Sjfb8856606 enic = (struct enic *)opaque; 1180579bf1e2Sjfb8856606 if (strcmp(value, "trunk") == 0) { 1181579bf1e2Sjfb8856606 /* Trunk mode: always tag */ 1182579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK; 1183579bf1e2Sjfb8856606 } else if (strcmp(value, "untag") == 0) { 1184579bf1e2Sjfb8856606 /* Untag default VLAN mode: untag if VLAN = default VLAN */ 1185579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = 1186579bf1e2Sjfb8856606 IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN; 1187579bf1e2Sjfb8856606 } else if (strcmp(value, "priority") == 0) { 1188579bf1e2Sjfb8856606 /* 1189579bf1e2Sjfb8856606 * Priority-tag default VLAN mode: priority tag (VLAN header 1190579bf1e2Sjfb8856606 * with ID=0) if VLAN = default 1191579bf1e2Sjfb8856606 */ 1192579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = 1193579bf1e2Sjfb8856606 IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN; 1194579bf1e2Sjfb8856606 } else if (strcmp(value, "pass") == 0) { 1195579bf1e2Sjfb8856606 /* Pass through mode: do not touch tags */ 1196579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU; 1197579bf1e2Sjfb8856606 } else { 1198579bf1e2Sjfb8856606 dev_err(enic, "Invalid value for " ENIC_DEVARG_IG_VLAN_REWRITE 1199579bf1e2Sjfb8856606 ": expected=trunk|untag|priority|pass given=%s\n", 1200579bf1e2Sjfb8856606 value); 1201579bf1e2Sjfb8856606 return -EINVAL; 1202579bf1e2Sjfb8856606 } 1203579bf1e2Sjfb8856606 return 0; 1204579bf1e2Sjfb8856606 } 1205579bf1e2Sjfb8856606 1206579bf1e2Sjfb8856606 static int enic_check_devargs(struct rte_eth_dev *dev) 1207579bf1e2Sjfb8856606 { 1208579bf1e2Sjfb8856606 static const char *const valid_keys[] = { 1209d30ea906Sjfb8856606 ENIC_DEVARG_DISABLE_OVERLAY, 1210d30ea906Sjfb8856606 ENIC_DEVARG_ENABLE_AVX2_RX, 1211*4418919fSjohnjiang ENIC_DEVARG_GENEVE_OPT, 1212579bf1e2Sjfb8856606 ENIC_DEVARG_IG_VLAN_REWRITE, 1213579bf1e2Sjfb8856606 NULL}; 1214579bf1e2Sjfb8856606 struct enic *enic = pmd_priv(dev); 1215579bf1e2Sjfb8856606 struct rte_kvargs *kvlist; 1216579bf1e2Sjfb8856606 1217579bf1e2Sjfb8856606 ENICPMD_FUNC_TRACE(); 1218579bf1e2Sjfb8856606 1219d30ea906Sjfb8856606 enic->disable_overlay = false; 1220d30ea906Sjfb8856606 enic->enable_avx2_rx = false; 1221*4418919fSjohnjiang enic->geneve_opt_request = false; 1222579bf1e2Sjfb8856606 enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU; 1223579bf1e2Sjfb8856606 if (!dev->device->devargs) 1224579bf1e2Sjfb8856606 return 0; 1225579bf1e2Sjfb8856606 kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys); 1226579bf1e2Sjfb8856606 if (!kvlist) 1227579bf1e2Sjfb8856606 return -EINVAL; 1228d30ea906Sjfb8856606 if (rte_kvargs_process(kvlist, ENIC_DEVARG_DISABLE_OVERLAY, 1229d30ea906Sjfb8856606 enic_parse_zero_one, enic) < 0 || 1230d30ea906Sjfb8856606 rte_kvargs_process(kvlist, ENIC_DEVARG_ENABLE_AVX2_RX, 1231d30ea906Sjfb8856606 enic_parse_zero_one, enic) < 0 || 1232*4418919fSjohnjiang rte_kvargs_process(kvlist, ENIC_DEVARG_GENEVE_OPT, 1233*4418919fSjohnjiang enic_parse_zero_one, enic) < 0 || 1234d30ea906Sjfb8856606 rte_kvargs_process(kvlist, ENIC_DEVARG_IG_VLAN_REWRITE, 1235579bf1e2Sjfb8856606 enic_parse_ig_vlan_rewrite, enic) < 0) { 1236579bf1e2Sjfb8856606 rte_kvargs_free(kvlist); 1237579bf1e2Sjfb8856606 return -EINVAL; 1238579bf1e2Sjfb8856606 } 1239579bf1e2Sjfb8856606 rte_kvargs_free(kvlist); 1240579bf1e2Sjfb8856606 return 0; 1241579bf1e2Sjfb8856606 } 1242579bf1e2Sjfb8856606 1243a9643ea8Slogwang /* Initialize the driver 1244a9643ea8Slogwang * It returns 0 on success. 1245a9643ea8Slogwang */ 1246a9643ea8Slogwang static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev) 1247a9643ea8Slogwang { 1248a9643ea8Slogwang struct rte_pci_device *pdev; 1249a9643ea8Slogwang struct rte_pci_addr *addr; 1250a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 1251579bf1e2Sjfb8856606 int err; 1252a9643ea8Slogwang 1253a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 1254a9643ea8Slogwang 1255a9643ea8Slogwang eth_dev->dev_ops = &enicpmd_eth_dev_ops; 1256a9643ea8Slogwang eth_dev->rx_pkt_burst = &enic_recv_pkts; 1257a9643ea8Slogwang eth_dev->tx_pkt_burst = &enic_xmit_pkts; 1258d30ea906Sjfb8856606 eth_dev->tx_pkt_prepare = &enic_prep_pkts; 1259*4418919fSjohnjiang if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 1260*4418919fSjohnjiang enic_pick_tx_handler(eth_dev); 1261*4418919fSjohnjiang enic_pick_rx_handler(eth_dev); 1262*4418919fSjohnjiang return 0; 1263*4418919fSjohnjiang } 1264*4418919fSjohnjiang /* Only the primary sets up adapter and other data in shared memory */ 1265*4418919fSjohnjiang enic->port_id = eth_dev->data->port_id; 1266*4418919fSjohnjiang enic->rte_dev = eth_dev; 1267*4418919fSjohnjiang enic->dev_data = eth_dev->data; 1268*4418919fSjohnjiang /* Let rte_eth_dev_close() release the port resources */ 1269*4418919fSjohnjiang eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; 1270a9643ea8Slogwang 12712bfe3f2eSlogwang pdev = RTE_ETH_DEV_TO_PCI(eth_dev); 1272a9643ea8Slogwang rte_eth_copy_pci_info(eth_dev, pdev); 1273a9643ea8Slogwang enic->pdev = pdev; 1274a9643ea8Slogwang addr = &pdev->addr; 1275a9643ea8Slogwang 1276a9643ea8Slogwang snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x", 1277a9643ea8Slogwang addr->domain, addr->bus, addr->devid, addr->function); 1278a9643ea8Slogwang 1279579bf1e2Sjfb8856606 err = enic_check_devargs(eth_dev); 1280579bf1e2Sjfb8856606 if (err) 1281579bf1e2Sjfb8856606 return err; 1282a9643ea8Slogwang return enic_probe(enic); 1283a9643ea8Slogwang } 1284a9643ea8Slogwang 12852bfe3f2eSlogwang static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 12862bfe3f2eSlogwang struct rte_pci_device *pci_dev) 1287a9643ea8Slogwang { 12882bfe3f2eSlogwang return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct enic), 12892bfe3f2eSlogwang eth_enicpmd_dev_init); 1290a9643ea8Slogwang } 1291a9643ea8Slogwang 12922bfe3f2eSlogwang static int eth_enic_pci_remove(struct rte_pci_device *pci_dev) 12932bfe3f2eSlogwang { 12942bfe3f2eSlogwang return rte_eth_dev_pci_generic_remove(pci_dev, NULL); 12952bfe3f2eSlogwang } 12962bfe3f2eSlogwang 12972bfe3f2eSlogwang static struct rte_pci_driver rte_enic_pmd = { 12982bfe3f2eSlogwang .id_table = pci_id_enic_map, 1299*4418919fSjohnjiang .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 13002bfe3f2eSlogwang .probe = eth_enic_pci_probe, 13012bfe3f2eSlogwang .remove = eth_enic_pci_remove, 1302a9643ea8Slogwang }; 1303a9643ea8Slogwang 1304*4418919fSjohnjiang int dev_is_enic(struct rte_eth_dev *dev) 1305*4418919fSjohnjiang { 1306*4418919fSjohnjiang return dev->device->driver == &rte_enic_pmd.driver; 1307*4418919fSjohnjiang } 1308*4418919fSjohnjiang 13092bfe3f2eSlogwang RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd); 13102bfe3f2eSlogwang RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map); 13112bfe3f2eSlogwang RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci"); 1312579bf1e2Sjfb8856606 RTE_PMD_REGISTER_PARAM_STRING(net_enic, 1313d30ea906Sjfb8856606 ENIC_DEVARG_DISABLE_OVERLAY "=0|1 " 1314d30ea906Sjfb8856606 ENIC_DEVARG_ENABLE_AVX2_RX "=0|1 " 1315*4418919fSjohnjiang ENIC_DEVARG_GENEVE_OPT "=0|1 " 1316579bf1e2Sjfb8856606 ENIC_DEVARG_IG_VLAN_REWRITE "=trunk|untag|priority|pass"); 1317