1*36a7a2e7SMaxime Coquelin /* SPDX-License-Identifier: BSD-3-Clause 2*36a7a2e7SMaxime Coquelin * Copyright(c) 2010-2016 Intel Corporation 3*36a7a2e7SMaxime Coquelin */ 4*36a7a2e7SMaxime Coquelin 5*36a7a2e7SMaxime Coquelin #include <stdint.h> 6*36a7a2e7SMaxime Coquelin #include <string.h> 7*36a7a2e7SMaxime Coquelin #include <stdio.h> 8*36a7a2e7SMaxime Coquelin #include <errno.h> 9*36a7a2e7SMaxime Coquelin #include <unistd.h> 10*36a7a2e7SMaxime Coquelin 11*36a7a2e7SMaxime Coquelin #include <ethdev_driver.h> 12*36a7a2e7SMaxime Coquelin #include <ethdev_pci.h> 13*36a7a2e7SMaxime Coquelin #include <rte_pci.h> 14*36a7a2e7SMaxime Coquelin #include <rte_bus_pci.h> 15*36a7a2e7SMaxime Coquelin #include <rte_errno.h> 16*36a7a2e7SMaxime Coquelin 17*36a7a2e7SMaxime Coquelin #include <rte_memory.h> 18*36a7a2e7SMaxime Coquelin #include <rte_eal.h> 19*36a7a2e7SMaxime Coquelin #include <rte_dev.h> 20*36a7a2e7SMaxime Coquelin #include <rte_kvargs.h> 21*36a7a2e7SMaxime Coquelin 22*36a7a2e7SMaxime Coquelin #include "virtio_ethdev.h" 23*36a7a2e7SMaxime Coquelin #include "virtio_pci.h" 24*36a7a2e7SMaxime Coquelin #include "virtio_logs.h" 25*36a7a2e7SMaxime Coquelin 26*36a7a2e7SMaxime Coquelin /* 27*36a7a2e7SMaxime Coquelin * The set of PCI devices this driver supports 28*36a7a2e7SMaxime Coquelin */ 29*36a7a2e7SMaxime Coquelin static const struct rte_pci_id pci_id_virtio_map[] = { 30*36a7a2e7SMaxime Coquelin { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_LEGACY_DEVICEID_NET) }, 31*36a7a2e7SMaxime Coquelin { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_MODERN_DEVICEID_NET) }, 32*36a7a2e7SMaxime Coquelin { .vendor_id = 0, /* sentinel */ }, 33*36a7a2e7SMaxime Coquelin }; 34*36a7a2e7SMaxime Coquelin 35*36a7a2e7SMaxime Coquelin static int 36*36a7a2e7SMaxime Coquelin eth_virtio_pci_init(struct rte_eth_dev *eth_dev) 37*36a7a2e7SMaxime Coquelin { 38*36a7a2e7SMaxime Coquelin return eth_virtio_dev_init(eth_dev); 39*36a7a2e7SMaxime Coquelin } 40*36a7a2e7SMaxime Coquelin 41*36a7a2e7SMaxime Coquelin static int 42*36a7a2e7SMaxime Coquelin eth_virtio_pci_uninit(struct rte_eth_dev *eth_dev) 43*36a7a2e7SMaxime Coquelin { 44*36a7a2e7SMaxime Coquelin int ret; 45*36a7a2e7SMaxime Coquelin PMD_INIT_FUNC_TRACE(); 46*36a7a2e7SMaxime Coquelin 47*36a7a2e7SMaxime Coquelin if (rte_eal_process_type() == RTE_PROC_SECONDARY) 48*36a7a2e7SMaxime Coquelin return 0; 49*36a7a2e7SMaxime Coquelin 50*36a7a2e7SMaxime Coquelin ret = virtio_dev_stop(eth_dev); 51*36a7a2e7SMaxime Coquelin virtio_dev_close(eth_dev); 52*36a7a2e7SMaxime Coquelin 53*36a7a2e7SMaxime Coquelin PMD_INIT_LOG(DEBUG, "dev_uninit completed"); 54*36a7a2e7SMaxime Coquelin 55*36a7a2e7SMaxime Coquelin return ret; 56*36a7a2e7SMaxime Coquelin } 57*36a7a2e7SMaxime Coquelin 58*36a7a2e7SMaxime Coquelin static int vdpa_check_handler(__rte_unused const char *key, 59*36a7a2e7SMaxime Coquelin const char *value, void *ret_val) 60*36a7a2e7SMaxime Coquelin { 61*36a7a2e7SMaxime Coquelin if (strcmp(value, "1") == 0) 62*36a7a2e7SMaxime Coquelin *(int *)ret_val = 1; 63*36a7a2e7SMaxime Coquelin else 64*36a7a2e7SMaxime Coquelin *(int *)ret_val = 0; 65*36a7a2e7SMaxime Coquelin 66*36a7a2e7SMaxime Coquelin return 0; 67*36a7a2e7SMaxime Coquelin } 68*36a7a2e7SMaxime Coquelin 69*36a7a2e7SMaxime Coquelin #define VIRTIO_ARG_VDPA "vdpa" 70*36a7a2e7SMaxime Coquelin 71*36a7a2e7SMaxime Coquelin static int 72*36a7a2e7SMaxime Coquelin virtio_pci_devargs_parse(struct rte_devargs *devargs, int *vdpa) 73*36a7a2e7SMaxime Coquelin { 74*36a7a2e7SMaxime Coquelin struct rte_kvargs *kvlist; 75*36a7a2e7SMaxime Coquelin int ret = 0; 76*36a7a2e7SMaxime Coquelin 77*36a7a2e7SMaxime Coquelin if (devargs == NULL) 78*36a7a2e7SMaxime Coquelin return 0; 79*36a7a2e7SMaxime Coquelin 80*36a7a2e7SMaxime Coquelin kvlist = rte_kvargs_parse(devargs->args, NULL); 81*36a7a2e7SMaxime Coquelin if (kvlist == NULL) { 82*36a7a2e7SMaxime Coquelin PMD_INIT_LOG(ERR, "error when parsing param"); 83*36a7a2e7SMaxime Coquelin return 0; 84*36a7a2e7SMaxime Coquelin } 85*36a7a2e7SMaxime Coquelin 86*36a7a2e7SMaxime Coquelin if (rte_kvargs_count(kvlist, VIRTIO_ARG_VDPA) == 1) { 87*36a7a2e7SMaxime Coquelin /* vdpa mode selected when there's a key-value pair: 88*36a7a2e7SMaxime Coquelin * vdpa=1 89*36a7a2e7SMaxime Coquelin */ 90*36a7a2e7SMaxime Coquelin ret = rte_kvargs_process(kvlist, VIRTIO_ARG_VDPA, 91*36a7a2e7SMaxime Coquelin vdpa_check_handler, vdpa); 92*36a7a2e7SMaxime Coquelin if (ret < 0) 93*36a7a2e7SMaxime Coquelin PMD_INIT_LOG(ERR, "Failed to parse %s", VIRTIO_ARG_VDPA); 94*36a7a2e7SMaxime Coquelin } 95*36a7a2e7SMaxime Coquelin 96*36a7a2e7SMaxime Coquelin rte_kvargs_free(kvlist); 97*36a7a2e7SMaxime Coquelin 98*36a7a2e7SMaxime Coquelin return ret; 99*36a7a2e7SMaxime Coquelin } 100*36a7a2e7SMaxime Coquelin 101*36a7a2e7SMaxime Coquelin static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 102*36a7a2e7SMaxime Coquelin struct rte_pci_device *pci_dev) 103*36a7a2e7SMaxime Coquelin { 104*36a7a2e7SMaxime Coquelin int vdpa = 0; 105*36a7a2e7SMaxime Coquelin int ret = 0; 106*36a7a2e7SMaxime Coquelin 107*36a7a2e7SMaxime Coquelin ret = virtio_pci_devargs_parse(pci_dev->device.devargs, &vdpa); 108*36a7a2e7SMaxime Coquelin if (ret < 0) { 109*36a7a2e7SMaxime Coquelin PMD_INIT_LOG(ERR, "devargs parsing is failed"); 110*36a7a2e7SMaxime Coquelin return ret; 111*36a7a2e7SMaxime Coquelin } 112*36a7a2e7SMaxime Coquelin /* virtio pmd skips probe if device needs to work in vdpa mode */ 113*36a7a2e7SMaxime Coquelin if (vdpa == 1) 114*36a7a2e7SMaxime Coquelin return 1; 115*36a7a2e7SMaxime Coquelin 116*36a7a2e7SMaxime Coquelin return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_pci_dev), 117*36a7a2e7SMaxime Coquelin eth_virtio_pci_init); 118*36a7a2e7SMaxime Coquelin } 119*36a7a2e7SMaxime Coquelin 120*36a7a2e7SMaxime Coquelin static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev) 121*36a7a2e7SMaxime Coquelin { 122*36a7a2e7SMaxime Coquelin int ret; 123*36a7a2e7SMaxime Coquelin 124*36a7a2e7SMaxime Coquelin ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_pci_uninit); 125*36a7a2e7SMaxime Coquelin /* Port has already been released by close. */ 126*36a7a2e7SMaxime Coquelin if (ret == -ENODEV) 127*36a7a2e7SMaxime Coquelin ret = 0; 128*36a7a2e7SMaxime Coquelin return ret; 129*36a7a2e7SMaxime Coquelin } 130*36a7a2e7SMaxime Coquelin 131*36a7a2e7SMaxime Coquelin static struct rte_pci_driver rte_virtio_net_pci_pmd = { 132*36a7a2e7SMaxime Coquelin .driver = { 133*36a7a2e7SMaxime Coquelin .name = "net_virtio", 134*36a7a2e7SMaxime Coquelin }, 135*36a7a2e7SMaxime Coquelin .id_table = pci_id_virtio_map, 136*36a7a2e7SMaxime Coquelin .drv_flags = 0, 137*36a7a2e7SMaxime Coquelin .probe = eth_virtio_pci_probe, 138*36a7a2e7SMaxime Coquelin .remove = eth_virtio_pci_remove, 139*36a7a2e7SMaxime Coquelin }; 140*36a7a2e7SMaxime Coquelin 141*36a7a2e7SMaxime Coquelin RTE_INIT(rte_virtio_net_pci_pmd_init) 142*36a7a2e7SMaxime Coquelin { 143*36a7a2e7SMaxime Coquelin rte_eal_iopl_init(); 144*36a7a2e7SMaxime Coquelin rte_pci_register(&rte_virtio_net_pci_pmd); 145*36a7a2e7SMaxime Coquelin } 146*36a7a2e7SMaxime Coquelin 147*36a7a2e7SMaxime Coquelin RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map); 148*36a7a2e7SMaxime Coquelin RTE_PMD_REGISTER_KMOD_DEP(net_virtio, "* igb_uio | uio_pci_generic | vfio-pci"); 149*36a7a2e7SMaxime Coquelin RTE_PMD_EXPORT_NAME(net_virtio, __COUNTER__); 150