1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2017 6WIND S.A. 3 * Copyright 2017 Mellanox Technologies, Ltd 4 */ 5 6 #include <rte_string_fns.h> 7 #include <rte_malloc.h> 8 9 #include "failsafe_private.h" 10 11 static int 12 fs_ethdev_portid_get(const char *name, uint16_t *port_id) 13 { 14 uint16_t pid; 15 size_t len; 16 17 if (name == NULL) { 18 DEBUG("Null pointer is specified\n"); 19 return -EINVAL; 20 } 21 len = strlen(name); 22 for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) { 23 if (rte_eth_dev_is_valid_port(pid) && 24 !strncmp(name, rte_eth_devices[pid].device->name, len)) { 25 *port_id = pid; 26 return 0; 27 } 28 } 29 return -ENODEV; 30 } 31 32 static int 33 fs_bus_init(struct rte_eth_dev *dev) 34 { 35 struct sub_device *sdev; 36 struct rte_devargs *da; 37 uint8_t i; 38 uint16_t pid; 39 int ret; 40 41 FOREACH_SUBDEV(sdev, i, dev) { 42 if (sdev->state != DEV_PARSED) 43 continue; 44 da = &sdev->devargs; 45 if (fs_ethdev_portid_get(da->name, &pid) != 0) { 46 struct rte_eth_dev_owner pid_owner; 47 48 ret = rte_eal_hotplug_add(da->bus->name, 49 da->name, 50 da->args); 51 if (ret < 0) { 52 ERROR("sub_device %d probe failed %s%s%s", i, 53 rte_errno ? "(" : "", 54 rte_errno ? strerror(rte_errno) : "", 55 rte_errno ? ")" : ""); 56 continue; 57 } 58 if (fs_ethdev_portid_get(da->name, &pid) != 0) { 59 ERROR("sub_device %d init went wrong", i); 60 return -ENODEV; 61 } 62 /* 63 * The NEW callback tried to take ownership, check 64 * whether it succeed or didn't. 65 */ 66 rte_eth_dev_owner_get(pid, &pid_owner); 67 if (pid_owner.id != PRIV(dev)->my_owner.id) { 68 INFO("sub_device %d owner(%s_%016"PRIX64") is not my," 69 " owner(%s_%016"PRIX64"), will try again later", 70 i, pid_owner.name, pid_owner.id, 71 PRIV(dev)->my_owner.name, 72 PRIV(dev)->my_owner.id); 73 continue; 74 } 75 } else { 76 /* The sub-device port was found. */ 77 char devstr[DEVARGS_MAXLEN] = ""; 78 struct rte_devargs *probed_da = 79 rte_eth_devices[pid].device->devargs; 80 81 /* Take control of probed device. */ 82 free(da->args); 83 memset(da, 0, sizeof(*da)); 84 if (probed_da != NULL) 85 snprintf(devstr, sizeof(devstr), "%s,%s", 86 probed_da->name, probed_da->args); 87 else 88 strlcpy(devstr, 89 rte_eth_devices[pid].device->name, 90 sizeof(devstr)); 91 ret = rte_devargs_parse(da, devstr); 92 if (ret) { 93 ERROR("Probed devargs parsing failed with code" 94 " %d", ret); 95 return ret; 96 } 97 INFO("Taking control of a probed sub device" 98 " %d named %s", i, da->name); 99 ret = rte_eth_dev_owner_set(pid, &PRIV(dev)->my_owner); 100 if (ret < 0) { 101 INFO("sub_device %d owner set failed (%s), " 102 "will try again later", i, strerror(-ret)); 103 continue; 104 } else if (strncmp(rte_eth_devices[pid].device->name, 105 da->name, strlen(da->name)) != 0) { 106 /* 107 * The device probably was removed and its port 108 * id was reallocated before ownership set. 109 */ 110 rte_eth_dev_owner_unset(pid, 111 PRIV(dev)->my_owner.id); 112 INFO("sub_device %d was removed before taking" 113 " ownership, will try again later", i); 114 continue; 115 } 116 } 117 sdev->sdev_port_id = pid; 118 SUB_ID(sdev) = i; 119 sdev->fs_port_id = dev->data->port_id; 120 sdev->dev = ETH(sdev)->device; 121 sdev->state = DEV_PROBED; 122 } 123 return 0; 124 } 125 126 int 127 failsafe_eal_init(struct rte_eth_dev *dev) 128 { 129 int ret; 130 131 ret = fs_bus_init(dev); 132 if (ret) 133 return ret; 134 if (PRIV(dev)->state < DEV_PROBED) 135 PRIV(dev)->state = DEV_PROBED; 136 fs_switch_dev(dev, NULL); 137 return 0; 138 } 139 140 static int 141 fs_bus_uninit(struct rte_eth_dev *dev) 142 { 143 struct sub_device *sdev = NULL; 144 uint8_t i; 145 int sdev_ret; 146 int ret = 0; 147 148 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { 149 sdev_ret = rte_dev_remove(sdev->dev); 150 if (sdev_ret < 0) { 151 ERROR("Failed to remove requested device %s (err: %d)", 152 sdev->dev->name, sdev_ret); 153 continue; 154 } 155 sdev->state = DEV_PROBED - 1; 156 } 157 return ret; 158 } 159 160 int 161 failsafe_eal_uninit(struct rte_eth_dev *dev) 162 { 163 int ret; 164 165 ret = fs_bus_uninit(dev); 166 PRIV(dev)->state = DEV_PROBED - 1; 167 return ret; 168 } 169