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> 40*2bfe3f2eSlogwang #include <rte_bus_pci.h> 41a9643ea8Slogwang #include <rte_ethdev.h> 42*2bfe3f2eSlogwang #include <rte_ethdev_pci.h> 43a9643ea8Slogwang #include <rte_string_fns.h> 44a9643ea8Slogwang 45a9643ea8Slogwang #include "vnic_intr.h" 46a9643ea8Slogwang #include "vnic_cq.h" 47a9643ea8Slogwang #include "vnic_wq.h" 48a9643ea8Slogwang #include "vnic_rq.h" 49a9643ea8Slogwang #include "vnic_enet.h" 50a9643ea8Slogwang #include "enic.h" 51a9643ea8Slogwang 52a9643ea8Slogwang #ifdef RTE_LIBRTE_ENIC_DEBUG 53a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() \ 54a9643ea8Slogwang RTE_LOG(DEBUG, PMD, "ENICPMD trace: %s\n", __func__) 55a9643ea8Slogwang #else 56a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() (void)0 57a9643ea8Slogwang #endif 58a9643ea8Slogwang 59a9643ea8Slogwang /* 60a9643ea8Slogwang * The set of PCI devices this driver supports 61a9643ea8Slogwang */ 62a9643ea8Slogwang #define CISCO_PCI_VENDOR_ID 0x1137 63a9643ea8Slogwang static const struct rte_pci_id pci_id_enic_map[] = { 64a9643ea8Slogwang { RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET) }, 65a9643ea8Slogwang { RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) }, 66a9643ea8Slogwang {.vendor_id = 0, /* sentinel */}, 67a9643ea8Slogwang }; 68a9643ea8Slogwang 69a9643ea8Slogwang static int 70a9643ea8Slogwang enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev, 71a9643ea8Slogwang enum rte_filter_op filter_op, void *arg) 72a9643ea8Slogwang { 73a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 74a9643ea8Slogwang int ret = 0; 75a9643ea8Slogwang 76a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 77a9643ea8Slogwang if (filter_op == RTE_ETH_FILTER_NOP) 78a9643ea8Slogwang return 0; 79a9643ea8Slogwang 80a9643ea8Slogwang if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) 81a9643ea8Slogwang return -EINVAL; 82a9643ea8Slogwang 83a9643ea8Slogwang switch (filter_op) { 84a9643ea8Slogwang case RTE_ETH_FILTER_ADD: 85a9643ea8Slogwang case RTE_ETH_FILTER_UPDATE: 86a9643ea8Slogwang ret = enic_fdir_add_fltr(enic, 87a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 88a9643ea8Slogwang break; 89a9643ea8Slogwang 90a9643ea8Slogwang case RTE_ETH_FILTER_DELETE: 91a9643ea8Slogwang ret = enic_fdir_del_fltr(enic, 92a9643ea8Slogwang (struct rte_eth_fdir_filter *)arg); 93a9643ea8Slogwang break; 94a9643ea8Slogwang 95a9643ea8Slogwang case RTE_ETH_FILTER_STATS: 96a9643ea8Slogwang enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg); 97a9643ea8Slogwang break; 98a9643ea8Slogwang 99a9643ea8Slogwang case RTE_ETH_FILTER_FLUSH: 100a9643ea8Slogwang dev_warning(enic, "unsupported operation %u", filter_op); 101a9643ea8Slogwang ret = -ENOTSUP; 102a9643ea8Slogwang break; 103*2bfe3f2eSlogwang case RTE_ETH_FILTER_INFO: 104*2bfe3f2eSlogwang enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg); 105*2bfe3f2eSlogwang break; 106a9643ea8Slogwang default: 107a9643ea8Slogwang dev_err(enic, "unknown operation %u", filter_op); 108a9643ea8Slogwang ret = -EINVAL; 109a9643ea8Slogwang break; 110a9643ea8Slogwang } 111a9643ea8Slogwang return ret; 112a9643ea8Slogwang } 113a9643ea8Slogwang 114a9643ea8Slogwang static int 115a9643ea8Slogwang enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev, 116a9643ea8Slogwang enum rte_filter_type filter_type, 117a9643ea8Slogwang enum rte_filter_op filter_op, 118a9643ea8Slogwang void *arg) 119a9643ea8Slogwang { 120*2bfe3f2eSlogwang int ret = 0; 121a9643ea8Slogwang 122*2bfe3f2eSlogwang ENICPMD_FUNC_TRACE(); 123*2bfe3f2eSlogwang 124*2bfe3f2eSlogwang switch (filter_type) { 125*2bfe3f2eSlogwang case RTE_ETH_FILTER_GENERIC: 126*2bfe3f2eSlogwang if (filter_op != RTE_ETH_FILTER_GET) 127*2bfe3f2eSlogwang return -EINVAL; 128*2bfe3f2eSlogwang *(const void **)arg = &enic_flow_ops; 129*2bfe3f2eSlogwang break; 130*2bfe3f2eSlogwang case RTE_ETH_FILTER_FDIR: 131a9643ea8Slogwang ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg); 132*2bfe3f2eSlogwang break; 133*2bfe3f2eSlogwang default: 134a9643ea8Slogwang dev_warning(enic, "Filter type (%d) not supported", 135a9643ea8Slogwang filter_type); 136*2bfe3f2eSlogwang ret = -EINVAL; 137*2bfe3f2eSlogwang break; 138*2bfe3f2eSlogwang } 139a9643ea8Slogwang 140a9643ea8Slogwang return ret; 141a9643ea8Slogwang } 142a9643ea8Slogwang 143a9643ea8Slogwang static void enicpmd_dev_tx_queue_release(void *txq) 144a9643ea8Slogwang { 145a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 146*2bfe3f2eSlogwang 147*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 148*2bfe3f2eSlogwang return; 149*2bfe3f2eSlogwang 150a9643ea8Slogwang enic_free_wq(txq); 151a9643ea8Slogwang } 152a9643ea8Slogwang 153a9643ea8Slogwang static int enicpmd_dev_setup_intr(struct enic *enic) 154a9643ea8Slogwang { 155a9643ea8Slogwang int ret; 156a9643ea8Slogwang unsigned int index; 157a9643ea8Slogwang 158a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 159a9643ea8Slogwang 160a9643ea8Slogwang /* Are we done with the init of all the queues? */ 161a9643ea8Slogwang for (index = 0; index < enic->cq_count; index++) { 162a9643ea8Slogwang if (!enic->cq[index].ctrl) 163a9643ea8Slogwang break; 164a9643ea8Slogwang } 165a9643ea8Slogwang if (enic->cq_count != index) 166a9643ea8Slogwang return 0; 167a9643ea8Slogwang for (index = 0; index < enic->wq_count; index++) { 168a9643ea8Slogwang if (!enic->wq[index].ctrl) 169a9643ea8Slogwang break; 170a9643ea8Slogwang } 171a9643ea8Slogwang if (enic->wq_count != index) 172a9643ea8Slogwang return 0; 173a9643ea8Slogwang /* check start of packet (SOP) RQs only in case scatter is disabled. */ 174a9643ea8Slogwang for (index = 0; index < enic->rq_count; index++) { 175*2bfe3f2eSlogwang if (!enic->rq[enic_rte_rq_idx_to_sop_idx(index)].ctrl) 176a9643ea8Slogwang break; 177a9643ea8Slogwang } 178a9643ea8Slogwang if (enic->rq_count != index) 179a9643ea8Slogwang return 0; 180a9643ea8Slogwang 181a9643ea8Slogwang ret = enic_alloc_intr_resources(enic); 182a9643ea8Slogwang if (ret) { 183a9643ea8Slogwang dev_err(enic, "alloc intr failed\n"); 184a9643ea8Slogwang return ret; 185a9643ea8Slogwang } 186a9643ea8Slogwang enic_init_vnic_resources(enic); 187a9643ea8Slogwang 188a9643ea8Slogwang ret = enic_setup_finish(enic); 189a9643ea8Slogwang if (ret) 190a9643ea8Slogwang dev_err(enic, "setup could not be finished\n"); 191a9643ea8Slogwang 192a9643ea8Slogwang return ret; 193a9643ea8Slogwang } 194a9643ea8Slogwang 195a9643ea8Slogwang static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 196a9643ea8Slogwang uint16_t queue_idx, 197a9643ea8Slogwang uint16_t nb_desc, 198a9643ea8Slogwang unsigned int socket_id, 199a9643ea8Slogwang __rte_unused const struct rte_eth_txconf *tx_conf) 200a9643ea8Slogwang { 201a9643ea8Slogwang int ret; 202a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 203a9643ea8Slogwang 204*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 205*2bfe3f2eSlogwang return -E_RTE_SECONDARY; 206a9643ea8Slogwang 207*2bfe3f2eSlogwang ENICPMD_FUNC_TRACE(); 208*2bfe3f2eSlogwang RTE_ASSERT(queue_idx < enic->conf_wq_count); 209a9643ea8Slogwang eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx]; 210a9643ea8Slogwang 211a9643ea8Slogwang ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc); 212a9643ea8Slogwang if (ret) { 213a9643ea8Slogwang dev_err(enic, "error in allocating wq\n"); 214a9643ea8Slogwang return ret; 215a9643ea8Slogwang } 216a9643ea8Slogwang 217a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 218a9643ea8Slogwang } 219a9643ea8Slogwang 220a9643ea8Slogwang static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev, 221a9643ea8Slogwang uint16_t queue_idx) 222a9643ea8Slogwang { 223a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 224a9643ea8Slogwang 225a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 226a9643ea8Slogwang 227a9643ea8Slogwang enic_start_wq(enic, queue_idx); 228a9643ea8Slogwang 229a9643ea8Slogwang return 0; 230a9643ea8Slogwang } 231a9643ea8Slogwang 232a9643ea8Slogwang static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, 233a9643ea8Slogwang uint16_t queue_idx) 234a9643ea8Slogwang { 235a9643ea8Slogwang int ret; 236a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 237a9643ea8Slogwang 238a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 239a9643ea8Slogwang 240a9643ea8Slogwang ret = enic_stop_wq(enic, queue_idx); 241a9643ea8Slogwang if (ret) 242a9643ea8Slogwang dev_err(enic, "error in stopping wq %d\n", queue_idx); 243a9643ea8Slogwang 244a9643ea8Slogwang return ret; 245a9643ea8Slogwang } 246a9643ea8Slogwang 247a9643ea8Slogwang static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev, 248a9643ea8Slogwang uint16_t queue_idx) 249a9643ea8Slogwang { 250a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 251a9643ea8Slogwang 252a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 253a9643ea8Slogwang 254a9643ea8Slogwang enic_start_rq(enic, queue_idx); 255a9643ea8Slogwang 256a9643ea8Slogwang return 0; 257a9643ea8Slogwang } 258a9643ea8Slogwang 259a9643ea8Slogwang static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, 260a9643ea8Slogwang uint16_t queue_idx) 261a9643ea8Slogwang { 262a9643ea8Slogwang int ret; 263a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 264a9643ea8Slogwang 265a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 266a9643ea8Slogwang 267a9643ea8Slogwang ret = enic_stop_rq(enic, queue_idx); 268a9643ea8Slogwang if (ret) 269a9643ea8Slogwang dev_err(enic, "error in stopping rq %d\n", queue_idx); 270a9643ea8Slogwang 271a9643ea8Slogwang return ret; 272a9643ea8Slogwang } 273a9643ea8Slogwang 274a9643ea8Slogwang static void enicpmd_dev_rx_queue_release(void *rxq) 275a9643ea8Slogwang { 276a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 277*2bfe3f2eSlogwang 278*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 279*2bfe3f2eSlogwang return; 280*2bfe3f2eSlogwang 281a9643ea8Slogwang enic_free_rq(rxq); 282a9643ea8Slogwang } 283a9643ea8Slogwang 284*2bfe3f2eSlogwang static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev, 285*2bfe3f2eSlogwang uint16_t rx_queue_id) 286*2bfe3f2eSlogwang { 287*2bfe3f2eSlogwang struct enic *enic = pmd_priv(dev); 288*2bfe3f2eSlogwang uint32_t queue_count = 0; 289*2bfe3f2eSlogwang struct vnic_cq *cq; 290*2bfe3f2eSlogwang uint32_t cq_tail; 291*2bfe3f2eSlogwang uint16_t cq_idx; 292*2bfe3f2eSlogwang int rq_num; 293*2bfe3f2eSlogwang 294*2bfe3f2eSlogwang rq_num = enic_rte_rq_idx_to_sop_idx(rx_queue_id); 295*2bfe3f2eSlogwang cq = &enic->cq[enic_cq_rq(enic, rq_num)]; 296*2bfe3f2eSlogwang cq_idx = cq->to_clean; 297*2bfe3f2eSlogwang 298*2bfe3f2eSlogwang cq_tail = ioread32(&cq->ctrl->cq_tail); 299*2bfe3f2eSlogwang 300*2bfe3f2eSlogwang if (cq_tail < cq_idx) 301*2bfe3f2eSlogwang cq_tail += cq->ring.desc_count; 302*2bfe3f2eSlogwang 303*2bfe3f2eSlogwang queue_count = cq_tail - cq_idx; 304*2bfe3f2eSlogwang 305*2bfe3f2eSlogwang return queue_count; 306*2bfe3f2eSlogwang } 307*2bfe3f2eSlogwang 308a9643ea8Slogwang static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 309a9643ea8Slogwang uint16_t queue_idx, 310a9643ea8Slogwang uint16_t nb_desc, 311a9643ea8Slogwang unsigned int socket_id, 312a9643ea8Slogwang const struct rte_eth_rxconf *rx_conf, 313a9643ea8Slogwang struct rte_mempool *mp) 314a9643ea8Slogwang { 315a9643ea8Slogwang int ret; 316a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 317a9643ea8Slogwang 318a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 319a9643ea8Slogwang 320*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 321*2bfe3f2eSlogwang return -E_RTE_SECONDARY; 322*2bfe3f2eSlogwang RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(queue_idx) < enic->conf_rq_count); 323a9643ea8Slogwang eth_dev->data->rx_queues[queue_idx] = 324*2bfe3f2eSlogwang (void *)&enic->rq[enic_rte_rq_idx_to_sop_idx(queue_idx)]; 325a9643ea8Slogwang 326a9643ea8Slogwang ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc, 327a9643ea8Slogwang rx_conf->rx_free_thresh); 328a9643ea8Slogwang if (ret) { 329a9643ea8Slogwang dev_err(enic, "error in allocating rq\n"); 330a9643ea8Slogwang return ret; 331a9643ea8Slogwang } 332a9643ea8Slogwang 333a9643ea8Slogwang return enicpmd_dev_setup_intr(enic); 334a9643ea8Slogwang } 335a9643ea8Slogwang 336a9643ea8Slogwang static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev, 337a9643ea8Slogwang uint16_t vlan_id, int on) 338a9643ea8Slogwang { 339a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 340a9643ea8Slogwang int err; 341a9643ea8Slogwang 342a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 343a9643ea8Slogwang if (on) 344a9643ea8Slogwang err = enic_add_vlan(enic, vlan_id); 345a9643ea8Slogwang else 346a9643ea8Slogwang err = enic_del_vlan(enic, vlan_id); 347a9643ea8Slogwang return err; 348a9643ea8Slogwang } 349a9643ea8Slogwang 350*2bfe3f2eSlogwang static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 351a9643ea8Slogwang { 352a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 353a9643ea8Slogwang 354a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 355a9643ea8Slogwang 356a9643ea8Slogwang if (mask & ETH_VLAN_STRIP_MASK) { 357a9643ea8Slogwang if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) 358a9643ea8Slogwang enic->ig_vlan_strip_en = 1; 359a9643ea8Slogwang else 360a9643ea8Slogwang enic->ig_vlan_strip_en = 0; 361a9643ea8Slogwang } 362a9643ea8Slogwang enic_set_rss_nic_cfg(enic); 363a9643ea8Slogwang 364a9643ea8Slogwang 365a9643ea8Slogwang if (mask & ETH_VLAN_FILTER_MASK) { 366a9643ea8Slogwang dev_warning(enic, 367a9643ea8Slogwang "Configuration of VLAN filter is not supported\n"); 368a9643ea8Slogwang } 369a9643ea8Slogwang 370a9643ea8Slogwang if (mask & ETH_VLAN_EXTEND_MASK) { 371a9643ea8Slogwang dev_warning(enic, 372a9643ea8Slogwang "Configuration of extended VLAN is not supported\n"); 373a9643ea8Slogwang } 374*2bfe3f2eSlogwang 375*2bfe3f2eSlogwang return 0; 376a9643ea8Slogwang } 377a9643ea8Slogwang 378a9643ea8Slogwang static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev) 379a9643ea8Slogwang { 380a9643ea8Slogwang int ret; 381a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 382a9643ea8Slogwang 383*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 384*2bfe3f2eSlogwang return -E_RTE_SECONDARY; 385*2bfe3f2eSlogwang 386a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 387a9643ea8Slogwang ret = enic_set_vnic_res(enic); 388a9643ea8Slogwang if (ret) { 389a9643ea8Slogwang dev_err(enic, "Set vNIC resource num failed, aborting\n"); 390a9643ea8Slogwang return ret; 391a9643ea8Slogwang } 392a9643ea8Slogwang 393a9643ea8Slogwang if (eth_dev->data->dev_conf.rxmode.split_hdr_size && 394a9643ea8Slogwang eth_dev->data->dev_conf.rxmode.header_split) { 395a9643ea8Slogwang /* Enable header-data-split */ 396a9643ea8Slogwang enic_set_hdr_split_size(enic, 397a9643ea8Slogwang eth_dev->data->dev_conf.rxmode.split_hdr_size); 398a9643ea8Slogwang } 399a9643ea8Slogwang 400a9643ea8Slogwang enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum; 401*2bfe3f2eSlogwang ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK); 402*2bfe3f2eSlogwang 403*2bfe3f2eSlogwang return ret; 404a9643ea8Slogwang } 405a9643ea8Slogwang 406a9643ea8Slogwang /* Start the device. 407a9643ea8Slogwang * It returns 0 on success. 408a9643ea8Slogwang */ 409a9643ea8Slogwang static int enicpmd_dev_start(struct rte_eth_dev *eth_dev) 410a9643ea8Slogwang { 411a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 412a9643ea8Slogwang 413*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 414*2bfe3f2eSlogwang return -E_RTE_SECONDARY; 415*2bfe3f2eSlogwang 416a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 417a9643ea8Slogwang return enic_enable(enic); 418a9643ea8Slogwang } 419a9643ea8Slogwang 420a9643ea8Slogwang /* 421a9643ea8Slogwang * Stop device: disable rx and tx functions to allow for reconfiguring. 422a9643ea8Slogwang */ 423a9643ea8Slogwang static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev) 424a9643ea8Slogwang { 425a9643ea8Slogwang struct rte_eth_link link; 426a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 427a9643ea8Slogwang 428*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 429*2bfe3f2eSlogwang return; 430*2bfe3f2eSlogwang 431a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 432a9643ea8Slogwang enic_disable(enic); 433a9643ea8Slogwang memset(&link, 0, sizeof(link)); 434a9643ea8Slogwang rte_atomic64_cmpset((uint64_t *)ð_dev->data->dev_link, 435a9643ea8Slogwang *(uint64_t *)ð_dev->data->dev_link, 436a9643ea8Slogwang *(uint64_t *)&link); 437a9643ea8Slogwang } 438a9643ea8Slogwang 439a9643ea8Slogwang /* 440a9643ea8Slogwang * Stop device. 441a9643ea8Slogwang */ 442a9643ea8Slogwang static void enicpmd_dev_close(struct rte_eth_dev *eth_dev) 443a9643ea8Slogwang { 444a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 445a9643ea8Slogwang 446a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 447a9643ea8Slogwang enic_remove(enic); 448a9643ea8Slogwang } 449a9643ea8Slogwang 450a9643ea8Slogwang static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev, 451a9643ea8Slogwang __rte_unused int wait_to_complete) 452a9643ea8Slogwang { 453a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 454a9643ea8Slogwang 455a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 456*2bfe3f2eSlogwang return enic_link_update(enic); 457a9643ea8Slogwang } 458a9643ea8Slogwang 459*2bfe3f2eSlogwang static int enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev, 460a9643ea8Slogwang struct rte_eth_stats *stats) 461a9643ea8Slogwang { 462a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 463a9643ea8Slogwang 464a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 465*2bfe3f2eSlogwang return enic_dev_stats_get(enic, stats); 466a9643ea8Slogwang } 467a9643ea8Slogwang 468a9643ea8Slogwang static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev) 469a9643ea8Slogwang { 470a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 471a9643ea8Slogwang 472a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 473a9643ea8Slogwang enic_dev_stats_clear(enic); 474a9643ea8Slogwang } 475a9643ea8Slogwang 476a9643ea8Slogwang static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, 477a9643ea8Slogwang struct rte_eth_dev_info *device_info) 478a9643ea8Slogwang { 479a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 480a9643ea8Slogwang 481a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 482*2bfe3f2eSlogwang device_info->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 483a9643ea8Slogwang /* Scattered Rx uses two receive queues per rx queue exposed to dpdk */ 484a9643ea8Slogwang device_info->max_rx_queues = enic->conf_rq_count / 2; 485a9643ea8Slogwang device_info->max_tx_queues = enic->conf_wq_count; 486a9643ea8Slogwang device_info->min_rx_bufsize = ENIC_MIN_MTU; 487a9643ea8Slogwang device_info->max_rx_pktlen = enic->max_mtu + ETHER_HDR_LEN + 4; 488*2bfe3f2eSlogwang device_info->max_mac_addrs = ENIC_MAX_MAC_ADDR; 489a9643ea8Slogwang device_info->rx_offload_capa = 490a9643ea8Slogwang DEV_RX_OFFLOAD_VLAN_STRIP | 491a9643ea8Slogwang DEV_RX_OFFLOAD_IPV4_CKSUM | 492a9643ea8Slogwang DEV_RX_OFFLOAD_UDP_CKSUM | 493a9643ea8Slogwang DEV_RX_OFFLOAD_TCP_CKSUM; 494a9643ea8Slogwang device_info->tx_offload_capa = 495a9643ea8Slogwang DEV_TX_OFFLOAD_VLAN_INSERT | 496a9643ea8Slogwang DEV_TX_OFFLOAD_IPV4_CKSUM | 497a9643ea8Slogwang DEV_TX_OFFLOAD_UDP_CKSUM | 498*2bfe3f2eSlogwang DEV_TX_OFFLOAD_TCP_CKSUM | 499*2bfe3f2eSlogwang DEV_TX_OFFLOAD_TCP_TSO; 500a9643ea8Slogwang device_info->default_rxconf = (struct rte_eth_rxconf) { 501a9643ea8Slogwang .rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH 502a9643ea8Slogwang }; 503a9643ea8Slogwang } 504a9643ea8Slogwang 505a9643ea8Slogwang static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev) 506a9643ea8Slogwang { 507a9643ea8Slogwang static const uint32_t ptypes[] = { 508*2bfe3f2eSlogwang RTE_PTYPE_L2_ETHER, 509*2bfe3f2eSlogwang RTE_PTYPE_L2_ETHER_VLAN, 510a9643ea8Slogwang RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 511a9643ea8Slogwang RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 512a9643ea8Slogwang RTE_PTYPE_L4_TCP, 513a9643ea8Slogwang RTE_PTYPE_L4_UDP, 514a9643ea8Slogwang RTE_PTYPE_L4_FRAG, 515a9643ea8Slogwang RTE_PTYPE_L4_NONFRAG, 516a9643ea8Slogwang RTE_PTYPE_UNKNOWN 517a9643ea8Slogwang }; 518a9643ea8Slogwang 519a9643ea8Slogwang if (dev->rx_pkt_burst == enic_recv_pkts) 520a9643ea8Slogwang return ptypes; 521a9643ea8Slogwang return NULL; 522a9643ea8Slogwang } 523a9643ea8Slogwang 524a9643ea8Slogwang static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 525a9643ea8Slogwang { 526a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 527a9643ea8Slogwang 528*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 529*2bfe3f2eSlogwang return; 530*2bfe3f2eSlogwang 531a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 532*2bfe3f2eSlogwang 533a9643ea8Slogwang enic->promisc = 1; 534a9643ea8Slogwang enic_add_packet_filter(enic); 535a9643ea8Slogwang } 536a9643ea8Slogwang 537a9643ea8Slogwang static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 538a9643ea8Slogwang { 539a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 540a9643ea8Slogwang 541*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 542*2bfe3f2eSlogwang return; 543*2bfe3f2eSlogwang 544a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 545a9643ea8Slogwang enic->promisc = 0; 546a9643ea8Slogwang enic_add_packet_filter(enic); 547a9643ea8Slogwang } 548a9643ea8Slogwang 549a9643ea8Slogwang static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 550a9643ea8Slogwang { 551a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 552a9643ea8Slogwang 553*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 554*2bfe3f2eSlogwang return; 555*2bfe3f2eSlogwang 556a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 557a9643ea8Slogwang enic->allmulti = 1; 558a9643ea8Slogwang enic_add_packet_filter(enic); 559a9643ea8Slogwang } 560a9643ea8Slogwang 561a9643ea8Slogwang static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 562a9643ea8Slogwang { 563a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 564a9643ea8Slogwang 565*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 566*2bfe3f2eSlogwang return; 567*2bfe3f2eSlogwang 568a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 569a9643ea8Slogwang enic->allmulti = 0; 570a9643ea8Slogwang enic_add_packet_filter(enic); 571a9643ea8Slogwang } 572a9643ea8Slogwang 573*2bfe3f2eSlogwang static int enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev, 574a9643ea8Slogwang struct ether_addr *mac_addr, 575a9643ea8Slogwang __rte_unused uint32_t index, __rte_unused uint32_t pool) 576a9643ea8Slogwang { 577a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 578a9643ea8Slogwang 579*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 580*2bfe3f2eSlogwang return -E_RTE_SECONDARY; 581*2bfe3f2eSlogwang 582a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 583*2bfe3f2eSlogwang return enic_set_mac_address(enic, mac_addr->addr_bytes); 584a9643ea8Slogwang } 585a9643ea8Slogwang 586*2bfe3f2eSlogwang static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, uint32_t index) 587a9643ea8Slogwang { 588a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 589a9643ea8Slogwang 590*2bfe3f2eSlogwang if (rte_eal_process_type() != RTE_PROC_PRIMARY) 591*2bfe3f2eSlogwang return; 592*2bfe3f2eSlogwang 593a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 594*2bfe3f2eSlogwang enic_del_mac_address(enic, index); 595a9643ea8Slogwang } 596a9643ea8Slogwang 597a9643ea8Slogwang static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) 598a9643ea8Slogwang { 599a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 600a9643ea8Slogwang 601a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 602a9643ea8Slogwang return enic_set_mtu(enic, mtu); 603a9643ea8Slogwang } 604a9643ea8Slogwang 605a9643ea8Slogwang static const struct eth_dev_ops enicpmd_eth_dev_ops = { 606a9643ea8Slogwang .dev_configure = enicpmd_dev_configure, 607a9643ea8Slogwang .dev_start = enicpmd_dev_start, 608a9643ea8Slogwang .dev_stop = enicpmd_dev_stop, 609a9643ea8Slogwang .dev_set_link_up = NULL, 610a9643ea8Slogwang .dev_set_link_down = NULL, 611a9643ea8Slogwang .dev_close = enicpmd_dev_close, 612a9643ea8Slogwang .promiscuous_enable = enicpmd_dev_promiscuous_enable, 613a9643ea8Slogwang .promiscuous_disable = enicpmd_dev_promiscuous_disable, 614a9643ea8Slogwang .allmulticast_enable = enicpmd_dev_allmulticast_enable, 615a9643ea8Slogwang .allmulticast_disable = enicpmd_dev_allmulticast_disable, 616a9643ea8Slogwang .link_update = enicpmd_dev_link_update, 617a9643ea8Slogwang .stats_get = enicpmd_dev_stats_get, 618a9643ea8Slogwang .stats_reset = enicpmd_dev_stats_reset, 619a9643ea8Slogwang .queue_stats_mapping_set = NULL, 620a9643ea8Slogwang .dev_infos_get = enicpmd_dev_info_get, 621a9643ea8Slogwang .dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get, 622a9643ea8Slogwang .mtu_set = enicpmd_mtu_set, 623a9643ea8Slogwang .vlan_filter_set = enicpmd_vlan_filter_set, 624a9643ea8Slogwang .vlan_tpid_set = NULL, 625a9643ea8Slogwang .vlan_offload_set = enicpmd_vlan_offload_set, 626a9643ea8Slogwang .vlan_strip_queue_set = NULL, 627a9643ea8Slogwang .rx_queue_start = enicpmd_dev_rx_queue_start, 628a9643ea8Slogwang .rx_queue_stop = enicpmd_dev_rx_queue_stop, 629a9643ea8Slogwang .tx_queue_start = enicpmd_dev_tx_queue_start, 630a9643ea8Slogwang .tx_queue_stop = enicpmd_dev_tx_queue_stop, 631a9643ea8Slogwang .rx_queue_setup = enicpmd_dev_rx_queue_setup, 632a9643ea8Slogwang .rx_queue_release = enicpmd_dev_rx_queue_release, 633*2bfe3f2eSlogwang .rx_queue_count = enicpmd_dev_rx_queue_count, 634a9643ea8Slogwang .rx_descriptor_done = NULL, 635a9643ea8Slogwang .tx_queue_setup = enicpmd_dev_tx_queue_setup, 636a9643ea8Slogwang .tx_queue_release = enicpmd_dev_tx_queue_release, 637a9643ea8Slogwang .dev_led_on = NULL, 638a9643ea8Slogwang .dev_led_off = NULL, 639a9643ea8Slogwang .flow_ctrl_get = NULL, 640a9643ea8Slogwang .flow_ctrl_set = NULL, 641a9643ea8Slogwang .priority_flow_ctrl_set = NULL, 642a9643ea8Slogwang .mac_addr_add = enicpmd_add_mac_addr, 643a9643ea8Slogwang .mac_addr_remove = enicpmd_remove_mac_addr, 644a9643ea8Slogwang .filter_ctrl = enicpmd_dev_filter_ctrl, 645a9643ea8Slogwang }; 646a9643ea8Slogwang 647a9643ea8Slogwang struct enic *enicpmd_list_head = NULL; 648a9643ea8Slogwang /* Initialize the driver 649a9643ea8Slogwang * It returns 0 on success. 650a9643ea8Slogwang */ 651a9643ea8Slogwang static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev) 652a9643ea8Slogwang { 653a9643ea8Slogwang struct rte_pci_device *pdev; 654a9643ea8Slogwang struct rte_pci_addr *addr; 655a9643ea8Slogwang struct enic *enic = pmd_priv(eth_dev); 656a9643ea8Slogwang 657a9643ea8Slogwang ENICPMD_FUNC_TRACE(); 658a9643ea8Slogwang 659a9643ea8Slogwang enic->port_id = eth_dev->data->port_id; 660a9643ea8Slogwang enic->rte_dev = eth_dev; 661a9643ea8Slogwang eth_dev->dev_ops = &enicpmd_eth_dev_ops; 662a9643ea8Slogwang eth_dev->rx_pkt_burst = &enic_recv_pkts; 663a9643ea8Slogwang eth_dev->tx_pkt_burst = &enic_xmit_pkts; 664a9643ea8Slogwang 665*2bfe3f2eSlogwang pdev = RTE_ETH_DEV_TO_PCI(eth_dev); 666a9643ea8Slogwang rte_eth_copy_pci_info(eth_dev, pdev); 667a9643ea8Slogwang enic->pdev = pdev; 668a9643ea8Slogwang addr = &pdev->addr; 669a9643ea8Slogwang 670a9643ea8Slogwang snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x", 671a9643ea8Slogwang addr->domain, addr->bus, addr->devid, addr->function); 672a9643ea8Slogwang 673a9643ea8Slogwang return enic_probe(enic); 674a9643ea8Slogwang } 675a9643ea8Slogwang 676*2bfe3f2eSlogwang static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 677*2bfe3f2eSlogwang struct rte_pci_device *pci_dev) 678a9643ea8Slogwang { 679*2bfe3f2eSlogwang return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct enic), 680*2bfe3f2eSlogwang eth_enicpmd_dev_init); 681a9643ea8Slogwang } 682a9643ea8Slogwang 683*2bfe3f2eSlogwang static int eth_enic_pci_remove(struct rte_pci_device *pci_dev) 684*2bfe3f2eSlogwang { 685*2bfe3f2eSlogwang return rte_eth_dev_pci_generic_remove(pci_dev, NULL); 686*2bfe3f2eSlogwang } 687*2bfe3f2eSlogwang 688*2bfe3f2eSlogwang static struct rte_pci_driver rte_enic_pmd = { 689*2bfe3f2eSlogwang .id_table = pci_id_enic_map, 690*2bfe3f2eSlogwang .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 691*2bfe3f2eSlogwang .probe = eth_enic_pci_probe, 692*2bfe3f2eSlogwang .remove = eth_enic_pci_remove, 693a9643ea8Slogwang }; 694a9643ea8Slogwang 695*2bfe3f2eSlogwang RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd); 696*2bfe3f2eSlogwang RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map); 697*2bfe3f2eSlogwang RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci"); 698