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 256 mtx_init(&sc->mtx, "tbcfg", "Thunderbolt Router Config", MTX_DEF); 257 TAILQ_INIT(&sc->cmd_queue); 258 259 /* 260 * This router is semi-virtual and represents the router that's part 261 * of the NHI DMA engine. Commands can't be issued to the topology 262 * until the NHI is initialized and this router is initialized, so 263 * there's no point in registering router interrupts earlier than this, 264 * even if other routers are found first. 265 */ 266 tb_config_set_root(sc); 267 error = router_register_interrupts(sc); 268 if (error) { 269 tb_router_detach(sc); 270 return (error); 271 } 272 273 error = _tb_router_attach(sc); 274 if (error) 275 return (error); 276 277 bcopy((uint8_t *)sc->uuid, nsc->uuid, 16); 278 return (0); 279 } 280 281 static int 282 _tb_router_attach(struct router_softc *sc) 283 { 284 struct tb_cfg_router *cfg; 285 uint32_t *buf; 286 int error; 287 int up __maybe_unused; 288 289 buf = malloc(9 * 4, M_THUNDERBOLT, M_NOWAIT|M_ZERO); 290 if (buf == NULL) 291 return (ENOMEM); 292 293 error = tb_config_router_read_polled(sc, 0, 9, buf); 294 if (error != 0) { 295 free(buf, M_THUNDERBOLT); 296 return (error); 297 } 298 299 cfg = (struct tb_cfg_router *)buf; 300 up = GET_ROUTER_CS_UPSTREAM_ADAP(cfg); 301 sc->max_adap = GET_ROUTER_CS_MAX_ADAP(cfg); 302 sc->depth = GET_ROUTER_CS_DEPTH(cfg); 303 sc->uuid[0] = cfg->uuid_lo; 304 sc->uuid[1] = cfg->uuid_hi; 305 sc->uuid[2] = 0xffffffff; 306 sc->uuid[3] = 0xffffffff; 307 tb_debug(sc, DBG_ROUTER, 308 "Router upstream_port= %d, max_port= %d, depth= %d\n", 309 up, sc->max_adap, sc->depth); 310 free(buf, M_THUNDERBOLT); 311 312 /* Downstream adapters are indexed in the array allocated here. */ 313 sc->max_adap = MIN(sc->max_adap, ROUTER_CS1_MAX_ADAPTERS); 314 sc->adapters = malloc((1 + sc->max_adap) * sizeof(void *), 315 M_THUNDERBOLT, M_NOWAIT|M_ZERO); 316 if (sc->adapters == NULL) { 317 tb_debug(sc, DBG_ROUTER, 318 "Cannot allocate downstream adapter memory\n"); 319 return (ENOMEM); 320 } 321 322 tb_debug(sc, DBG_ROUTER, "Router created, route 0x%08x%08x\n", 323 sc->route.hi, sc->route.lo); 324 325 return (0); 326 } 327 328 int 329 tb_router_detach(struct router_softc *sc) 330 { 331 332 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "tb_router_deattach called\n"); 333 334 if (TAILQ_FIRST(&sc->cmd_queue) != NULL) 335 return (EBUSY); 336 337 mtx_destroy(&sc->mtx); 338 339 if (sc->adapters != NULL) 340 free(sc->adapters, M_THUNDERBOLT); 341 342 if (sc != NULL) 343 free(sc, M_THUNDERBOLT); 344 345 return (0); 346 } 347 348 static void 349 router_get_config_cb(struct router_softc *sc, struct router_command *cmd, 350 void *arg) 351 { 352 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_get_config_cb called\n"); 353 354 /* 355 * Only do the copy if the command didn't have a notify event thrown. 356 * These events serve as asynchronous exception signals, which is 357 * cumbersome. 358 */ 359 if (cmd->ev == 0) 360 bcopy((uint8_t *)cmd->resp_buffer, 361 (uint8_t *)cmd->callback_arg, cmd->dwlen * 4); 362 363 mtx_lock(&sc->mtx); 364 sc->inflight_cmd = NULL; 365 366 if ((cmd->flags & RCMD_POLLED) == 0) 367 wakeup(cmd); 368 else 369 cmd->flags |= RCMD_POLL_COMPLETE; 370 371 router_schedule_locked(sc, NULL); 372 mtx_unlock(&sc->mtx); 373 } 374 375 int 376 tb_config_read(struct router_softc *sc, u_int space, u_int adapter, 377 u_int offset, u_int dwlen, uint32_t *buf) 378 { 379 struct router_command *cmd; 380 int error, retries; 381 382 if ((error = _tb_config_read(sc, space, adapter, offset, dwlen, buf, 383 router_get_config_cb, &cmd)) != 0) 384 return (error); 385 386 retries = cmd->retries; 387 mtx_lock(&sc->mtx); 388 while (retries-- >= 0) { 389 error = router_schedule_locked(sc, cmd); 390 if (error) 391 break; 392 393 error = msleep(cmd, &sc->mtx, 0, "tbtcfg", cmd->timeout * hz); 394 if (error != EWOULDBLOCK) 395 break; 396 sc->inflight_cmd = NULL; 397 tb_debug(sc, DBG_ROUTER, "Config command timed out, retries=%d\n", retries); 398 } 399 400 if (cmd->ev != 0) 401 error = EINVAL; 402 router_free_cmd(sc, cmd); 403 mtx_unlock(&sc->mtx); 404 return (error); 405 } 406 407 int 408 tb_config_read_polled(struct router_softc *sc, u_int space, u_int adapter, 409 u_int offset, u_int dwlen, uint32_t *buf) 410 { 411 struct router_command *cmd; 412 int error, retries, timeout; 413 414 if ((error = _tb_config_read(sc, space, adapter, offset, dwlen, buf, 415 router_get_config_cb, &cmd)) != 0) 416 return (error); 417 418 retries = cmd->retries; 419 cmd->flags |= RCMD_POLLED; 420 timeout = cmd->timeout * 1000000; 421 422 mtx_lock(&sc->mtx); 423 while (retries-- >= 0) { 424 error = router_schedule_locked(sc, cmd); 425 if (error) 426 break; 427 mtx_unlock(&sc->mtx); 428 429 while (timeout > 0) { 430 DELAY(100 * 1000); 431 if ((cmd->flags & RCMD_POLL_COMPLETE) != 0) 432 break; 433 timeout -= 100000; 434 } 435 436 mtx_lock(&sc->mtx); 437 if ((cmd->flags & RCMD_POLL_COMPLETE) == 0) { 438 error = ETIMEDOUT; 439 sc->inflight_cmd = NULL; 440 tb_debug(sc, DBG_ROUTER, "Config command timed out, retries=%d\n", retries); 441 continue; 442 } else 443 break; 444 } 445 446 if (cmd->ev != 0) 447 error = EINVAL; 448 router_free_cmd(sc, cmd); 449 mtx_unlock(&sc->mtx); 450 return (error); 451 } 452 453 int 454 tb_config_read_async(struct router_softc *sc, u_int space, u_int adapter, 455 u_int offset, u_int dwlen, uint32_t *buf, void *cb) 456 { 457 struct router_command *cmd; 458 int error; 459 460 if ((error = _tb_config_read(sc, space, adapter, offset, dwlen, buf, 461 cb, &cmd)) != 0) 462 return (error); 463 464 error = router_schedule(sc, cmd); 465 466 return (error); 467 } 468 469 static int 470 _tb_config_read(struct router_softc *sc, u_int space, u_int adapter, 471 u_int offset, u_int dwlen, uint32_t *buf, void *cb, 472 struct router_command **rcmd) 473 { 474 struct router_command *cmd; 475 struct tb_cfg_read *msg; 476 int error; 477 478 if ((error = router_alloc_cmd(sc, &cmd)) != 0) 479 return (error); 480 481 msg = router_get_frame_data(cmd); 482 bzero(msg, sizeof(*msg)); 483 msg->route.hi = sc->route.hi; 484 msg->route.lo = sc->route.lo; 485 msg->addr_attrs = TB_CONFIG_ADDR(0, space, adapter, dwlen, offset); 486 cmd->callback = cb; 487 cmd->callback_arg = buf; 488 cmd->dwlen = dwlen; 489 router_prepare_read(sc, cmd, sizeof(*msg)); 490 491 if (rcmd != NULL) 492 *rcmd = cmd; 493 494 return (0); 495 } 496 497 int 498 tb_config_write(struct router_softc *sc, u_int space, u_int adapter, 499 u_int offset, u_int dwlen, uint32_t *buf) 500 { 501 struct router_command *cmd; 502 int error, retries; 503 504 if ((error = _tb_config_write(sc, space, adapter, offset, dwlen, buf, 505 router_get_config_cb, &cmd)) != 0) 506 return (error); 507 508 retries = cmd->retries; 509 mtx_lock(&sc->mtx); 510 while (retries-- >= 0) { 511 error = router_schedule_locked(sc, cmd); 512 if (error) 513 break; 514 515 error = msleep(cmd, &sc->mtx, 0, "tbtcfg", cmd->timeout * hz); 516 if (error != EWOULDBLOCK) 517 break; 518 sc->inflight_cmd = NULL; 519 tb_debug(sc, DBG_ROUTER, "Config command timed out, " 520 "retries=%d\n", retries); 521 } 522 523 if (cmd->ev != 0) 524 error = EINVAL; 525 router_free_cmd(sc, cmd); 526 mtx_unlock(&sc->mtx); 527 return (error); 528 } 529 530 static int 531 _tb_config_write(struct router_softc *sc, u_int space, u_int adapter, 532 u_int offset, u_int dwlen, uint32_t *buf, void *cb, 533 struct router_command **rcmd) 534 { 535 struct router_command *cmd; 536 struct tb_cfg_write *msg; 537 size_t msglen = sizeof(*msg) + dwlen * 4; 538 int error; 539 540 if ((error = router_alloc_cmd(sc, &cmd)) != 0) 541 return (error); 542 543 msg = router_get_frame_data(cmd); 544 bzero(msg, msglen); 545 msg->route.hi = sc->route.hi; 546 msg->route.lo = sc->route.lo; 547 msg->addr_attrs = TB_CONFIG_ADDR(0, space, adapter, dwlen, offset); 548 for (size_t i = 0; i < dwlen; i++) 549 msg->data[i] = buf[i]; 550 cmd->callback = cb; 551 cmd->callback_arg = buf; 552 cmd->dwlen = dwlen; 553 router_prepare_write(sc, cmd, msglen); 554 555 if (rcmd != NULL) 556 *rcmd = cmd; 557 558 return (0); 559 } 560 561 static int 562 router_alloc_cmd(struct router_softc *sc, struct router_command **rcmd) 563 { 564 struct router_command *cmd; 565 566 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_alloc_cmd\n"); 567 568 cmd = malloc(sizeof(*cmd), M_THUNDERBOLT, M_ZERO|M_NOWAIT); 569 if (cmd == NULL) { 570 tb_debug(sc, DBG_ROUTER, "Cannot allocate cmd/response\n"); 571 return (ENOMEM); 572 } 573 574 cmd->nhicmd = nhi_alloc_tx_frame(sc->ring0); 575 if (cmd->nhicmd == NULL) { 576 tb_debug(sc, DBG_ROUTER, "Cannot allocate command frame\n"); 577 free(cmd, M_THUNDERBOLT); 578 return (EBUSY); 579 } 580 581 cmd->sc = sc; 582 *rcmd = cmd; 583 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Allocated command with index %d\n", 584 cmd->nhicmd->idx); 585 586 return (0); 587 } 588 589 static void 590 router_free_cmd(struct router_softc *sc, struct router_command *cmd) 591 { 592 593 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_free_cmd\n"); 594 595 if (cmd == NULL) 596 return; 597 598 if (cmd->nhicmd != NULL) { 599 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Freeing nhi command %d\n", 600 cmd->nhicmd->idx); 601 nhi_free_tx_frame(sc->ring0, cmd->nhicmd); 602 } 603 free(cmd, M_THUNDERBOLT); 604 605 return; 606 } 607 608 static void 609 router_prepare_cmd(struct router_softc *sc, struct router_command *cmd, 610 size_t len, uint16_t pdf) 611 { 612 struct nhi_cmd_frame *nhicmd; 613 uint32_t *msg; 614 int msglen, i; 615 616 KASSERT(cmd != NULL, ("cmd cannot be NULL\n")); 617 KASSERT(len != 0, ("Invalid zero-length command\n")); 618 KASSERT(len % 4 == 0, ("Message must be 32bit padded\n")); 619 620 nhicmd = cmd->nhicmd; 621 msglen = (len - 4) / 4; 622 for (i = 0; i < msglen; i++) 623 nhicmd->data[i] = htobe32(nhicmd->data[i]); 624 625 msg = (uint32_t *)nhicmd->data; 626 /* The last 4 bytes of data is the CRC. Compute CRC for just data. */ 627 msg[msglen] = htobe32(tb_calc_crc(nhicmd->data, len - 4)); 628 629 nhicmd->pdf = pdf; 630 nhicmd->req_len = len; 631 632 nhicmd->timeout = NHI_CMD_TIMEOUT; 633 nhicmd->retries = 0; 634 nhicmd->context = cmd; 635 636 cmd->retries = CFG_DEFAULT_RETRIES; 637 cmd->timeout = CFG_DEFAULT_TIMEOUT; 638 } 639 640 static void 641 router_prepare_read(struct router_softc *sc, struct router_command *cmd, 642 size_t len) 643 { 644 router_prepare_cmd(sc, cmd, len, PDF_READ); 645 646 cmd->nhicmd->resp_buffer = (uint32_t *)cmd->resp_buffer; 647 cmd->nhicmd->resp_len = (cmd->dwlen + 3) * 4; 648 } 649 650 static void 651 router_prepare_write(struct router_softc *sc, struct router_command *cmd, 652 size_t len) 653 { 654 router_prepare_cmd(sc, cmd, len, PDF_WRITE); 655 656 cmd->nhicmd->resp_buffer = (uint32_t *)cmd->resp_buffer; 657 cmd->nhicmd->resp_len = (cmd->dwlen + 3) * 4; 658 } 659 660 static int 661 router_schedule(struct router_softc *sc, struct router_command *cmd) 662 { 663 int error; 664 665 mtx_lock(&sc->mtx); 666 error = router_schedule_locked(sc, cmd); 667 mtx_unlock(&sc->mtx); 668 669 return(error); 670 } 671 672 static int 673 router_schedule_locked(struct router_softc *sc, struct router_command *cmd) 674 { 675 struct nhi_cmd_frame *nhicmd; 676 int error; 677 678 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_schedule\n"); 679 680 if (cmd != NULL) 681 TAILQ_INSERT_TAIL(&sc->cmd_queue, cmd, link); 682 683 while ((sc->inflight_cmd == NULL) && 684 ((cmd = TAILQ_FIRST(&sc->cmd_queue)) != NULL)) { 685 686 TAILQ_REMOVE(&sc->cmd_queue, cmd, link); 687 nhicmd = cmd->nhicmd; 688 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 689 "Scheduling command with index %d\n", nhicmd->idx); 690 sc->inflight_cmd = cmd; 691 if ((error = nhi_tx_schedule(sc->ring0, nhicmd)) != 0) { 692 tb_debug(sc, DBG_ROUTER, "nhi ring error " 693 "%d\n", error); 694 sc->inflight_cmd = NULL; 695 if (error == EBUSY) { 696 TAILQ_INSERT_HEAD(&sc->cmd_queue, cmd, link); 697 error = 0; 698 } 699 break; 700 } 701 } 702 703 return (error); 704 } 705 706 static void 707 router_complete_intr(void *context, union nhi_ring_desc *ring, 708 struct nhi_cmd_frame *nhicmd) 709 { 710 struct router_softc *sc; 711 struct router_command *cmd; 712 713 KASSERT(context != NULL, ("context cannot be NULL\n")); 714 KASSERT(nhicmd != NULL, ("nhicmd cannot be NULL\n")); 715 716 cmd = (struct router_command *)(nhicmd->context); 717 sc = cmd->sc; 718 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_complete_intr called\n"); 719 720 if (nhicmd->flags & CMD_RESP_COMPLETE) { 721 cmd->callback(sc, cmd, cmd->callback_arg); 722 } 723 724 return; 725 } 726 727 static void 728 router_response_intr(void *context, union nhi_ring_desc *ring, struct nhi_cmd_frame *nhicmd) 729 { 730 struct router_softc *sc, *dev; 731 struct tb_cfg_read_resp *read; 732 struct tb_cfg_write_resp *write; 733 struct router_command *cmd; 734 tb_route_t route; 735 u_int error, i, eof, len; 736 uint32_t attrs; 737 738 KASSERT(context != NULL, ("context cannot be NULL\n")); 739 740 sc = (struct router_softc *)context; 741 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_response_intr called\n"); 742 743 eof = ring->rxpost.eof_len >> RX_BUFFER_DESC_EOF_SHIFT; 744 745 if (eof == PDF_WRITE) { 746 write = (struct tb_cfg_write_resp *)nhicmd->data; 747 route.hi = be32toh(write->route.hi); 748 route.lo = be32toh(write->route.lo); 749 } else { 750 read = (struct tb_cfg_read_resp *)nhicmd->data; 751 route.hi = be32toh(read->route.hi); 752 route.lo = be32toh(read->route.lo); 753 attrs = be32toh(read->addr_attrs); 754 len = (attrs & TB_CFG_SIZE_MASK) >> TB_CFG_SIZE_SHIFT; 755 } 756 757 /* XXX Is this a problem? */ 758 if ((route.hi & 0x80000000) == 0) 759 tb_debug(sc, DBG_ROUTER, "Invalid route\n"); 760 route.hi &= ~0x80000000; 761 762 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Looking up route 0x%08x%08x\n", 763 route.hi, route.lo); 764 765 error = router_lookup_device(sc, route, &dev); 766 if (error != 0 || dev == NULL) { 767 tb_debug(sc, DBG_ROUTER, "Cannot find device, error= %d\n", 768 error); 769 return; 770 } 771 772 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Found device %s route 0x%08x%08x, " 773 "inflight_cmd= %p\n", device_get_nameunit(dev->dev), dev->route.hi, 774 dev->route.lo, dev->inflight_cmd); 775 776 cmd = dev->inflight_cmd; 777 if (cmd == NULL) { 778 tb_debug(dev, DBG_ROUTER, "Null inflight cmd\n"); 779 return; 780 } 781 782 if (eof == PDF_READ) { 783 for (i = 0; i < len; i++) 784 cmd->nhicmd->resp_buffer[i] = be32toh(read->data[i]); 785 } 786 787 cmd->nhicmd->flags |= CMD_RESP_COMPLETE; 788 if (cmd->nhicmd->flags & CMD_REQ_COMPLETE) { 789 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "TX_COMPLETE set\n"); 790 cmd->callback(dev, cmd, cmd->callback_arg); 791 } 792 793 return; 794 } 795 796 static void 797 router_notify_intr(void *context, union nhi_ring_desc *ring, struct nhi_cmd_frame *nhicmd) 798 { 799 struct router_softc *sc; 800 struct router_command *cmd; 801 struct tb_cfg_notify event; 802 u_int adap __maybe_unused; 803 u_int ev; 804 805 KASSERT(context != NULL, ("context cannot be NULL\n")); 806 807 sc = (struct router_softc *)context; 808 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "router_notify_intr called\n"); 809 810 event.route.hi = be32toh(nhicmd->data[0]); 811 event.route.lo = be32toh(nhicmd->data[1]); 812 event.event_adap = be32toh(nhicmd->data[2]); 813 814 ev = GET_NOTIFY_EVENT(&event); 815 adap = GET_NOTIFY_ADAPTER(&event); 816 817 tb_debug(sc, DBG_ROUTER, "Event route 0x%08x%08x adap %d code %s\n", 818 event.route.hi, event.route.lo, adap, 819 tb_get_string(ev, tb_notify_event)); 820 821 switch (ev) { 822 case TB_CFG_ERR_CONN: 823 case TB_CFG_ERR_LINK: 824 case TB_CFG_ERR_ADDR: 825 case TB_CFG_ERR_ADP: 826 case TB_CFG_ERR_ENUM: 827 case TB_CFG_ERR_NUA: 828 case TB_CFG_ERR_LEN: 829 case TB_CFG_ERR_HEC: 830 case TB_CFG_ERR_FC: 831 case TB_CFG_ERR_PLUG: 832 case TB_CFG_ERR_LOCK: 833 case TB_CFG_HP_ACK: 834 case TB_CFG_DP_BW: 835 if (sc->inflight_cmd != NULL) { 836 cmd = sc->inflight_cmd; 837 cmd->ev = ev; 838 cmd->callback(sc, cmd, cmd->callback_arg); 839 } 840 break; 841 default: 842 break; 843 } 844 return; 845 } 846 847 int 848 tb_config_next_cap(struct router_softc *sc, struct router_cfg_cap *cap) 849 { 850 union tb_cfg_cap *tbcap; 851 uint32_t *buf; 852 uint16_t current; 853 int error; 854 855 KASSERT(cap != NULL, ("cap cannot be NULL\n")); 856 KASSERT(cap->next_cap != 0, ("next_cap cannot be 0\n")); 857 858 buf = malloc(sizeof(*tbcap), M_THUNDERBOLT, M_NOWAIT|M_ZERO); 859 860 current = cap->next_cap; 861 error = tb_config_read(sc, cap->space, cap->adap, current, 1, buf); 862 if (error) 863 return (error); 864 865 tbcap = (union tb_cfg_cap *)buf; 866 cap->cap_id = tbcap->hdr.cap_id; 867 cap->next_cap = tbcap->hdr.next_cap; 868 cap->current_cap = current; 869 870 if ((cap->space != TB_CFG_CS_ROUTER) && 871 (tbcap->hdr.cap_id != TB_CFG_CAP_VSC)) { 872 free(buf, M_THUNDERBOLT); 873 return (0); 874 } 875 876 tb_config_read(sc, cap->space, cap->adap, current, 2, buf); 877 if (error) { 878 free(buf, M_THUNDERBOLT); 879 return (error); 880 } 881 882 cap->vsc_id = tbcap->vsc.vsc_id; 883 cap->vsc_len = tbcap->vsc.len; 884 if (tbcap->vsc.len == 0) { 885 cap->next_cap = tbcap->vsec.vsec_next_cap; 886 cap->vsec_len = tbcap->vsec.vsec_len; 887 } 888 889 free(buf, M_THUNDERBOLT); 890 return (0); 891 } 892 893 int 894 tb_config_find_cap(struct router_softc *sc, struct router_cfg_cap *cap) 895 { 896 u_int cap_id, vsc_id; 897 int error; 898 899 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "tb_config_find_cap called\n"); 900 901 cap_id = cap->cap_id; 902 vsc_id = cap->vsc_id; 903 904 cap->cap_id = cap->vsc_id = 0; 905 while ((cap->cap_id != cap_id) || (cap->vsc_id != vsc_id)) { 906 tb_debug(sc, DBG_ROUTER|DBG_EXTRA, 907 "Looking for cap %d at offset %d\n", cap->cap_id, 908 cap->next_cap); 909 if ((cap->next_cap == 0) || 910 (cap->next_cap > TB_CFG_CAP_OFFSET_MAX)) 911 return (EINVAL); 912 error = tb_config_next_cap(sc, cap); 913 if (error) 914 break; 915 } 916 917 return (0); 918 } 919 920 int 921 tb_config_find_router_cap(struct router_softc *sc, u_int cap, u_int vsc, u_int *offset) 922 { 923 struct router_cfg_cap rcap; 924 struct tb_cfg_router *cfg; 925 uint32_t *buf; 926 int error; 927 928 buf = malloc(8 * 4, M_THUNDERBOLT, M_NOWAIT|M_ZERO); 929 if (buf == NULL) 930 return (ENOMEM); 931 932 error = tb_config_router_read(sc, 0, 5, buf); 933 if (error != 0) { 934 free(buf, M_THUNDERBOLT); 935 return (error); 936 } 937 938 cfg = (struct tb_cfg_router *)buf; 939 rcap.space = TB_CFG_CS_ROUTER; 940 rcap.adap = 0; 941 rcap.next_cap = GET_ROUTER_CS_NEXT_CAP(cfg); 942 rcap.cap_id = cap; 943 rcap.vsc_id = vsc; 944 error = tb_config_find_cap(sc, &rcap); 945 if (error == 0) 946 *offset = rcap.current_cap; 947 948 free(buf, M_THUNDERBOLT); 949 return (error); 950 } 951 952 int 953 tb_config_find_router_vsc(struct router_softc *sc, u_int cap, u_int *offset) 954 { 955 956 return (tb_config_find_router_cap(sc, TB_CFG_CAP_VSC, cap, offset)); 957 } 958 959 int 960 tb_config_find_router_vsec(struct router_softc *sc, u_int cap, u_int *offset) 961 { 962 963 return (tb_config_find_router_cap(sc, TB_CFG_CAP_VSEC, cap, offset)); 964 } 965 966 int 967 tb_config_find_adapter_cap(struct router_softc *sc, u_int adap, u_int cap, u_int *offset) 968 { 969 struct router_cfg_cap rcap; 970 struct tb_cfg_adapter *cfg; 971 uint32_t *buf; 972 int error; 973 974 buf = malloc(8 * 4, M_THUNDERBOLT, M_NOWAIT|M_ZERO); 975 if (buf == NULL) 976 return (ENOMEM); 977 978 error = tb_config_adapter_read(sc, adap, 0, 8, buf); 979 if (error != 0) { 980 free(buf, M_THUNDERBOLT); 981 return (error); 982 } 983 984 cfg = (struct tb_cfg_adapter *)buf; 985 rcap.space = TB_CFG_CS_ADAPTER; 986 rcap.adap = adap; 987 rcap.next_cap = GET_ADP_CS_NEXT_CAP(cfg); 988 rcap.cap_id = cap; 989 rcap.vsc_id = 0; 990 error = tb_config_find_cap(sc, &rcap); 991 if (error == 0) 992 *offset = rcap.current_cap; 993 994 free(buf, M_THUNDERBOLT); 995 return (error); 996 } 997 998 int 999 tb_config_get_lc_uuid(struct router_softc *rsc, uint8_t *uuid) 1000 { 1001 u_int error, offset; 1002 uint32_t buf[8]; 1003 1004 bzero(buf, sizeof(buf)); 1005 1006 error = tb_config_find_router_vsec(rsc, TB_CFG_VSEC_LC, &offset); 1007 if (error != 0) { 1008 tb_debug(rsc, DBG_ROUTER, "Error finding LC registers: %d\n", 1009 error); 1010 return (error); 1011 } 1012 1013 error = tb_config_router_read(rsc, offset + TB_LC_UUID, 4, buf); 1014 if (error != 0) { 1015 tb_debug(rsc, DBG_ROUTER, "Error fetching UUID: %d\n", error); 1016 return (error); 1017 } 1018 1019 bcopy(buf, uuid, 16); 1020 return (0); 1021 } 1022