1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2020 Joyent, Inc. 25 */ 26 27 #include <sys/fm/protocol.h> 28 #include <assert.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <alloca.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 #include <sys/param.h> 37 #include <sys/pci.h> 38 #include <sys/pcie.h> 39 #include <libdevinfo.h> 40 #include <libnvpair.h> 41 #include <fm/topo_mod.h> 42 #include <fm/topo_hc.h> 43 #include <sys/stat.h> 44 #include <sys/types.h> 45 46 #include <hostbridge.h> 47 #include <pcibus.h> 48 #include <did.h> 49 #include <did_props.h> 50 #include <util.h> 51 #include <topo_nic.h> 52 #include <topo_usb.h> 53 #include <topo_ufm.h> 54 55 extern txprop_t Bus_common_props[]; 56 extern txprop_t Dev_common_props[]; 57 extern txprop_t Fn_common_props[]; 58 extern int Bus_propcnt; 59 extern int Dev_propcnt; 60 extern int Fn_propcnt; 61 62 extern int platform_pci_label(topo_mod_t *mod, tnode_t *, nvlist_t *, 63 nvlist_t **); 64 extern int platform_pci_fru(topo_mod_t *mod, tnode_t *, nvlist_t *, 65 nvlist_t **); 66 static void pci_release(topo_mod_t *, tnode_t *); 67 static int pci_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, 68 topo_instance_t, void *, void *); 69 static int pci_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 70 nvlist_t **); 71 static int pci_fru(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 72 nvlist_t **); 73 74 static const topo_modops_t Pci_ops = 75 { pci_enum, pci_release }; 76 static const topo_modinfo_t Pci_info = 77 { PCI_BUS, FM_FMRI_SCHEME_HC, PCI_ENUMR_VERS, &Pci_ops }; 78 79 static const topo_method_t Pci_methods[] = { 80 { TOPO_METH_LABEL, TOPO_METH_LABEL_DESC, 81 TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, pci_label }, 82 { TOPO_METH_FRU_COMPUTE, TOPO_METH_FRU_COMPUTE_DESC, 83 TOPO_METH_FRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL, pci_fru }, 84 { NULL } 85 }; 86 87 int 88 _topo_init(topo_mod_t *modhdl, topo_version_t version) 89 { 90 /* 91 * Turn on module debugging output 92 */ 93 if (getenv("TOPOPCIDBG") != NULL) 94 topo_mod_setdebug(modhdl); 95 topo_mod_dprintf(modhdl, "initializing pcibus builtin\n"); 96 97 if (version != PCI_ENUMR_VERS) 98 return (topo_mod_seterrno(modhdl, EMOD_VER_NEW)); 99 100 if (topo_mod_register(modhdl, &Pci_info, TOPO_VERSION) != 0) { 101 topo_mod_dprintf(modhdl, "failed to register module"); 102 return (-1); 103 } 104 topo_mod_dprintf(modhdl, "PCI Enumr initd\n"); 105 106 return (0); 107 } 108 109 void 110 _topo_fini(topo_mod_t *modhdl) 111 { 112 topo_mod_unregister(modhdl); 113 } 114 115 static int 116 pci_label(topo_mod_t *mp, tnode_t *node, topo_version_t version, 117 nvlist_t *in, nvlist_t **out) 118 { 119 if (version > TOPO_METH_LABEL_VERSION) 120 return (topo_mod_seterrno(mp, EMOD_VER_NEW)); 121 return (platform_pci_label(mp, node, in, out)); 122 } 123 static int 124 pci_fru(topo_mod_t *mp, tnode_t *node, topo_version_t version, 125 nvlist_t *in, nvlist_t **out) 126 { 127 if (version > TOPO_METH_FRU_COMPUTE_VERSION) 128 return (topo_mod_seterrno(mp, EMOD_VER_NEW)); 129 return (platform_pci_fru(mp, node, in, out)); 130 } 131 static tnode_t * 132 pci_tnode_create(topo_mod_t *mod, tnode_t *parent, 133 const char *name, topo_instance_t i, void *priv) 134 { 135 tnode_t *ntn; 136 137 if ((ntn = tnode_create(mod, parent, name, i, priv)) == NULL) 138 return (NULL); 139 if (topo_method_register(mod, ntn, Pci_methods) < 0) { 140 topo_mod_dprintf(mod, "topo_method_register failed: %s\n", 141 topo_strerror(topo_mod_errno(mod))); 142 topo_node_unbind(ntn); 143 return (NULL); 144 } 145 return (ntn); 146 } 147 148 /*ARGSUSED*/ 149 static int 150 hostbridge_asdevice(topo_mod_t *mod, tnode_t *bus) 151 { 152 di_node_t di; 153 tnode_t *dev32; 154 155 di = topo_node_getspecific(bus); 156 assert(di != DI_NODE_NIL); 157 158 if ((dev32 = pcidev_declare(mod, bus, di, 32)) == NULL) 159 return (-1); 160 if (pcifn_declare(mod, dev32, di, 0) == NULL) { 161 topo_node_unbind(dev32); 162 return (-1); 163 } 164 return (0); 165 } 166 167 static int 168 pciexfn_add_ufm(topo_mod_t *mod, tnode_t *parent, tnode_t *node) 169 { 170 int err; 171 char *devpath = NULL; 172 tnode_t *create; 173 topo_ufm_devinfo_t tud; 174 175 if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV, &devpath, 176 &err) != 0) { 177 return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); 178 } 179 180 /* 181 * In general, almost all UFMs are device-wide. That is, in a 182 * multi-function device, there is still a single global firmware image. 183 * At this time, we default to putting the UFM data always on the device 184 * node. However, if someone creates a UFM on something that's not the 185 * first function, we'll create a UFM under that function for now. If we 186 * add support for hardware that has per-function UFMs, then we should 187 * update the UFM API to convey that scope. 188 */ 189 if (topo_node_instance(node) != 0) { 190 create = node; 191 } else { 192 create = parent; 193 } 194 195 if (topo_mod_load(mod, TOPO_MOD_UFM, TOPO_VERSION) == NULL) { 196 topo_mod_dprintf(mod, "pcibus enum could not load ufm module"); 197 topo_mod_strfree(mod, devpath); 198 return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM)); 199 } 200 201 tud.tud_method = TOPO_UFM_M_DEVINFO; 202 tud.tud_path = devpath; 203 err = topo_mod_enumerate(mod, create, TOPO_MOD_UFM, UFM, 0, UINT32_MAX, 204 &tud); 205 topo_mod_strfree(mod, devpath); 206 207 return (err); 208 } 209 210 tnode_t * 211 pciexfn_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 212 topo_instance_t i) 213 { 214 did_t *pd; 215 tnode_t *ntn, *ptn; 216 di_node_t pdn; 217 uint_t class, subclass; 218 char *devtyp, *pdevtyp; 219 int pcie_devtyp, pexcap; 220 boolean_t dev_is_pcie, pdev_is_pcie; 221 222 /* We need the parent's dev info node for some of the info */ 223 ptn = find_predecessor(parent, PCIEX_FUNCTION); 224 /* If this is the first child under root, get root's ptn */ 225 if (ptn == NULL) 226 ptn = find_predecessor(parent, PCIEX_ROOT); 227 if (ptn == NULL) 228 return (NULL); 229 pdn = topo_node_getspecific(ptn); 230 231 /* Get the required info to populate the excap */ 232 (void) pci_classcode_get(mod, dn, &class, &subclass); 233 devtyp = pci_devtype_get(mod, dn); 234 pdevtyp = pci_devtype_get(mod, pdn); 235 pexcap = pciex_cap_get(mod, pdn); 236 237 dev_is_pcie = devtyp && (strcmp(devtyp, "pciex") == 0); 238 pdev_is_pcie = pdevtyp && (strcmp(pdevtyp, "pciex") == 0); 239 240 /* 241 * Populate the excap with correct PCIe device type. 242 * 243 * Device Parent Device Parent Device 244 * excap device-type device-type excap Class Code 245 * ------------------------------------------------------------------- 246 * PCI(default) pci N/A N/A != bridge 247 * PCIe pciex N/A N/A != bridge 248 * Root Port Defined in hostbridge 249 * Switch Up pciex pciex != up = bridge 250 * Switch Down pciex pciex = up = bridge 251 * PCIe-PCI pciex pci N/A = bridge 252 * PCI-PCIe pci pciex N/A = bridge 253 */ 254 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCI_DEV; 255 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI) { 256 if (pdev_is_pcie) { 257 if (dev_is_pcie) { 258 if (pexcap != PCIE_PCIECAP_DEV_TYPE_UP) 259 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_UP; 260 else 261 pcie_devtyp = 262 PCIE_PCIECAP_DEV_TYPE_DOWN; 263 } else { 264 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCIE2PCI; 265 } 266 } else { 267 if (dev_is_pcie) 268 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCI2PCIE; 269 } 270 } else { 271 if (pdev_is_pcie) 272 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCIE_DEV; 273 } 274 275 if ((pd = did_find(mod, dn)) == NULL) 276 return (NULL); 277 did_excap_set(pd, pcie_devtyp); 278 279 if ((ntn = pci_tnode_create(mod, parent, PCIEX_FUNCTION, i, dn)) 280 == NULL) 281 return (NULL); 282 if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt) < 0) { 283 topo_node_unbind(ntn); 284 return (NULL); 285 } 286 287 /* 288 * Check if the driver associated with this function exports firmware 289 * information via the DDI UFM subsystem and, if so, create the 290 * corresponding ufm topo nodes. 291 */ 292 if (pciexfn_add_ufm(mod, parent, ntn) != 0) { 293 topo_node_unbind(ntn); 294 return (NULL); 295 } 296 297 /* 298 * We may find pci-express buses or plain-pci buses beneath a function 299 */ 300 if (child_range_add(mod, ntn, PCIEX_BUS, 0, MAX_HB_BUSES) < 0) { 301 topo_node_unbind(ntn); 302 return (NULL); 303 } 304 if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) { 305 topo_node_range_destroy(ntn, PCIEX_BUS); 306 topo_node_unbind(ntn); 307 return (NULL); 308 } 309 return (ntn); 310 } 311 312 tnode_t * 313 pciexdev_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 314 topo_instance_t i) 315 { 316 did_t *pd; 317 tnode_t *ntn; 318 319 if ((pd = did_find(mod, dn)) == NULL) 320 return (NULL); 321 did_settnode(pd, parent); 322 323 if ((ntn = pci_tnode_create(mod, parent, PCIEX_DEVICE, i, dn)) == NULL) 324 return (NULL); 325 if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt) < 0) { 326 topo_node_unbind(ntn); 327 return (NULL); 328 } 329 330 if (pci_create_dev_sensors(mod, ntn) < 0) { 331 topo_node_unbind(ntn); 332 return (NULL); 333 } 334 335 /* 336 * We can expect to find pci-express functions beneath the device 337 */ 338 if (child_range_add(mod, 339 ntn, PCIEX_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) { 340 topo_node_unbind(ntn); 341 return (NULL); 342 } 343 return (ntn); 344 } 345 346 tnode_t * 347 pciexbus_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 348 topo_instance_t i) 349 { 350 did_t *pd; 351 tnode_t *ntn; 352 353 if ((pd = did_find(mod, dn)) == NULL) 354 return (NULL); 355 did_settnode(pd, parent); 356 if ((ntn = pci_tnode_create(mod, parent, PCIEX_BUS, i, dn)) == NULL) 357 return (NULL); 358 if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt) < 0) { 359 topo_node_unbind(ntn); 360 return (NULL); 361 } 362 /* 363 * We can expect to find pci-express devices beneath the bus 364 */ 365 if (child_range_add(mod, 366 ntn, PCIEX_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) { 367 topo_node_unbind(ntn); 368 return (NULL); 369 } 370 return (ntn); 371 } 372 373 tnode_t * 374 pcifn_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 375 topo_instance_t i) 376 { 377 did_t *pd; 378 tnode_t *ntn; 379 380 if ((pd = did_find(mod, dn)) == NULL) 381 return (NULL); 382 did_excap_set(pd, PCIE_PCIECAP_DEV_TYPE_PCI_DEV); 383 384 if ((ntn = pci_tnode_create(mod, parent, PCI_FUNCTION, i, dn)) == NULL) 385 return (NULL); 386 if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt) < 0) { 387 topo_node_unbind(ntn); 388 return (NULL); 389 } 390 /* 391 * We may find pci buses beneath a function 392 */ 393 if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) { 394 topo_node_unbind(ntn); 395 return (NULL); 396 } 397 return (ntn); 398 } 399 400 tnode_t * 401 pcidev_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 402 topo_instance_t i) 403 { 404 did_t *pd; 405 tnode_t *ntn; 406 407 if ((pd = did_find(mod, dn)) == NULL) 408 return (NULL); 409 /* remember parent tnode */ 410 did_settnode(pd, parent); 411 412 if ((ntn = pci_tnode_create(mod, parent, PCI_DEVICE, i, dn)) == NULL) 413 return (NULL); 414 if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt) < 0) { 415 topo_node_unbind(ntn); 416 return (NULL); 417 } 418 419 if (pci_create_dev_sensors(mod, ntn) < 0) { 420 topo_node_unbind(ntn); 421 return (NULL); 422 } 423 424 /* 425 * We can expect to find pci functions beneath the device 426 */ 427 if (child_range_add(mod, ntn, PCI_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) { 428 topo_node_unbind(ntn); 429 return (NULL); 430 } 431 return (ntn); 432 } 433 434 tnode_t * 435 pcibus_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 436 topo_instance_t i) 437 { 438 did_t *pd; 439 tnode_t *ntn; 440 int hbchild = 0; 441 442 if ((pd = did_find(mod, dn)) == NULL) 443 return (NULL); 444 did_settnode(pd, parent); 445 if ((ntn = pci_tnode_create(mod, parent, PCI_BUS, i, dn)) == NULL) 446 return (NULL); 447 /* 448 * If our devinfo node is lacking certain information of its 449 * own, and our parent topology node is a hostbridge, we may 450 * need/want to inherit information available in the 451 * hostbridge node's private data. 452 */ 453 if (strcmp(topo_node_name(parent), HOSTBRIDGE) == 0) 454 hbchild = 1; 455 if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt) < 0) { 456 topo_node_unbind(ntn); 457 return (NULL); 458 } 459 /* 460 * We can expect to find pci devices beneath the bus 461 */ 462 if (child_range_add(mod, ntn, PCI_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) { 463 topo_node_unbind(ntn); 464 return (NULL); 465 } 466 /* 467 * On each bus child of the hostbridge, we represent the 468 * hostbridge as a device outside the range of legal device 469 * numbers. 470 */ 471 if (hbchild == 1) { 472 if (hostbridge_asdevice(mod, ntn) < 0) { 473 topo_node_range_destroy(ntn, PCI_DEVICE); 474 topo_node_unbind(ntn); 475 return (NULL); 476 } 477 } 478 return (ntn); 479 } 480 481 static int 482 pci_bridge_declare(topo_mod_t *mod, tnode_t *fn, di_node_t din, int board, 483 int bridge, int rc, int depth) 484 { 485 int err; 486 char *devtyp; 487 488 devtyp = pci_devtype_get(mod, din); 489 /* Check if the children are PCI or PCIe */ 490 if (devtyp && (strcmp(devtyp, "pciex") == 0)) 491 err = pci_children_instantiate(mod, fn, din, board, bridge, 492 rc, TRUST_BDF, depth + 1); 493 else 494 err = pci_children_instantiate(mod, fn, din, board, bridge, 495 rc - TO_PCI, TRUST_BDF, depth + 1); 496 return (err); 497 } 498 499 static void 500 declare_dev_and_fn(topo_mod_t *mod, tnode_t *bus, tnode_t **dev, di_node_t din, 501 int board, int bridge, int rc, int devno, int fnno, int depth) 502 { 503 int dcnt = 0, rcnt, err; 504 char *propstr, *label = NULL, *pdev = NULL; 505 tnode_t *fn; 506 uint_t class, subclass; 507 uint_t vid, did; 508 uint_t pdev_sz = 0; 509 did_t *dp = NULL; 510 511 if (*dev == NULL) { 512 if (rc >= 0) 513 *dev = pciexdev_declare(mod, bus, din, devno); 514 else 515 *dev = pcidev_declare(mod, bus, din, devno); 516 if (*dev == NULL) 517 return; 518 ++dcnt; 519 } 520 if (rc >= 0) 521 fn = pciexfn_declare(mod, *dev, din, fnno); 522 else 523 fn = pcifn_declare(mod, *dev, din, fnno); 524 525 if (fn == NULL) { 526 if (dcnt) { 527 topo_node_unbind(*dev); 528 *dev = NULL; 529 } 530 return; 531 } 532 533 if (pci_classcode_get(mod, din, &class, &subclass) < 0) { 534 topo_node_unbind(fn); 535 if (dcnt) 536 topo_node_unbind(*dev); 537 return; 538 } 539 540 /* 541 * This function may be a bridge. If not, check for a possible 542 * topology map file and kick off its enumeration of lower-level 543 * devices. 544 */ 545 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI) { 546 (void) pci_bridge_declare(mod, fn, din, board, bridge, rc, 547 depth); 548 } 549 550 /* 551 * Check for a Neptune-based NIC. This could either be a Neptune 552 * adapter card or an Neptune ASIC on a board (e.g. motherboard) 553 * 554 * For Netpune adapter cards, use xfp-hc-topology.xml to expand 555 * topology to include the XFP optical module, which is a FRU on 556 * the Neptune based 10giga fiber NICs. 557 * 558 * For Neptune ASICs, use the XAUI enumerator to expand topology. 559 * The 10giga ports are externalized by a XAUI cards, which 560 * are FRUs. The XAUI enumerator in turn instantiates the XFP 561 * optical module FRUs. 562 */ 563 else if (class == PCI_CLASS_NET && 564 di_uintprop_get(mod, din, DI_VENDIDPROP, &vid) >= 0 && 565 di_uintprop_get(mod, din, DI_DEVIDPROP, &did) >= 0 && 566 vid == SUN_VENDOR_ID && did == NEPTUNE_DEVICE_ID) { 567 /* 568 * Is this an adapter card? Check the bus's physlot 569 */ 570 dp = did_find(mod, topo_node_getspecific(bus)); 571 if (did_physlot(dp) >= 0) { 572 topo_mod_dprintf(mod, "Found Neptune slot\n"); 573 (void) topo_mod_enummap(mod, fn, 574 "xfp", FM_FMRI_SCHEME_HC); 575 } else { 576 topo_mod_dprintf(mod, "Found Neptune ASIC\n"); 577 if (topo_mod_load(mod, XAUI, TOPO_VERSION) == NULL) { 578 topo_mod_dprintf(mod, "pcibus enum " 579 "could not load xaui enum\n"); 580 (void) topo_mod_seterrno(mod, 581 EMOD_PARTIAL_ENUM); 582 return; 583 } else { 584 if (topo_node_range_create(mod, fn, 585 XAUI, 0, 1) < 0) { 586 topo_mod_dprintf(mod, 587 "child_range_add for " 588 "XAUI failed: %s\n", 589 topo_strerror( 590 topo_mod_errno(mod))); 591 return; 592 } 593 (void) topo_mod_enumerate(mod, fn, 594 XAUI, XAUI, fnno, fnno, fn); 595 } 596 } 597 } else if (class == PCI_CLASS_NET) { 598 /* 599 * Ask the nic module if there are any nodes that need to be 600 * enumerated under this device. This might include things like 601 * transceivers or some day, LEDs. 602 */ 603 if (topo_mod_load(mod, NIC, NIC_VERSION) == NULL) { 604 topo_mod_dprintf(mod, "pcibus enum could not load " 605 "nic enum\n"); 606 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM); 607 return; 608 } 609 610 (void) topo_mod_enumerate(mod, fn, NIC, NIC, 0, 0, din); 611 } else if (class == PCI_CLASS_SERIALBUS && subclass == PCI_SERIAL_USB) { 612 /* 613 * If we encounter a USB controller, make sure to enumerate all 614 * of its USB ports. 615 */ 616 if (topo_mod_load(mod, USB, USB_VERSION) == NULL) { 617 topo_mod_dprintf(mod, "pcibus enum could not load " 618 "usb enum\n"); 619 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM); 620 return; 621 } 622 623 (void) topo_mod_enumerate(mod, fn, USB, USB_PCI, 0, 0, din); 624 } else if (class == PCI_CLASS_MASS) { 625 di_node_t cn; 626 int niports = 0; 627 extern void pci_iports_instantiate(topo_mod_t *, tnode_t *, 628 di_node_t, int); 629 extern void pci_receptacle_instantiate(topo_mod_t *, tnode_t *, 630 di_node_t); 631 632 for (cn = di_child_node(din); cn != DI_NODE_NIL; 633 cn = di_sibling_node(cn)) { 634 if (strcmp(di_node_name(cn), IPORT) == 0) 635 niports++; 636 } 637 if (niports > 0) 638 pci_iports_instantiate(mod, fn, din, niports); 639 640 if ((rcnt = di_prop_lookup_strings(DDI_DEV_T_ANY, din, 641 DI_RECEPTACLE_PHYMASK, &propstr)) > 0) { 642 if (topo_node_range_create(mod, fn, RECEPTACLE, 0, 643 rcnt) >= 0) 644 pci_receptacle_instantiate(mod, fn, din); 645 } 646 } 647 648 /* 649 * If this is an NVMe device and if the FRU label indicates it's not an 650 * onboard device then invoke the disk enumerator to enumerate the NVMe 651 * controller and associated namespaces. 652 * 653 * We skip NVMe devices that appear to be onboard as those are likely 654 * M.2 or U.2 devices and so should be enumerated via a 655 * platform-specific XML map so that they can be associated with the 656 * correct physical bay/slot. This code is intended to pick up NVMe 657 * devices that are part of PCIe add-in cards. 658 */ 659 if (topo_node_label(fn, &label, &err) != 0) { 660 topo_mod_dprintf(mod, "%s: failed to lookup FRU label on " 661 "%s=%" PRIu64, __func__, topo_node_name(fn), 662 topo_node_instance(fn)); 663 goto out; 664 } 665 666 if (class == PCI_CLASS_MASS && subclass == PCI_MASS_NVME && 667 strcmp(label, "MB") != 0) { 668 char *driver = di_driver_name(din); 669 char *slash; 670 topo_pgroup_info_t pgi; 671 672 if (topo_prop_get_string(fn, TOPO_PGROUP_IO, TOPO_IO_DEV, 673 &pdev, &err) != 0) { 674 topo_mod_dprintf(mod, "%s: failed to lookup %s on " 675 "%s=%" PRIu64, __func__, TOPO_IO_DEV, 676 topo_node_name(fn), topo_node_instance(fn)); 677 goto out; 678 } 679 680 /* 681 * Add the binding properties that are required by the disk 682 * enumerator to discover the accociated NVMe controller. 683 */ 684 pdev_sz = strlen(pdev) + 1; 685 if ((slash = strrchr(pdev, '/')) == NULL) { 686 topo_mod_dprintf(mod, "%s: malformed dev path\n", 687 __func__); 688 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM); 689 goto out; 690 } 691 *slash = '\0'; 692 693 pgi.tpi_name = TOPO_PGROUP_BINDING; 694 pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; 695 pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; 696 pgi.tpi_version = TOPO_VERSION; 697 if (topo_pgroup_create(fn, &pgi, &err) != 0 || 698 topo_prop_set_string(fn, TOPO_PGROUP_BINDING, 699 TOPO_BINDING_DRIVER, TOPO_PROP_IMMUTABLE, driver, 700 &err) != 0 || 701 topo_prop_set_string(fn, TOPO_PGROUP_BINDING, 702 TOPO_BINDING_PARENT_DEV, TOPO_PROP_IMMUTABLE, pdev, 703 &err) != 0) { 704 topo_mod_dprintf(mod, "%s: failed to set binding " 705 "props", __func__); 706 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM); 707 goto out; 708 } 709 710 /* 711 * Load and invoke the disk enumerator module. 712 */ 713 if (topo_mod_load(mod, DISK, TOPO_VERSION) == NULL) { 714 topo_mod_dprintf(mod, "pcibus enum could not load " 715 "disk enum\n"); 716 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM); 717 goto out; 718 } 719 (void) topo_mod_enumerate(mod, fn, DISK, NVME, 0, 0, NULL); 720 } 721 out: 722 if (pdev != NULL) { 723 topo_mod_free(mod, pdev, pdev_sz); 724 } 725 topo_mod_strfree(mod, label); 726 } 727 728 int 729 pci_children_instantiate(topo_mod_t *mod, tnode_t *parent, di_node_t pn, 730 int board, int bridge, int rc, int bover, int depth) 731 { 732 did_t *pps[MAX_PCIBUS_DEVS][MAX_PCIDEV_FNS]; 733 did_t *bp = NULL; 734 did_t *np; 735 di_node_t sib; 736 di_node_t din; 737 tnode_t *bn = NULL; 738 tnode_t *dn = NULL; 739 int pb = -1; 740 int b, d, f; 741 742 for (d = 0; d < MAX_PCIBUS_DEVS; d++) 743 for (f = 0; f < MAX_PCIDEV_FNS; f++) 744 pps[d][f] = NULL; 745 746 /* start at the parent's first sibling */ 747 sib = di_child_node(pn); 748 while (sib != DI_NODE_NIL) { 749 np = did_create(mod, sib, board, bridge, rc, bover); 750 if (np == NULL) 751 return (-1); 752 did_BDF(np, &b, &d, &f); 753 pps[d][f] = np; 754 if (bp == NULL) 755 bp = np; 756 if (pb < 0) 757 pb = ((bover == TRUST_BDF) ? b : bover); 758 sib = di_sibling_node(sib); 759 } 760 if (pb < 0 && bover < 0) 761 return (0); 762 if (rc >= 0) 763 bn = pciexbus_declare(mod, parent, pn, ((pb < 0) ? bover : pb)); 764 else 765 bn = pcibus_declare(mod, parent, pn, ((pb < 0) ? bover : pb)); 766 if (bn == NULL) 767 return (-1); 768 if (pb < 0) 769 return (0); 770 771 for (d = 0; d < MAX_PCIBUS_DEVS; d++) { 772 for (f = 0; f < MAX_PCIDEV_FNS; f++) { 773 if (pps[d][f] == NULL) 774 continue; 775 din = did_dinode(pps[d][f]); 776 777 /* 778 * Try to enumerate as many devices and functions as 779 * possible. If we fail to declare a device, break 780 * out of the function loop. 781 */ 782 declare_dev_and_fn(mod, bn, 783 &dn, din, board, bridge, rc, d, f, depth); 784 did_rele(pps[d][f]); 785 786 if (dn == NULL) 787 break; 788 } 789 dn = NULL; 790 } 791 return (0); 792 } 793 794 static int 795 pciexbus_enum(topo_mod_t *mp, tnode_t *ptn, char *pnm, topo_instance_t min, 796 topo_instance_t max) 797 { 798 di_node_t pdn; 799 int rc, hb; 800 tnode_t *hbtn; 801 int retval; 802 803 /* 804 * PCI-Express; parent node's private data is a simple di_node_t 805 * and we have to construct our own did hash and did_t. 806 */ 807 rc = topo_node_instance(ptn); 808 if ((hbtn = topo_node_parent(ptn)) != NULL) 809 hb = topo_node_instance(hbtn); 810 else 811 hb = rc; 812 813 if ((pdn = topo_node_getspecific(ptn)) == DI_NODE_NIL) { 814 topo_mod_dprintf(mp, 815 "Parent %s node missing private data.\n" 816 "Unable to proceed with %s enumeration.\n", pnm, PCIEX_BUS); 817 return (0); 818 } 819 if (did_hash_init(mp) != 0) 820 return (-1); 821 if ((did_create(mp, pdn, 0, hb, rc, TRUST_BDF)) == NULL) 822 return (-1); /* errno already set */ 823 824 retval = pci_children_instantiate(mp, ptn, pdn, 0, hb, rc, 825 (min == max) ? min : TRUST_BDF, 0); 826 did_hash_fini(mp); 827 828 return (retval); 829 } 830 831 static int 832 pcibus_enum(topo_mod_t *mp, tnode_t *ptn, char *pnm, topo_instance_t min, 833 topo_instance_t max, void *data) 834 { 835 did_t *didp, *hbdid = (did_t *)data; 836 int retval; 837 838 /* 839 * XXTOPO: we should not be sharing private node data with another 840 * module. PCI Bus; Parent node's private data is a did_t. We'll 841 * use the did hash established by the parent. 842 */ 843 did_setspecific(mp, data); 844 845 /* 846 * If we're looking for a specific bus-instance, find the right 847 * did_t in the chain, otherwise, there should be only one did_t. 848 */ 849 if (min == max) { 850 int b; 851 didp = hbdid; 852 while (didp != NULL) { 853 did_BDF(didp, &b, NULL, NULL); 854 if (b == min) 855 break; 856 didp = did_link_get(didp); 857 } 858 if (didp == NULL) { 859 topo_mod_dprintf(mp, 860 "Parent %s node missing private data related\n" 861 "to %s instance %" PRIu64 ".\n", pnm, PCI_BUS, min); 862 topo_mod_setspecific(mp, NULL); 863 return (0); 864 } 865 } else { 866 assert(did_link_get(hbdid) == NULL); 867 didp = hbdid; 868 } 869 retval = pci_children_instantiate(mp, ptn, did_dinode(didp), 870 did_board(didp), did_bridge(didp), did_rc(didp), 871 (min == max) ? min : TRUST_BDF, 0); 872 873 topo_mod_setspecific(mp, NULL); 874 875 return (retval); 876 } 877 878 /*ARGSUSED*/ 879 static int 880 pci_enum(topo_mod_t *mod, tnode_t *ptn, const char *name, 881 topo_instance_t min, topo_instance_t max, void *notused, void *data) 882 { 883 int retval; 884 char *pname; 885 886 topo_mod_dprintf(mod, "Enumerating pci!\n"); 887 888 if (strcmp(name, PCI_BUS) != 0 && strcmp(name, PCIEX_BUS) != 0) { 889 topo_mod_dprintf(mod, 890 "Currently only know how to enumerate %s or %s.\n", 891 PCI_BUS, PCIEX_BUS); 892 return (0); 893 } 894 pname = topo_node_name(ptn); 895 if (strcmp(pname, HOSTBRIDGE) != 0 && strcmp(pname, PCIEX_ROOT) != 0) { 896 topo_mod_dprintf(mod, 897 "Currently can only enumerate a %s or %s directly\n", 898 PCI_BUS, PCIEX_BUS); 899 topo_mod_dprintf(mod, 900 "descended from a %s or %s node.\n", 901 HOSTBRIDGE, PCIEX_ROOT); 902 return (0); 903 } 904 905 if (strcmp(name, PCI_BUS) == 0) { 906 retval = pcibus_enum(mod, ptn, pname, min, max, data); 907 } else if (strcmp(name, PCIEX_BUS) == 0) { 908 retval = pciexbus_enum(mod, ptn, pname, min, max); 909 } else { 910 topo_mod_dprintf(mod, 911 "Currently only know how to enumerate %s or %s not %s.\n", 912 PCI_BUS, PCIEX_BUS, name); 913 return (0); 914 } 915 916 return (retval); 917 } 918 919 /*ARGSUSED*/ 920 static void 921 pci_release(topo_mod_t *mp, tnode_t *node) 922 { 923 topo_method_unregister_all(mp, node); 924 925 /* 926 * node private data (did_t) for this node is destroyed in 927 * did_hash_destroy() 928 */ 929 930 topo_node_unbind(node); 931 } 932