1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022 Scott Long 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "opt_thunderbolt.h" 30 31 /* Config space access for switches, ports, and devices in TB3 and USB4 */ 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/bus.h> 38 #include <sys/conf.h> 39 #include <sys/malloc.h> 40 #include <sys/queue.h> 41 #include <sys/sysctl.h> 42 #include <sys/lock.h> 43 #include <sys/mutex.h> 44 #include <sys/taskqueue.h> 45 #include <sys/gsb_crc32.h> 46 #include <sys/endian.h> 47 #include <vm/vm.h> 48 #include <vm/pmap.h> 49 50 #include <machine/bus.h> 51 #include <machine/stdarg.h> 52 53 #include <dev/thunderbolt/nhi_reg.h> 54 #include <dev/thunderbolt/nhi_var.h> 55 #include <dev/thunderbolt/tb_reg.h> 56 #include <dev/thunderbolt/tb_var.h> 57 #include <dev/thunderbolt/tbcfg_reg.h> 58 #include <dev/thunderbolt/router_var.h> 59 #include <dev/thunderbolt/tb_debug.h> 60 61 static int router_alloc_cmd(struct router_softc *, struct router_command **); 62 static void router_free_cmd(struct router_softc *, struct router_command *); 63 static int _tb_router_attach(struct router_softc *); 64 static void router_prepare_cmd(struct router_softc *, struct router_command *, 65 size_t, uint16_t); 66 static void router_prepare_read(struct router_softc *, struct router_command *, 67 size_t); 68 static void router_prepare_write(struct router_softc *, struct router_command *, 69 size_t); 70 static int _tb_config_read(struct router_softc *, u_int, u_int, u_int, u_int, 71 uint32_t *, void *, struct router_command **); 72 static int _tb_config_write(struct router_softc *, u_int, u_int, u_int, u_int, 73 uint32_t *, void *, struct router_command **); 74 static int router_schedule(struct router_softc *, struct router_command *); 75 static int router_schedule_locked(struct router_softc *, 76 struct router_command *); 77 static nhi_ring_cb_t router_complete_intr; 78 static nhi_ring_cb_t router_response_intr; 79 static nhi_ring_cb_t router_notify_intr; 80 81 #define CFG_DEFAULT_RETRIES 3 82 #define CFG_DEFAULT_TIMEOUT 2 83 84 static int 85 router_lookup_device(struct router_softc *sc, tb_route_t route, 86 struct router_softc **dev) 87 { 88 struct router_softc *cursor; 89 uint64_t search_rt, remainder_rt, this_rt; 90 uint8_t hop; 91 92 KASSERT(dev != NULL, ("dev cannot be NULL\n")); 93 94 cursor = tb_config_get_root(sc); 95 remainder_rt = search_rt = route.lo | ((uint64_t)route.hi << 32); 96 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 97 "%s: Searching for router 0x%016jx\n", __func__, search_rt); 98 99 while (cursor != NULL) { 100 this_rt = TB_ROUTE(cursor); 101 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 102 "Comparing cursor route 0x%016jx\n", this_rt); 103 if (this_rt == search_rt) 104 break; 105 106 /* Prepare to go to the next hop node in the route */ 107 hop = remainder_rt & 0xff; 108 remainder_rt >>= 8; 109 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 110 "hop= 0x%02x, remainder= 0x%016jx\n", hop, remainder_rt); 111 112 /* 113 * An adapter index of 0x0 is only for the host interface 114 * adapter on the root route. The only time that 115 * it's valid for searches is when you're looking for the 116 * root route, and that case has already been handled. 117 */ 118 if (hop == 0) { 119 tb_debug(sc, DBG_ROUTER, 120 "End of route chain, route not found\n"); 121 return (ENOENT); 122 } 123 124 if (hop > cursor->max_adap) { 125 tb_debug(sc, DBG_ROUTER, 126 "Route hop out of range for parent\n"); 127 return (EINVAL); 128 } 129 130 if (cursor->adapters == NULL) { 131 tb_debug(sc, DBG_ROUTER, 132 "Error, router not fully initialized\n"); 133 return (EINVAL); 134 } 135 136 cursor = cursor->adapters[hop]; 137 } 138 139 if (cursor == NULL) 140 return (ENOENT); 141 142 *dev = cursor; 143 return (0); 144 } 145 146 static int 147 router_insert(struct router_softc *sc, struct router_softc *parent) 148 { 149 uint64_t this_rt; 150 uint8_t this_hop; 151 152 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_insert called\n"); 153 154 if (parent == NULL) { 155 tb_debug(sc, DBG_ROUTER, "Parent cannot be NULL in insert\n"); 156 return (EINVAL); 157 } 158 159 this_rt = TB_ROUTE(sc); 160 if (((this_rt >> (sc->depth * 8)) > 0xffULL) || 161 (parent->depth + 1 != sc->depth)) { 162 tb_debug(sc, DBG_ROUTER, "Added route 0x%08x%08x is not a " 163 "direct child of the parent route 0x%08x%08x\n", 164 sc->route.hi, sc->route.lo, parent->route.hi, 165 parent->route.lo); 166 return (EINVAL); 167 } 168 169 this_hop = (uint8_t)(this_rt >> (sc->depth * 8)); 170 171 tb_debug(sc, DBG_ROUTER, "Inserting route 0x%08x%08x with last hop " 172 "of 0x%02x and depth of %d\n", sc->route.hi, sc->route.lo, 173 this_hop, sc->depth); 174 175 if (this_hop > parent->max_adap) { 176 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 177 "Inserted route is out of range of the parent\n"); 178 return (EINVAL); 179 } 180 181 if (parent->adapters[this_hop] != NULL) { 182 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 183 "Inserted route already exists\n"); 184 return (EEXIST); 185 } 186 187 parent->adapters[this_hop] = sc; 188 189 tb_debug(sc, DBG_ROUTER, "Added router 0x%08x%08x to parent " 190 "0x%08x%08x\n", sc->route.hi, sc->route.lo, parent->route.hi, 191 parent->route.lo); 192 return (0); 193 } 194 195 static int 196 router_register_interrupts(struct router_softc *sc) 197 { 198 struct nhi_dispatch tx[] = { { PDF_READ, router_complete_intr, sc }, 199 { PDF_WRITE, router_complete_intr, sc }, 200 { 0, NULL, NULL } }; 201 struct nhi_dispatch rx[] = { { PDF_READ, router_response_intr, sc }, 202 { PDF_WRITE, router_response_intr, sc }, 203 { PDF_NOTIFY, router_notify_intr, sc }, 204 { 0, NULL, NULL } }; 205 206 return (nhi_register_pdf(sc->ring0, tx, rx)); 207 } 208 209 int 210 tb_router_attach(struct router_softc *parent, tb_route_t route) 211 { 212 struct router_softc *sc; 213 214 tb_debug(parent, DBG_ROUTER|DBG_EXTRA, "tb_router_attach called\n"); 215 216 sc = malloc(sizeof(*sc), M_THUNDERBOLT, M_ZERO|M_NOWAIT); 217 if (sc == NULL) { 218 tb_debug(parent, DBG_ROUTER, "Cannot allocate root router\n"); 219 return (ENOMEM); 220 } 221 222 sc->dev = parent->dev; 223 sc->debug = parent->debug; 224 sc->ring0 = parent->ring0; 225 sc->route = route; 226 sc->nsc = parent->nsc; 227 228 mtx_init(&sc->mtx, "tbcfg", "Thunderbolt Router Config", MTX_DEF); 229 TAILQ_INIT(&sc->cmd_queue); 230 231 router_insert(sc, parent); 232 233 return (_tb_router_attach(sc)); 234 } 235 236 int 237 tb_router_attach_root(struct nhi_softc *nsc, tb_route_t route) 238 { 239 struct router_softc *sc; 240 int error; 241 242 tb_debug(nsc, DBG_ROUTER|DBG_EXTRA, "tb_router_attach_root called\n"); 243 244 sc = malloc(sizeof(*sc), M_THUNDERBOLT, M_ZERO|M_NOWAIT); 245 if (sc == NULL) { 246 tb_debug(nsc, DBG_ROUTER, "Cannot allocate root router\n"); 247 return (ENOMEM); 248 } 249 250 sc->dev = nsc->dev; 251 sc->debug = nsc->debug; 252 sc->ring0 = nsc->ring0; 253 sc->route = route; 254 sc->nsc = nsc; 255 sc->suspended = false; 256 257 mtx_init(&sc->mtx, "tbcfg", "Thunderbolt Router Config", MTX_DEF); 258 TAILQ_INIT(&sc->cmd_queue); 259 260 /* 261 * This router is semi-virtual and represents the router that's part 262 * of the NHI DMA engine. Commands can't be issued to the topology 263 * until the NHI is initialized and this router is initialized, so 264 * there's no point in registering router interrupts earlier than this, 265 * even if other routers are found first. 266 */ 267 tb_config_set_root(sc); 268 error = router_register_interrupts(sc); 269 if (error) { 270 tb_router_detach(sc); 271 return (error); 272 } 273 274 error = _tb_router_attach(sc); 275 if (error) 276 return (error); 277 278 bcopy((uint8_t *)sc->uuid, nsc->uuid, 16); 279 return (0); 280 } 281 282 static int 283 _tb_router_attach(struct router_softc *sc) 284 { 285 struct tb_cfg_router *cfg; 286 uint32_t *buf; 287 int error; 288 int up __maybe_unused; 289 290 buf = malloc(9 * 4, M_THUNDERBOLT, M_NOWAIT|M_ZERO); 291 if (buf == NULL) 292 return (ENOMEM); 293 294 error = tb_config_router_read_polled(sc, 0, 9, buf); 295 if (error != 0) { 296 free(buf, M_THUNDERBOLT); 297 return (error); 298 } 299 300 cfg = (struct tb_cfg_router *)buf; 301 up = GET_ROUTER_CS_UPSTREAM_ADAP(cfg); 302 sc->max_adap = GET_ROUTER_CS_MAX_ADAP(cfg); 303 sc->depth = GET_ROUTER_CS_DEPTH(cfg); 304 sc->uuid[0] = cfg->uuid_lo; 305 sc->uuid[1] = cfg->uuid_hi; 306 sc->uuid[2] = 0xffffffff; 307 sc->uuid[3] = 0xffffffff; 308 tb_debug(sc, DBG_ROUTER, 309 "Router upstream_port= %d, max_port= %d, depth= %d\n", 310 up, sc->max_adap, sc->depth); 311 free(buf, M_THUNDERBOLT); 312 313 /* Downstream adapters are indexed in the array allocated here. */ 314 sc->max_adap = MIN(sc->max_adap, ROUTER_CS1_MAX_ADAPTERS); 315 sc->adapters = malloc((1 + sc->max_adap) * sizeof(void *), 316 M_THUNDERBOLT, M_NOWAIT|M_ZERO); 317 if (sc->adapters == NULL) { 318 tb_debug(sc, DBG_ROUTER, 319 "Cannot allocate downstream adapter memory\n"); 320 return (ENOMEM); 321 } 322 323 tb_debug(sc, DBG_ROUTER, "Router created, route 0x%08x%08x\n", 324 sc->route.hi, sc->route.lo); 325 326 return (0); 327 } 328 329 int 330 tb_router_detach(struct router_softc *sc) 331 { 332 333 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "tb_router_deattach called\n"); 334 335 if (TAILQ_FIRST(&sc->cmd_queue) != NULL) 336 return (EBUSY); 337 338 mtx_destroy(&sc->mtx); 339 340 if (sc->adapters != NULL) 341 free(sc->adapters, M_THUNDERBOLT); 342 343 if (sc != NULL) 344 free(sc, M_THUNDERBOLT); 345 346 return (0); 347 } 348 349 /* 350 * Suspend a USB4 router and it's downstreams. 351 * 352 * TODO(Bug 299199): fully flesh out the implementation. 353 */ 354 int 355 tb_router_suspend(struct router_softc *sc) 356 { 357 int err; 358 uint32_t reg; 359 360 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "%s called\n", __func__); 361 if (sc->suspended) { 362 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Already suspended\n"); 363 return (0); 364 } 365 366 /* 367 * TODO Before we do anything, we've first got to make sure that the 368 * USB3 hub is in the U3 state, and the PCIe endpoint is in D3. 369 * 370 * Also check for "USB4 Port is Configured" to know if we support 371 * sleep state. 372 */ 373 374 /* First, we've got to set ROUTER_CS_5.SLP (enter sleep). */ 375 err = tb_config_router_read(sc, ROUTER_CS_5, 1, ®); 376 if (err != 0) { 377 tb_debug(sc, DBG_ROUTER, "Cannot read ROUTER_CS5\n"); 378 return (err); 379 } 380 /* 381 * We want to set the enter sleep bit, as well as preventing wake 382 * events from: 383 * - Wake on PCIe (WoP). 384 * - Wake on USB3 (WoU). 385 * - Wake on DisplayPort (WoD). 386 * TODO Eventually, we will want the user to be able to control this. 387 */ 388 reg |= ROUTER_SLP; 389 reg &= ~(ROUTER_WOP | ROUTER_WOU | ROUTER_WOD); 390 err = tb_config_router_write(sc, ROUTER_CS_5, 1, ®); 391 if (err != 0) { 392 tb_debug(sc, DBG_ROUTER, "Cannot write to ROUTER_CS5\n"); 393 return (err); 394 } 395 396 /* 397 * The ROUTER_CS_6.SLPR (sleep ready) bit should be set tSetSR after 398 * we set the SLP bit. Poll for it to be set. 399 * 400 * TODO On a v2 router, we should wait for the ROP_CMPLT notification, 401 * but in the meantime just polling is also valid. 402 */ 403 for (size_t i = 0; i < NHI_SLPR_POLL_TRIES; i++) { 404 pause_sbt("tbrouter", ustosbt(NHI_SLPR_POLL_US), 0, 0); 405 err = tb_config_router_read(sc, ROUTER_CS_6, 1, ®); 406 if (err != 0) { 407 tb_debug(sc, DBG_ROUTER, "Cannot read ROUTER_CS6\n"); 408 return (err); 409 } 410 if ((reg & ROUTER_SLPR) != 0) 411 goto ready; 412 } 413 tb_printf(sc, "Timed out waiting for the sleep ready bit to be set\n"); 414 return (ETIMEDOUT); 415 416 ready: 417 tb_printf(sc, "Ready to enter sleep\n"); 418 sc->suspended = true; 419 /* 420 * TODO We must tell the host router to send LT_LRoff on the sideband 421 * channel of each DFP. 422 */ 423 return (0); 424 } 425 426 static void 427 router_get_config_cb(struct router_softc *sc, struct router_command *cmd, 428 void *arg) 429 { 430 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_get_config_cb called\n"); 431 432 /* 433 * Only do the copy if the command didn't have a notify event thrown. 434 * These events serve as asynchronous exception signals, which is 435 * cumbersome. 436 */ 437 if (cmd->ev == 0) 438 bcopy((uint8_t *)cmd->resp_buffer, 439 (uint8_t *)cmd->callback_arg, cmd->dwlen * 4); 440 441 mtx_lock(&sc->mtx); 442 sc->inflight_cmd = NULL; 443 444 if ((cmd->flags & RCMD_POLLED) == 0) 445 wakeup(cmd); 446 else 447 cmd->flags |= RCMD_POLL_COMPLETE; 448 449 router_schedule_locked(sc, NULL); 450 mtx_unlock(&sc->mtx); 451 } 452 453 int 454 tb_config_read(struct router_softc *sc, u_int space, u_int adapter, 455 u_int offset, u_int dwlen, uint32_t *buf) 456 { 457 struct router_command *cmd; 458 int error, retries; 459 460 if ((error = _tb_config_read(sc, space, adapter, offset, dwlen, buf, 461 router_get_config_cb, &cmd)) != 0) 462 return (error); 463 464 retries = cmd->retries; 465 mtx_lock(&sc->mtx); 466 while (retries-- >= 0) { 467 error = router_schedule_locked(sc, cmd); 468 if (error) 469 break; 470 471 error = msleep(cmd, &sc->mtx, 0, "tbtcfg", cmd->timeout * hz); 472 if (error != EWOULDBLOCK) 473 break; 474 sc->inflight_cmd = NULL; 475 tb_debug(sc, DBG_ROUTER, "Config command timed out, retries=%d\n", retries); 476 } 477 478 if (cmd->ev != 0) 479 error = EINVAL; 480 router_free_cmd(sc, cmd); 481 mtx_unlock(&sc->mtx); 482 return (error); 483 } 484 485 int 486 tb_config_read_polled(struct router_softc *sc, u_int space, u_int adapter, 487 u_int offset, u_int dwlen, uint32_t *buf) 488 { 489 struct router_command *cmd; 490 int error, retries, timeout; 491 492 if ((error = _tb_config_read(sc, space, adapter, offset, dwlen, buf, 493 router_get_config_cb, &cmd)) != 0) 494 return (error); 495 496 retries = cmd->retries; 497 cmd->flags |= RCMD_POLLED; 498 timeout = cmd->timeout * 1000000; 499 500 mtx_lock(&sc->mtx); 501 while (retries-- >= 0) { 502 error = router_schedule_locked(sc, cmd); 503 if (error) 504 break; 505 mtx_unlock(&sc->mtx); 506 507 while (timeout > 0) { 508 DELAY(100 * 1000); 509 if ((cmd->flags & RCMD_POLL_COMPLETE) != 0) 510 break; 511 timeout -= 100000; 512 } 513 514 mtx_lock(&sc->mtx); 515 if ((cmd->flags & RCMD_POLL_COMPLETE) == 0) { 516 error = ETIMEDOUT; 517 sc->inflight_cmd = NULL; 518 tb_debug(sc, DBG_ROUTER, "Config command timed out, retries=%d\n", retries); 519 continue; 520 } else 521 break; 522 } 523 524 if (cmd->ev != 0) 525 error = EINVAL; 526 router_free_cmd(sc, cmd); 527 mtx_unlock(&sc->mtx); 528 return (error); 529 } 530 531 int 532 tb_config_read_async(struct router_softc *sc, u_int space, u_int adapter, 533 u_int offset, u_int dwlen, uint32_t *buf, void *cb) 534 { 535 struct router_command *cmd; 536 int error; 537 538 if ((error = _tb_config_read(sc, space, adapter, offset, dwlen, buf, 539 cb, &cmd)) != 0) 540 return (error); 541 542 error = router_schedule(sc, cmd); 543 544 return (error); 545 } 546 547 static int 548 _tb_config_read(struct router_softc *sc, u_int space, u_int adapter, 549 u_int offset, u_int dwlen, uint32_t *buf, void *cb, 550 struct router_command **rcmd) 551 { 552 struct router_command *cmd; 553 struct tb_cfg_read *msg; 554 int error; 555 556 if ((error = router_alloc_cmd(sc, &cmd)) != 0) 557 return (error); 558 559 msg = router_get_frame_data(cmd); 560 bzero(msg, sizeof(*msg)); 561 msg->route.hi = sc->route.hi; 562 msg->route.lo = sc->route.lo; 563 msg->addr_attrs = TB_CONFIG_ADDR(0, space, adapter, dwlen, offset); 564 cmd->callback = cb; 565 cmd->callback_arg = buf; 566 cmd->dwlen = dwlen; 567 router_prepare_read(sc, cmd, sizeof(*msg)); 568 569 if (rcmd != NULL) 570 *rcmd = cmd; 571 572 return (0); 573 } 574 575 int 576 tb_config_write(struct router_softc *sc, u_int space, u_int adapter, 577 u_int offset, u_int dwlen, uint32_t *buf) 578 { 579 struct router_command *cmd; 580 int error, retries; 581 582 if ((error = _tb_config_write(sc, space, adapter, offset, dwlen, buf, 583 router_get_config_cb, &cmd)) != 0) 584 return (error); 585 586 retries = cmd->retries; 587 mtx_lock(&sc->mtx); 588 while (retries-- >= 0) { 589 error = router_schedule_locked(sc, cmd); 590 if (error) 591 break; 592 593 error = msleep(cmd, &sc->mtx, 0, "tbtcfg", cmd->timeout * hz); 594 if (error != EWOULDBLOCK) 595 break; 596 sc->inflight_cmd = NULL; 597 tb_debug(sc, DBG_ROUTER, "Config command timed out, " 598 "retries=%d\n", retries); 599 } 600 601 if (cmd->ev != 0) 602 error = EINVAL; 603 router_free_cmd(sc, cmd); 604 mtx_unlock(&sc->mtx); 605 return (error); 606 } 607 608 static int 609 _tb_config_write(struct router_softc *sc, u_int space, u_int adapter, 610 u_int offset, u_int dwlen, uint32_t *buf, void *cb, 611 struct router_command **rcmd) 612 { 613 struct router_command *cmd; 614 struct tb_cfg_write *msg; 615 /* +4 to account for the CRC at the end. */ 616 size_t msglen = sizeof(*msg) + dwlen * 4 + 4; 617 int error; 618 619 if ((error = router_alloc_cmd(sc, &cmd)) != 0) 620 return (error); 621 622 msg = router_get_frame_data(cmd); 623 bzero(msg, msglen); 624 msg->route.hi = sc->route.hi; 625 msg->route.lo = sc->route.lo; 626 msg->addr_attrs = TB_CONFIG_ADDR(0, space, adapter, dwlen, offset); 627 for (size_t i = 0; i < dwlen; i++) 628 msg->data[i] = buf[i]; 629 cmd->callback = cb; 630 cmd->callback_arg = buf; 631 cmd->dwlen = dwlen; 632 router_prepare_write(sc, cmd, msglen); 633 634 if (rcmd != NULL) 635 *rcmd = cmd; 636 637 return (0); 638 } 639 640 static int 641 router_alloc_cmd(struct router_softc *sc, struct router_command **rcmd) 642 { 643 struct router_command *cmd; 644 645 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_alloc_cmd\n"); 646 647 cmd = malloc(sizeof(*cmd), M_THUNDERBOLT, M_ZERO|M_NOWAIT); 648 if (cmd == NULL) { 649 tb_debug(sc, DBG_ROUTER, "Cannot allocate cmd/response\n"); 650 return (ENOMEM); 651 } 652 653 cmd->nhicmd = nhi_alloc_tx_frame(sc->ring0); 654 if (cmd->nhicmd == NULL) { 655 tb_debug(sc, DBG_ROUTER, "Cannot allocate command frame\n"); 656 free(cmd, M_THUNDERBOLT); 657 return (EBUSY); 658 } 659 660 cmd->sc = sc; 661 *rcmd = cmd; 662 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Allocated command with index %d\n", 663 cmd->nhicmd->idx); 664 665 return (0); 666 } 667 668 static void 669 router_free_cmd(struct router_softc *sc, struct router_command *cmd) 670 { 671 672 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_free_cmd\n"); 673 674 if (cmd == NULL) 675 return; 676 677 if (cmd->nhicmd != NULL) { 678 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Freeing nhi command %d\n", 679 cmd->nhicmd->idx); 680 nhi_free_tx_frame(sc->ring0, cmd->nhicmd); 681 } 682 free(cmd, M_THUNDERBOLT); 683 684 return; 685 } 686 687 static void 688 router_prepare_cmd(struct router_softc *sc, struct router_command *cmd, 689 size_t len, uint16_t pdf) 690 { 691 struct nhi_cmd_frame *nhicmd; 692 uint32_t *msg; 693 int msglen, i; 694 695 KASSERT(cmd != NULL, ("cmd cannot be NULL\n")); 696 KASSERT(len != 0, ("Invalid zero-length command\n")); 697 KASSERT(len % 4 == 0, ("Message must be 32bit padded\n")); 698 699 nhicmd = cmd->nhicmd; 700 msglen = (len - 4) / 4; 701 for (i = 0; i < msglen; i++) 702 nhicmd->data[i] = htobe32(nhicmd->data[i]); 703 704 msg = (uint32_t *)nhicmd->data; 705 /* The last 4 bytes of data is the CRC. Compute CRC for just data. */ 706 msg[msglen] = htobe32(tb_calc_crc(nhicmd->data, len - 4)); 707 708 nhicmd->pdf = pdf; 709 nhicmd->req_len = len; 710 711 nhicmd->timeout = NHI_CMD_TIMEOUT; 712 nhicmd->retries = 0; 713 nhicmd->context = cmd; 714 715 cmd->retries = CFG_DEFAULT_RETRIES; 716 cmd->timeout = CFG_DEFAULT_TIMEOUT; 717 } 718 719 static void 720 router_prepare_read(struct router_softc *sc, struct router_command *cmd, 721 size_t len) 722 { 723 router_prepare_cmd(sc, cmd, len, PDF_READ); 724 725 cmd->nhicmd->resp_buffer = (uint32_t *)cmd->resp_buffer; 726 cmd->nhicmd->resp_len = (cmd->dwlen + 3) * 4; 727 } 728 729 static void 730 router_prepare_write(struct router_softc *sc, struct router_command *cmd, 731 size_t len) 732 { 733 router_prepare_cmd(sc, cmd, len, PDF_WRITE); 734 735 cmd->nhicmd->resp_buffer = (uint32_t *)cmd->resp_buffer; 736 cmd->nhicmd->resp_len = (cmd->dwlen + 3) * 4; 737 } 738 739 static int 740 router_schedule(struct router_softc *sc, struct router_command *cmd) 741 { 742 int error; 743 744 mtx_lock(&sc->mtx); 745 error = router_schedule_locked(sc, cmd); 746 mtx_unlock(&sc->mtx); 747 748 return(error); 749 } 750 751 static int 752 router_schedule_locked(struct router_softc *sc, struct router_command *cmd) 753 { 754 struct nhi_cmd_frame *nhicmd; 755 int error; 756 757 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_schedule\n"); 758 759 if (cmd != NULL) 760 TAILQ_INSERT_TAIL(&sc->cmd_queue, cmd, link); 761 762 while ((sc->inflight_cmd == NULL) && 763 ((cmd = TAILQ_FIRST(&sc->cmd_queue)) != NULL)) { 764 765 TAILQ_REMOVE(&sc->cmd_queue, cmd, link); 766 nhicmd = cmd->nhicmd; 767 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 768 "Scheduling command with index %d\n", nhicmd->idx); 769 sc->inflight_cmd = cmd; 770 if ((error = nhi_tx_schedule(sc->ring0, nhicmd)) != 0) { 771 tb_debug(sc, DBG_ROUTER, "nhi ring error " 772 "%d\n", error); 773 sc->inflight_cmd = NULL; 774 if (error == EBUSY) { 775 TAILQ_INSERT_HEAD(&sc->cmd_queue, cmd, link); 776 error = 0; 777 } 778 break; 779 } 780 } 781 782 return (error); 783 } 784 785 static void 786 router_complete_intr(void *context, union nhi_ring_desc *ring, 787 struct nhi_cmd_frame *nhicmd) 788 { 789 struct router_softc *sc; 790 struct router_command *cmd; 791 792 KASSERT(context != NULL, ("context cannot be NULL\n")); 793 KASSERT(nhicmd != NULL, ("nhicmd cannot be NULL\n")); 794 795 cmd = (struct router_command *)(nhicmd->context); 796 sc = cmd->sc; 797 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_complete_intr called\n"); 798 799 if (nhicmd->flags & CMD_RESP_COMPLETE) { 800 cmd->callback(sc, cmd, cmd->callback_arg); 801 } 802 803 return; 804 } 805 806 static void 807 router_response_intr(void *context, union nhi_ring_desc *ring, struct nhi_cmd_frame *nhicmd) 808 { 809 struct router_softc *sc, *dev; 810 struct tb_cfg_read_resp *read; 811 struct tb_cfg_write_resp *write; 812 struct router_command *cmd; 813 tb_route_t route; 814 u_int error, i, eof, len; 815 uint32_t attrs; 816 817 KASSERT(context != NULL, ("context cannot be NULL\n")); 818 819 sc = (struct router_softc *)context; 820 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_response_intr called\n"); 821 822 eof = ring->rxpost.eof_len >> RX_BUFFER_DESC_EOF_SHIFT; 823 824 if (eof == PDF_WRITE) { 825 write = (struct tb_cfg_write_resp *)nhicmd->data; 826 route.hi = be32toh(write->route.hi); 827 route.lo = be32toh(write->route.lo); 828 } else { 829 read = (struct tb_cfg_read_resp *)nhicmd->data; 830 route.hi = be32toh(read->route.hi); 831 route.lo = be32toh(read->route.lo); 832 attrs = be32toh(read->addr_attrs); 833 len = (attrs & TB_CFG_SIZE_MASK) >> TB_CFG_SIZE_SHIFT; 834 } 835 836 /* XXX Is this a problem? */ 837 if ((route.hi & 0x80000000) == 0) 838 tb_debug(sc, DBG_ROUTER, "Invalid route\n"); 839 route.hi &= ~0x80000000; 840 841 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Looking up route 0x%08x%08x\n", 842 route.hi, route.lo); 843 844 error = router_lookup_device(sc, route, &dev); 845 if (error != 0 || dev == NULL) { 846 tb_debug(sc, DBG_ROUTER, "Cannot find device, error= %d\n", 847 error); 848 return; 849 } 850 851 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Found device %s route 0x%08x%08x, " 852 "inflight_cmd= %p\n", device_get_nameunit(dev->dev), dev->route.hi, 853 dev->route.lo, dev->inflight_cmd); 854 855 cmd = dev->inflight_cmd; 856 if (cmd == NULL) { 857 tb_debug(dev, DBG_ROUTER, "Null inflight cmd\n"); 858 return; 859 } 860 861 if (eof == PDF_READ) { 862 for (i = 0; i < len; i++) 863 cmd->nhicmd->resp_buffer[i] = be32toh(read->data[i]); 864 } 865 866 cmd->nhicmd->flags |= CMD_RESP_COMPLETE; 867 if (cmd->nhicmd->flags & CMD_REQ_COMPLETE) { 868 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "TX_COMPLETE set\n"); 869 cmd->callback(dev, cmd, cmd->callback_arg); 870 } 871 872 return; 873 } 874 875 static void 876 router_notify_intr(void *context, union nhi_ring_desc *ring, struct nhi_cmd_frame *nhicmd) 877 { 878 struct router_softc *sc; 879 struct router_command *cmd; 880 struct tb_cfg_notify event; 881 u_int adap __maybe_unused; 882 u_int ev; 883 884 KASSERT(context != NULL, ("context cannot be NULL\n")); 885 886 sc = (struct router_softc *)context; 887 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_notify_intr called\n"); 888 889 event.route.hi = be32toh(nhicmd->data[0]); 890 event.route.lo = be32toh(nhicmd->data[1]); 891 event.event_adap = be32toh(nhicmd->data[2]); 892 893 ev = GET_NOTIFY_EVENT(&event); 894 adap = GET_NOTIFY_ADAPTER(&event); 895 896 tb_debug(sc, DBG_ROUTER, "Event route 0x%08x%08x adap %d code %s\n", 897 event.route.hi, event.route.lo, adap, 898 tb_get_string(ev, tb_notify_event)); 899 900 switch (ev) { 901 case TB_CFG_ERR_CONN: 902 case TB_CFG_ERR_LINK: 903 case TB_CFG_ERR_ADDR: 904 case TB_CFG_ERR_ADP: 905 case TB_CFG_ERR_ENUM: 906 case TB_CFG_ERR_NUA: 907 case TB_CFG_ERR_LEN: 908 case TB_CFG_ERR_HEC: 909 case TB_CFG_ERR_FC: 910 case TB_CFG_ERR_PLUG: 911 case TB_CFG_ERR_LOCK: 912 case TB_CFG_HP_ACK: 913 case TB_CFG_DP_BW: 914 if (sc->inflight_cmd != NULL) { 915 cmd = sc->inflight_cmd; 916 cmd->ev = ev; 917 cmd->callback(sc, cmd, cmd->callback_arg); 918 } 919 break; 920 default: 921 break; 922 } 923 return; 924 } 925 926 int 927 tb_config_next_cap(struct router_softc *sc, struct router_cfg_cap *cap) 928 { 929 union tb_cfg_cap *tbcap; 930 uint32_t *buf; 931 uint16_t current; 932 int error; 933 934 KASSERT(cap != NULL, ("cap cannot be NULL\n")); 935 KASSERT(cap->next_cap != 0, ("next_cap cannot be 0\n")); 936 937 buf = malloc(sizeof(*tbcap), M_THUNDERBOLT, M_NOWAIT|M_ZERO); 938 939 current = cap->next_cap; 940 error = tb_config_read(sc, cap->space, cap->adap, current, 1, buf); 941 if (error) 942 return (error); 943 944 tbcap = (union tb_cfg_cap *)buf; 945 cap->cap_id = tbcap->hdr.cap_id; 946 cap->next_cap = tbcap->hdr.next_cap; 947 cap->current_cap = current; 948 949 if ((cap->space != TB_CFG_CS_ROUTER) && 950 (tbcap->hdr.cap_id != TB_CFG_CAP_VSC)) { 951 free(buf, M_THUNDERBOLT); 952 return (0); 953 } 954 955 tb_config_read(sc, cap->space, cap->adap, current, 2, buf); 956 if (error) { 957 free(buf, M_THUNDERBOLT); 958 return (error); 959 } 960 961 cap->vsc_id = tbcap->vsc.vsc_id; 962 cap->vsc_len = tbcap->vsc.len; 963 if (tbcap->vsc.len == 0) { 964 cap->next_cap = tbcap->vsec.vsec_next_cap; 965 cap->vsec_len = tbcap->vsec.vsec_len; 966 } 967 968 free(buf, M_THUNDERBOLT); 969 return (0); 970 } 971 972 int 973 tb_config_find_cap(struct router_softc *sc, struct router_cfg_cap *cap) 974 { 975 u_int cap_id, vsc_id; 976 int error; 977 978 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "tb_config_find_cap called\n"); 979 980 cap_id = cap->cap_id; 981 vsc_id = cap->vsc_id; 982 983 cap->cap_id = cap->vsc_id = 0; 984 while ((cap->cap_id != cap_id) || (cap->vsc_id != vsc_id)) { 985 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 986 "Looking for cap %d at offset %d\n", cap->cap_id, 987 cap->next_cap); 988 if ((cap->next_cap == 0) || 989 (cap->next_cap > TB_CFG_CAP_OFFSET_MAX)) 990 return (EINVAL); 991 error = tb_config_next_cap(sc, cap); 992 if (error) 993 break; 994 } 995 996 return (0); 997 } 998 999 int 1000 tb_config_find_router_cap(struct router_softc *sc, u_int cap, u_int vsc, u_int *offset) 1001 { 1002 struct router_cfg_cap rcap; 1003 struct tb_cfg_router *cfg; 1004 uint32_t *buf; 1005 int error; 1006 1007 buf = malloc(8 * 4, M_THUNDERBOLT, M_NOWAIT|M_ZERO); 1008 if (buf == NULL) 1009 return (ENOMEM); 1010 1011 error = tb_config_router_read(sc, 0, 5, buf); 1012 if (error != 0) { 1013 free(buf, M_THUNDERBOLT); 1014 return (error); 1015 } 1016 1017 cfg = (struct tb_cfg_router *)buf; 1018 rcap.space = TB_CFG_CS_ROUTER; 1019 rcap.adap = 0; 1020 rcap.next_cap = GET_ROUTER_CS_NEXT_CAP(cfg); 1021 rcap.cap_id = cap; 1022 rcap.vsc_id = vsc; 1023 error = tb_config_find_cap(sc, &rcap); 1024 if (error == 0) 1025 *offset = rcap.current_cap; 1026 1027 free(buf, M_THUNDERBOLT); 1028 return (error); 1029 } 1030 1031 int 1032 tb_config_find_router_vsc(struct router_softc *sc, u_int cap, u_int *offset) 1033 { 1034 1035 return (tb_config_find_router_cap(sc, TB_CFG_CAP_VSC, cap, offset)); 1036 } 1037 1038 int 1039 tb_config_find_router_vsec(struct router_softc *sc, u_int cap, u_int *offset) 1040 { 1041 1042 return (tb_config_find_router_cap(sc, TB_CFG_CAP_VSEC, cap, offset)); 1043 } 1044 1045 int 1046 tb_config_find_adapter_cap(struct router_softc *sc, u_int adap, u_int cap, u_int *offset) 1047 { 1048 struct router_cfg_cap rcap; 1049 struct tb_cfg_adapter *cfg; 1050 uint32_t *buf; 1051 int error; 1052 1053 buf = malloc(8 * 4, M_THUNDERBOLT, M_NOWAIT|M_ZERO); 1054 if (buf == NULL) 1055 return (ENOMEM); 1056 1057 error = tb_config_adapter_read(sc, adap, 0, 8, buf); 1058 if (error != 0) { 1059 free(buf, M_THUNDERBOLT); 1060 return (error); 1061 } 1062 1063 cfg = (struct tb_cfg_adapter *)buf; 1064 rcap.space = TB_CFG_CS_ADAPTER; 1065 rcap.adap = adap; 1066 rcap.next_cap = GET_ADP_CS_NEXT_CAP(cfg); 1067 rcap.cap_id = cap; 1068 rcap.vsc_id = 0; 1069 error = tb_config_find_cap(sc, &rcap); 1070 if (error == 0) 1071 *offset = rcap.current_cap; 1072 1073 free(buf, M_THUNDERBOLT); 1074 return (error); 1075 } 1076 1077 int 1078 tb_config_get_lc_uuid(struct router_softc *rsc, uint8_t *uuid) 1079 { 1080 u_int error, offset; 1081 uint32_t buf[8]; 1082 1083 bzero(buf, sizeof(buf)); 1084 1085 error = tb_config_find_router_vsec(rsc, TB_CFG_VSEC_LC, &offset); 1086 if (error != 0) { 1087 tb_debug(rsc, DBG_ROUTER, "Error finding LC registers: %d\n", 1088 error); 1089 return (error); 1090 } 1091 1092 error = tb_config_router_read(rsc, offset + TB_LC_UUID, 4, buf); 1093 if (error != 0) { 1094 tb_debug(rsc, DBG_ROUTER, "Error fetching UUID: %d\n", error); 1095 return (error); 1096 } 1097 1098 bcopy(buf, uuid, 16); 1099 return (0); 1100 } 1101