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
_topo_init(topo_mod_t * modhdl,topo_version_t version)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
_topo_fini(topo_mod_t * modhdl)110 _topo_fini(topo_mod_t *modhdl)
111 {
112 topo_mod_unregister(modhdl);
113 }
114
115 static int
pci_label(topo_mod_t * mp,tnode_t * node,topo_version_t version,nvlist_t * in,nvlist_t ** out)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
pci_fru(topo_mod_t * mp,tnode_t * node,topo_version_t version,nvlist_t * in,nvlist_t ** out)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 *
pci_tnode_create(topo_mod_t * mod,tnode_t * parent,const char * name,topo_instance_t i,void * priv)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
hostbridge_asdevice(topo_mod_t * mod,tnode_t * bus)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
pciexfn_add_ufm(topo_mod_t * mod,tnode_t * parent,tnode_t * node)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 *
pciexfn_declare(topo_mod_t * mod,tnode_t * parent,di_node_t dn,topo_instance_t i)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 *
pciexdev_declare(topo_mod_t * mod,tnode_t * parent,di_node_t dn,topo_instance_t i)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 *
pciexbus_declare(topo_mod_t * mod,tnode_t * parent,di_node_t dn,topo_instance_t i)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 *
pcifn_declare(topo_mod_t * mod,tnode_t * parent,di_node_t dn,topo_instance_t i)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 *
pcidev_declare(topo_mod_t * mod,tnode_t * parent,di_node_t dn,topo_instance_t i)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 *
pcibus_declare(topo_mod_t * mod,tnode_t * parent,di_node_t dn,topo_instance_t i)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
pci_bridge_declare(topo_mod_t * mod,tnode_t * fn,di_node_t din,int board,int bridge,int rc,int depth)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
declare_dev_and_fn(topo_mod_t * mod,tnode_t * bus,tnode_t ** dev,di_node_t din,int board,int bridge,int rc,int devno,int fnno,int depth)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
pci_children_instantiate(topo_mod_t * mod,tnode_t * parent,di_node_t pn,int board,int bridge,int rc,int bover,int depth)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
pciexbus_enum(topo_mod_t * mp,tnode_t * ptn,char * pnm,topo_instance_t min,topo_instance_t max)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
pcibus_enum(topo_mod_t * mp,tnode_t * ptn,char * pnm,topo_instance_t min,topo_instance_t max,void * data)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
pci_enum(topo_mod_t * mod,tnode_t * ptn,const char * name,topo_instance_t min,topo_instance_t max,void * notused,void * data)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
pci_release(topo_mod_t * mp,tnode_t * node)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