1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2016 NXP 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <sys/queue.h> 8 9 #include <rte_bus.h> 10 #include <rte_debug.h> 11 #include <rte_string_fns.h> 12 #include <rte_errno.h> 13 14 #include "eal_private.h" 15 16 static struct rte_bus_list rte_bus_list = 17 TAILQ_HEAD_INITIALIZER(rte_bus_list); 18 19 const char * 20 rte_bus_name(const struct rte_bus *bus) 21 { 22 return bus->name; 23 } 24 25 void 26 rte_bus_register(struct rte_bus *bus) 27 { 28 RTE_VERIFY(bus); 29 RTE_VERIFY(rte_bus_name(bus) && strlen(rte_bus_name(bus))); 30 /* A bus should mandatorily have the scan implemented */ 31 RTE_VERIFY(bus->scan); 32 RTE_VERIFY(bus->probe); 33 RTE_VERIFY(bus->find_device); 34 /* Buses supporting driver plug also require unplug. */ 35 RTE_VERIFY(!bus->plug || bus->unplug); 36 37 TAILQ_INSERT_TAIL(&rte_bus_list, bus, next); 38 RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", rte_bus_name(bus)); 39 } 40 41 void 42 rte_bus_unregister(struct rte_bus *bus) 43 { 44 TAILQ_REMOVE(&rte_bus_list, bus, next); 45 RTE_LOG(DEBUG, EAL, "Unregistered [%s] bus.\n", rte_bus_name(bus)); 46 } 47 48 /* Scan all the buses for registered devices */ 49 int 50 rte_bus_scan(void) 51 { 52 int ret; 53 struct rte_bus *bus = NULL; 54 55 TAILQ_FOREACH(bus, &rte_bus_list, next) { 56 ret = bus->scan(); 57 if (ret) 58 RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n", 59 rte_bus_name(bus)); 60 } 61 62 return 0; 63 } 64 65 /* Probe all devices of all buses */ 66 int 67 rte_bus_probe(void) 68 { 69 int ret; 70 struct rte_bus *bus, *vbus = NULL; 71 72 TAILQ_FOREACH(bus, &rte_bus_list, next) { 73 if (!strcmp(rte_bus_name(bus), "vdev")) { 74 vbus = bus; 75 continue; 76 } 77 78 ret = bus->probe(); 79 if (ret) 80 RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n", 81 rte_bus_name(bus)); 82 } 83 84 if (vbus) { 85 ret = vbus->probe(); 86 if (ret) 87 RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n", 88 rte_bus_name(vbus)); 89 } 90 91 return 0; 92 } 93 94 /* Dump information of a single bus */ 95 static int 96 bus_dump_one(FILE *f, struct rte_bus *bus) 97 { 98 int ret; 99 100 /* For now, dump only the bus name */ 101 ret = fprintf(f, " %s\n", rte_bus_name(bus)); 102 103 /* Error in case of inability in writing to stream */ 104 if (ret < 0) 105 return ret; 106 107 return 0; 108 } 109 110 void 111 rte_bus_dump(FILE *f) 112 { 113 int ret; 114 struct rte_bus *bus; 115 116 TAILQ_FOREACH(bus, &rte_bus_list, next) { 117 ret = bus_dump_one(f, bus); 118 if (ret) { 119 RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n", 120 ret); 121 break; 122 } 123 } 124 } 125 126 struct rte_bus * 127 rte_bus_find(const struct rte_bus *start, rte_bus_cmp_t cmp, 128 const void *data) 129 { 130 struct rte_bus *bus; 131 132 if (start != NULL) 133 bus = TAILQ_NEXT(start, next); 134 else 135 bus = TAILQ_FIRST(&rte_bus_list); 136 while (bus != NULL) { 137 if (cmp(bus, data) == 0) 138 break; 139 bus = TAILQ_NEXT(bus, next); 140 } 141 return bus; 142 } 143 144 static int 145 cmp_rte_device(const struct rte_device *dev1, const void *_dev2) 146 { 147 const struct rte_device *dev2 = _dev2; 148 149 return dev1 != dev2; 150 } 151 152 static int 153 bus_find_device(const struct rte_bus *bus, const void *_dev) 154 { 155 struct rte_device *dev; 156 157 dev = bus->find_device(NULL, cmp_rte_device, _dev); 158 return dev == NULL; 159 } 160 161 struct rte_bus * 162 rte_bus_find_by_device(const struct rte_device *dev) 163 { 164 return rte_bus_find(NULL, bus_find_device, (const void *)dev); 165 } 166 167 static int 168 cmp_bus_name(const struct rte_bus *bus, const void *_name) 169 { 170 const char *name = _name; 171 172 return strcmp(rte_bus_name(bus), name); 173 } 174 175 struct rte_bus * 176 rte_bus_find_by_name(const char *busname) 177 { 178 return rte_bus_find(NULL, cmp_bus_name, (const void *)busname); 179 } 180 181 static int 182 bus_can_parse(const struct rte_bus *bus, const void *_name) 183 { 184 const char *name = _name; 185 186 return !(bus->parse && bus->parse(name, NULL) == 0); 187 } 188 189 struct rte_bus * 190 rte_bus_find_by_device_name(const char *str) 191 { 192 char name[RTE_DEV_NAME_MAX_LEN]; 193 char *c; 194 195 strlcpy(name, str, sizeof(name)); 196 c = strchr(name, ','); 197 if (c != NULL) 198 c[0] = '\0'; 199 return rte_bus_find(NULL, bus_can_parse, name); 200 } 201 202 203 /* 204 * Get iommu class of devices on the bus. 205 */ 206 enum rte_iova_mode 207 rte_bus_get_iommu_class(void) 208 { 209 enum rte_iova_mode mode = RTE_IOVA_DC; 210 bool buses_want_va = false; 211 bool buses_want_pa = false; 212 struct rte_bus *bus; 213 214 TAILQ_FOREACH(bus, &rte_bus_list, next) { 215 enum rte_iova_mode bus_iova_mode; 216 217 if (bus->get_iommu_class == NULL) 218 continue; 219 220 bus_iova_mode = bus->get_iommu_class(); 221 RTE_LOG(DEBUG, EAL, "Bus %s wants IOVA as '%s'\n", 222 rte_bus_name(bus), 223 bus_iova_mode == RTE_IOVA_DC ? "DC" : 224 (bus_iova_mode == RTE_IOVA_PA ? "PA" : "VA")); 225 if (bus_iova_mode == RTE_IOVA_PA) 226 buses_want_pa = true; 227 else if (bus_iova_mode == RTE_IOVA_VA) 228 buses_want_va = true; 229 } 230 if (buses_want_va && !buses_want_pa) { 231 mode = RTE_IOVA_VA; 232 } else if (buses_want_pa && !buses_want_va) { 233 mode = RTE_IOVA_PA; 234 } else { 235 mode = RTE_IOVA_DC; 236 if (buses_want_va) { 237 RTE_LOG(WARNING, EAL, "Some buses want 'VA' but forcing 'DC' because other buses want 'PA'.\n"); 238 RTE_LOG(WARNING, EAL, "Depending on the final decision by the EAL, not all buses may be able to initialize.\n"); 239 } 240 } 241 242 return mode; 243 } 244 245 static int 246 bus_handle_sigbus(const struct rte_bus *bus, 247 const void *failure_addr) 248 { 249 int ret; 250 251 if (!bus->sigbus_handler) 252 return -1; 253 254 ret = bus->sigbus_handler(failure_addr); 255 256 /* find bus but handle failed, keep the errno be set. */ 257 if (ret < 0 && rte_errno == 0) 258 rte_errno = ENOTSUP; 259 260 return ret > 0; 261 } 262 263 int 264 rte_bus_sigbus_handler(const void *failure_addr) 265 { 266 struct rte_bus *bus; 267 268 int ret = 0; 269 int old_errno = rte_errno; 270 271 rte_errno = 0; 272 273 bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); 274 /* can not find bus. */ 275 if (!bus) 276 return 1; 277 /* find bus but handle failed, pass on the new errno. */ 278 else if (rte_errno != 0) 279 return -1; 280 281 /* restore the old errno. */ 282 rte_errno = old_errno; 283 284 return ret; 285 } 286