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 6a46f8d58SGaetan Rivet #include <rte_alarm.h> 7a46f8d58SGaetan Rivet #include <rte_malloc.h> 8ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 9a46f8d58SGaetan Rivet #include <rte_ethdev_vdev.h> 10a46f8d58SGaetan Rivet #include <rte_devargs.h> 11a46f8d58SGaetan Rivet #include <rte_kvargs.h> 12d4a586d2SJianfeng Tan #include <rte_bus_vdev.h> 13a46f8d58SGaetan Rivet 14a46f8d58SGaetan Rivet #include "failsafe_private.h" 15a46f8d58SGaetan Rivet 16ebeb72ecSStephen Hemminger int failsafe_logtype; 17ebeb72ecSStephen Hemminger 18a46f8d58SGaetan Rivet const char pmd_failsafe_driver_name[] = FAILSAFE_DRIVER_NAME; 19a46f8d58SGaetan Rivet static const struct rte_eth_link eth_link = { 20a46f8d58SGaetan Rivet .link_speed = ETH_SPEED_NUM_10G, 21a46f8d58SGaetan Rivet .link_duplex = ETH_LINK_FULL_DUPLEX, 22a46f8d58SGaetan Rivet .link_status = ETH_LINK_UP, 231e3a958fSThomas Monjalon .link_autoneg = ETH_LINK_AUTONEG, 24a46f8d58SGaetan Rivet }; 25a46f8d58SGaetan Rivet 26a46f8d58SGaetan Rivet static int 27a46f8d58SGaetan Rivet fs_sub_device_alloc(struct rte_eth_dev *dev, 28a46f8d58SGaetan Rivet const char *params) 29a46f8d58SGaetan Rivet { 30a46f8d58SGaetan Rivet uint8_t nb_subs; 31a46f8d58SGaetan Rivet int ret; 328052bbd9SMatan Azrad int i; 33a46f8d58SGaetan Rivet 34a46f8d58SGaetan Rivet ret = failsafe_args_count_subdevice(dev, params); 35a46f8d58SGaetan Rivet if (ret) 36a46f8d58SGaetan Rivet return ret; 37a46f8d58SGaetan Rivet if (PRIV(dev)->subs_tail > FAILSAFE_MAX_ETHPORTS) { 38a46f8d58SGaetan Rivet ERROR("Cannot allocate more than %d ports", 39a46f8d58SGaetan Rivet FAILSAFE_MAX_ETHPORTS); 40a46f8d58SGaetan Rivet return -ENOSPC; 41a46f8d58SGaetan Rivet } 42a46f8d58SGaetan Rivet nb_subs = PRIV(dev)->subs_tail; 43a46f8d58SGaetan Rivet PRIV(dev)->subs = rte_zmalloc(NULL, 44a46f8d58SGaetan Rivet sizeof(struct sub_device) * nb_subs, 45a46f8d58SGaetan Rivet RTE_CACHE_LINE_SIZE); 46a46f8d58SGaetan Rivet if (PRIV(dev)->subs == NULL) { 47a46f8d58SGaetan Rivet ERROR("Could not allocate sub_devices"); 48a46f8d58SGaetan Rivet return -ENOMEM; 49a46f8d58SGaetan Rivet } 508052bbd9SMatan Azrad /* Initiate static sub devices linked list. */ 518052bbd9SMatan Azrad for (i = 1; i < nb_subs; i++) 528052bbd9SMatan Azrad PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs + i; 538052bbd9SMatan Azrad PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs; 54a46f8d58SGaetan Rivet return 0; 55a46f8d58SGaetan Rivet } 56a46f8d58SGaetan Rivet 57a46f8d58SGaetan Rivet static void 58a46f8d58SGaetan Rivet fs_sub_device_free(struct rte_eth_dev *dev) 59a46f8d58SGaetan Rivet { 60a46f8d58SGaetan Rivet rte_free(PRIV(dev)->subs); 61a46f8d58SGaetan Rivet } 62a46f8d58SGaetan Rivet 63ebea83f8SGaetan Rivet static void fs_hotplug_alarm(void *arg); 64ebea83f8SGaetan Rivet 65ebea83f8SGaetan Rivet int 66ebea83f8SGaetan Rivet failsafe_hotplug_alarm_install(struct rte_eth_dev *dev) 67ebea83f8SGaetan Rivet { 68ebea83f8SGaetan Rivet int ret; 69ebea83f8SGaetan Rivet 70ebea83f8SGaetan Rivet if (dev == NULL) 71ebea83f8SGaetan Rivet return -EINVAL; 72ebea83f8SGaetan Rivet if (PRIV(dev)->pending_alarm) 73ebea83f8SGaetan Rivet return 0; 74ebea83f8SGaetan Rivet ret = rte_eal_alarm_set(hotplug_poll * 1000, 75ebea83f8SGaetan Rivet fs_hotplug_alarm, 76ebea83f8SGaetan Rivet dev); 77ebea83f8SGaetan Rivet if (ret) { 78ebea83f8SGaetan Rivet ERROR("Could not set up plug-in event detection"); 79ebea83f8SGaetan Rivet return ret; 80ebea83f8SGaetan Rivet } 81ebea83f8SGaetan Rivet PRIV(dev)->pending_alarm = 1; 82ebea83f8SGaetan Rivet return 0; 83ebea83f8SGaetan Rivet } 84ebea83f8SGaetan Rivet 85ebea83f8SGaetan Rivet int 86ebea83f8SGaetan Rivet failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev) 87ebea83f8SGaetan Rivet { 88ebea83f8SGaetan Rivet int ret = 0; 89ebea83f8SGaetan Rivet 90ebea83f8SGaetan Rivet rte_errno = 0; 91ebea83f8SGaetan Rivet rte_eal_alarm_cancel(fs_hotplug_alarm, dev); 92ebea83f8SGaetan Rivet if (rte_errno) { 93ebea83f8SGaetan Rivet ERROR("rte_eal_alarm_cancel failed (errno: %s)", 94ebea83f8SGaetan Rivet strerror(rte_errno)); 95ebea83f8SGaetan Rivet ret = -rte_errno; 96ebea83f8SGaetan Rivet } else { 97ebea83f8SGaetan Rivet PRIV(dev)->pending_alarm = 0; 98ebea83f8SGaetan Rivet } 99ebea83f8SGaetan Rivet return ret; 100ebea83f8SGaetan Rivet } 101ebea83f8SGaetan Rivet 102ebea83f8SGaetan Rivet static void 103ebea83f8SGaetan Rivet fs_hotplug_alarm(void *arg) 104ebea83f8SGaetan Rivet { 105ebea83f8SGaetan Rivet struct rte_eth_dev *dev = arg; 106ebea83f8SGaetan Rivet struct sub_device *sdev; 107ebea83f8SGaetan Rivet int ret; 108ebea83f8SGaetan Rivet uint8_t i; 109ebea83f8SGaetan Rivet 110ebea83f8SGaetan Rivet if (!PRIV(dev)->pending_alarm) 111ebea83f8SGaetan Rivet return; 112ebea83f8SGaetan Rivet PRIV(dev)->pending_alarm = 0; 113ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 114ebea83f8SGaetan Rivet if (sdev->state != PRIV(dev)->state) 115ebea83f8SGaetan Rivet break; 116ebea83f8SGaetan Rivet /* if we have non-probed device */ 117ebea83f8SGaetan Rivet if (i != PRIV(dev)->subs_tail) { 118655fcd68SMatan Azrad if (fs_lock(dev, 1) != 0) 119655fcd68SMatan Azrad goto reinstall; 120ebea83f8SGaetan Rivet ret = failsafe_eth_dev_state_sync(dev); 121655fcd68SMatan Azrad fs_unlock(dev, 1); 122ebea83f8SGaetan Rivet if (ret) 123ebea83f8SGaetan Rivet ERROR("Unable to synchronize sub_device state"); 124ebea83f8SGaetan Rivet } 125598fb8aeSGaetan Rivet failsafe_dev_remove(dev); 126655fcd68SMatan Azrad reinstall: 127ebea83f8SGaetan Rivet ret = failsafe_hotplug_alarm_install(dev); 128ebea83f8SGaetan Rivet if (ret) 129ebea83f8SGaetan Rivet ERROR("Unable to set up next alarm"); 130ebea83f8SGaetan Rivet } 131ebea83f8SGaetan Rivet 132a46f8d58SGaetan Rivet static int 133655fcd68SMatan Azrad fs_mutex_init(struct fs_priv *priv) 134655fcd68SMatan Azrad { 135655fcd68SMatan Azrad int ret; 136655fcd68SMatan Azrad pthread_mutexattr_t attr; 137655fcd68SMatan Azrad 138655fcd68SMatan Azrad ret = pthread_mutexattr_init(&attr); 139655fcd68SMatan Azrad if (ret) { 140655fcd68SMatan Azrad ERROR("Cannot initiate mutex attributes - %s", strerror(ret)); 141655fcd68SMatan Azrad return ret; 142655fcd68SMatan Azrad } 143655fcd68SMatan Azrad /* Allow mutex relocks for the thread holding the mutex. */ 144655fcd68SMatan Azrad ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 145655fcd68SMatan Azrad if (ret) { 146655fcd68SMatan Azrad ERROR("Cannot set mutex type - %s", strerror(ret)); 147655fcd68SMatan Azrad return ret; 148655fcd68SMatan Azrad } 149655fcd68SMatan Azrad ret = pthread_mutex_init(&priv->hotplug_mutex, &attr); 150655fcd68SMatan Azrad if (ret) { 151655fcd68SMatan Azrad ERROR("Cannot initiate mutex - %s", strerror(ret)); 152655fcd68SMatan Azrad return ret; 153655fcd68SMatan Azrad } 154655fcd68SMatan Azrad return 0; 155655fcd68SMatan Azrad } 156655fcd68SMatan Azrad 157655fcd68SMatan Azrad static int 158a46f8d58SGaetan Rivet fs_eth_dev_create(struct rte_vdev_device *vdev) 159a46f8d58SGaetan Rivet { 160a46f8d58SGaetan Rivet struct rte_eth_dev *dev; 161a46f8d58SGaetan Rivet struct ether_addr *mac; 162a46f8d58SGaetan Rivet struct fs_priv *priv; 163a46f8d58SGaetan Rivet struct sub_device *sdev; 164a46f8d58SGaetan Rivet const char *params; 165a46f8d58SGaetan Rivet unsigned int socket_id; 166a46f8d58SGaetan Rivet uint8_t i; 167a46f8d58SGaetan Rivet int ret; 168a46f8d58SGaetan Rivet 169a46f8d58SGaetan Rivet dev = NULL; 170a46f8d58SGaetan Rivet priv = NULL; 171a46f8d58SGaetan Rivet socket_id = rte_socket_id(); 172a46f8d58SGaetan Rivet INFO("Creating fail-safe device on NUMA socket %u", socket_id); 173a46f8d58SGaetan Rivet params = rte_vdev_device_args(vdev); 174a46f8d58SGaetan Rivet if (params == NULL) { 175a46f8d58SGaetan Rivet ERROR("This PMD requires sub-devices, none provided"); 176a46f8d58SGaetan Rivet return -1; 177a46f8d58SGaetan Rivet } 178a46f8d58SGaetan Rivet dev = rte_eth_vdev_allocate(vdev, sizeof(*priv)); 179a46f8d58SGaetan Rivet if (dev == NULL) { 180a46f8d58SGaetan Rivet ERROR("Unable to allocate rte_eth_dev"); 181a46f8d58SGaetan Rivet return -1; 182a46f8d58SGaetan Rivet } 183a46f8d58SGaetan Rivet priv = PRIV(dev); 184a46f8d58SGaetan Rivet priv->dev = dev; 185a46f8d58SGaetan Rivet dev->dev_ops = &failsafe_ops; 186a46f8d58SGaetan Rivet dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0]; 187a46f8d58SGaetan Rivet dev->data->dev_link = eth_link; 188a46f8d58SGaetan Rivet PRIV(dev)->nb_mac_addr = 1; 189b737a1eeSGaetan Rivet TAILQ_INIT(&PRIV(dev)->flow_list); 190a46f8d58SGaetan Rivet dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 191a46f8d58SGaetan Rivet dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 192a46f8d58SGaetan Rivet ret = fs_sub_device_alloc(dev, params); 193a46f8d58SGaetan Rivet if (ret) { 194a46f8d58SGaetan Rivet ERROR("Could not allocate sub_devices"); 195a46f8d58SGaetan Rivet goto free_dev; 196a46f8d58SGaetan Rivet } 197a46f8d58SGaetan Rivet ret = failsafe_args_parse(dev, params); 198a46f8d58SGaetan Rivet if (ret) 199a46f8d58SGaetan Rivet goto free_subs; 200dcd0c9c3SMatan Azrad ret = rte_eth_dev_owner_new(&priv->my_owner.id); 201dcd0c9c3SMatan Azrad if (ret) { 202dcd0c9c3SMatan Azrad ERROR("Failed to get unique owner identifier"); 203dcd0c9c3SMatan Azrad goto free_args; 204dcd0c9c3SMatan Azrad } 205dcd0c9c3SMatan Azrad snprintf(priv->my_owner.name, sizeof(priv->my_owner.name), 206dcd0c9c3SMatan Azrad FAILSAFE_OWNER_NAME); 2077fda13d3SMatan Azrad DEBUG("Failsafe port %u owner info: %s_%016"PRIX64, dev->data->port_id, 2087fda13d3SMatan Azrad priv->my_owner.name, priv->my_owner.id); 2097fda13d3SMatan Azrad ret = rte_eth_dev_callback_register(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 2107fda13d3SMatan Azrad failsafe_eth_new_event_callback, 2117fda13d3SMatan Azrad dev); 2127fda13d3SMatan Azrad if (ret) { 2137fda13d3SMatan Azrad ERROR("Failed to register NEW callback"); 2147fda13d3SMatan Azrad goto free_args; 2157fda13d3SMatan Azrad } 216a46f8d58SGaetan Rivet ret = failsafe_eal_init(dev); 217a46f8d58SGaetan Rivet if (ret) 2187fda13d3SMatan Azrad goto unregister_new_callback; 219655fcd68SMatan Azrad ret = fs_mutex_init(priv); 220655fcd68SMatan Azrad if (ret) 2217fda13d3SMatan Azrad goto unregister_new_callback; 222ebea83f8SGaetan Rivet ret = failsafe_hotplug_alarm_install(dev); 223ebea83f8SGaetan Rivet if (ret) { 224ebea83f8SGaetan Rivet ERROR("Could not set up plug-in event detection"); 2257fda13d3SMatan Azrad goto unregister_new_callback; 226ebea83f8SGaetan Rivet } 227a46f8d58SGaetan Rivet mac = &dev->data->mac_addrs[0]; 228a46f8d58SGaetan Rivet if (mac_from_arg) { 229a46f8d58SGaetan Rivet /* 230a46f8d58SGaetan Rivet * If MAC address was provided as a parameter, 231a46f8d58SGaetan Rivet * apply to all probed slaves. 232a46f8d58SGaetan Rivet */ 233a46f8d58SGaetan Rivet FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { 234a46f8d58SGaetan Rivet ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 235a46f8d58SGaetan Rivet mac); 236a46f8d58SGaetan Rivet if (ret) { 237a46f8d58SGaetan Rivet ERROR("Failed to set default MAC address"); 23895e7a72fSRaslan Darawsheh goto cancel_alarm; 239a46f8d58SGaetan Rivet } 240a46f8d58SGaetan Rivet } 241a46f8d58SGaetan Rivet } else { 242a46f8d58SGaetan Rivet /* 243a46f8d58SGaetan Rivet * Use the ether_addr from first probed 244a46f8d58SGaetan Rivet * device, either preferred or fallback. 245a46f8d58SGaetan Rivet */ 246a46f8d58SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 247a46f8d58SGaetan Rivet if (sdev->state >= DEV_PROBED) { 248a46f8d58SGaetan Rivet ether_addr_copy(Ð(sdev)->data->mac_addrs[0], 249a46f8d58SGaetan Rivet mac); 250a46f8d58SGaetan Rivet break; 251a46f8d58SGaetan Rivet } 252a46f8d58SGaetan Rivet /* 253a46f8d58SGaetan Rivet * If no device has been probed and no ether_addr 254a46f8d58SGaetan Rivet * has been provided on the command line, use a random 255a46f8d58SGaetan Rivet * valid one. 256a46f8d58SGaetan Rivet * It will be applied during future slave state syncs to 257a46f8d58SGaetan Rivet * probed slaves. 258a46f8d58SGaetan Rivet */ 259a46f8d58SGaetan Rivet if (i == priv->subs_tail) 260a46f8d58SGaetan Rivet eth_random_addr(&mac->addr_bytes[0]); 261a46f8d58SGaetan Rivet } 262a46f8d58SGaetan Rivet INFO("MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 263a46f8d58SGaetan Rivet mac->addr_bytes[0], mac->addr_bytes[1], 264a46f8d58SGaetan Rivet mac->addr_bytes[2], mac->addr_bytes[3], 265a46f8d58SGaetan Rivet mac->addr_bytes[4], mac->addr_bytes[5]); 266ad7d6a35SGaetan Rivet dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 2679e0360aeSMoti Haimovsky PRIV(dev)->intr_handle = (struct rte_intr_handle){ 2689e0360aeSMoti Haimovsky .fd = -1, 2699e0360aeSMoti Haimovsky .type = RTE_INTR_HANDLE_EXT, 2709e0360aeSMoti Haimovsky }; 271fbe90cddSThomas Monjalon rte_eth_dev_probing_finish(dev); 272a46f8d58SGaetan Rivet return 0; 27395e7a72fSRaslan Darawsheh cancel_alarm: 27495e7a72fSRaslan Darawsheh failsafe_hotplug_alarm_cancel(dev); 2757fda13d3SMatan Azrad unregister_new_callback: 2767fda13d3SMatan Azrad rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 2777fda13d3SMatan Azrad failsafe_eth_new_event_callback, dev); 278a46f8d58SGaetan Rivet free_args: 279a46f8d58SGaetan Rivet failsafe_args_free(dev); 280a46f8d58SGaetan Rivet free_subs: 281a46f8d58SGaetan Rivet fs_sub_device_free(dev); 282a46f8d58SGaetan Rivet free_dev: 283a46f8d58SGaetan Rivet rte_free(PRIV(dev)); 284a46f8d58SGaetan Rivet rte_eth_dev_release_port(dev); 285a46f8d58SGaetan Rivet return -1; 286a46f8d58SGaetan Rivet } 287a46f8d58SGaetan Rivet 288a46f8d58SGaetan Rivet static int 289a46f8d58SGaetan Rivet fs_rte_eth_free(const char *name) 290a46f8d58SGaetan Rivet { 291a46f8d58SGaetan Rivet struct rte_eth_dev *dev; 292a46f8d58SGaetan Rivet int ret; 293a46f8d58SGaetan Rivet 294a46f8d58SGaetan Rivet dev = rte_eth_dev_allocated(name); 295a46f8d58SGaetan Rivet if (dev == NULL) 296a46f8d58SGaetan Rivet return -ENODEV; 2977fda13d3SMatan Azrad rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 2987fda13d3SMatan Azrad failsafe_eth_new_event_callback, dev); 299a46f8d58SGaetan Rivet ret = failsafe_eal_uninit(dev); 300a46f8d58SGaetan Rivet if (ret) 301a46f8d58SGaetan Rivet ERROR("Error while uninitializing sub-EAL"); 302a46f8d58SGaetan Rivet failsafe_args_free(dev); 303a46f8d58SGaetan Rivet fs_sub_device_free(dev); 304655fcd68SMatan Azrad ret = pthread_mutex_destroy(&PRIV(dev)->hotplug_mutex); 305655fcd68SMatan Azrad if (ret) 306655fcd68SMatan Azrad ERROR("Error while destroying hotplug mutex"); 307a46f8d58SGaetan Rivet rte_free(PRIV(dev)); 308a46f8d58SGaetan Rivet rte_eth_dev_release_port(dev); 309a46f8d58SGaetan Rivet return ret; 310a46f8d58SGaetan Rivet } 311a46f8d58SGaetan Rivet 312a46f8d58SGaetan Rivet static int 313a46f8d58SGaetan Rivet rte_pmd_failsafe_probe(struct rte_vdev_device *vdev) 314a46f8d58SGaetan Rivet { 315a46f8d58SGaetan Rivet const char *name; 316ee27edbeSJianfeng Tan struct rte_eth_dev *eth_dev; 317a46f8d58SGaetan Rivet 318a46f8d58SGaetan Rivet name = rte_vdev_device_name(vdev); 319a46f8d58SGaetan Rivet INFO("Initializing " FAILSAFE_DRIVER_NAME " for %s", 320a46f8d58SGaetan Rivet name); 321ee27edbeSJianfeng Tan 322ee27edbeSJianfeng Tan if (rte_eal_process_type() == RTE_PROC_SECONDARY && 323ee27edbeSJianfeng Tan strlen(rte_vdev_device_args(vdev)) == 0) { 324ee27edbeSJianfeng Tan eth_dev = rte_eth_dev_attach_secondary(name); 325ee27edbeSJianfeng Tan if (!eth_dev) { 326ebeb72ecSStephen Hemminger ERROR("Failed to probe %s", name); 327ee27edbeSJianfeng Tan return -1; 328ee27edbeSJianfeng Tan } 329ee27edbeSJianfeng Tan /* TODO: request info from primary to set up Rx and Tx */ 330ee27edbeSJianfeng Tan eth_dev->dev_ops = &failsafe_ops; 331*d1c3ab22SFerruh Yigit eth_dev->device = &vdev->device; 332fbe90cddSThomas Monjalon rte_eth_dev_probing_finish(eth_dev); 333ee27edbeSJianfeng Tan return 0; 334ee27edbeSJianfeng Tan } 335ee27edbeSJianfeng Tan 336a46f8d58SGaetan Rivet return fs_eth_dev_create(vdev); 337a46f8d58SGaetan Rivet } 338a46f8d58SGaetan Rivet 339a46f8d58SGaetan Rivet static int 340a46f8d58SGaetan Rivet rte_pmd_failsafe_remove(struct rte_vdev_device *vdev) 341a46f8d58SGaetan Rivet { 342a46f8d58SGaetan Rivet const char *name; 343a46f8d58SGaetan Rivet 344a46f8d58SGaetan Rivet name = rte_vdev_device_name(vdev); 345a46f8d58SGaetan Rivet INFO("Uninitializing " FAILSAFE_DRIVER_NAME " for %s", name); 346a46f8d58SGaetan Rivet return fs_rte_eth_free(name); 347a46f8d58SGaetan Rivet } 348a46f8d58SGaetan Rivet 349a46f8d58SGaetan Rivet static struct rte_vdev_driver failsafe_drv = { 350a46f8d58SGaetan Rivet .probe = rte_pmd_failsafe_probe, 351a46f8d58SGaetan Rivet .remove = rte_pmd_failsafe_remove, 352a46f8d58SGaetan Rivet }; 353a46f8d58SGaetan Rivet 354a46f8d58SGaetan Rivet RTE_PMD_REGISTER_VDEV(net_failsafe, failsafe_drv); 355a46f8d58SGaetan Rivet RTE_PMD_REGISTER_PARAM_STRING(net_failsafe, PMD_FAILSAFE_PARAM_STRING); 356ebeb72ecSStephen Hemminger 357f8e99896SThomas Monjalon RTE_INIT(failsafe_init_log) 358ebeb72ecSStephen Hemminger { 359ebeb72ecSStephen Hemminger failsafe_logtype = rte_log_register("pmd.net.failsafe"); 360ebeb72ecSStephen Hemminger if (failsafe_logtype >= 0) 361ebeb72ecSStephen Hemminger rte_log_set_level(failsafe_logtype, RTE_LOG_NOTICE); 362ebeb72ecSStephen Hemminger } 363