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 #include "sfc_ev.h" 41 42 43 static void 44 sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 45 { 46 struct sfc_adapter *sa = dev->data->dev_private; 47 48 sfc_log_init(sa, "entry"); 49 50 dev_info->pci_dev = RTE_DEV_TO_PCI(dev->device); 51 dev_info->max_rx_pktlen = EFX_MAC_PDU_MAX; 52 } 53 54 static int 55 sfc_dev_configure(struct rte_eth_dev *dev) 56 { 57 struct rte_eth_dev_data *dev_data = dev->data; 58 struct sfc_adapter *sa = dev_data->dev_private; 59 int rc; 60 61 sfc_log_init(sa, "entry n_rxq=%u n_txq=%u", 62 dev_data->nb_rx_queues, dev_data->nb_tx_queues); 63 64 sfc_adapter_lock(sa); 65 switch (sa->state) { 66 case SFC_ADAPTER_CONFIGURED: 67 sfc_close(sa); 68 SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED); 69 /* FALLTHROUGH */ 70 case SFC_ADAPTER_INITIALIZED: 71 rc = sfc_configure(sa); 72 break; 73 default: 74 sfc_err(sa, "unexpected adapter state %u to configure", 75 sa->state); 76 rc = EINVAL; 77 break; 78 } 79 sfc_adapter_unlock(sa); 80 81 sfc_log_init(sa, "done %d", rc); 82 SFC_ASSERT(rc >= 0); 83 return -rc; 84 } 85 86 static int 87 sfc_dev_start(struct rte_eth_dev *dev) 88 { 89 struct sfc_adapter *sa = dev->data->dev_private; 90 int rc; 91 92 sfc_log_init(sa, "entry"); 93 94 sfc_adapter_lock(sa); 95 rc = sfc_start(sa); 96 sfc_adapter_unlock(sa); 97 98 sfc_log_init(sa, "done %d", rc); 99 SFC_ASSERT(rc >= 0); 100 return -rc; 101 } 102 103 static int 104 sfc_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) 105 { 106 struct sfc_adapter *sa = dev->data->dev_private; 107 struct rte_eth_link *dev_link = &dev->data->dev_link; 108 struct rte_eth_link old_link; 109 struct rte_eth_link current_link; 110 111 sfc_log_init(sa, "entry"); 112 113 if (sa->state != SFC_ADAPTER_STARTED) 114 return 0; 115 116 retry: 117 EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t)); 118 *(int64_t *)&old_link = rte_atomic64_read((rte_atomic64_t *)dev_link); 119 120 if (wait_to_complete) { 121 efx_link_mode_t link_mode; 122 123 efx_port_poll(sa->nic, &link_mode); 124 sfc_port_link_mode_to_info(link_mode, ¤t_link); 125 126 if (!rte_atomic64_cmpset((volatile uint64_t *)dev_link, 127 *(uint64_t *)&old_link, 128 *(uint64_t *)¤t_link)) 129 goto retry; 130 } else { 131 sfc_ev_mgmt_qpoll(sa); 132 *(int64_t *)¤t_link = 133 rte_atomic64_read((rte_atomic64_t *)dev_link); 134 } 135 136 if (old_link.link_status != current_link.link_status) 137 sfc_info(sa, "Link status is %s", 138 current_link.link_status ? "UP" : "DOWN"); 139 140 return old_link.link_status == current_link.link_status ? 0 : -1; 141 } 142 143 static void 144 sfc_dev_stop(struct rte_eth_dev *dev) 145 { 146 struct sfc_adapter *sa = dev->data->dev_private; 147 148 sfc_log_init(sa, "entry"); 149 150 sfc_adapter_lock(sa); 151 sfc_stop(sa); 152 sfc_adapter_unlock(sa); 153 154 sfc_log_init(sa, "done"); 155 } 156 157 static void 158 sfc_dev_close(struct rte_eth_dev *dev) 159 { 160 struct sfc_adapter *sa = dev->data->dev_private; 161 162 sfc_log_init(sa, "entry"); 163 164 sfc_adapter_lock(sa); 165 switch (sa->state) { 166 case SFC_ADAPTER_STARTED: 167 sfc_stop(sa); 168 SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED); 169 /* FALLTHROUGH */ 170 case SFC_ADAPTER_CONFIGURED: 171 sfc_close(sa); 172 SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED); 173 /* FALLTHROUGH */ 174 case SFC_ADAPTER_INITIALIZED: 175 break; 176 default: 177 sfc_err(sa, "unexpected adapter state %u on close", sa->state); 178 break; 179 } 180 sfc_adapter_unlock(sa); 181 182 sfc_log_init(sa, "done"); 183 } 184 185 static const struct eth_dev_ops sfc_eth_dev_ops = { 186 .dev_configure = sfc_dev_configure, 187 .dev_start = sfc_dev_start, 188 .dev_stop = sfc_dev_stop, 189 .dev_close = sfc_dev_close, 190 .link_update = sfc_dev_link_update, 191 .dev_infos_get = sfc_dev_infos_get, 192 }; 193 194 static int 195 sfc_eth_dev_init(struct rte_eth_dev *dev) 196 { 197 struct sfc_adapter *sa = dev->data->dev_private; 198 struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(dev); 199 int rc; 200 const efx_nic_cfg_t *encp; 201 const struct ether_addr *from; 202 203 /* Required for logging */ 204 sa->eth_dev = dev; 205 206 /* Copy PCI device info to the dev->data */ 207 rte_eth_copy_pci_info(dev, pci_dev); 208 209 rc = sfc_kvargs_parse(sa); 210 if (rc != 0) 211 goto fail_kvargs_parse; 212 213 rc = sfc_kvargs_process(sa, SFC_KVARG_DEBUG_INIT, 214 sfc_kvarg_bool_handler, &sa->debug_init); 215 if (rc != 0) 216 goto fail_kvarg_debug_init; 217 218 sfc_log_init(sa, "entry"); 219 220 dev->data->mac_addrs = rte_zmalloc("sfc", ETHER_ADDR_LEN, 0); 221 if (dev->data->mac_addrs == NULL) { 222 rc = ENOMEM; 223 goto fail_mac_addrs; 224 } 225 226 sfc_adapter_lock_init(sa); 227 sfc_adapter_lock(sa); 228 229 sfc_log_init(sa, "attaching"); 230 rc = sfc_attach(sa); 231 if (rc != 0) 232 goto fail_attach; 233 234 encp = efx_nic_cfg_get(sa->nic); 235 236 /* 237 * The arguments are really reverse order in comparison to 238 * Linux kernel. Copy from NIC config to Ethernet device data. 239 */ 240 from = (const struct ether_addr *)(encp->enc_mac_addr); 241 ether_addr_copy(from, &dev->data->mac_addrs[0]); 242 243 dev->dev_ops = &sfc_eth_dev_ops; 244 245 sfc_adapter_unlock(sa); 246 247 sfc_log_init(sa, "done"); 248 return 0; 249 250 fail_attach: 251 sfc_adapter_unlock(sa); 252 sfc_adapter_lock_fini(sa); 253 rte_free(dev->data->mac_addrs); 254 dev->data->mac_addrs = NULL; 255 256 fail_mac_addrs: 257 fail_kvarg_debug_init: 258 sfc_kvargs_cleanup(sa); 259 260 fail_kvargs_parse: 261 sfc_log_init(sa, "failed %d", rc); 262 SFC_ASSERT(rc > 0); 263 return -rc; 264 } 265 266 static int 267 sfc_eth_dev_uninit(struct rte_eth_dev *dev) 268 { 269 struct sfc_adapter *sa = dev->data->dev_private; 270 271 sfc_log_init(sa, "entry"); 272 273 sfc_adapter_lock(sa); 274 275 sfc_detach(sa); 276 277 rte_free(dev->data->mac_addrs); 278 dev->data->mac_addrs = NULL; 279 280 dev->dev_ops = NULL; 281 282 sfc_kvargs_cleanup(sa); 283 284 sfc_adapter_unlock(sa); 285 sfc_adapter_lock_fini(sa); 286 287 sfc_log_init(sa, "done"); 288 289 /* Required for logging, so cleanup last */ 290 sa->eth_dev = NULL; 291 return 0; 292 } 293 294 static const struct rte_pci_id pci_id_sfc_efx_map[] = { 295 { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE) }, 296 { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT) }, 297 { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD) }, 298 { .vendor_id = 0 /* sentinel */ } 299 }; 300 301 static struct eth_driver sfc_efx_pmd = { 302 .pci_drv = { 303 .id_table = pci_id_sfc_efx_map, 304 .drv_flags = 305 RTE_PCI_DRV_NEED_MAPPING, 306 .probe = rte_eth_dev_pci_probe, 307 .remove = rte_eth_dev_pci_remove, 308 }, 309 .eth_dev_init = sfc_eth_dev_init, 310 .eth_dev_uninit = sfc_eth_dev_uninit, 311 .dev_private_size = sizeof(struct sfc_adapter), 312 }; 313 314 RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd.pci_drv); 315 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map); 316 RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx, 317 SFC_KVARG_DEBUG_INIT "=" SFC_KVARG_VALUES_BOOL); 318