1 /*- 2 * Copyright (c) 2016 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * This software was jointly developed between OKTET Labs (under contract 6 * for Solarflare) and Solarflare Communications, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <rte_dev.h> 31 #include <rte_ethdev.h> 32 #include <rte_pci.h> 33 34 #include "efx.h" 35 36 #include "sfc.h" 37 #include "sfc_debug.h" 38 #include "sfc_log.h" 39 #include "sfc_kvargs.h" 40 41 42 static void 43 sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 44 { 45 struct sfc_adapter *sa = dev->data->dev_private; 46 47 sfc_log_init(sa, "entry"); 48 49 dev_info->pci_dev = RTE_DEV_TO_PCI(dev->device); 50 } 51 52 static int 53 sfc_dev_configure(struct rte_eth_dev *dev) 54 { 55 struct rte_eth_dev_data *dev_data = dev->data; 56 struct sfc_adapter *sa = dev_data->dev_private; 57 int rc; 58 59 sfc_log_init(sa, "entry n_rxq=%u n_txq=%u", 60 dev_data->nb_rx_queues, dev_data->nb_tx_queues); 61 62 sfc_adapter_lock(sa); 63 switch (sa->state) { 64 case SFC_ADAPTER_CONFIGURED: 65 sfc_close(sa); 66 SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED); 67 /* FALLTHROUGH */ 68 case SFC_ADAPTER_INITIALIZED: 69 rc = sfc_configure(sa); 70 break; 71 default: 72 sfc_err(sa, "unexpected adapter state %u to configure", 73 sa->state); 74 rc = EINVAL; 75 break; 76 } 77 sfc_adapter_unlock(sa); 78 79 sfc_log_init(sa, "done %d", rc); 80 SFC_ASSERT(rc >= 0); 81 return -rc; 82 } 83 84 static void 85 sfc_dev_close(struct rte_eth_dev *dev) 86 { 87 struct sfc_adapter *sa = dev->data->dev_private; 88 89 sfc_log_init(sa, "entry"); 90 91 sfc_adapter_lock(sa); 92 switch (sa->state) { 93 case SFC_ADAPTER_CONFIGURED: 94 sfc_close(sa); 95 SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED); 96 /* FALLTHROUGH */ 97 case SFC_ADAPTER_INITIALIZED: 98 break; 99 default: 100 sfc_err(sa, "unexpected adapter state %u on close", sa->state); 101 break; 102 } 103 sfc_adapter_unlock(sa); 104 105 sfc_log_init(sa, "done"); 106 } 107 108 static const struct eth_dev_ops sfc_eth_dev_ops = { 109 .dev_configure = sfc_dev_configure, 110 .dev_close = sfc_dev_close, 111 .dev_infos_get = sfc_dev_infos_get, 112 }; 113 114 static int 115 sfc_eth_dev_init(struct rte_eth_dev *dev) 116 { 117 struct sfc_adapter *sa = dev->data->dev_private; 118 struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(dev); 119 int rc; 120 const efx_nic_cfg_t *encp; 121 const struct ether_addr *from; 122 123 /* Required for logging */ 124 sa->eth_dev = dev; 125 126 /* Copy PCI device info to the dev->data */ 127 rte_eth_copy_pci_info(dev, pci_dev); 128 129 rc = sfc_kvargs_parse(sa); 130 if (rc != 0) 131 goto fail_kvargs_parse; 132 133 rc = sfc_kvargs_process(sa, SFC_KVARG_DEBUG_INIT, 134 sfc_kvarg_bool_handler, &sa->debug_init); 135 if (rc != 0) 136 goto fail_kvarg_debug_init; 137 138 sfc_log_init(sa, "entry"); 139 140 dev->data->mac_addrs = rte_zmalloc("sfc", ETHER_ADDR_LEN, 0); 141 if (dev->data->mac_addrs == NULL) { 142 rc = ENOMEM; 143 goto fail_mac_addrs; 144 } 145 146 sfc_adapter_lock_init(sa); 147 sfc_adapter_lock(sa); 148 149 sfc_log_init(sa, "attaching"); 150 rc = sfc_attach(sa); 151 if (rc != 0) 152 goto fail_attach; 153 154 encp = efx_nic_cfg_get(sa->nic); 155 156 /* 157 * The arguments are really reverse order in comparison to 158 * Linux kernel. Copy from NIC config to Ethernet device data. 159 */ 160 from = (const struct ether_addr *)(encp->enc_mac_addr); 161 ether_addr_copy(from, &dev->data->mac_addrs[0]); 162 163 dev->dev_ops = &sfc_eth_dev_ops; 164 165 sfc_adapter_unlock(sa); 166 167 sfc_log_init(sa, "done"); 168 return 0; 169 170 fail_attach: 171 sfc_adapter_unlock(sa); 172 sfc_adapter_lock_fini(sa); 173 rte_free(dev->data->mac_addrs); 174 dev->data->mac_addrs = NULL; 175 176 fail_mac_addrs: 177 fail_kvarg_debug_init: 178 sfc_kvargs_cleanup(sa); 179 180 fail_kvargs_parse: 181 sfc_log_init(sa, "failed %d", rc); 182 SFC_ASSERT(rc > 0); 183 return -rc; 184 } 185 186 static int 187 sfc_eth_dev_uninit(struct rte_eth_dev *dev) 188 { 189 struct sfc_adapter *sa = dev->data->dev_private; 190 191 sfc_log_init(sa, "entry"); 192 193 sfc_adapter_lock(sa); 194 195 sfc_detach(sa); 196 197 rte_free(dev->data->mac_addrs); 198 dev->data->mac_addrs = NULL; 199 200 dev->dev_ops = NULL; 201 202 sfc_kvargs_cleanup(sa); 203 204 sfc_adapter_unlock(sa); 205 sfc_adapter_lock_fini(sa); 206 207 sfc_log_init(sa, "done"); 208 209 /* Required for logging, so cleanup last */ 210 sa->eth_dev = NULL; 211 return 0; 212 } 213 214 static const struct rte_pci_id pci_id_sfc_efx_map[] = { 215 { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE) }, 216 { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT) }, 217 { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD) }, 218 { .vendor_id = 0 /* sentinel */ } 219 }; 220 221 static struct eth_driver sfc_efx_pmd = { 222 .pci_drv = { 223 .id_table = pci_id_sfc_efx_map, 224 .drv_flags = 225 RTE_PCI_DRV_NEED_MAPPING, 226 .probe = rte_eth_dev_pci_probe, 227 .remove = rte_eth_dev_pci_remove, 228 }, 229 .eth_dev_init = sfc_eth_dev_init, 230 .eth_dev_uninit = sfc_eth_dev_uninit, 231 .dev_private_size = sizeof(struct sfc_adapter), 232 }; 233 234 RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd.pci_drv); 235 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map); 236 RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx, 237 SFC_KVARG_DEBUG_INIT "=" SFC_KVARG_VALUES_BOOL); 238