1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause 22bfe3f2eSlogwang * Copyright 2017 6WIND S.A. 3d30ea906Sjfb8856606 * Copyright 2017 Mellanox Technologies, Ltd 42bfe3f2eSlogwang */ 52bfe3f2eSlogwang 64418919fSjohnjiang #include <stdbool.h> 74418919fSjohnjiang 82bfe3f2eSlogwang #include <rte_alarm.h> 92bfe3f2eSlogwang #include <rte_malloc.h> 10d30ea906Sjfb8856606 #include <rte_ethdev_driver.h> 112bfe3f2eSlogwang #include <rte_ethdev_vdev.h> 122bfe3f2eSlogwang #include <rte_devargs.h> 132bfe3f2eSlogwang #include <rte_kvargs.h> 142bfe3f2eSlogwang #include <rte_bus_vdev.h> 152bfe3f2eSlogwang 162bfe3f2eSlogwang #include "failsafe_private.h" 172bfe3f2eSlogwang 18d30ea906Sjfb8856606 int failsafe_logtype; 19d30ea906Sjfb8856606 202bfe3f2eSlogwang const char pmd_failsafe_driver_name[] = FAILSAFE_DRIVER_NAME; 212bfe3f2eSlogwang static const struct rte_eth_link eth_link = { 222bfe3f2eSlogwang .link_speed = ETH_SPEED_NUM_10G, 232bfe3f2eSlogwang .link_duplex = ETH_LINK_FULL_DUPLEX, 242bfe3f2eSlogwang .link_status = ETH_LINK_UP, 252bfe3f2eSlogwang .link_autoneg = ETH_LINK_AUTONEG, 262bfe3f2eSlogwang }; 272bfe3f2eSlogwang 282bfe3f2eSlogwang static int 292bfe3f2eSlogwang fs_sub_device_alloc(struct rte_eth_dev *dev, 302bfe3f2eSlogwang const char *params) 312bfe3f2eSlogwang { 322bfe3f2eSlogwang uint8_t nb_subs; 332bfe3f2eSlogwang int ret; 34d30ea906Sjfb8856606 int i; 354418919fSjohnjiang struct sub_device *sdev; 364418919fSjohnjiang uint8_t sdev_iterator; 372bfe3f2eSlogwang 382bfe3f2eSlogwang ret = failsafe_args_count_subdevice(dev, params); 392bfe3f2eSlogwang if (ret) 402bfe3f2eSlogwang return ret; 412bfe3f2eSlogwang if (PRIV(dev)->subs_tail > FAILSAFE_MAX_ETHPORTS) { 422bfe3f2eSlogwang ERROR("Cannot allocate more than %d ports", 432bfe3f2eSlogwang FAILSAFE_MAX_ETHPORTS); 442bfe3f2eSlogwang return -ENOSPC; 452bfe3f2eSlogwang } 462bfe3f2eSlogwang nb_subs = PRIV(dev)->subs_tail; 472bfe3f2eSlogwang PRIV(dev)->subs = rte_zmalloc(NULL, 482bfe3f2eSlogwang sizeof(struct sub_device) * nb_subs, 492bfe3f2eSlogwang RTE_CACHE_LINE_SIZE); 502bfe3f2eSlogwang if (PRIV(dev)->subs == NULL) { 512bfe3f2eSlogwang ERROR("Could not allocate sub_devices"); 522bfe3f2eSlogwang return -ENOMEM; 532bfe3f2eSlogwang } 54d30ea906Sjfb8856606 /* Initiate static sub devices linked list. */ 55d30ea906Sjfb8856606 for (i = 1; i < nb_subs; i++) 56d30ea906Sjfb8856606 PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs + i; 57d30ea906Sjfb8856606 PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs; 584418919fSjohnjiang 594418919fSjohnjiang FOREACH_SUBDEV(sdev, sdev_iterator, dev) { 604418919fSjohnjiang sdev->sdev_port_id = RTE_MAX_ETHPORTS; 614418919fSjohnjiang } 622bfe3f2eSlogwang return 0; 632bfe3f2eSlogwang } 642bfe3f2eSlogwang 652bfe3f2eSlogwang static void 662bfe3f2eSlogwang fs_sub_device_free(struct rte_eth_dev *dev) 672bfe3f2eSlogwang { 682bfe3f2eSlogwang rte_free(PRIV(dev)->subs); 692bfe3f2eSlogwang } 702bfe3f2eSlogwang 712bfe3f2eSlogwang static void fs_hotplug_alarm(void *arg); 722bfe3f2eSlogwang 732bfe3f2eSlogwang int 742bfe3f2eSlogwang failsafe_hotplug_alarm_install(struct rte_eth_dev *dev) 752bfe3f2eSlogwang { 762bfe3f2eSlogwang int ret; 772bfe3f2eSlogwang 782bfe3f2eSlogwang if (dev == NULL) 792bfe3f2eSlogwang return -EINVAL; 802bfe3f2eSlogwang if (PRIV(dev)->pending_alarm) 812bfe3f2eSlogwang return 0; 82d30ea906Sjfb8856606 ret = rte_eal_alarm_set(failsafe_hotplug_poll * 1000, 832bfe3f2eSlogwang fs_hotplug_alarm, 842bfe3f2eSlogwang dev); 852bfe3f2eSlogwang if (ret) { 862bfe3f2eSlogwang ERROR("Could not set up plug-in event detection"); 872bfe3f2eSlogwang return ret; 882bfe3f2eSlogwang } 892bfe3f2eSlogwang PRIV(dev)->pending_alarm = 1; 902bfe3f2eSlogwang return 0; 912bfe3f2eSlogwang } 922bfe3f2eSlogwang 932bfe3f2eSlogwang int 942bfe3f2eSlogwang failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev) 952bfe3f2eSlogwang { 962bfe3f2eSlogwang int ret = 0; 972bfe3f2eSlogwang 982bfe3f2eSlogwang rte_errno = 0; 992bfe3f2eSlogwang rte_eal_alarm_cancel(fs_hotplug_alarm, dev); 1002bfe3f2eSlogwang if (rte_errno) { 1012bfe3f2eSlogwang ERROR("rte_eal_alarm_cancel failed (errno: %s)", 1022bfe3f2eSlogwang strerror(rte_errno)); 1032bfe3f2eSlogwang ret = -rte_errno; 1042bfe3f2eSlogwang } else { 1052bfe3f2eSlogwang PRIV(dev)->pending_alarm = 0; 1062bfe3f2eSlogwang } 1072bfe3f2eSlogwang return ret; 1082bfe3f2eSlogwang } 1092bfe3f2eSlogwang 1102bfe3f2eSlogwang static void 1112bfe3f2eSlogwang fs_hotplug_alarm(void *arg) 1122bfe3f2eSlogwang { 1132bfe3f2eSlogwang struct rte_eth_dev *dev = arg; 1142bfe3f2eSlogwang struct sub_device *sdev; 1152bfe3f2eSlogwang int ret; 1162bfe3f2eSlogwang uint8_t i; 1172bfe3f2eSlogwang 1182bfe3f2eSlogwang if (!PRIV(dev)->pending_alarm) 1192bfe3f2eSlogwang return; 1202bfe3f2eSlogwang PRIV(dev)->pending_alarm = 0; 1212bfe3f2eSlogwang FOREACH_SUBDEV(sdev, i, dev) 1222bfe3f2eSlogwang if (sdev->state != PRIV(dev)->state) 1232bfe3f2eSlogwang break; 1242bfe3f2eSlogwang /* if we have non-probed device */ 1252bfe3f2eSlogwang if (i != PRIV(dev)->subs_tail) { 126d30ea906Sjfb8856606 if (fs_lock(dev, 1) != 0) 127d30ea906Sjfb8856606 goto reinstall; 1282bfe3f2eSlogwang ret = failsafe_eth_dev_state_sync(dev); 129d30ea906Sjfb8856606 fs_unlock(dev, 1); 1302bfe3f2eSlogwang if (ret) 1312bfe3f2eSlogwang ERROR("Unable to synchronize sub_device state"); 1322bfe3f2eSlogwang } 1332bfe3f2eSlogwang failsafe_dev_remove(dev); 134d30ea906Sjfb8856606 reinstall: 1352bfe3f2eSlogwang ret = failsafe_hotplug_alarm_install(dev); 1362bfe3f2eSlogwang if (ret) 1372bfe3f2eSlogwang ERROR("Unable to set up next alarm"); 1382bfe3f2eSlogwang } 1392bfe3f2eSlogwang 1402bfe3f2eSlogwang static int 141d30ea906Sjfb8856606 fs_mutex_init(struct fs_priv *priv) 142d30ea906Sjfb8856606 { 143d30ea906Sjfb8856606 int ret; 144d30ea906Sjfb8856606 pthread_mutexattr_t attr; 145d30ea906Sjfb8856606 146d30ea906Sjfb8856606 ret = pthread_mutexattr_init(&attr); 147d30ea906Sjfb8856606 if (ret) { 148d30ea906Sjfb8856606 ERROR("Cannot initiate mutex attributes - %s", strerror(ret)); 149d30ea906Sjfb8856606 return ret; 150d30ea906Sjfb8856606 } 151d30ea906Sjfb8856606 /* Allow mutex relocks for the thread holding the mutex. */ 152d30ea906Sjfb8856606 ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 153d30ea906Sjfb8856606 if (ret) { 154d30ea906Sjfb8856606 ERROR("Cannot set mutex type - %s", strerror(ret)); 155d30ea906Sjfb8856606 return ret; 156d30ea906Sjfb8856606 } 157d30ea906Sjfb8856606 ret = pthread_mutex_init(&priv->hotplug_mutex, &attr); 158d30ea906Sjfb8856606 if (ret) { 159d30ea906Sjfb8856606 ERROR("Cannot initiate mutex - %s", strerror(ret)); 160d30ea906Sjfb8856606 return ret; 161d30ea906Sjfb8856606 } 162d30ea906Sjfb8856606 return 0; 163d30ea906Sjfb8856606 } 164d30ea906Sjfb8856606 165d30ea906Sjfb8856606 static int 1662bfe3f2eSlogwang fs_eth_dev_create(struct rte_vdev_device *vdev) 1672bfe3f2eSlogwang { 1682bfe3f2eSlogwang struct rte_eth_dev *dev; 1694418919fSjohnjiang struct rte_ether_addr *mac; 1702bfe3f2eSlogwang struct fs_priv *priv; 1712bfe3f2eSlogwang struct sub_device *sdev; 1722bfe3f2eSlogwang const char *params; 1732bfe3f2eSlogwang unsigned int socket_id; 1742bfe3f2eSlogwang uint8_t i; 1752bfe3f2eSlogwang int ret; 1762bfe3f2eSlogwang 1772bfe3f2eSlogwang dev = NULL; 1782bfe3f2eSlogwang priv = NULL; 1792bfe3f2eSlogwang socket_id = rte_socket_id(); 1802bfe3f2eSlogwang INFO("Creating fail-safe device on NUMA socket %u", socket_id); 1812bfe3f2eSlogwang params = rte_vdev_device_args(vdev); 1822bfe3f2eSlogwang if (params == NULL) { 1832bfe3f2eSlogwang ERROR("This PMD requires sub-devices, none provided"); 1842bfe3f2eSlogwang return -1; 1852bfe3f2eSlogwang } 1862bfe3f2eSlogwang dev = rte_eth_vdev_allocate(vdev, sizeof(*priv)); 1872bfe3f2eSlogwang if (dev == NULL) { 1882bfe3f2eSlogwang ERROR("Unable to allocate rte_eth_dev"); 1892bfe3f2eSlogwang return -1; 1902bfe3f2eSlogwang } 1912bfe3f2eSlogwang priv = PRIV(dev); 1924418919fSjohnjiang priv->data = dev->data; 193*0c6bd470Sfengbojiang priv->rxp = FS_RX_PROXY_INIT; 1942bfe3f2eSlogwang dev->dev_ops = &failsafe_ops; 1952bfe3f2eSlogwang dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0]; 1962bfe3f2eSlogwang dev->data->dev_link = eth_link; 1972bfe3f2eSlogwang PRIV(dev)->nb_mac_addr = 1; 1982bfe3f2eSlogwang TAILQ_INIT(&PRIV(dev)->flow_list); 1992bfe3f2eSlogwang dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 2002bfe3f2eSlogwang dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 2012bfe3f2eSlogwang ret = fs_sub_device_alloc(dev, params); 2022bfe3f2eSlogwang if (ret) { 2032bfe3f2eSlogwang ERROR("Could not allocate sub_devices"); 2042bfe3f2eSlogwang goto free_dev; 2052bfe3f2eSlogwang } 2062bfe3f2eSlogwang ret = failsafe_args_parse(dev, params); 2072bfe3f2eSlogwang if (ret) 2082bfe3f2eSlogwang goto free_subs; 209d30ea906Sjfb8856606 ret = rte_eth_dev_owner_new(&priv->my_owner.id); 210d30ea906Sjfb8856606 if (ret) { 211d30ea906Sjfb8856606 ERROR("Failed to get unique owner identifier"); 212d30ea906Sjfb8856606 goto free_args; 213d30ea906Sjfb8856606 } 214d30ea906Sjfb8856606 snprintf(priv->my_owner.name, sizeof(priv->my_owner.name), 215d30ea906Sjfb8856606 FAILSAFE_OWNER_NAME); 216d30ea906Sjfb8856606 DEBUG("Failsafe port %u owner info: %s_%016"PRIX64, dev->data->port_id, 217d30ea906Sjfb8856606 priv->my_owner.name, priv->my_owner.id); 218d30ea906Sjfb8856606 ret = rte_eth_dev_callback_register(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 219d30ea906Sjfb8856606 failsafe_eth_new_event_callback, 220d30ea906Sjfb8856606 dev); 221d30ea906Sjfb8856606 if (ret) { 222d30ea906Sjfb8856606 ERROR("Failed to register NEW callback"); 223d30ea906Sjfb8856606 goto free_args; 224d30ea906Sjfb8856606 } 2252bfe3f2eSlogwang ret = failsafe_eal_init(dev); 2262bfe3f2eSlogwang if (ret) 227d30ea906Sjfb8856606 goto unregister_new_callback; 228d30ea906Sjfb8856606 ret = fs_mutex_init(priv); 229d30ea906Sjfb8856606 if (ret) 230d30ea906Sjfb8856606 goto unregister_new_callback; 2312bfe3f2eSlogwang ret = failsafe_hotplug_alarm_install(dev); 2322bfe3f2eSlogwang if (ret) { 2332bfe3f2eSlogwang ERROR("Could not set up plug-in event detection"); 234d30ea906Sjfb8856606 goto unregister_new_callback; 2352bfe3f2eSlogwang } 2362bfe3f2eSlogwang mac = &dev->data->mac_addrs[0]; 237d30ea906Sjfb8856606 if (failsafe_mac_from_arg) { 2382bfe3f2eSlogwang /* 2392bfe3f2eSlogwang * If MAC address was provided as a parameter, 2402bfe3f2eSlogwang * apply to all probed slaves. 2412bfe3f2eSlogwang */ 2422bfe3f2eSlogwang FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { 2432bfe3f2eSlogwang ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 2442bfe3f2eSlogwang mac); 2452bfe3f2eSlogwang if (ret) { 2462bfe3f2eSlogwang ERROR("Failed to set default MAC address"); 247579bf1e2Sjfb8856606 goto cancel_alarm; 2482bfe3f2eSlogwang } 2492bfe3f2eSlogwang } 2502bfe3f2eSlogwang } else { 2512bfe3f2eSlogwang /* 2522bfe3f2eSlogwang * Use the ether_addr from first probed 2532bfe3f2eSlogwang * device, either preferred or fallback. 2542bfe3f2eSlogwang */ 2552bfe3f2eSlogwang FOREACH_SUBDEV(sdev, i, dev) 2562bfe3f2eSlogwang if (sdev->state >= DEV_PROBED) { 2574418919fSjohnjiang rte_ether_addr_copy( 2584418919fSjohnjiang Ð(sdev)->data->mac_addrs[0], mac); 2592bfe3f2eSlogwang break; 2602bfe3f2eSlogwang } 2612bfe3f2eSlogwang /* 2622bfe3f2eSlogwang * If no device has been probed and no ether_addr 2632bfe3f2eSlogwang * has been provided on the command line, use a random 2642bfe3f2eSlogwang * valid one. 2652bfe3f2eSlogwang * It will be applied during future slave state syncs to 2662bfe3f2eSlogwang * probed slaves. 2672bfe3f2eSlogwang */ 2682bfe3f2eSlogwang if (i == priv->subs_tail) 2694418919fSjohnjiang rte_eth_random_addr(&mac->addr_bytes[0]); 2702bfe3f2eSlogwang } 2712bfe3f2eSlogwang INFO("MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 2722bfe3f2eSlogwang mac->addr_bytes[0], mac->addr_bytes[1], 2732bfe3f2eSlogwang mac->addr_bytes[2], mac->addr_bytes[3], 2742bfe3f2eSlogwang mac->addr_bytes[4], mac->addr_bytes[5]); 2752bfe3f2eSlogwang dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 276d30ea906Sjfb8856606 PRIV(dev)->intr_handle = (struct rte_intr_handle){ 277d30ea906Sjfb8856606 .fd = -1, 278d30ea906Sjfb8856606 .type = RTE_INTR_HANDLE_EXT, 279d30ea906Sjfb8856606 }; 280d30ea906Sjfb8856606 rte_eth_dev_probing_finish(dev); 2812bfe3f2eSlogwang return 0; 282579bf1e2Sjfb8856606 cancel_alarm: 283579bf1e2Sjfb8856606 failsafe_hotplug_alarm_cancel(dev); 284d30ea906Sjfb8856606 unregister_new_callback: 285d30ea906Sjfb8856606 rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 286d30ea906Sjfb8856606 failsafe_eth_new_event_callback, dev); 2872bfe3f2eSlogwang free_args: 2882bfe3f2eSlogwang failsafe_args_free(dev); 2892bfe3f2eSlogwang free_subs: 2902bfe3f2eSlogwang fs_sub_device_free(dev); 2912bfe3f2eSlogwang free_dev: 292d30ea906Sjfb8856606 /* mac_addrs must not be freed alone because part of dev_private */ 293d30ea906Sjfb8856606 dev->data->mac_addrs = NULL; 2942bfe3f2eSlogwang rte_eth_dev_release_port(dev); 2952bfe3f2eSlogwang return -1; 2962bfe3f2eSlogwang } 2972bfe3f2eSlogwang 2982bfe3f2eSlogwang static int 2992bfe3f2eSlogwang fs_rte_eth_free(const char *name) 3002bfe3f2eSlogwang { 3012bfe3f2eSlogwang struct rte_eth_dev *dev; 3022bfe3f2eSlogwang int ret; 3032bfe3f2eSlogwang 3042bfe3f2eSlogwang dev = rte_eth_dev_allocated(name); 3052bfe3f2eSlogwang if (dev == NULL) 3062bfe3f2eSlogwang return -ENODEV; 307d30ea906Sjfb8856606 rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 308d30ea906Sjfb8856606 failsafe_eth_new_event_callback, dev); 3092bfe3f2eSlogwang ret = failsafe_eal_uninit(dev); 3102bfe3f2eSlogwang if (ret) 3112bfe3f2eSlogwang ERROR("Error while uninitializing sub-EAL"); 3122bfe3f2eSlogwang failsafe_args_free(dev); 3132bfe3f2eSlogwang fs_sub_device_free(dev); 314d30ea906Sjfb8856606 ret = pthread_mutex_destroy(&PRIV(dev)->hotplug_mutex); 315d30ea906Sjfb8856606 if (ret) 316d30ea906Sjfb8856606 ERROR("Error while destroying hotplug mutex"); 317d30ea906Sjfb8856606 rte_free(PRIV(dev)->mcast_addrs); 318d30ea906Sjfb8856606 /* mac_addrs must not be freed alone because part of dev_private */ 319d30ea906Sjfb8856606 dev->data->mac_addrs = NULL; 3202bfe3f2eSlogwang rte_eth_dev_release_port(dev); 3212bfe3f2eSlogwang return ret; 3222bfe3f2eSlogwang } 3232bfe3f2eSlogwang 3244418919fSjohnjiang static bool 3254418919fSjohnjiang devargs_already_listed(struct rte_devargs *devargs) 3264418919fSjohnjiang { 3274418919fSjohnjiang struct rte_devargs *list_da; 3284418919fSjohnjiang 3294418919fSjohnjiang RTE_EAL_DEVARGS_FOREACH(devargs->bus->name, list_da) { 3304418919fSjohnjiang if (strcmp(list_da->name, devargs->name) == 0) 3314418919fSjohnjiang /* devargs already in the list */ 3324418919fSjohnjiang return true; 3334418919fSjohnjiang } 3344418919fSjohnjiang return false; 3354418919fSjohnjiang } 3364418919fSjohnjiang 3372bfe3f2eSlogwang static int 3382bfe3f2eSlogwang rte_pmd_failsafe_probe(struct rte_vdev_device *vdev) 3392bfe3f2eSlogwang { 3402bfe3f2eSlogwang const char *name; 341d30ea906Sjfb8856606 struct rte_eth_dev *eth_dev; 3424418919fSjohnjiang struct sub_device *sdev; 3434418919fSjohnjiang struct rte_devargs devargs; 3444418919fSjohnjiang uint8_t i; 3454418919fSjohnjiang int ret; 3462bfe3f2eSlogwang 3472bfe3f2eSlogwang name = rte_vdev_device_name(vdev); 3482bfe3f2eSlogwang INFO("Initializing " FAILSAFE_DRIVER_NAME " for %s", 3492bfe3f2eSlogwang name); 350d30ea906Sjfb8856606 351d30ea906Sjfb8856606 if (rte_eal_process_type() == RTE_PROC_SECONDARY && 352d30ea906Sjfb8856606 strlen(rte_vdev_device_args(vdev)) == 0) { 353d30ea906Sjfb8856606 eth_dev = rte_eth_dev_attach_secondary(name); 354d30ea906Sjfb8856606 if (!eth_dev) { 355d30ea906Sjfb8856606 ERROR("Failed to probe %s", name); 356d30ea906Sjfb8856606 return -1; 357d30ea906Sjfb8856606 } 358d30ea906Sjfb8856606 eth_dev->dev_ops = &failsafe_ops; 359d30ea906Sjfb8856606 eth_dev->device = &vdev->device; 3604418919fSjohnjiang eth_dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 3614418919fSjohnjiang eth_dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 3624418919fSjohnjiang /* 3634418919fSjohnjiang * Failsafe will attempt to probe all of its sub-devices. 3644418919fSjohnjiang * Any failure in sub-devices is not a fatal error. 3654418919fSjohnjiang * A sub-device can be plugged later. 3664418919fSjohnjiang */ 3674418919fSjohnjiang FOREACH_SUBDEV(sdev, i, eth_dev) { 3684418919fSjohnjiang /* skip empty devargs */ 3694418919fSjohnjiang if (sdev->devargs.name[0] == '\0') 3704418919fSjohnjiang continue; 3714418919fSjohnjiang 3724418919fSjohnjiang /* rebuild devargs to be able to get the bus name. */ 3734418919fSjohnjiang ret = rte_devargs_parse(&devargs, 3744418919fSjohnjiang sdev->devargs.name); 3754418919fSjohnjiang if (ret != 0) { 3764418919fSjohnjiang ERROR("Failed to parse devargs %s", 3774418919fSjohnjiang devargs.name); 3784418919fSjohnjiang continue; 3794418919fSjohnjiang } 3804418919fSjohnjiang if (!devargs_already_listed(&devargs)) { 3814418919fSjohnjiang ret = rte_dev_probe(devargs.name); 3824418919fSjohnjiang if (ret < 0) { 3834418919fSjohnjiang ERROR("Failed to probe devargs %s", 3844418919fSjohnjiang devargs.name); 3854418919fSjohnjiang continue; 3864418919fSjohnjiang } 3874418919fSjohnjiang } 3884418919fSjohnjiang } 389d30ea906Sjfb8856606 rte_eth_dev_probing_finish(eth_dev); 390d30ea906Sjfb8856606 return 0; 391d30ea906Sjfb8856606 } 392d30ea906Sjfb8856606 3932bfe3f2eSlogwang return fs_eth_dev_create(vdev); 3942bfe3f2eSlogwang } 3952bfe3f2eSlogwang 3962bfe3f2eSlogwang static int 3972bfe3f2eSlogwang rte_pmd_failsafe_remove(struct rte_vdev_device *vdev) 3982bfe3f2eSlogwang { 3992bfe3f2eSlogwang const char *name; 4002bfe3f2eSlogwang 4012bfe3f2eSlogwang name = rte_vdev_device_name(vdev); 4022bfe3f2eSlogwang INFO("Uninitializing " FAILSAFE_DRIVER_NAME " for %s", name); 4032bfe3f2eSlogwang return fs_rte_eth_free(name); 4042bfe3f2eSlogwang } 4052bfe3f2eSlogwang 4062bfe3f2eSlogwang static struct rte_vdev_driver failsafe_drv = { 4072bfe3f2eSlogwang .probe = rte_pmd_failsafe_probe, 4082bfe3f2eSlogwang .remove = rte_pmd_failsafe_remove, 4092bfe3f2eSlogwang }; 4102bfe3f2eSlogwang 4112bfe3f2eSlogwang RTE_PMD_REGISTER_VDEV(net_failsafe, failsafe_drv); 4122bfe3f2eSlogwang RTE_PMD_REGISTER_PARAM_STRING(net_failsafe, PMD_FAILSAFE_PARAM_STRING); 413d30ea906Sjfb8856606 414d30ea906Sjfb8856606 RTE_INIT(failsafe_init_log) 415d30ea906Sjfb8856606 { 416d30ea906Sjfb8856606 failsafe_logtype = rte_log_register("pmd.net.failsafe"); 417d30ea906Sjfb8856606 if (failsafe_logtype >= 0) 418d30ea906Sjfb8856606 rte_log_set_level(failsafe_logtype, RTE_LOG_NOTICE); 419d30ea906Sjfb8856606 } 420