xref: /illumos-gate/usr/src/lib/fm/topo/modules/common/pciebus/topo_pcie_prop.c (revision 84ceaea936ebcf122d4f0756d298adf307fd491d)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2023 Oxide Computer Company
14  */
15 
16 #include <fcntl.h>
17 #include <libdevinfo.h>
18 #include <stdbool.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <unistd.h>
22 #include <sys/debug.h>
23 #include <sys/pci.h>
24 #include <sys/pcie.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 
28 #include <sys/fm/protocol.h>
29 #include <fm/topo_mod.h>
30 #include <fm/topo_list.h>
31 #include <fm/topo_method.h>
32 #include <fm/topo_hc.h>
33 
34 #include "topo_pcie_impl.h"
35 
36 static const topo_pgroup_info_t io_pgroup = {
37 	.tpi_name = TOPO_PCIE_PGROUP_IO,
38 	.tpi_namestab = TOPO_STABILITY_PRIVATE,
39 	.tpi_datastab = TOPO_STABILITY_PRIVATE,
40 	.tpi_version = 1
41 };
42 
43 static const topo_pgroup_info_t pcicfg_pgroup = {
44 	.tpi_name = TOPO_PCIE_PGROUP_PCI_CFG,
45 	.tpi_namestab = TOPO_STABILITY_PRIVATE,
46 	.tpi_datastab = TOPO_STABILITY_PRIVATE,
47 	.tpi_version = 1
48 };
49 
50 static const topo_pgroup_info_t pci_pgroup = {
51 	.tpi_name = TOPO_PCIE_PGROUP_PCI,
52 	.tpi_namestab = TOPO_STABILITY_PRIVATE,
53 	.tpi_datastab = TOPO_STABILITY_PRIVATE,
54 	.tpi_version = 1
55 };
56 
57 static const topo_pgroup_info_t port_pgroup = {
58 	.tpi_name = TOPO_PCIE_PGROUP_PORT,
59 	.tpi_namestab = TOPO_STABILITY_PRIVATE,
60 	.tpi_datastab = TOPO_STABILITY_PRIVATE,
61 	.tpi_version = 1
62 };
63 
64 const topo_pgroup_info_t pcielink_pgroup = {
65 	.tpi_name = TOPO_PCIE_PGROUP_PCIE_LINK,
66 	.tpi_namestab = TOPO_STABILITY_PRIVATE,
67 	.tpi_datastab = TOPO_STABILITY_PRIVATE,
68 	.tpi_version = 1
69 };
70 
71 static const topo_pgroup_info_t pcilink_pgroup = {
72 	.tpi_name = TOPO_PCIE_PGROUP_PCI_LINK,
73 	.tpi_namestab = TOPO_STABILITY_PRIVATE,
74 	.tpi_datastab = TOPO_STABILITY_PRIVATE,
75 	.tpi_version = 1
76 };
77 
78 typedef struct pcie_prop pcie_prop_t;
79 typedef bool (*f_prop)(topo_mod_t *, pcie_t *, pcie_node_t *, tnode_t *,
80     pcie_prop_t *);
81 typedef struct pcie_prop {
82 	const topo_pgroup_info_t	*pp_group;
83 	const char			*pp_di_prop;
84 	const char			*pp_topo_prop;
85 	f_prop				pp_func;
86 } pcie_prop_t;
87 
88 static bool
devinfostr(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)89 devinfostr(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
90     pcie_prop_t *prop)
91 {
92 	return (pcie_topo_prop_copy(mod, node->pn_did, tn, prop->pp_group,
93 	    TOPO_TYPE_STRING, prop->pp_di_prop, prop->pp_topo_prop));
94 }
95 
96 static bool
opt_devinfostr(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)97 opt_devinfostr(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
98     pcie_prop_t *prop)
99 {
100 	(void) devinfostr(mod, pcie, node, tn, prop);
101 	return (true);
102 }
103 
104 static bool
devinfo32(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)105 devinfo32(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
106     pcie_prop_t *prop)
107 {
108 	return (pcie_topo_prop_copy(mod, node->pn_did, tn, prop->pp_group,
109 	    TOPO_TYPE_UINT32, prop->pp_di_prop, prop->pp_topo_prop));
110 }
111 
112 static bool
opt_devinfo32(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)113 opt_devinfo32(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
114     pcie_prop_t *prop)
115 {
116 	(void) devinfo32(mod, pcie, node, tn, prop);
117 	return (true);
118 }
119 
120 static bool
devinfo64(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)121 devinfo64(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
122     pcie_prop_t *prop)
123 {
124 	return (pcie_topo_prop_copy(mod, node->pn_did, tn, prop->pp_group,
125 	    TOPO_TYPE_UINT64, prop->pp_di_prop, prop->pp_topo_prop));
126 }
127 
128 static bool
devinfo64_array(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)129 devinfo64_array(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
130     pcie_prop_t *prop)
131 {
132 	return (pcie_topo_prop_copy(mod, node->pn_did, tn, prop->pp_group,
133 	    TOPO_TYPE_UINT64_ARRAY, prop->pp_di_prop, prop->pp_topo_prop));
134 }
135 
136 static bool
opt_devinfo32_array(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)137 opt_devinfo32_array(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
138     tnode_t *tn, pcie_prop_t *prop)
139 {
140 	(void) pcie_topo_prop_copy(mod, node->pn_did, tn, prop->pp_group,
141 	    TOPO_TYPE_UINT32_ARRAY, prop->pp_di_prop, prop->pp_topo_prop);
142 	return (true);
143 }
144 
145 static bool
devinfobool(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)146 devinfobool(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
147     tnode_t *tn, pcie_prop_t *prop)
148 {
149 	bool val =  pcie_devinfo_getbool(mod, node->pn_did, prop->pp_di_prop);
150 
151 	return (pcie_topo_prop_set32(mod, tn, prop->pp_group,
152 	    prop->pp_topo_prop, val ? 1 : 0));
153 }
154 
155 /* io properties */
156 
157 static bool
set_devpath(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)158 set_devpath(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
159     pcie_prop_t *prop)
160 {
161 	return (pcie_topo_prop_setstr(mod, tn, prop->pp_group,
162 	    prop->pp_topo_prop, node->pn_path));
163 }
164 
165 static bool
set_driver(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)166 set_driver(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
167     pcie_prop_t *prop)
168 {
169 	if (node->pn_drvname == NULL)
170 		return (true);
171 
172 	return (pcie_topo_prop_setstr(mod, tn, prop->pp_group,
173 	    prop->pp_topo_prop, node->pn_drvname));
174 }
175 
176 static bool
set_instance(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)177 set_instance(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
178     pcie_prop_t *prop)
179 {
180 	if (node->pn_drvname == NULL)
181 		return (true);
182 
183 	return (pcie_topo_prop_set64(mod, tn, prop->pp_group,
184 	    prop->pp_topo_prop, node->pn_drvinst));
185 }
186 
187 static pcie_prop_t io_props[] = {
188 	{ &io_pgroup, NULL, TOPO_PCIE_IO_DEV_PATH, set_devpath },
189 	{ &io_pgroup, NULL, TOPO_PCIE_IO_DRIVER, set_driver },
190 	{ &io_pgroup, NULL, TOPO_PCIE_IO_INSTANCE, set_instance },
191 };
192 
193 /* link properties */
194 
195 static bool
link_state(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)196 link_state(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
197     pcie_prop_t *prop)
198 {
199 	const char *val;
200 
201 	switch (topo_pcie_link_status(mod, node)) {
202 	case PCI_LINK_UP:
203 		val = TOPO_PCIE_LINK_UP_STR;
204 		break;
205 	case PCI_LINK_DOWN:
206 		val = TOPO_PCIE_LINK_DOWN_STR;
207 		break;
208 	default:
209 		/* Omit the property if link status is unknown */
210 		return (true);
211 	}
212 
213 	return (pcie_topo_prop_setstr(mod, tn, prop->pp_group,
214 	    prop->pp_topo_prop, val));
215 }
216 
217 static bool
link_targspeed(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)218 link_targspeed(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
219     pcie_prop_t *prop)
220 {
221 	if (!pcie_devinfo_getbool(mod, node->pn_did, DI_PCIE_ADMIN_TAG))
222 		return (true);
223 
224 	return (devinfo64(mod, pcie, node, tn, prop));
225 }
226 
227 static pcie_prop_t pcie_link_props[] = {
228 	{ &pcielink_pgroup, NULL, TOPO_PCIE_LINK_STATE, link_state },
229 	{ &pcielink_pgroup, DI_PCIE_CUR_SPEED, TOPO_PCIE_LINK_CUR_SPEED,
230 	    devinfo64 },
231 	{ &pcielink_pgroup, DI_PCIE_CUR_WIDTH, TOPO_PCIE_LINK_CUR_WIDTH,
232 	    devinfo32 },
233 	{ &pcielink_pgroup, DI_PCIE_MAX_SPEED, TOPO_PCIE_LINK_MAX_SPEED,
234 	    devinfo64 },
235 	{ &pcielink_pgroup, DI_PCIE_MAX_WIDTH, TOPO_PCIE_LINK_MAX_WIDTH,
236 	    devinfo32 },
237 	{ &pcielink_pgroup, DI_PCIE_SUP_SPEEDS, TOPO_PCIE_LINK_SUP_SPEED,
238 	    devinfo64_array },
239 	{ &pcielink_pgroup, DI_PCIE_TARG_SPEED, TOPO_PCIE_LINK_ADMIN_SPEED,
240 	    link_targspeed },
241 };
242 
243 static pcie_prop_t pci_link_props[] = {
244 	{ &pcilink_pgroup, NULL, TOPO_PCIE_LINK_STATE, link_state },
245 	{ &pcilink_pgroup, DI_PCI_66MHZ_CAPABLE, TOPO_PCIE_LINK_66MHZ_CAPABLE,
246 	    devinfobool },
247 };
248 
249 /* link methods */
250 
251 static int
topo_pcie_link_unusable(topo_mod_t * mod,tnode_t * tn,topo_version_t ver,nvlist_t * in,nvlist_t ** out)252 topo_pcie_link_unusable(topo_mod_t *mod, tnode_t *tn, topo_version_t ver,
253     nvlist_t *in, nvlist_t **out)
254 {
255 	pcie_node_t *node = topo_node_getspecific(tn);
256 	nvlist_t *nvl;
257 	uint32_t unusable;
258 
259 	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0)
260 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
261 
262 	unusable = 1;
263 	if (node != NULL && topo_pcie_link_status(mod, node) == PCI_LINK_UP)
264 		unusable = 0;
265 
266 	if (nvlist_add_uint32(nvl, TOPO_METH_UNUSABLE_RET, unusable) != 0) {
267 		nvlist_free(nvl);
268 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
269 	}
270 
271 	*out = nvl;
272 
273 	return (0);
274 }
275 
276 static const topo_method_t link_methods[] = {
277 	{
278 		.tm_name = TOPO_METH_UNUSABLE,
279 		.tm_desc = TOPO_METH_UNUSABLE_DESC,
280 		.tm_version = TOPO_METH_UNUSABLE_VERSION,
281 		.tm_stability = TOPO_STABILITY_INTERNAL,
282 		.tm_func = topo_pcie_link_unusable
283 	},
284 	{ .tm_name = NULL }
285 };
286 
287 /* pci properties */
288 
289 static bool
set_bdf(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)290 set_bdf(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
291     pcie_prop_t *prop)
292 {
293 	int32_t *val;
294 	int nval;
295 
296 	if (node->pn_type == PCIE_NODE_ROOTNEXUS)
297 		return (true);
298 
299 	nval = di_prop_lookup_ints(DDI_DEV_T_ANY, node->pn_did,
300 	    prop->pp_di_prop, &val);
301 	if (nval < 1)
302 		return (true);
303 
304 	return (
305 	    pcie_topo_prop_set32(mod, tn, prop->pp_group,
306 	    TOPO_PCIE_PCI_BUS, PCI_REG_BUS_G(val[0])) &&
307 	    pcie_topo_prop_set32(mod, tn, prop->pp_group,
308 	    TOPO_PCIE_PCI_DEVICE, PCI_REG_DEV_G(val[0])) &&
309 	    pcie_topo_prop_set32(mod, tn, prop->pp_group,
310 	    TOPO_PCIE_PCI_FUNCTION, PCI_REG_FUNC_G(val[0])) &&
311 	    pcie_topo_prop_set32(mod, tn, prop->pp_group,
312 	    TOPO_PCIE_PCI_SEGMENT, 0));
313 }
314 
315 static bool
set_pci_type(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)316 set_pci_type(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
317     pcie_prop_t *prop)
318 {
319 	return (pcie_topo_prop_setstr(mod, tn, prop->pp_group,
320 	    prop->pp_topo_prop, pcie_type_name(node->pn_type)));
321 }
322 
323 static bool
set_class(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)324 set_class(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
325     pcie_prop_t *prop)
326 {
327 	if (node->pn_class == 0)
328 		return (true);
329 
330 	return (pcie_topo_prop_set32(mod, tn, prop->pp_group,
331 	    TOPO_PCIE_PCI_CLASS, node->pn_class) &&
332 	    pcie_topo_prop_set32(mod, tn, prop->pp_group,
333 	    TOPO_PCIE_PCI_SUBCLASS, node->pn_subclass) &&
334 	    pcie_topo_prop_set32(mod, tn, prop->pp_group,
335 	    TOPO_PCIE_PCI_INTERFACE, node->pn_intf));
336 }
337 
338 static bool
set_pcidb(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)339 set_pcidb(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
340     pcie_prop_t *prop)
341 {
342 	int32_t vid, devid, ssvid, ssdevid;
343 	pcidb_vendor_t *pciv;
344 	pcidb_device_t *pcid;
345 	pcidb_subvd_t *pcis;
346 	di_node_t did = node->pn_did;
347 
348 	if (pcie->tp_pcidb_hdl == NULL)
349 		goto out;
350 
351 	vid = pcie_devinfo_get32(mod, did, DI_VENDIDPROP);
352 	devid = pcie_devinfo_get32(mod, did, DI_DEVIDPROP);
353 	ssvid = pcie_devinfo_get32(mod, did, DI_SUBVENDIDPROP);
354 	ssdevid = pcie_devinfo_get32(mod, did, DI_SUBSYSTEMID);
355 
356 	if (vid == -1)
357 		goto out;
358 
359 	pciv = pcidb_lookup_vendor(pcie->tp_pcidb_hdl, (uint16_t)vid);
360 	if (pciv == NULL)
361 		goto out;
362 	(void) pcie_topo_prop_setstr(mod, tn, prop->pp_group,
363 	    TOPO_PCIE_PCI_VENDOR_NAME, pcidb_vendor_name(pciv));
364 
365 	if (devid == -1)
366 		goto out;
367 
368 	pcid = pcidb_lookup_device_by_vendor(pciv, (uint16_t)devid);
369 	if (pcid == NULL)
370 		goto out;
371 	(void) pcie_topo_prop_setstr(mod, tn, prop->pp_group,
372 	    TOPO_PCIE_PCI_DEV_NAME, pcidb_device_name(pcid));
373 
374 	if (ssvid == -1 || ssdevid == -1 || ssvid == 0 || ssdevid == 0)
375 		goto out;
376 
377 	pcis = pcidb_lookup_subvd_by_device(pcid, (uint16_t)ssvid,
378 	    (uint16_t)ssdevid);
379 	if (pcis == NULL)
380 		goto out;
381 	(void) pcie_topo_prop_setstr(mod, tn, prop->pp_group,
382 	    TOPO_PCIE_PCI_SUBSYSTEM_NAME, pcidb_subvd_name(pcis));
383 
384 out:
385 	/*
386 	 * We always return success here, even if one or more of the lookups
387 	 * failed, or if the we don't have an open database handle.
388 	 */
389 	return (true);
390 }
391 
392 static bool
set_busrange(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t * prop)393 set_busrange(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node, tnode_t *tn,
394     pcie_prop_t *prop)
395 {
396 	int32_t *val;
397 	int nval;
398 	uint32_t arr[3];
399 
400 	nval = di_prop_lookup_ints(DDI_DEV_T_ANY, node->pn_did,
401 	    prop->pp_di_prop, &val);
402 	if (nval != 2)
403 		return (true);
404 
405 	arr[0] = val[0];
406 	arr[1] = val[1];
407 
408 	return (pcie_topo_prop_set32_array(mod, tn, prop->pp_group,
409 	    prop->pp_topo_prop, arr, 2));
410 }
411 
412 static pcie_prop_t pci_props[] = {
413 	/* io */
414 	{ &io_pgroup, NULL, TOPO_PCIE_IO_DEV_PATH, set_devpath },
415 	{ &io_pgroup, NULL, TOPO_PCIE_IO_DRIVER, set_driver },
416 	{ &io_pgroup, NULL, TOPO_PCIE_IO_INSTANCE, set_instance },
417 	{ &io_pgroup, DI_DEVTYPPROP, TOPO_PCIE_IO_DEVTYPE, opt_devinfostr },
418 
419 	/* pci-cfg */
420 	{ &pcicfg_pgroup, DI_REGPROP, NULL, set_bdf },
421 	{ &pcicfg_pgroup, DI_BUSRANGE, TOPO_PCIE_PCI_BUS_RANGE, set_busrange },
422 	{ &pcicfg_pgroup, DI_AADDRPROP, TOPO_PCIE_PCI_ASSIGNED_ADDR,
423 	    opt_devinfo32_array }, // XXX - decode further?
424 
425 	/* pci */
426 	{ &pci_pgroup, NULL, TOPO_PCIE_PCI_TYPE, set_pci_type },
427 	{ &pci_pgroup, NULL, NULL, set_class },
428 	{ &pci_pgroup, DI_MODELNAME, TOPO_PCIE_PCI_CLASS_STRING,
429 	    opt_devinfostr },
430 	{ &pci_pgroup, DI_VENDIDPROP, TOPO_PCIE_PCI_VENDOR_ID, opt_devinfo32 },
431 	{ &pci_pgroup, DI_DEVIDPROP, TOPO_PCIE_PCI_DEV_ID, opt_devinfo32 },
432 	{ &pci_pgroup, DI_SUBVENDIDPROP, TOPO_PCIE_PCI_SSVENDORID,
433 	    opt_devinfo32 },
434 	{ &pci_pgroup, DI_SUBSYSTEMID, TOPO_PCIE_PCI_SSID, opt_devinfo32 },
435 	{ &pci_pgroup, DI_REVIDPROP, TOPO_PCIE_PCI_REVID, opt_devinfo32 },
436 	{ &pci_pgroup, DI_PHYSPROP, TOPO_PCIE_PCI_SLOT, opt_devinfo32 },
437 	{ &pci_pgroup, NULL, NULL, set_pcidb },
438 };
439 
440 static bool
pcie_apply_props(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,pcie_prop_t props[],size_t num)441 pcie_apply_props(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
442     tnode_t *tn, pcie_prop_t props[], size_t num)
443 {
444 	bool ret = true;
445 
446 	for (size_t i = 0; i < num; i++) {
447 		pcie_prop_t *p = &props[i];
448 
449 		if (p->pp_group != NULL &&
450 		    !pcie_topo_pgroup_create(mod, tn, p->pp_group)) {
451 			return (false);
452 		}
453 
454 		if (!p->pp_func(mod, pcie, node, tn, p))
455 			ret = false;
456 	}
457 
458 	return (ret);
459 }
460 
461 bool
topo_pcie_set_io_props(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn)462 topo_pcie_set_io_props(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
463     tnode_t *tn)
464 {
465 	return (pcie_apply_props(mod, pcie, node, tn, io_props,
466 	    ARRAY_SIZE(io_props)));
467 }
468 
469 bool
topo_pcie_set_pci_props(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn)470 topo_pcie_set_pci_props(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
471     tnode_t *tn)
472 {
473 	return (pcie_apply_props(mod, pcie, node, tn, pci_props,
474 	    ARRAY_SIZE(pci_props)));
475 }
476 
477 bool
topo_pcie_set_port_props(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn,topo_port_type_t type)478 topo_pcie_set_port_props(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
479     tnode_t *tn, topo_port_type_t type)
480 {
481 	const topo_pgroup_info_t *pg = &port_pgroup;
482 
483 	if (!pcie_topo_pgroup_create(mod, tn, pg))
484 		return (false);
485 
486 	return (pcie_topo_prop_setstr(mod, tn, pg, TOPO_PCIE_PORT_TYPE,
487 	    type == TOPO_PORT_DOWNSTREAM ? TOPO_PCIE_PORT_TYPE_DS :
488 	    TOPO_PCIE_PORT_TYPE_US));
489 }
490 
491 bool
topo_pcie_set_link_props(topo_mod_t * mod,pcie_t * pcie,pcie_node_t * node,tnode_t * tn)492 topo_pcie_set_link_props(topo_mod_t *mod, pcie_t *pcie, pcie_node_t *node,
493     tnode_t *tn)
494 {
495 	bool ret = false;
496 
497 	switch (node->pn_type) {
498 	case PCIE_NODE_PCI_DEV:
499 	case PCIE_NODE_PCIE_PCI:
500 		ret = pcie_apply_props(mod, pcie, node, tn, pci_link_props,
501 		    ARRAY_SIZE(pci_link_props));
502 		break;
503 	default:
504 		ret = pcie_apply_props(mod, pcie, node, tn, pcie_link_props,
505 		    ARRAY_SIZE(pcie_link_props));
506 		break;
507 	}
508 
509 	if (topo_method_register(mod, tn, link_methods) != 0) {
510 		topo_mod_dprintf(mod, "failed to register link methods: %s",
511 		    topo_mod_errmsg(mod));
512 		ret = false;
513 	}
514 
515 	return (ret);
516 }
517