xref: /illumos-gate/usr/src/lib/fm/topo/libtopo/common/pcie.c (revision 84ceaea936ebcf122d4f0756d298adf307fd491d)
1*84ceaea9SAndy Fiddaman /*
2*84ceaea9SAndy Fiddaman  * This file and its contents are supplied under the terms of the
3*84ceaea9SAndy Fiddaman  * Common Development and Distribution License ("CDDL"), version 1.0.
4*84ceaea9SAndy Fiddaman  * You may only use this file in accordance with the terms of version
5*84ceaea9SAndy Fiddaman  * 1.0 of the CDDL.
6*84ceaea9SAndy Fiddaman  *
7*84ceaea9SAndy Fiddaman  * A full copy of the text of the CDDL should have accompanied this
8*84ceaea9SAndy Fiddaman  * source.  A copy of the CDDL is also available via the Internet at
9*84ceaea9SAndy Fiddaman  * http://www.illumos.org/license/CDDL.
10*84ceaea9SAndy Fiddaman  */
11*84ceaea9SAndy Fiddaman 
12*84ceaea9SAndy Fiddaman /*
13*84ceaea9SAndy Fiddaman  * Copyright 2023 Oxide Computer Company
14*84ceaea9SAndy Fiddaman  */
15*84ceaea9SAndy Fiddaman 
16*84ceaea9SAndy Fiddaman /*
17*84ceaea9SAndy Fiddaman  * This provides the basic mechanisms for dealing with the pcie schema. A pcie
18*84ceaea9SAndy Fiddaman  * FMRI has the form:
19*84ceaea9SAndy Fiddaman  *
20*84ceaea9SAndy Fiddaman  *     pcie:///cpu=C[/root-complex=R[function=F[...]]]
21*84ceaea9SAndy Fiddaman  *
22*84ceaea9SAndy Fiddaman  * That is to say that the top level nodes represent physical CPUs in the
23*84ceaea9SAndy Fiddaman  * system and their PCIe root complexes are enumerated directly under that.
24*84ceaea9SAndy Fiddaman  *
25*84ceaea9SAndy Fiddaman  * Each node inherits the FMRI of its parent, and then appends a new
26*84ceaea9SAndy Fiddaman  * '/<type>=<instance>' part, for example:
27*84ceaea9SAndy Fiddaman  *
28*84ceaea9SAndy Fiddaman  *     pcie:///cpu=0
29*84ceaea9SAndy Fiddaman  *     pcie:///cpu=0/root-complex=0
30*84ceaea9SAndy Fiddaman  *     pcie:///cpu=0/root-complex=0/function=0
31*84ceaea9SAndy Fiddaman  *     pcie:///cpu=0/root-complex=0/function=0/port=0
32*84ceaea9SAndy Fiddaman  *
33*84ceaea9SAndy Fiddaman  * Types used in the scheme are:
34*84ceaea9SAndy Fiddaman  *	cpu
35*84ceaea9SAndy Fiddaman  *	root-complex
36*84ceaea9SAndy Fiddaman  *	device
37*84ceaea9SAndy Fiddaman  *	function
38*84ceaea9SAndy Fiddaman  *	port
39*84ceaea9SAndy Fiddaman  *	link
40*84ceaea9SAndy Fiddaman  */
41*84ceaea9SAndy Fiddaman 
42*84ceaea9SAndy Fiddaman #include <stdio.h>
43*84ceaea9SAndy Fiddaman #include <stdlib.h>
44*84ceaea9SAndy Fiddaman #include <string.h>
45*84ceaea9SAndy Fiddaman #include <errno.h>
46*84ceaea9SAndy Fiddaman #include <stdbool.h>
47*84ceaea9SAndy Fiddaman #include <ctype.h>
48*84ceaea9SAndy Fiddaman #include <alloca.h>
49*84ceaea9SAndy Fiddaman #include <limits.h>
50*84ceaea9SAndy Fiddaman #include <fm/topo_mod.h>
51*84ceaea9SAndy Fiddaman #include <sys/param.h>
52*84ceaea9SAndy Fiddaman #include <sys/systeminfo.h>
53*84ceaea9SAndy Fiddaman #include <sys/fm/protocol.h>
54*84ceaea9SAndy Fiddaman #include <sys/stat.h>
55*84ceaea9SAndy Fiddaman 
56*84ceaea9SAndy Fiddaman #include <topo_method.h>
57*84ceaea9SAndy Fiddaman #include <topo_subr.h>
58*84ceaea9SAndy Fiddaman #include <pthread.h>
59*84ceaea9SAndy Fiddaman 
60*84ceaea9SAndy Fiddaman #include <pcie.h>
61*84ceaea9SAndy Fiddaman 
62*84ceaea9SAndy Fiddaman static size_t
fmri_nvl2str(nvlist_t * nvl,char * buf,size_t buflen)63*84ceaea9SAndy Fiddaman fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
64*84ceaea9SAndy Fiddaman {
65*84ceaea9SAndy Fiddaman 	size_t size = 0;
66*84ceaea9SAndy Fiddaman 	uint8_t version;
67*84ceaea9SAndy Fiddaman 	nvlist_t **plist;
68*84ceaea9SAndy Fiddaman 	uint_t nplist;
69*84ceaea9SAndy Fiddaman 	int err;
70*84ceaea9SAndy Fiddaman 
71*84ceaea9SAndy Fiddaman 	if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 ||
72*84ceaea9SAndy Fiddaman 	    version > FM_PCIE_SCHEME_VERSION) {
73*84ceaea9SAndy Fiddaman 		return (0);
74*84ceaea9SAndy Fiddaman 	}
75*84ceaea9SAndy Fiddaman 
76*84ceaea9SAndy Fiddaman 	if (!topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_PCIE, NULL,
77*84ceaea9SAndy Fiddaman 	    ":///")) {
78*84ceaea9SAndy Fiddaman 		return (0);
79*84ceaea9SAndy Fiddaman 	}
80*84ceaea9SAndy Fiddaman 
81*84ceaea9SAndy Fiddaman 	err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_PCIE_LIST,
82*84ceaea9SAndy Fiddaman 	    &plist, &nplist);
83*84ceaea9SAndy Fiddaman 	if (err != 0 || plist == NULL)
84*84ceaea9SAndy Fiddaman 		return (0);
85*84ceaea9SAndy Fiddaman 
86*84ceaea9SAndy Fiddaman 	for (uint_t i = 0; i < nplist; i++) {
87*84ceaea9SAndy Fiddaman 		char *name = NULL;
88*84ceaea9SAndy Fiddaman 		char *id = NULL;
89*84ceaea9SAndy Fiddaman 
90*84ceaea9SAndy Fiddaman 		if (i > 0) {
91*84ceaea9SAndy Fiddaman 			if (!topo_fmristr_build(&size, buf, buflen, "/", NULL,
92*84ceaea9SAndy Fiddaman 			    NULL)) {
93*84ceaea9SAndy Fiddaman 				return (0);
94*84ceaea9SAndy Fiddaman 			}
95*84ceaea9SAndy Fiddaman 		}
96*84ceaea9SAndy Fiddaman 		if (nvlist_lookup_string(plist[i],
97*84ceaea9SAndy Fiddaman 		    FM_FMRI_PCIE_NAME, &name) != 0 ||
98*84ceaea9SAndy Fiddaman 		    nvlist_lookup_string(plist[i],
99*84ceaea9SAndy Fiddaman 		    FM_FMRI_PCIE_ID, &id) != 0) {
100*84ceaea9SAndy Fiddaman 			return (0);
101*84ceaea9SAndy Fiddaman 		}
102*84ceaea9SAndy Fiddaman 		if (name == NULL || id == NULL)
103*84ceaea9SAndy Fiddaman 			return (0);
104*84ceaea9SAndy Fiddaman 		if (!topo_fmristr_build(&size, buf, buflen, "=", name, id))
105*84ceaea9SAndy Fiddaman 			return (0);
106*84ceaea9SAndy Fiddaman 	}
107*84ceaea9SAndy Fiddaman 
108*84ceaea9SAndy Fiddaman 	return (size);
109*84ceaea9SAndy Fiddaman }
110*84ceaea9SAndy Fiddaman 
111*84ceaea9SAndy Fiddaman static int
pcie_fmri_nvl2str(topo_mod_t * mod,tnode_t * node,topo_version_t version,nvlist_t * nvl,nvlist_t ** out)112*84ceaea9SAndy Fiddaman pcie_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version,
113*84ceaea9SAndy Fiddaman     nvlist_t *nvl, nvlist_t **out)
114*84ceaea9SAndy Fiddaman {
115*84ceaea9SAndy Fiddaman 	size_t len;
116*84ceaea9SAndy Fiddaman 	char *name = NULL;
117*84ceaea9SAndy Fiddaman 	nvlist_t *fmristr;
118*84ceaea9SAndy Fiddaman 
119*84ceaea9SAndy Fiddaman 	if (version > TOPO_METH_NVL2STR_VERSION)
120*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
121*84ceaea9SAndy Fiddaman 
122*84ceaea9SAndy Fiddaman 	if ((len = fmri_nvl2str(nvl, NULL, 0)) == 0)
123*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
124*84ceaea9SAndy Fiddaman 
125*84ceaea9SAndy Fiddaman 	if ((name = topo_mod_alloc(mod, len + 1)) == NULL)
126*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_NOMEM));
127*84ceaea9SAndy Fiddaman 
128*84ceaea9SAndy Fiddaman 	if (fmri_nvl2str(nvl, name, len + 1) == 0) {
129*84ceaea9SAndy Fiddaman 		topo_mod_free(mod, name, len + 1);
130*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
131*84ceaea9SAndy Fiddaman 	}
132*84ceaea9SAndy Fiddaman 
133*84ceaea9SAndy Fiddaman 	if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) {
134*84ceaea9SAndy Fiddaman 		topo_mod_free(mod, name, len + 1);
135*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
136*84ceaea9SAndy Fiddaman 	}
137*84ceaea9SAndy Fiddaman 	if (nvlist_add_string(fmristr, "fmri-string", name) != 0) {
138*84ceaea9SAndy Fiddaman 		topo_mod_free(mod, name, len + 1);
139*84ceaea9SAndy Fiddaman 		nvlist_free(fmristr);
140*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
141*84ceaea9SAndy Fiddaman 	}
142*84ceaea9SAndy Fiddaman 	topo_mod_free(mod, name, len + 1);
143*84ceaea9SAndy Fiddaman 	*out = fmristr;
144*84ceaea9SAndy Fiddaman 
145*84ceaea9SAndy Fiddaman 	return (0);
146*84ceaea9SAndy Fiddaman }
147*84ceaea9SAndy Fiddaman 
148*84ceaea9SAndy Fiddaman static nvlist_t *
fmri_create_err(topo_mod_t * mod,nvlist_t ** list,uint_t elems,nvlist_t * fmri,int err)149*84ceaea9SAndy Fiddaman fmri_create_err(topo_mod_t *mod, nvlist_t **list, uint_t elems,
150*84ceaea9SAndy Fiddaman     nvlist_t *fmri, int err)
151*84ceaea9SAndy Fiddaman {
152*84ceaea9SAndy Fiddaman 	if (list != NULL) {
153*84ceaea9SAndy Fiddaman 		for (uint_t i = 0; i < elems; i++)
154*84ceaea9SAndy Fiddaman 			nvlist_free(list[i]);
155*84ceaea9SAndy Fiddaman 
156*84ceaea9SAndy Fiddaman 		topo_mod_free(mod, list, sizeof (nvlist_t *) * elems);
157*84ceaea9SAndy Fiddaman 	}
158*84ceaea9SAndy Fiddaman 
159*84ceaea9SAndy Fiddaman 	nvlist_free(fmri);
160*84ceaea9SAndy Fiddaman 
161*84ceaea9SAndy Fiddaman 	(void) topo_mod_seterrno(mod, err);
162*84ceaea9SAndy Fiddaman 
163*84ceaea9SAndy Fiddaman 	topo_mod_dprintf(mod, "unable to create pcie FMRI: %s\n",
164*84ceaea9SAndy Fiddaman 	    topo_mod_errmsg(mod));
165*84ceaea9SAndy Fiddaman 
166*84ceaea9SAndy Fiddaman 	return (NULL);
167*84ceaea9SAndy Fiddaman }
168*84ceaea9SAndy Fiddaman 
169*84ceaea9SAndy Fiddaman static nvlist_t *
fmri_create_component(topo_mod_t * mod,const char * name,topo_instance_t inst)170*84ceaea9SAndy Fiddaman fmri_create_component(topo_mod_t *mod, const char *name, topo_instance_t inst)
171*84ceaea9SAndy Fiddaman {
172*84ceaea9SAndy Fiddaman 	char str[21]; /* decimal representation of UINT64_MAX + '\0' */
173*84ceaea9SAndy Fiddaman 	nvlist_t *comp;
174*84ceaea9SAndy Fiddaman 
175*84ceaea9SAndy Fiddaman 	if (topo_mod_nvalloc(mod, &comp, NV_UNIQUE_NAME) != 0)
176*84ceaea9SAndy Fiddaman 		return (NULL);
177*84ceaea9SAndy Fiddaman 
178*84ceaea9SAndy Fiddaman 	(void) snprintf(str, sizeof (str), "%" PRIu64, inst);
179*84ceaea9SAndy Fiddaman 
180*84ceaea9SAndy Fiddaman 	if (nvlist_add_string(comp, FM_FMRI_PCIE_NAME, name) != 0 ||
181*84ceaea9SAndy Fiddaman 	    nvlist_add_string(comp, FM_FMRI_PCIE_ID, str) != 0) {
182*84ceaea9SAndy Fiddaman 		nvlist_free(comp);
183*84ceaea9SAndy Fiddaman 		return (NULL);
184*84ceaea9SAndy Fiddaman 	}
185*84ceaea9SAndy Fiddaman 
186*84ceaea9SAndy Fiddaman 	return (comp);
187*84ceaea9SAndy Fiddaman }
188*84ceaea9SAndy Fiddaman 
189*84ceaea9SAndy Fiddaman static nvlist_t *
fmri_create(topo_mod_t * mod,nvlist_t * pfmri,const char * name,topo_instance_t inst,nvlist_t * auth)190*84ceaea9SAndy Fiddaman fmri_create(topo_mod_t *mod, nvlist_t *pfmri, const char *name,
191*84ceaea9SAndy Fiddaman     topo_instance_t inst, nvlist_t *auth)
192*84ceaea9SAndy Fiddaman {
193*84ceaea9SAndy Fiddaman 	nvlist_t **pplist = NULL;
194*84ceaea9SAndy Fiddaman 	nvlist_t **plist = NULL;
195*84ceaea9SAndy Fiddaman 	nvlist_t *fmri = NULL;
196*84ceaea9SAndy Fiddaman 	uint_t pelems = 0, elems;
197*84ceaea9SAndy Fiddaman 	uint_t i;
198*84ceaea9SAndy Fiddaman 
199*84ceaea9SAndy Fiddaman 	/*
200*84ceaea9SAndy Fiddaman 	 * This FMRI will be constructed from the FMRI of the parent, with a
201*84ceaea9SAndy Fiddaman 	 * new path component (name=inst) after it. We copy the parent's
202*84ceaea9SAndy Fiddaman 	 * property list to this node, and then add our new property to the
203*84ceaea9SAndy Fiddaman 	 * end.
204*84ceaea9SAndy Fiddaman 	 */
205*84ceaea9SAndy Fiddaman 
206*84ceaea9SAndy Fiddaman 	/* Retrieve the parent's property list */
207*84ceaea9SAndy Fiddaman 	if (pfmri != NULL) {
208*84ceaea9SAndy Fiddaman 		if (nvlist_lookup_nvlist_array(pfmri, FM_FMRI_PCIE_LIST,
209*84ceaea9SAndy Fiddaman 		    &pplist, &pelems) != 0) {
210*84ceaea9SAndy Fiddaman 			return (fmri_create_err(mod, plist, pelems, fmri,
211*84ceaea9SAndy Fiddaman 			    EMOD_FMRI_MALFORM));
212*84ceaea9SAndy Fiddaman 		}
213*84ceaea9SAndy Fiddaman 	}
214*84ceaea9SAndy Fiddaman 
215*84ceaea9SAndy Fiddaman 	/* We want space for an extra entry in the new FMRI's property list */
216*84ceaea9SAndy Fiddaman 	elems = pelems + 1;
217*84ceaea9SAndy Fiddaman 
218*84ceaea9SAndy Fiddaman 	plist = topo_mod_zalloc(mod, sizeof (nvlist_t *) * elems);
219*84ceaea9SAndy Fiddaman 	if (plist == NULL) {
220*84ceaea9SAndy Fiddaman 		return (fmri_create_err(mod, plist, elems, fmri,
221*84ceaea9SAndy Fiddaman 		    ETOPO_FMRI_NOMEM));
222*84ceaea9SAndy Fiddaman 	}
223*84ceaea9SAndy Fiddaman 
224*84ceaea9SAndy Fiddaman 	/* Copy the parent properties */
225*84ceaea9SAndy Fiddaman 	for (i = 0; i < pelems; i++) {
226*84ceaea9SAndy Fiddaman 		if (topo_mod_nvdup(mod, pplist[i], &plist[i]) != 0) {
227*84ceaea9SAndy Fiddaman 			return (fmri_create_err(mod, plist, elems, fmri,
228*84ceaea9SAndy Fiddaman 			    EMOD_FMRI_NVL));
229*84ceaea9SAndy Fiddaman 		}
230*84ceaea9SAndy Fiddaman 	}
231*84ceaea9SAndy Fiddaman 
232*84ceaea9SAndy Fiddaman 	/* Add the new path component */
233*84ceaea9SAndy Fiddaman 	if ((plist[i] = fmri_create_component(mod, name, inst)) == NULL) {
234*84ceaea9SAndy Fiddaman 		return (fmri_create_err(mod, plist, elems, fmri,
235*84ceaea9SAndy Fiddaman 		    EMOD_FMRI_NVL));
236*84ceaea9SAndy Fiddaman 	}
237*84ceaea9SAndy Fiddaman 
238*84ceaea9SAndy Fiddaman 	/* Create the fmri */
239*84ceaea9SAndy Fiddaman 	if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0) {
240*84ceaea9SAndy Fiddaman 		return (fmri_create_err(mod, plist, elems, fmri,
241*84ceaea9SAndy Fiddaman 		    EMOD_FMRI_NVL));
242*84ceaea9SAndy Fiddaman 	}
243*84ceaea9SAndy Fiddaman 
244*84ceaea9SAndy Fiddaman 	if (nvlist_add_uint8(fmri, FM_VERSION, FM_PCIE_SCHEME_VERSION) ||
245*84ceaea9SAndy Fiddaman 	    nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_PCIE)) {
246*84ceaea9SAndy Fiddaman 		return (fmri_create_err(mod, plist, elems, fmri,
247*84ceaea9SAndy Fiddaman 		    EMOD_FMRI_NVL));
248*84ceaea9SAndy Fiddaman 	}
249*84ceaea9SAndy Fiddaman 
250*84ceaea9SAndy Fiddaman 	/* Add the new property list */
251*84ceaea9SAndy Fiddaman 	if (nvlist_add_nvlist_array(fmri, FM_FMRI_PCIE_LIST,
252*84ceaea9SAndy Fiddaman 	    plist, elems) != 0) {
253*84ceaea9SAndy Fiddaman 		return (fmri_create_err(mod, plist, elems, fmri,
254*84ceaea9SAndy Fiddaman 		    EMOD_FMRI_NVL));
255*84ceaea9SAndy Fiddaman 	}
256*84ceaea9SAndy Fiddaman 
257*84ceaea9SAndy Fiddaman 	if (auth != NULL)
258*84ceaea9SAndy Fiddaman 		(void) nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY, auth);
259*84ceaea9SAndy Fiddaman 
260*84ceaea9SAndy Fiddaman 	if (plist != NULL) {
261*84ceaea9SAndy Fiddaman 		for (uint_t i = 0; i < elems; i++)
262*84ceaea9SAndy Fiddaman 			nvlist_free(plist[i]);
263*84ceaea9SAndy Fiddaman 		topo_mod_free(mod, plist, sizeof (nvlist_t *) * elems);
264*84ceaea9SAndy Fiddaman 	}
265*84ceaea9SAndy Fiddaman 
266*84ceaea9SAndy Fiddaman 	return (fmri);
267*84ceaea9SAndy Fiddaman }
268*84ceaea9SAndy Fiddaman 
269*84ceaea9SAndy Fiddaman static int
pcie_fmri_create_meth(topo_mod_t * mod,tnode_t * tnode,topo_version_t version,nvlist_t * in,nvlist_t ** out)270*84ceaea9SAndy Fiddaman pcie_fmri_create_meth(topo_mod_t *mod, tnode_t *tnode, topo_version_t version,
271*84ceaea9SAndy Fiddaman     nvlist_t *in, nvlist_t **out)
272*84ceaea9SAndy Fiddaman {
273*84ceaea9SAndy Fiddaman 	char *name;
274*84ceaea9SAndy Fiddaman 	topo_instance_t inst;
275*84ceaea9SAndy Fiddaman 	nvlist_t *args, *auth = NULL, *pfmri = NULL;
276*84ceaea9SAndy Fiddaman 	int ret;
277*84ceaea9SAndy Fiddaman 
278*84ceaea9SAndy Fiddaman 	if (version > TOPO_METH_FMRI_VERSION)
279*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
280*84ceaea9SAndy Fiddaman 
281*84ceaea9SAndy Fiddaman 	if (nvlist_lookup_string(in, TOPO_METH_FMRI_ARG_NAME, &name) != 0 ||
282*84ceaea9SAndy Fiddaman 	    nvlist_lookup_uint64(in, TOPO_METH_FMRI_ARG_INST, &inst) != 0) {
283*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
284*84ceaea9SAndy Fiddaman 	}
285*84ceaea9SAndy Fiddaman 
286*84ceaea9SAndy Fiddaman 	if ((ret = nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL,
287*84ceaea9SAndy Fiddaman 	    &args)) != 0) {
288*84ceaea9SAndy Fiddaman 		if (ret != ENOENT)
289*84ceaea9SAndy Fiddaman 			return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
290*84ceaea9SAndy Fiddaman 	} else {
291*84ceaea9SAndy Fiddaman 		(void) nvlist_lookup_nvlist(args, TOPO_METH_FMRI_ARG_PARENT,
292*84ceaea9SAndy Fiddaman 		    &pfmri);
293*84ceaea9SAndy Fiddaman 		(void) nvlist_lookup_nvlist(args, TOPO_METH_FMRI_ARG_AUTH,
294*84ceaea9SAndy Fiddaman 		    &auth);
295*84ceaea9SAndy Fiddaman 	}
296*84ceaea9SAndy Fiddaman 
297*84ceaea9SAndy Fiddaman 	*out = fmri_create(mod, pfmri, name, inst, auth);
298*84ceaea9SAndy Fiddaman 	if (*out == NULL)
299*84ceaea9SAndy Fiddaman 		return (-1);
300*84ceaea9SAndy Fiddaman 
301*84ceaea9SAndy Fiddaman 	return (0);
302*84ceaea9SAndy Fiddaman }
303*84ceaea9SAndy Fiddaman 
304*84ceaea9SAndy Fiddaman const topo_method_t pcie_methods[] = {
305*84ceaea9SAndy Fiddaman 	{
306*84ceaea9SAndy Fiddaman 		.tm_name = TOPO_METH_NVL2STR,
307*84ceaea9SAndy Fiddaman 		.tm_desc = TOPO_METH_NVL2STR_DESC,
308*84ceaea9SAndy Fiddaman 		.tm_version = TOPO_METH_NVL2STR_VERSION,
309*84ceaea9SAndy Fiddaman 		.tm_stability = TOPO_STABILITY_INTERNAL,
310*84ceaea9SAndy Fiddaman 		.tm_func = pcie_fmri_nvl2str
311*84ceaea9SAndy Fiddaman 	},
312*84ceaea9SAndy Fiddaman 	{
313*84ceaea9SAndy Fiddaman 		.tm_name = TOPO_METH_FMRI,
314*84ceaea9SAndy Fiddaman 		.tm_desc = TOPO_METH_FMRI_DESC,
315*84ceaea9SAndy Fiddaman 		.tm_version = TOPO_METH_FMRI_VERSION,
316*84ceaea9SAndy Fiddaman 		.tm_stability = TOPO_STABILITY_INTERNAL,
317*84ceaea9SAndy Fiddaman 		.tm_func = pcie_fmri_create_meth
318*84ceaea9SAndy Fiddaman 	},
319*84ceaea9SAndy Fiddaman 	{ NULL }
320*84ceaea9SAndy Fiddaman };
321*84ceaea9SAndy Fiddaman 
322*84ceaea9SAndy Fiddaman int
pcie_enum(topo_mod_t * mod,tnode_t * pnode,const char * name,topo_instance_t min,topo_instance_t max,void * u1 __unused,void * u2 __unused)323*84ceaea9SAndy Fiddaman pcie_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
324*84ceaea9SAndy Fiddaman     topo_instance_t min, topo_instance_t max, void *u1 __unused,
325*84ceaea9SAndy Fiddaman     void *u2 __unused)
326*84ceaea9SAndy Fiddaman {
327*84ceaea9SAndy Fiddaman 	topo_mod_dprintf(mod, "enumerating pcie: %s (%"PRIu64" - %"PRIu64")",
328*84ceaea9SAndy Fiddaman 	    name, min, max);
329*84ceaea9SAndy Fiddaman 
330*84ceaea9SAndy Fiddaman 	(void) topo_method_register(mod, pnode, pcie_methods);
331*84ceaea9SAndy Fiddaman 	return (0);
332*84ceaea9SAndy Fiddaman }
333*84ceaea9SAndy Fiddaman 
334*84ceaea9SAndy Fiddaman static void
pcie_rele(topo_mod_t * mp,tnode_t * node)335*84ceaea9SAndy Fiddaman pcie_rele(topo_mod_t *mp, tnode_t *node)
336*84ceaea9SAndy Fiddaman {
337*84ceaea9SAndy Fiddaman 	topo_method_unregister_all(mp, node);
338*84ceaea9SAndy Fiddaman }
339*84ceaea9SAndy Fiddaman 
340*84ceaea9SAndy Fiddaman static const topo_modops_t pcie_ops = {
341*84ceaea9SAndy Fiddaman 	.tmo_enum = pcie_enum,
342*84ceaea9SAndy Fiddaman 	.tmo_release = pcie_rele
343*84ceaea9SAndy Fiddaman };
344*84ceaea9SAndy Fiddaman 
345*84ceaea9SAndy Fiddaman static const topo_modinfo_t pcie_info = {
346*84ceaea9SAndy Fiddaman 	.tmi_desc = PCIE,
347*84ceaea9SAndy Fiddaman 	.tmi_scheme = FM_FMRI_SCHEME_PCIE,
348*84ceaea9SAndy Fiddaman 	.tmi_version = PCIE_VERSION,
349*84ceaea9SAndy Fiddaman 	.tmi_ops = &pcie_ops
350*84ceaea9SAndy Fiddaman };
351*84ceaea9SAndy Fiddaman 
352*84ceaea9SAndy Fiddaman int
pcie_init(topo_mod_t * mod,topo_version_t version)353*84ceaea9SAndy Fiddaman pcie_init(topo_mod_t *mod, topo_version_t version)
354*84ceaea9SAndy Fiddaman {
355*84ceaea9SAndy Fiddaman 	if (getenv("TOPOPCIEDEBUG"))
356*84ceaea9SAndy Fiddaman 		topo_mod_setdebug(mod);
357*84ceaea9SAndy Fiddaman 
358*84ceaea9SAndy Fiddaman 	topo_mod_dprintf(mod, "initializing pcie builtin");
359*84ceaea9SAndy Fiddaman 
360*84ceaea9SAndy Fiddaman 	if (version != PCIE_VERSION)
361*84ceaea9SAndy Fiddaman 		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
362*84ceaea9SAndy Fiddaman 
363*84ceaea9SAndy Fiddaman 	if (topo_mod_register(mod, &pcie_info, TOPO_VERSION) != 0) {
364*84ceaea9SAndy Fiddaman 		topo_mod_dprintf(mod, "failed to register pcie: %s",
365*84ceaea9SAndy Fiddaman 		    topo_mod_errmsg(mod));
366*84ceaea9SAndy Fiddaman 		return (-1); /* mod errno already set */
367*84ceaea9SAndy Fiddaman 	}
368*84ceaea9SAndy Fiddaman 
369*84ceaea9SAndy Fiddaman 	return (0);
370*84ceaea9SAndy Fiddaman }
371*84ceaea9SAndy Fiddaman 
372*84ceaea9SAndy Fiddaman void
pcie_fini(topo_mod_t * mod)373*84ceaea9SAndy Fiddaman pcie_fini(topo_mod_t *mod)
374*84ceaea9SAndy Fiddaman {
375*84ceaea9SAndy Fiddaman 	topo_mod_unregister(mod);
376*84ceaea9SAndy Fiddaman }
377