1009c327cSOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2a46f8d58SGaetan Rivet * Copyright 2017 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2017 Mellanox Technologies, Ltd 4a46f8d58SGaetan Rivet */ 5a46f8d58SGaetan Rivet 649377908SRaslan Darawsheh #include <stdbool.h> 749377908SRaslan Darawsheh 8a46f8d58SGaetan Rivet #include <rte_alarm.h> 9a46f8d58SGaetan Rivet #include <rte_malloc.h> 10df96fd0dSBruce Richardson #include <ethdev_driver.h> 11df96fd0dSBruce Richardson #include <ethdev_vdev.h> 12a46f8d58SGaetan Rivet #include <rte_devargs.h> 13a46f8d58SGaetan Rivet #include <rte_kvargs.h> 14a04322f6SDavid Marchand #include <bus_driver.h> 154851ef2bSDavid Marchand #include <bus_vdev_driver.h> 16a46f8d58SGaetan Rivet 17a46f8d58SGaetan Rivet #include "failsafe_private.h" 18a46f8d58SGaetan Rivet 19a46f8d58SGaetan Rivet const char pmd_failsafe_driver_name[] = FAILSAFE_DRIVER_NAME; 20a46f8d58SGaetan Rivet static const struct rte_eth_link eth_link = { 21295968d1SFerruh Yigit .link_speed = RTE_ETH_SPEED_NUM_10G, 22295968d1SFerruh Yigit .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, 23295968d1SFerruh Yigit .link_status = RTE_ETH_LINK_UP, 24295968d1SFerruh Yigit .link_autoneg = RTE_ETH_LINK_AUTONEG, 25a46f8d58SGaetan Rivet }; 26a46f8d58SGaetan Rivet 27a46f8d58SGaetan Rivet static int 28a46f8d58SGaetan Rivet fs_sub_device_alloc(struct rte_eth_dev *dev, 29a46f8d58SGaetan Rivet const char *params) 30a46f8d58SGaetan Rivet { 31a46f8d58SGaetan Rivet uint8_t nb_subs; 32a46f8d58SGaetan Rivet int ret; 338052bbd9SMatan Azrad int i; 342f4b9983SRaslan Darawsheh struct sub_device *sdev; 352f4b9983SRaslan Darawsheh uint8_t sdev_iterator; 36a46f8d58SGaetan Rivet 37a46f8d58SGaetan Rivet ret = failsafe_args_count_subdevice(dev, params); 38a46f8d58SGaetan Rivet if (ret) 39a46f8d58SGaetan Rivet return ret; 40a46f8d58SGaetan Rivet if (PRIV(dev)->subs_tail > FAILSAFE_MAX_ETHPORTS) { 41a46f8d58SGaetan Rivet ERROR("Cannot allocate more than %d ports", 42a46f8d58SGaetan Rivet FAILSAFE_MAX_ETHPORTS); 43a46f8d58SGaetan Rivet return -ENOSPC; 44a46f8d58SGaetan Rivet } 45a46f8d58SGaetan Rivet nb_subs = PRIV(dev)->subs_tail; 46a46f8d58SGaetan Rivet PRIV(dev)->subs = rte_zmalloc(NULL, 47a46f8d58SGaetan Rivet sizeof(struct sub_device) * nb_subs, 48a46f8d58SGaetan Rivet RTE_CACHE_LINE_SIZE); 49a46f8d58SGaetan Rivet if (PRIV(dev)->subs == NULL) { 50a46f8d58SGaetan Rivet ERROR("Could not allocate sub_devices"); 51a46f8d58SGaetan Rivet return -ENOMEM; 52a46f8d58SGaetan Rivet } 538052bbd9SMatan Azrad /* Initiate static sub devices linked list. */ 548052bbd9SMatan Azrad for (i = 1; i < nb_subs; i++) 558052bbd9SMatan Azrad PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs + i; 568052bbd9SMatan Azrad PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs; 572f4b9983SRaslan Darawsheh 582f4b9983SRaslan Darawsheh FOREACH_SUBDEV(sdev, sdev_iterator, dev) { 592f4b9983SRaslan Darawsheh sdev->sdev_port_id = RTE_MAX_ETHPORTS; 602f4b9983SRaslan Darawsheh } 61a46f8d58SGaetan Rivet return 0; 62a46f8d58SGaetan Rivet } 63a46f8d58SGaetan Rivet 64ebea83f8SGaetan Rivet static void fs_hotplug_alarm(void *arg); 65ebea83f8SGaetan Rivet 66ebea83f8SGaetan Rivet int 67ebea83f8SGaetan Rivet failsafe_hotplug_alarm_install(struct rte_eth_dev *dev) 68ebea83f8SGaetan Rivet { 69ebea83f8SGaetan Rivet int ret; 70ebea83f8SGaetan Rivet 71ebea83f8SGaetan Rivet if (dev == NULL) 72ebea83f8SGaetan Rivet return -EINVAL; 73ebea83f8SGaetan Rivet if (PRIV(dev)->pending_alarm) 74ebea83f8SGaetan Rivet return 0; 75520dd992SFerruh Yigit ret = rte_eal_alarm_set(failsafe_hotplug_poll * 1000, 76ebea83f8SGaetan Rivet fs_hotplug_alarm, 77ebea83f8SGaetan Rivet dev); 78ebea83f8SGaetan Rivet if (ret) { 79ebea83f8SGaetan Rivet ERROR("Could not set up plug-in event detection"); 80ebea83f8SGaetan Rivet return ret; 81ebea83f8SGaetan Rivet } 82ebea83f8SGaetan Rivet PRIV(dev)->pending_alarm = 1; 83ebea83f8SGaetan Rivet return 0; 84ebea83f8SGaetan Rivet } 85ebea83f8SGaetan Rivet 86ebea83f8SGaetan Rivet int 87ebea83f8SGaetan Rivet failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev) 88ebea83f8SGaetan Rivet { 89ebea83f8SGaetan Rivet int ret = 0; 90ebea83f8SGaetan Rivet 91ebea83f8SGaetan Rivet rte_errno = 0; 92ebea83f8SGaetan Rivet rte_eal_alarm_cancel(fs_hotplug_alarm, dev); 93ebea83f8SGaetan Rivet if (rte_errno) { 94ebea83f8SGaetan Rivet ERROR("rte_eal_alarm_cancel failed (errno: %s)", 95ebea83f8SGaetan Rivet strerror(rte_errno)); 96ebea83f8SGaetan Rivet ret = -rte_errno; 97ebea83f8SGaetan Rivet } else { 98ebea83f8SGaetan Rivet PRIV(dev)->pending_alarm = 0; 99ebea83f8SGaetan Rivet } 100ebea83f8SGaetan Rivet return ret; 101ebea83f8SGaetan Rivet } 102ebea83f8SGaetan Rivet 103ebea83f8SGaetan Rivet static void 104ebea83f8SGaetan Rivet fs_hotplug_alarm(void *arg) 105ebea83f8SGaetan Rivet { 106ebea83f8SGaetan Rivet struct rte_eth_dev *dev = arg; 107ebea83f8SGaetan Rivet struct sub_device *sdev; 108ebea83f8SGaetan Rivet int ret; 109ebea83f8SGaetan Rivet uint8_t i; 110ebea83f8SGaetan Rivet 111ebea83f8SGaetan Rivet if (!PRIV(dev)->pending_alarm) 112ebea83f8SGaetan Rivet return; 113ebea83f8SGaetan Rivet PRIV(dev)->pending_alarm = 0; 114ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 115ebea83f8SGaetan Rivet if (sdev->state != PRIV(dev)->state) 116ebea83f8SGaetan Rivet break; 117ebea83f8SGaetan Rivet /* if we have non-probed device */ 118ebea83f8SGaetan Rivet if (i != PRIV(dev)->subs_tail) { 119655fcd68SMatan Azrad if (fs_lock(dev, 1) != 0) 120655fcd68SMatan Azrad goto reinstall; 121ebea83f8SGaetan Rivet ret = failsafe_eth_dev_state_sync(dev); 122655fcd68SMatan Azrad fs_unlock(dev, 1); 123ebea83f8SGaetan Rivet if (ret) 124ebea83f8SGaetan Rivet ERROR("Unable to synchronize sub_device state"); 125ebea83f8SGaetan Rivet } 126598fb8aeSGaetan Rivet failsafe_dev_remove(dev); 127655fcd68SMatan Azrad reinstall: 128ebea83f8SGaetan Rivet ret = failsafe_hotplug_alarm_install(dev); 129ebea83f8SGaetan Rivet if (ret) 130ebea83f8SGaetan Rivet ERROR("Unable to set up next alarm"); 131ebea83f8SGaetan Rivet } 132ebea83f8SGaetan Rivet 133a46f8d58SGaetan Rivet static int 134655fcd68SMatan Azrad fs_mutex_init(struct fs_priv *priv) 135655fcd68SMatan Azrad { 136655fcd68SMatan Azrad int ret; 137655fcd68SMatan Azrad pthread_mutexattr_t attr; 138655fcd68SMatan Azrad 139655fcd68SMatan Azrad ret = pthread_mutexattr_init(&attr); 140655fcd68SMatan Azrad if (ret) { 141655fcd68SMatan Azrad ERROR("Cannot initiate mutex attributes - %s", strerror(ret)); 142655fcd68SMatan Azrad return ret; 143655fcd68SMatan Azrad } 144655fcd68SMatan Azrad /* Allow mutex relocks for the thread holding the mutex. */ 145655fcd68SMatan Azrad ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 146655fcd68SMatan Azrad if (ret) { 147655fcd68SMatan Azrad ERROR("Cannot set mutex type - %s", strerror(ret)); 148655fcd68SMatan Azrad return ret; 149655fcd68SMatan Azrad } 150*58825f41SAriel Otilibili 151*58825f41SAriel Otilibili return pthread_mutex_init(&priv->hotplug_mutex, &attr); 152655fcd68SMatan Azrad } 153655fcd68SMatan Azrad 154655fcd68SMatan Azrad static int 155a46f8d58SGaetan Rivet fs_eth_dev_create(struct rte_vdev_device *vdev) 156a46f8d58SGaetan Rivet { 157a46f8d58SGaetan Rivet struct rte_eth_dev *dev; 1586d13ea8eSOlivier Matz struct rte_ether_addr *mac; 159a46f8d58SGaetan Rivet struct fs_priv *priv; 160a46f8d58SGaetan Rivet struct sub_device *sdev; 161a46f8d58SGaetan Rivet const char *params; 162a46f8d58SGaetan Rivet unsigned int socket_id; 163a46f8d58SGaetan Rivet uint8_t i; 164a46f8d58SGaetan Rivet int ret; 165a46f8d58SGaetan Rivet 166a46f8d58SGaetan Rivet dev = NULL; 167a46f8d58SGaetan Rivet priv = NULL; 168a46f8d58SGaetan Rivet socket_id = rte_socket_id(); 169a46f8d58SGaetan Rivet INFO("Creating fail-safe device on NUMA socket %u", socket_id); 170a46f8d58SGaetan Rivet params = rte_vdev_device_args(vdev); 171a46f8d58SGaetan Rivet if (params == NULL) { 172a46f8d58SGaetan Rivet ERROR("This PMD requires sub-devices, none provided"); 173a46f8d58SGaetan Rivet return -1; 174a46f8d58SGaetan Rivet } 175a46f8d58SGaetan Rivet dev = rte_eth_vdev_allocate(vdev, sizeof(*priv)); 176a46f8d58SGaetan Rivet if (dev == NULL) { 177a46f8d58SGaetan Rivet ERROR("Unable to allocate rte_eth_dev"); 178a46f8d58SGaetan Rivet return -1; 179a46f8d58SGaetan Rivet } 180a46f8d58SGaetan Rivet priv = PRIV(dev); 18108647012SRaslan Darawsheh priv->data = dev->data; 182b9663f60SYunjian Wang priv->rxp = FS_RX_PROXY_INIT; 183a46f8d58SGaetan Rivet dev->dev_ops = &failsafe_ops; 184a46f8d58SGaetan Rivet dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0]; 185a46f8d58SGaetan Rivet dev->data->dev_link = eth_link; 186a46f8d58SGaetan Rivet PRIV(dev)->nb_mac_addr = 1; 187b737a1eeSGaetan Rivet TAILQ_INIT(&PRIV(dev)->flow_list); 188a46f8d58SGaetan Rivet dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 189a46f8d58SGaetan Rivet dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 190a46f8d58SGaetan Rivet ret = fs_sub_device_alloc(dev, params); 191a46f8d58SGaetan Rivet if (ret) { 192a46f8d58SGaetan Rivet ERROR("Could not allocate sub_devices"); 193a46f8d58SGaetan Rivet goto free_dev; 194a46f8d58SGaetan Rivet } 195a46f8d58SGaetan Rivet ret = failsafe_args_parse(dev, params); 196a46f8d58SGaetan Rivet if (ret) 197a46f8d58SGaetan Rivet goto free_subs; 198dcd0c9c3SMatan Azrad ret = rte_eth_dev_owner_new(&priv->my_owner.id); 199dcd0c9c3SMatan Azrad if (ret) { 200dcd0c9c3SMatan Azrad ERROR("Failed to get unique owner identifier"); 201dcd0c9c3SMatan Azrad goto free_args; 202dcd0c9c3SMatan Azrad } 203dcd0c9c3SMatan Azrad snprintf(priv->my_owner.name, sizeof(priv->my_owner.name), 204dcd0c9c3SMatan Azrad FAILSAFE_OWNER_NAME); 2057fda13d3SMatan Azrad DEBUG("Failsafe port %u owner info: %s_%016"PRIX64, dev->data->port_id, 2067fda13d3SMatan Azrad priv->my_owner.name, priv->my_owner.id); 2077fda13d3SMatan Azrad ret = rte_eth_dev_callback_register(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 2087fda13d3SMatan Azrad failsafe_eth_new_event_callback, 2097fda13d3SMatan Azrad dev); 2107fda13d3SMatan Azrad if (ret) { 2117fda13d3SMatan Azrad ERROR("Failed to register NEW callback"); 2127fda13d3SMatan Azrad goto free_args; 2137fda13d3SMatan Azrad } 214a46f8d58SGaetan Rivet ret = failsafe_eal_init(dev); 215a46f8d58SGaetan Rivet if (ret) 2167fda13d3SMatan Azrad goto unregister_new_callback; 217655fcd68SMatan Azrad ret = fs_mutex_init(priv); 218655fcd68SMatan Azrad if (ret) 2197fda13d3SMatan Azrad goto unregister_new_callback; 220ebea83f8SGaetan Rivet ret = failsafe_hotplug_alarm_install(dev); 221ebea83f8SGaetan Rivet if (ret) { 222ebea83f8SGaetan Rivet ERROR("Could not set up plug-in event detection"); 2237fda13d3SMatan Azrad goto unregister_new_callback; 224ebea83f8SGaetan Rivet } 225a46f8d58SGaetan Rivet mac = &dev->data->mac_addrs[0]; 226520dd992SFerruh Yigit if (failsafe_mac_from_arg) { 227a46f8d58SGaetan Rivet /* 228a46f8d58SGaetan Rivet * If MAC address was provided as a parameter, 22939fab5a0SStephen Hemminger * apply to all probed subdevices. 230a46f8d58SGaetan Rivet */ 231a46f8d58SGaetan Rivet FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { 232a46f8d58SGaetan Rivet ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 233a46f8d58SGaetan Rivet mac); 234a46f8d58SGaetan Rivet if (ret) { 235a46f8d58SGaetan Rivet ERROR("Failed to set default MAC address"); 23695e7a72fSRaslan Darawsheh goto cancel_alarm; 237a46f8d58SGaetan Rivet } 238a46f8d58SGaetan Rivet } 239a46f8d58SGaetan Rivet } else { 240a46f8d58SGaetan Rivet /* 241a46f8d58SGaetan Rivet * Use the ether_addr from first probed 242a46f8d58SGaetan Rivet * device, either preferred or fallback. 243a46f8d58SGaetan Rivet */ 244a46f8d58SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 245a46f8d58SGaetan Rivet if (sdev->state >= DEV_PROBED) { 246538da7a1SOlivier Matz rte_ether_addr_copy( 247538da7a1SOlivier Matz Ð(sdev)->data->mac_addrs[0], mac); 248a46f8d58SGaetan Rivet break; 249a46f8d58SGaetan Rivet } 250a46f8d58SGaetan Rivet /* 251a46f8d58SGaetan Rivet * If no device has been probed and no ether_addr 252a46f8d58SGaetan Rivet * has been provided on the command line, use a random 253a46f8d58SGaetan Rivet * valid one. 25439fab5a0SStephen Hemminger * It will be applied during future state syncs to 25539fab5a0SStephen Hemminger * probed subdevices. 256a46f8d58SGaetan Rivet */ 257a46f8d58SGaetan Rivet if (i == priv->subs_tail) 258538da7a1SOlivier Matz rte_eth_random_addr(&mac->addr_bytes[0]); 259a46f8d58SGaetan Rivet } 260c2c4f87bSAman Deep Singh INFO("MAC address is " RTE_ETHER_ADDR_PRT_FMT, 261a7db3afcSAman Deep Singh RTE_ETHER_ADDR_BYTES(mac)); 262f30e69b4SFerruh Yigit dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC | 263f30e69b4SFerruh Yigit RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 264d61138d4SHarman Kalra 265d61138d4SHarman Kalra /* Allocate interrupt instance */ 266d61138d4SHarman Kalra PRIV(dev)->intr_handle = 267d61138d4SHarman Kalra rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); 268d61138d4SHarman Kalra if (PRIV(dev)->intr_handle == NULL) { 269d61138d4SHarman Kalra ERROR("Failed to allocate intr handle"); 270d61138d4SHarman Kalra goto cancel_alarm; 271d61138d4SHarman Kalra } 272d61138d4SHarman Kalra 273d61138d4SHarman Kalra if (rte_intr_fd_set(PRIV(dev)->intr_handle, -1)) 274d61138d4SHarman Kalra goto cancel_alarm; 275d61138d4SHarman Kalra 276d61138d4SHarman Kalra if (rte_intr_type_set(PRIV(dev)->intr_handle, RTE_INTR_HANDLE_EXT)) 277d61138d4SHarman Kalra goto cancel_alarm; 278d61138d4SHarman Kalra 279fbe90cddSThomas Monjalon rte_eth_dev_probing_finish(dev); 280d61138d4SHarman Kalra 281a46f8d58SGaetan Rivet return 0; 28295e7a72fSRaslan Darawsheh cancel_alarm: 28395e7a72fSRaslan Darawsheh failsafe_hotplug_alarm_cancel(dev); 2847fda13d3SMatan Azrad unregister_new_callback: 2857fda13d3SMatan Azrad rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 2867fda13d3SMatan Azrad failsafe_eth_new_event_callback, dev); 287a46f8d58SGaetan Rivet free_args: 288a46f8d58SGaetan Rivet failsafe_args_free(dev); 289a46f8d58SGaetan Rivet free_subs: 2901a7fa562SThomas Monjalon rte_free(PRIV(dev)->subs); 291a46f8d58SGaetan Rivet free_dev: 292e16adf08SThomas Monjalon /* mac_addrs must not be freed alone because part of dev_private */ 293e16adf08SThomas Monjalon dev->data->mac_addrs = NULL; 294a46f8d58SGaetan Rivet rte_eth_dev_release_port(dev); 295a46f8d58SGaetan Rivet return -1; 296a46f8d58SGaetan Rivet } 297a46f8d58SGaetan Rivet 298a46f8d58SGaetan Rivet static int 299a46f8d58SGaetan Rivet fs_rte_eth_free(const char *name) 300a46f8d58SGaetan Rivet { 301a46f8d58SGaetan Rivet struct rte_eth_dev *dev; 302a46f8d58SGaetan Rivet int ret; 303a46f8d58SGaetan Rivet 304a46f8d58SGaetan Rivet dev = rte_eth_dev_allocated(name); 305a46f8d58SGaetan Rivet if (dev == NULL) 3061a7fa562SThomas Monjalon return 0; /* port already released */ 3071a7fa562SThomas Monjalon ret = failsafe_eth_dev_close(dev); 308d61138d4SHarman Kalra rte_intr_instance_free(PRIV(dev)->intr_handle); 309fd819cadSYunjian Wang rte_eth_dev_release_port(dev); 310a46f8d58SGaetan Rivet return ret; 311a46f8d58SGaetan Rivet } 312a46f8d58SGaetan Rivet 31349377908SRaslan Darawsheh static bool 31449377908SRaslan Darawsheh devargs_already_listed(struct rte_devargs *devargs) 31549377908SRaslan Darawsheh { 31649377908SRaslan Darawsheh struct rte_devargs *list_da; 31749377908SRaslan Darawsheh 31849377908SRaslan Darawsheh RTE_EAL_DEVARGS_FOREACH(devargs->bus->name, list_da) { 31949377908SRaslan Darawsheh if (strcmp(list_da->name, devargs->name) == 0) 32049377908SRaslan Darawsheh /* devargs already in the list */ 32149377908SRaslan Darawsheh return true; 32249377908SRaslan Darawsheh } 32349377908SRaslan Darawsheh return false; 32449377908SRaslan Darawsheh } 32549377908SRaslan Darawsheh 326a46f8d58SGaetan Rivet static int 327a46f8d58SGaetan Rivet rte_pmd_failsafe_probe(struct rte_vdev_device *vdev) 328a46f8d58SGaetan Rivet { 329a46f8d58SGaetan Rivet const char *name; 330ee27edbeSJianfeng Tan struct rte_eth_dev *eth_dev; 33149377908SRaslan Darawsheh struct sub_device *sdev; 33249377908SRaslan Darawsheh struct rte_devargs devargs; 33349377908SRaslan Darawsheh uint8_t i; 33449377908SRaslan Darawsheh int ret; 335a46f8d58SGaetan Rivet 336a46f8d58SGaetan Rivet name = rte_vdev_device_name(vdev); 337a46f8d58SGaetan Rivet INFO("Initializing " FAILSAFE_DRIVER_NAME " for %s", 338a46f8d58SGaetan Rivet name); 339ee27edbeSJianfeng Tan 34047f5dee1SKumara Parameshwaran if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 341ee27edbeSJianfeng Tan eth_dev = rte_eth_dev_attach_secondary(name); 342ee27edbeSJianfeng Tan if (!eth_dev) { 343ebeb72ecSStephen Hemminger ERROR("Failed to probe %s", name); 344ee27edbeSJianfeng Tan return -1; 345ee27edbeSJianfeng Tan } 346ee27edbeSJianfeng Tan eth_dev->dev_ops = &failsafe_ops; 347d1c3ab22SFerruh Yigit eth_dev->device = &vdev->device; 34849377908SRaslan Darawsheh eth_dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 34949377908SRaslan Darawsheh eth_dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 35049377908SRaslan Darawsheh /* 35149377908SRaslan Darawsheh * Failsafe will attempt to probe all of its sub-devices. 35249377908SRaslan Darawsheh * Any failure in sub-devices is not a fatal error. 35349377908SRaslan Darawsheh * A sub-device can be plugged later. 35449377908SRaslan Darawsheh */ 35549377908SRaslan Darawsheh FOREACH_SUBDEV(sdev, i, eth_dev) { 35669a27a5fSStephen Hemminger /* skip empty devargs */ 35769a27a5fSStephen Hemminger if (sdev->devargs.name[0] == '\0') 35869a27a5fSStephen Hemminger continue; 35969a27a5fSStephen Hemminger 36049377908SRaslan Darawsheh /* rebuild devargs to be able to get the bus name. */ 36149377908SRaslan Darawsheh ret = rte_devargs_parse(&devargs, 36249377908SRaslan Darawsheh sdev->devargs.name); 36349377908SRaslan Darawsheh if (ret != 0) { 36449377908SRaslan Darawsheh ERROR("Failed to parse devargs %s", 36549377908SRaslan Darawsheh devargs.name); 36649377908SRaslan Darawsheh continue; 36749377908SRaslan Darawsheh } 36849377908SRaslan Darawsheh if (!devargs_already_listed(&devargs)) { 36949377908SRaslan Darawsheh ret = rte_dev_probe(devargs.name); 37075b66decSIlya Maximets if (ret < 0) { 37149377908SRaslan Darawsheh ERROR("Failed to probe devargs %s", 37249377908SRaslan Darawsheh devargs.name); 37349377908SRaslan Darawsheh continue; 37449377908SRaslan Darawsheh } 37549377908SRaslan Darawsheh } 37649377908SRaslan Darawsheh } 377fbe90cddSThomas Monjalon rte_eth_dev_probing_finish(eth_dev); 378ee27edbeSJianfeng Tan return 0; 379ee27edbeSJianfeng Tan } 380ee27edbeSJianfeng Tan 381a46f8d58SGaetan Rivet return fs_eth_dev_create(vdev); 382a46f8d58SGaetan Rivet } 383a46f8d58SGaetan Rivet 384a46f8d58SGaetan Rivet static int 385a46f8d58SGaetan Rivet rte_pmd_failsafe_remove(struct rte_vdev_device *vdev) 386a46f8d58SGaetan Rivet { 387a46f8d58SGaetan Rivet const char *name; 388a46f8d58SGaetan Rivet 389a46f8d58SGaetan Rivet name = rte_vdev_device_name(vdev); 390a46f8d58SGaetan Rivet INFO("Uninitializing " FAILSAFE_DRIVER_NAME " for %s", name); 391a46f8d58SGaetan Rivet return fs_rte_eth_free(name); 392a46f8d58SGaetan Rivet } 393a46f8d58SGaetan Rivet 394a46f8d58SGaetan Rivet static struct rte_vdev_driver failsafe_drv = { 395a46f8d58SGaetan Rivet .probe = rte_pmd_failsafe_probe, 396a46f8d58SGaetan Rivet .remove = rte_pmd_failsafe_remove, 397a46f8d58SGaetan Rivet }; 398a46f8d58SGaetan Rivet 399a46f8d58SGaetan Rivet RTE_PMD_REGISTER_VDEV(net_failsafe, failsafe_drv); 400a46f8d58SGaetan Rivet RTE_PMD_REGISTER_PARAM_STRING(net_failsafe, PMD_FAILSAFE_PARAM_STRING); 401eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(failsafe_logtype, NOTICE) 402