1*a9643ea8Slogwang /* 2*a9643ea8Slogwang * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. 3*a9643ea8Slogwang * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4*a9643ea8Slogwang * 5*a9643ea8Slogwang * Copyright (c) 2014, Cisco Systems, Inc. 6*a9643ea8Slogwang * All rights reserved. 7*a9643ea8Slogwang * 8*a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 9*a9643ea8Slogwang * modification, are permitted provided that the following conditions 10*a9643ea8Slogwang * are met: 11*a9643ea8Slogwang * 12*a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright 13*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 14*a9643ea8Slogwang * 15*a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright 16*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in 17*a9643ea8Slogwang * the documentation and/or other materials provided with the 18*a9643ea8Slogwang * distribution. 19*a9643ea8Slogwang * 20*a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*a9643ea8Slogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*a9643ea8Slogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*a9643ea8Slogwang * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24*a9643ea8Slogwang * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*a9643ea8Slogwang * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*a9643ea8Slogwang * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27*a9643ea8Slogwang * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28*a9643ea8Slogwang * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30*a9643ea8Slogwang * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31*a9643ea8Slogwang * POSSIBILITY OF SUCH DAMAGE. 32*a9643ea8Slogwang * 33*a9643ea8Slogwang */ 34*a9643ea8Slogwang 35*a9643ea8Slogwang #include <stdio.h> 36*a9643ea8Slogwang #include <stdint.h> 37*a9643ea8Slogwang 38*a9643ea8Slogwang #include <rte_dev.h> 39*a9643ea8Slogwang #include <rte_pci.h> 40*a9643ea8Slogwang #include <rte_ethdev.h> 41*a9643ea8Slogwang #include <rte_string_fns.h> 42*a9643ea8Slogwang 43*a9643ea8Slogwang #include "vnic_intr.h" 44*a9643ea8Slogwang #include "vnic_cq.h" 45*a9643ea8Slogwang #include "vnic_wq.h" 46*a9643ea8Slogwang #include "vnic_rq.h" 47*a9643ea8Slogwang #include "vnic_enet.h" 48*a9643ea8Slogwang #include "enic.h" 49*a9643ea8Slogwang 50*a9643ea8Slogwang #ifdef RTE_LIBRTE_ENIC_DEBUG 51*a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() \ 52*a9643ea8Slogwang RTE_LOG(DEBUG, PMD, "ENICPMD trace: %s\n", __func__) 53*a9643ea8Slogwang #else 54*a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() (void)0 55*a9643ea8Slogwang #endif 56*a9643ea8Slogwang 57*a9643ea8Slogwang /* 58*a9643ea8Slogwang * The set of PCI devices this driver supports 59*a9643ea8Slogwang */ 60*a9643ea8Slogwang #define CISCO_PCI_VENDOR_ID 0x1137 61*a9643ea8Slogwang static const struct rte_pci_id pci_id_enic_map[] = { 62*a9643ea8Slogwang { RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET) }, 63*a9643ea8Slogwang { RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) }, 64*a9643ea8Slogwang {.vendor_id = 0, /* sentinel */}, 65*a9643ea8Slogwang }; 66*a9643ea8Slogwang 67*a9643ea8Slogwang static int 68*a9643ea8Slogwang enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev, 69*a9643ea8Slogwang enum rte_filter_op filter_op, void *arg) 70*a9643ea8Slogwang { 71*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 72*a9643ea8Slogwang int ret = 0; 73*a9643ea8Slogwang 74*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 75*a9643ea8Slogwang if (filter_op == RTE_ETH_FILTER_NOP) 76*a9643ea8Slogwang return 0; 77*a9643ea8Slogwang 78*a9643ea8Slogwang if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) 79*a9643ea8Slogwang return -EINVAL; 80*a9643ea8Slogwang 81*a9643ea8Slogwang switch (filter_op) { 82*a9643ea8Slogwang case RTE_ETH_FILTER_ADD: 83*a9643ea8Slogwang case RTE_ETH_FILTER_UPDATE: 84*a9643ea8Slogwang ret = enic_fdir_add_fltr(enic, 85*a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 86*a9643ea8Slogwang break; 87*a9643ea8Slogwang 88*a9643ea8Slogwang case RTE_ETH_FILTER_DELETE: 89*a9643ea8Slogwang ret = enic_fdir_del_fltr(enic, 90*a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 91*a9643ea8Slogwang break; 92*a9643ea8Slogwang 93*a9643ea8Slogwang case RTE_ETH_FILTER_STATS: 94*a9643ea8Slogwang enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg); 95*a9643ea8Slogwang break; 96*a9643ea8Slogwang 97*a9643ea8Slogwang case RTE_ETH_FILTER_FLUSH: 98*a9643ea8Slogwang case RTE_ETH_FILTER_INFO: 99*a9643ea8Slogwang dev_warning(enic, "unsupported operation %u", filter_op); 100*a9643ea8Slogwang ret = -ENOTSUP; 101*a9643ea8Slogwang break; 102*a9643ea8Slogwang default: 103*a9643ea8Slogwang dev_err(enic, "unknown operation %u", filter_op); 104*a9643ea8Slogwang ret = -EINVAL; 105*a9643ea8Slogwang break; 106*a9643ea8Slogwang } 107*a9643ea8Slogwang return ret; 108*a9643ea8Slogwang } 109*a9643ea8Slogwang 110*a9643ea8Slogwang static int 111*a9643ea8Slogwang enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev, 112*a9643ea8Slogwang enum rte_filter_type filter_type, 113*a9643ea8Slogwang enum rte_filter_op filter_op, 114*a9643ea8Slogwang void *arg) 115*a9643ea8Slogwang { 116*a9643ea8Slogwang int ret = -EINVAL; 117*a9643ea8Slogwang 118*a9643ea8Slogwang if (RTE_ETH_FILTER_FDIR == filter_type) 119*a9643ea8Slogwang ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg); 120*a9643ea8Slogwang else 121*a9643ea8Slogwang dev_warning(enic, "Filter type (%d) not supported", 122*a9643ea8Slogwang filter_type); 123*a9643ea8Slogwang 124*a9643ea8Slogwang return ret; 125*a9643ea8Slogwang } 126*a9643ea8Slogwang 127*a9643ea8Slogwang static void enicpmd_dev_tx_queue_release(void *txq) 128*a9643ea8Slogwang { 129*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 130*a9643ea8Slogwang enic_free_wq(txq); 131*a9643ea8Slogwang } 132*a9643ea8Slogwang 133*a9643ea8Slogwang static int enicpmd_dev_setup_intr(struct enic *enic) 134*a9643ea8Slogwang { 135*a9643ea8Slogwang int ret; 136*a9643ea8Slogwang unsigned int index; 137*a9643ea8Slogwang 138*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 139*a9643ea8Slogwang 140*a9643ea8Slogwang /* Are we done with the init of all the queues? */ 141*a9643ea8Slogwang for (index = 0; index < enic->cq_count; index++) { 142*a9643ea8Slogwang if (!enic->cq[index].ctrl) 143*a9643ea8Slogwang break; 144*a9643ea8Slogwang } 145*a9643ea8Slogwang if (enic->cq_count != index) 146*a9643ea8Slogwang return 0; 147*a9643ea8Slogwang for (index = 0; index < enic->wq_count; index++) { 148*a9643ea8Slogwang if (!enic->wq[index].ctrl) 149*a9643ea8Slogwang break; 150*a9643ea8Slogwang } 151*a9643ea8Slogwang if (enic->wq_count != index) 152*a9643ea8Slogwang return 0; 153*a9643ea8Slogwang /* check start of packet (SOP) RQs only in case scatter is disabled. */ 154*a9643ea8Slogwang for (index = 0; index < enic->rq_count; index++) { 155*a9643ea8Slogwang if (!enic->rq[enic_sop_rq(index)].ctrl) 156*a9643ea8Slogwang break; 157*a9643ea8Slogwang } 158*a9643ea8Slogwang if (enic->rq_count != index) 159*a9643ea8Slogwang return 0; 160*a9643ea8Slogwang 161*a9643ea8Slogwang ret = enic_alloc_intr_resources(enic); 162*a9643ea8Slogwang if (ret) { 163*a9643ea8Slogwang dev_err(enic, "alloc intr failed\n"); 164*a9643ea8Slogwang return ret; 165*a9643ea8Slogwang } 166*a9643ea8Slogwang enic_init_vnic_resources(enic); 167*a9643ea8Slogwang 168*a9643ea8Slogwang ret = enic_setup_finish(enic); 169*a9643ea8Slogwang if (ret) 170*a9643ea8Slogwang dev_err(enic, "setup could not be finished\n"); 171*a9643ea8Slogwang 172*a9643ea8Slogwang return ret; 173*a9643ea8Slogwang } 174*a9643ea8Slogwang 175*a9643ea8Slogwang static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 176*a9643ea8Slogwang uint16_t queue_idx, 177*a9643ea8Slogwang uint16_t nb_desc, 178*a9643ea8Slogwang unsigned int socket_id, 179*a9643ea8Slogwang __rte_unused const struct rte_eth_txconf *tx_conf) 180*a9643ea8Slogwang { 181*a9643ea8Slogwang int ret; 182*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 183*a9643ea8Slogwang 184*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 185*a9643ea8Slogwang if (queue_idx >= ENIC_WQ_MAX) { 186*a9643ea8Slogwang dev_err(enic, 187*a9643ea8Slogwang "Max number of TX queues exceeded. Max is %d\n", 188*a9643ea8Slogwang ENIC_WQ_MAX); 189*a9643ea8Slogwang return -EINVAL; 190*a9643ea8Slogwang } 191*a9643ea8Slogwang 192*a9643ea8Slogwang eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx]; 193*a9643ea8Slogwang 194*a9643ea8Slogwang ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc); 195*a9643ea8Slogwang if (ret) { 196*a9643ea8Slogwang dev_err(enic, "error in allocating wq\n"); 197*a9643ea8Slogwang return ret; 198*a9643ea8Slogwang } 199*a9643ea8Slogwang 200*a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 201*a9643ea8Slogwang } 202*a9643ea8Slogwang 203*a9643ea8Slogwang static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev, 204*a9643ea8Slogwang uint16_t queue_idx) 205*a9643ea8Slogwang { 206*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 207*a9643ea8Slogwang 208*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 209*a9643ea8Slogwang 210*a9643ea8Slogwang enic_start_wq(enic, queue_idx); 211*a9643ea8Slogwang 212*a9643ea8Slogwang return 0; 213*a9643ea8Slogwang } 214*a9643ea8Slogwang 215*a9643ea8Slogwang static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, 216*a9643ea8Slogwang uint16_t queue_idx) 217*a9643ea8Slogwang { 218*a9643ea8Slogwang int ret; 219*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 220*a9643ea8Slogwang 221*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 222*a9643ea8Slogwang 223*a9643ea8Slogwang ret = enic_stop_wq(enic, queue_idx); 224*a9643ea8Slogwang if (ret) 225*a9643ea8Slogwang dev_err(enic, "error in stopping wq %d\n", queue_idx); 226*a9643ea8Slogwang 227*a9643ea8Slogwang return ret; 228*a9643ea8Slogwang } 229*a9643ea8Slogwang 230*a9643ea8Slogwang static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev, 231*a9643ea8Slogwang uint16_t queue_idx) 232*a9643ea8Slogwang { 233*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 234*a9643ea8Slogwang 235*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 236*a9643ea8Slogwang 237*a9643ea8Slogwang enic_start_rq(enic, queue_idx); 238*a9643ea8Slogwang 239*a9643ea8Slogwang return 0; 240*a9643ea8Slogwang } 241*a9643ea8Slogwang 242*a9643ea8Slogwang static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, 243*a9643ea8Slogwang uint16_t queue_idx) 244*a9643ea8Slogwang { 245*a9643ea8Slogwang int ret; 246*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 247*a9643ea8Slogwang 248*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 249*a9643ea8Slogwang 250*a9643ea8Slogwang ret = enic_stop_rq(enic, queue_idx); 251*a9643ea8Slogwang if (ret) 252*a9643ea8Slogwang dev_err(enic, "error in stopping rq %d\n", queue_idx); 253*a9643ea8Slogwang 254*a9643ea8Slogwang return ret; 255*a9643ea8Slogwang } 256*a9643ea8Slogwang 257*a9643ea8Slogwang static void enicpmd_dev_rx_queue_release(void *rxq) 258*a9643ea8Slogwang { 259*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 260*a9643ea8Slogwang enic_free_rq(rxq); 261*a9643ea8Slogwang } 262*a9643ea8Slogwang 263*a9643ea8Slogwang static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 264*a9643ea8Slogwang uint16_t queue_idx, 265*a9643ea8Slogwang uint16_t nb_desc, 266*a9643ea8Slogwang unsigned int socket_id, 267*a9643ea8Slogwang const struct rte_eth_rxconf *rx_conf, 268*a9643ea8Slogwang struct rte_mempool *mp) 269*a9643ea8Slogwang { 270*a9643ea8Slogwang int ret; 271*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 272*a9643ea8Slogwang 273*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 274*a9643ea8Slogwang /* With Rx scatter support, two RQs are now used on VIC per RQ used 275*a9643ea8Slogwang * by the application. 276*a9643ea8Slogwang */ 277*a9643ea8Slogwang if (queue_idx * 2 >= ENIC_RQ_MAX) { 278*a9643ea8Slogwang dev_err(enic, 279*a9643ea8Slogwang "Max number of RX queues exceeded. Max is %d. This PMD uses 2 RQs on VIC per RQ used by DPDK.\n", 280*a9643ea8Slogwang ENIC_RQ_MAX); 281*a9643ea8Slogwang return -EINVAL; 282*a9643ea8Slogwang } 283*a9643ea8Slogwang 284*a9643ea8Slogwang eth_dev->data->rx_queues[queue_idx] = 285*a9643ea8Slogwang (void *)&enic->rq[enic_sop_rq(queue_idx)]; 286*a9643ea8Slogwang 287*a9643ea8Slogwang ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc, 288*a9643ea8Slogwang rx_conf->rx_free_thresh); 289*a9643ea8Slogwang if (ret) { 290*a9643ea8Slogwang dev_err(enic, "error in allocating rq\n"); 291*a9643ea8Slogwang return ret; 292*a9643ea8Slogwang } 293*a9643ea8Slogwang 294*a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 295*a9643ea8Slogwang } 296*a9643ea8Slogwang 297*a9643ea8Slogwang static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev, 298*a9643ea8Slogwang uint16_t vlan_id, int on) 299*a9643ea8Slogwang { 300*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 301*a9643ea8Slogwang int err; 302*a9643ea8Slogwang 303*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 304*a9643ea8Slogwang if (on) 305*a9643ea8Slogwang err = enic_add_vlan(enic, vlan_id); 306*a9643ea8Slogwang else 307*a9643ea8Slogwang err = enic_del_vlan(enic, vlan_id); 308*a9643ea8Slogwang return err; 309*a9643ea8Slogwang } 310*a9643ea8Slogwang 311*a9643ea8Slogwang static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 312*a9643ea8Slogwang { 313*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 314*a9643ea8Slogwang 315*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 316*a9643ea8Slogwang 317*a9643ea8Slogwang if (mask & ETH_VLAN_STRIP_MASK) { 318*a9643ea8Slogwang if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) 319*a9643ea8Slogwang enic->ig_vlan_strip_en = 1; 320*a9643ea8Slogwang else 321*a9643ea8Slogwang enic->ig_vlan_strip_en = 0; 322*a9643ea8Slogwang } 323*a9643ea8Slogwang enic_set_rss_nic_cfg(enic); 324*a9643ea8Slogwang 325*a9643ea8Slogwang 326*a9643ea8Slogwang if (mask & ETH_VLAN_FILTER_MASK) { 327*a9643ea8Slogwang dev_warning(enic, 328*a9643ea8Slogwang "Configuration of VLAN filter is not supported\n"); 329*a9643ea8Slogwang } 330*a9643ea8Slogwang 331*a9643ea8Slogwang if (mask & ETH_VLAN_EXTEND_MASK) { 332*a9643ea8Slogwang dev_warning(enic, 333*a9643ea8Slogwang "Configuration of extended VLAN is not supported\n"); 334*a9643ea8Slogwang } 335*a9643ea8Slogwang } 336*a9643ea8Slogwang 337*a9643ea8Slogwang static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev) 338*a9643ea8Slogwang { 339*a9643ea8Slogwang int ret; 340*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 341*a9643ea8Slogwang 342*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 343*a9643ea8Slogwang ret = enic_set_vnic_res(enic); 344*a9643ea8Slogwang if (ret) { 345*a9643ea8Slogwang dev_err(enic, "Set vNIC resource num failed, aborting\n"); 346*a9643ea8Slogwang return ret; 347*a9643ea8Slogwang } 348*a9643ea8Slogwang 349*a9643ea8Slogwang if (eth_dev->data->dev_conf.rxmode.split_hdr_size && 350*a9643ea8Slogwang eth_dev->data->dev_conf.rxmode.header_split) { 351*a9643ea8Slogwang /* Enable header-data-split */ 352*a9643ea8Slogwang enic_set_hdr_split_size(enic, 353*a9643ea8Slogwang eth_dev->data->dev_conf.rxmode.split_hdr_size); 354*a9643ea8Slogwang } 355*a9643ea8Slogwang 356*a9643ea8Slogwang enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK); 357*a9643ea8Slogwang enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum; 358*a9643ea8Slogwang return 0; 359*a9643ea8Slogwang } 360*a9643ea8Slogwang 361*a9643ea8Slogwang /* Start the device. 362*a9643ea8Slogwang * It returns 0 on success. 363*a9643ea8Slogwang */ 364*a9643ea8Slogwang static int enicpmd_dev_start(struct rte_eth_dev *eth_dev) 365*a9643ea8Slogwang { 366*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 367*a9643ea8Slogwang 368*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 369*a9643ea8Slogwang return enic_enable(enic); 370*a9643ea8Slogwang } 371*a9643ea8Slogwang 372*a9643ea8Slogwang /* 373*a9643ea8Slogwang * Stop device: disable rx and tx functions to allow for reconfiguring. 374*a9643ea8Slogwang */ 375*a9643ea8Slogwang static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev) 376*a9643ea8Slogwang { 377*a9643ea8Slogwang struct rte_eth_link link; 378*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 379*a9643ea8Slogwang 380*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 381*a9643ea8Slogwang enic_disable(enic); 382*a9643ea8Slogwang memset(&link, 0, sizeof(link)); 383*a9643ea8Slogwang rte_atomic64_cmpset((uint64_t *)ð_dev->data->dev_link, 384*a9643ea8Slogwang *(uint64_t *)ð_dev->data->dev_link, 385*a9643ea8Slogwang *(uint64_t *)&link); 386*a9643ea8Slogwang } 387*a9643ea8Slogwang 388*a9643ea8Slogwang /* 389*a9643ea8Slogwang * Stop device. 390*a9643ea8Slogwang */ 391*a9643ea8Slogwang static void enicpmd_dev_close(struct rte_eth_dev *eth_dev) 392*a9643ea8Slogwang { 393*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 394*a9643ea8Slogwang 395*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 396*a9643ea8Slogwang enic_remove(enic); 397*a9643ea8Slogwang } 398*a9643ea8Slogwang 399*a9643ea8Slogwang static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev, 400*a9643ea8Slogwang __rte_unused int wait_to_complete) 401*a9643ea8Slogwang { 402*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 403*a9643ea8Slogwang int ret; 404*a9643ea8Slogwang int link_status = 0; 405*a9643ea8Slogwang 406*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 407*a9643ea8Slogwang link_status = enic_get_link_status(enic); 408*a9643ea8Slogwang ret = (link_status == enic->link_status); 409*a9643ea8Slogwang enic->link_status = link_status; 410*a9643ea8Slogwang eth_dev->data->dev_link.link_status = link_status; 411*a9643ea8Slogwang eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; 412*a9643ea8Slogwang eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev); 413*a9643ea8Slogwang return ret; 414*a9643ea8Slogwang } 415*a9643ea8Slogwang 416*a9643ea8Slogwang static void enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev, 417*a9643ea8Slogwang struct rte_eth_stats *stats) 418*a9643ea8Slogwang { 419*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 420*a9643ea8Slogwang 421*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 422*a9643ea8Slogwang enic_dev_stats_get(enic, stats); 423*a9643ea8Slogwang } 424*a9643ea8Slogwang 425*a9643ea8Slogwang static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev) 426*a9643ea8Slogwang { 427*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 428*a9643ea8Slogwang 429*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 430*a9643ea8Slogwang enic_dev_stats_clear(enic); 431*a9643ea8Slogwang } 432*a9643ea8Slogwang 433*a9643ea8Slogwang static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, 434*a9643ea8Slogwang struct rte_eth_dev_info *device_info) 435*a9643ea8Slogwang { 436*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 437*a9643ea8Slogwang 438*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 439*a9643ea8Slogwang /* Scattered Rx uses two receive queues per rx queue exposed to dpdk */ 440*a9643ea8Slogwang device_info->max_rx_queues = enic->conf_rq_count / 2; 441*a9643ea8Slogwang device_info->max_tx_queues = enic->conf_wq_count; 442*a9643ea8Slogwang device_info->min_rx_bufsize = ENIC_MIN_MTU; 443*a9643ea8Slogwang device_info->max_rx_pktlen = enic->max_mtu + ETHER_HDR_LEN + 4; 444*a9643ea8Slogwang device_info->max_mac_addrs = 1; 445*a9643ea8Slogwang device_info->rx_offload_capa = 446*a9643ea8Slogwang DEV_RX_OFFLOAD_VLAN_STRIP | 447*a9643ea8Slogwang DEV_RX_OFFLOAD_IPV4_CKSUM | 448*a9643ea8Slogwang DEV_RX_OFFLOAD_UDP_CKSUM | 449*a9643ea8Slogwang DEV_RX_OFFLOAD_TCP_CKSUM; 450*a9643ea8Slogwang device_info->tx_offload_capa = 451*a9643ea8Slogwang DEV_TX_OFFLOAD_VLAN_INSERT | 452*a9643ea8Slogwang DEV_TX_OFFLOAD_IPV4_CKSUM | 453*a9643ea8Slogwang DEV_TX_OFFLOAD_UDP_CKSUM | 454*a9643ea8Slogwang DEV_TX_OFFLOAD_TCP_CKSUM; 455*a9643ea8Slogwang device_info->default_rxconf = (struct rte_eth_rxconf) { 456*a9643ea8Slogwang .rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH 457*a9643ea8Slogwang }; 458*a9643ea8Slogwang } 459*a9643ea8Slogwang 460*a9643ea8Slogwang static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev) 461*a9643ea8Slogwang { 462*a9643ea8Slogwang static const uint32_t ptypes[] = { 463*a9643ea8Slogwang RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 464*a9643ea8Slogwang RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 465*a9643ea8Slogwang RTE_PTYPE_L4_TCP, 466*a9643ea8Slogwang RTE_PTYPE_L4_UDP, 467*a9643ea8Slogwang RTE_PTYPE_L4_FRAG, 468*a9643ea8Slogwang RTE_PTYPE_L4_NONFRAG, 469*a9643ea8Slogwang RTE_PTYPE_UNKNOWN 470*a9643ea8Slogwang }; 471*a9643ea8Slogwang 472*a9643ea8Slogwang if (dev->rx_pkt_burst == enic_recv_pkts) 473*a9643ea8Slogwang return ptypes; 474*a9643ea8Slogwang return NULL; 475*a9643ea8Slogwang } 476*a9643ea8Slogwang 477*a9643ea8Slogwang static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 478*a9643ea8Slogwang { 479*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 480*a9643ea8Slogwang 481*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 482*a9643ea8Slogwang enic->promisc = 1; 483*a9643ea8Slogwang enic_add_packet_filter(enic); 484*a9643ea8Slogwang } 485*a9643ea8Slogwang 486*a9643ea8Slogwang static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 487*a9643ea8Slogwang { 488*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 489*a9643ea8Slogwang 490*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 491*a9643ea8Slogwang enic->promisc = 0; 492*a9643ea8Slogwang enic_add_packet_filter(enic); 493*a9643ea8Slogwang } 494*a9643ea8Slogwang 495*a9643ea8Slogwang static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 496*a9643ea8Slogwang { 497*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 498*a9643ea8Slogwang 499*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 500*a9643ea8Slogwang enic->allmulti = 1; 501*a9643ea8Slogwang enic_add_packet_filter(enic); 502*a9643ea8Slogwang } 503*a9643ea8Slogwang 504*a9643ea8Slogwang static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 505*a9643ea8Slogwang { 506*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 507*a9643ea8Slogwang 508*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 509*a9643ea8Slogwang enic->allmulti = 0; 510*a9643ea8Slogwang enic_add_packet_filter(enic); 511*a9643ea8Slogwang } 512*a9643ea8Slogwang 513*a9643ea8Slogwang static void enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev, 514*a9643ea8Slogwang struct ether_addr *mac_addr, 515*a9643ea8Slogwang __rte_unused uint32_t index, __rte_unused uint32_t pool) 516*a9643ea8Slogwang { 517*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 518*a9643ea8Slogwang 519*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 520*a9643ea8Slogwang enic_set_mac_address(enic, mac_addr->addr_bytes); 521*a9643ea8Slogwang } 522*a9643ea8Slogwang 523*a9643ea8Slogwang static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, __rte_unused uint32_t index) 524*a9643ea8Slogwang { 525*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 526*a9643ea8Slogwang 527*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 528*a9643ea8Slogwang enic_del_mac_address(enic); 529*a9643ea8Slogwang } 530*a9643ea8Slogwang 531*a9643ea8Slogwang static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) 532*a9643ea8Slogwang { 533*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 534*a9643ea8Slogwang 535*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 536*a9643ea8Slogwang return enic_set_mtu(enic, mtu); 537*a9643ea8Slogwang } 538*a9643ea8Slogwang 539*a9643ea8Slogwang static const struct eth_dev_ops enicpmd_eth_dev_ops = { 540*a9643ea8Slogwang .dev_configure = enicpmd_dev_configure, 541*a9643ea8Slogwang .dev_start = enicpmd_dev_start, 542*a9643ea8Slogwang .dev_stop = enicpmd_dev_stop, 543*a9643ea8Slogwang .dev_set_link_up = NULL, 544*a9643ea8Slogwang .dev_set_link_down = NULL, 545*a9643ea8Slogwang .dev_close = enicpmd_dev_close, 546*a9643ea8Slogwang .promiscuous_enable = enicpmd_dev_promiscuous_enable, 547*a9643ea8Slogwang .promiscuous_disable = enicpmd_dev_promiscuous_disable, 548*a9643ea8Slogwang .allmulticast_enable = enicpmd_dev_allmulticast_enable, 549*a9643ea8Slogwang .allmulticast_disable = enicpmd_dev_allmulticast_disable, 550*a9643ea8Slogwang .link_update = enicpmd_dev_link_update, 551*a9643ea8Slogwang .stats_get = enicpmd_dev_stats_get, 552*a9643ea8Slogwang .stats_reset = enicpmd_dev_stats_reset, 553*a9643ea8Slogwang .queue_stats_mapping_set = NULL, 554*a9643ea8Slogwang .dev_infos_get = enicpmd_dev_info_get, 555*a9643ea8Slogwang .dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get, 556*a9643ea8Slogwang .mtu_set = enicpmd_mtu_set, 557*a9643ea8Slogwang .vlan_filter_set = enicpmd_vlan_filter_set, 558*a9643ea8Slogwang .vlan_tpid_set = NULL, 559*a9643ea8Slogwang .vlan_offload_set = enicpmd_vlan_offload_set, 560*a9643ea8Slogwang .vlan_strip_queue_set = NULL, 561*a9643ea8Slogwang .rx_queue_start = enicpmd_dev_rx_queue_start, 562*a9643ea8Slogwang .rx_queue_stop = enicpmd_dev_rx_queue_stop, 563*a9643ea8Slogwang .tx_queue_start = enicpmd_dev_tx_queue_start, 564*a9643ea8Slogwang .tx_queue_stop = enicpmd_dev_tx_queue_stop, 565*a9643ea8Slogwang .rx_queue_setup = enicpmd_dev_rx_queue_setup, 566*a9643ea8Slogwang .rx_queue_release = enicpmd_dev_rx_queue_release, 567*a9643ea8Slogwang .rx_queue_count = NULL, 568*a9643ea8Slogwang .rx_descriptor_done = NULL, 569*a9643ea8Slogwang .tx_queue_setup = enicpmd_dev_tx_queue_setup, 570*a9643ea8Slogwang .tx_queue_release = enicpmd_dev_tx_queue_release, 571*a9643ea8Slogwang .dev_led_on = NULL, 572*a9643ea8Slogwang .dev_led_off = NULL, 573*a9643ea8Slogwang .flow_ctrl_get = NULL, 574*a9643ea8Slogwang .flow_ctrl_set = NULL, 575*a9643ea8Slogwang .priority_flow_ctrl_set = NULL, 576*a9643ea8Slogwang .mac_addr_add = enicpmd_add_mac_addr, 577*a9643ea8Slogwang .mac_addr_remove = enicpmd_remove_mac_addr, 578*a9643ea8Slogwang .filter_ctrl = enicpmd_dev_filter_ctrl, 579*a9643ea8Slogwang }; 580*a9643ea8Slogwang 581*a9643ea8Slogwang struct enic *enicpmd_list_head = NULL; 582*a9643ea8Slogwang /* Initialize the driver 583*a9643ea8Slogwang * It returns 0 on success. 584*a9643ea8Slogwang */ 585*a9643ea8Slogwang static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev) 586*a9643ea8Slogwang { 587*a9643ea8Slogwang struct rte_pci_device *pdev; 588*a9643ea8Slogwang struct rte_pci_addr *addr; 589*a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 590*a9643ea8Slogwang 591*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 592*a9643ea8Slogwang 593*a9643ea8Slogwang enic->port_id = eth_dev->data->port_id; 594*a9643ea8Slogwang enic->rte_dev = eth_dev; 595*a9643ea8Slogwang eth_dev->dev_ops = &enicpmd_eth_dev_ops; 596*a9643ea8Slogwang eth_dev->rx_pkt_burst = &enic_recv_pkts; 597*a9643ea8Slogwang eth_dev->tx_pkt_burst = &enic_xmit_pkts; 598*a9643ea8Slogwang 599*a9643ea8Slogwang pdev = eth_dev->pci_dev; 600*a9643ea8Slogwang rte_eth_copy_pci_info(eth_dev, pdev); 601*a9643ea8Slogwang enic->pdev = pdev; 602*a9643ea8Slogwang addr = &pdev->addr; 603*a9643ea8Slogwang 604*a9643ea8Slogwang snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x", 605*a9643ea8Slogwang addr->domain, addr->bus, addr->devid, addr->function); 606*a9643ea8Slogwang 607*a9643ea8Slogwang return enic_probe(enic); 608*a9643ea8Slogwang } 609*a9643ea8Slogwang 610*a9643ea8Slogwang static struct eth_driver rte_enic_pmd = { 611*a9643ea8Slogwang .pci_drv = { 612*a9643ea8Slogwang .name = "rte_enic_pmd", 613*a9643ea8Slogwang .id_table = pci_id_enic_map, 614*a9643ea8Slogwang .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 615*a9643ea8Slogwang }, 616*a9643ea8Slogwang .eth_dev_init = eth_enicpmd_dev_init, 617*a9643ea8Slogwang .dev_private_size = sizeof(struct enic), 618*a9643ea8Slogwang }; 619*a9643ea8Slogwang 620*a9643ea8Slogwang /* Driver initialization routine. 621*a9643ea8Slogwang * Invoked once at EAL init time. 622*a9643ea8Slogwang * Register as the [Poll Mode] Driver of Cisco ENIC device. 623*a9643ea8Slogwang */ 624*a9643ea8Slogwang static int 625*a9643ea8Slogwang rte_enic_pmd_init(__rte_unused const char *name, 626*a9643ea8Slogwang __rte_unused const char *params) 627*a9643ea8Slogwang { 628*a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 629*a9643ea8Slogwang 630*a9643ea8Slogwang rte_eth_driver_register(&rte_enic_pmd); 631*a9643ea8Slogwang return 0; 632*a9643ea8Slogwang } 633*a9643ea8Slogwang 634*a9643ea8Slogwang static struct rte_driver rte_enic_driver = { 635*a9643ea8Slogwang .type = PMD_PDEV, 636*a9643ea8Slogwang .init = rte_enic_pmd_init, 637*a9643ea8Slogwang }; 638*a9643ea8Slogwang 639*a9643ea8Slogwang PMD_REGISTER_DRIVER(rte_enic_driver, enic); 640*a9643ea8Slogwang DRIVER_REGISTER_PCI_TABLE(enic, pci_id_enic_map); 641