xref: /titanic_41/usr/src/lib/fm/topo/modules/sun4v/hostbridge/hb_mdesc.c (revision 25351652d920ae27c5a56c199da581033ce763f6)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <string.h>
28 #include <strings.h>
29 #include <umem.h>
30 #include <sys/mdesc.h>
31 #include <sys/systeminfo.h>
32 #include <sys/fm/ldom.h>
33 
34 #include <hb_mdesc.h>
35 
36 #include "hb_rcid.h"
37 
38 static void *
hb_alloc(size_t size)39 hb_alloc(size_t size)
40 {
41 	return (umem_alloc(size, UMEM_DEFAULT));
42 }
43 
44 static void
hb_free(void * data,size_t size)45 hb_free(void *data, size_t size)
46 {
47 	umem_free(data, size);
48 }
49 
50 /*
51  * hb_find_hb()
52  * Description:
53  *     Return the pointer of hostbridge entry
54  */
55 md_hb_t *
hb_find_hb(md_info_t * phbmd,int hbid)56 hb_find_hb(md_info_t *phbmd, int hbid) {
57 	int i;
58 	md_hb_t *phb;
59 
60 	/* search the processor based on the physical id */
61 	for (i = 0, phb = phbmd->hbs; i < phbmd->nhbs; i++, phb++) {
62 		if (phb->rcs != NULL && phb->id == hbid) {
63 			return (phb);
64 		}
65 	}
66 
67 	return (NULL);
68 }
69 
70 /*
71  * hb_rc_init()
72  * Description:
73  *     Read the hostbridge/pciexrc information from the MD
74  *     The hostbridge/pciexrc information is not specified in the PRI of
75  *     the existing sun4v platforms, the enumerator assumes there is only
76  *     one hostbridge and its physical id is 0. It will create all the
77  *     pciexrc nodes under the topo node hostbridge=0.
78  */
79 static int
hb_rc_init(topo_mod_t * mod,md_t * mdp,md_info_t * hbmdp)80 hb_rc_init(topo_mod_t *mod, md_t *mdp, md_info_t *hbmdp)
81 {
82 	int i, rc;
83 	int id, nnode, nio, nrcs;
84 	char *s = NULL;
85 	uint64_t x;
86 	mde_cookie_t *listp;
87 	md_hb_t *hbp;
88 	char platform[MAXNAMELEN];
89 
90 	bzero(hbmdp, sizeof (md_info_t));
91 	nnode = md_node_count(mdp);
92 	listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode);
93 
94 	/* find the pciex bus nodes */
95 	nio = md_scan_dag(mdp,
96 	    MDE_INVAL_ELEM_COOKIE,
97 	    md_find_name(mdp, MD_STR_IODEVICE),
98 	    md_find_name(mdp, "fwd"),
99 	    listp);
100 	if (nio <= 0) {
101 		topo_mod_dprintf(mod, "iodevice nodes not found\n");
102 		topo_mod_free(mod, listp, sizeof (mde_cookie_t) * nnode);
103 		return (-1);
104 	}
105 	topo_mod_dprintf(mod, "Found %d %s nodes\n", nio, MD_STR_IODEVICE);
106 
107 	for (i = 0, nrcs = 0; i < nio; i++) {
108 		rc = md_get_prop_str(mdp, listp[i], MD_STR_DEVICE_TYPE, &s);
109 		if ((rc == 0) && (s != NULL) && (strcmp(s, MD_STR_PCIEX) == 0))
110 			nrcs++;
111 	}
112 	topo_mod_dprintf(mod, "Found %d pciex buses\n", nrcs);
113 	if (nrcs == 0) {
114 		topo_mod_dprintf(mod, "pciex nodes not found\n");
115 		topo_mod_free(mod, listp, sizeof (mde_cookie_t) * nnode);
116 		return (-1);
117 	}
118 
119 	platform[0] = '\0';
120 	(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
121 
122 	/*
123 	 * All existing sun4v platforms have only one hostdridge.
124 	 */
125 	hbmdp->shbs = hbmdp->nhbs = 1;
126 	hbp = topo_mod_zalloc(mod, sizeof (md_hb_t) * hbmdp->nhbs);
127 	hbp->id = 0;
128 	hbmdp->hbs = hbp;
129 
130 	hbp->srcs = nrcs;
131 	hbp->rcs = topo_mod_zalloc(mod, sizeof (md_rc_t) * nrcs);
132 	hbp->nrcs = 0;
133 	for (i = 0, nrcs = 0; i < nio; i++) {
134 		rc = md_get_prop_str(mdp, listp[i], MD_STR_DEVICE_TYPE, &s);
135 		if ((rc != 0) || s == NULL || strcmp(s, MD_STR_PCIEX) != 0)
136 			continue;
137 
138 		hbp->rcs[nrcs].id = -1;		/* invalidate the entry */
139 
140 		/* bus address */
141 		if (md_get_prop_val(mdp, listp[i], MD_STR_CFGHDL, &x) < 0) {
142 			nrcs++;
143 			continue;
144 		}
145 		hbp->rcs[nrcs].cfg_handle = x;
146 		topo_mod_dprintf(mod, "Found rc=%d ba=%llx\n", nrcs, x);
147 
148 		/* Assign the physical id of the pciexrc */
149 		if ((id = hb_find_rc_pid(platform, x)) >= 0)
150 			hbp->rcs[nrcs].id = id;
151 		else
152 			hbp->rcs[nrcs].id = hbp->nrcs;
153 
154 		nrcs++;
155 		hbp->nrcs++;
156 	}
157 
158 	topo_mod_free(mod, listp, sizeof (mde_cookie_t) * nnode);
159 
160 	return (0);
161 }
162 
163 /*
164  * Get the info. of the hb and rc from the PRI/MD
165  */
166 int
hb_mdesc_init(topo_mod_t * mod,md_info_t * phbmd)167 hb_mdesc_init(topo_mod_t *mod, md_info_t *phbmd)
168 {
169 	int rc = -1;
170 	md_t *mdp;
171 	ssize_t bufsiz = 0;
172 	uint64_t *bufp;
173 	uint32_t type = 0;
174 	ldom_hdl_t *lhp;
175 
176 	/* get the PRI/MD */
177 	if ((lhp = ldom_init(hb_alloc, hb_free)) == NULL) {
178 		topo_mod_dprintf(mod, "ldom_init() failed\n");
179 		return (topo_mod_seterrno(mod, EMOD_NOMEM));
180 	}
181 
182 	(void) ldom_get_type(lhp, &type);
183 	if ((type & LDOM_TYPE_CONTROL) != 0) {
184 		bufsiz = ldom_get_core_md(lhp, &bufp);
185 	} else {
186 		bufsiz = ldom_get_local_md(lhp, &bufp);
187 	}
188 	if (bufsiz <= 0) {
189 		topo_mod_dprintf(mod, "failed to get the PRI/MD\n");
190 		ldom_fini(lhp);
191 		return (-1);
192 	}
193 
194 	if ((mdp = md_init_intern(bufp, hb_alloc, hb_free)) == NULL ||
195 	    md_node_count(mdp) <= 0) {
196 		hb_free(bufp, (size_t)bufsiz);
197 		ldom_fini(lhp);
198 		return (-1);
199 	}
200 
201 	rc = hb_rc_init(mod, mdp, phbmd);
202 
203 	hb_free(bufp, (size_t)bufsiz);
204 	(void) md_fini(mdp);
205 	ldom_fini(lhp);
206 
207 	return (rc);
208 }
209 
210 void
hb_mdesc_fini(topo_mod_t * mod,md_info_t * hbmdp)211 hb_mdesc_fini(topo_mod_t *mod, md_info_t *hbmdp)
212 {
213 	int i;
214 	md_hb_t *hbp;
215 
216 	if (hbmdp->hbs == NULL)
217 		return;
218 
219 	for (i = 0, hbp = hbmdp->hbs; i < hbmdp->nhbs; i++, hbp++) {
220 		if (hbp->rcs == NULL)
221 			continue;
222 		topo_mod_free(mod, hbp->rcs, hbp->srcs * sizeof (md_rc_t));
223 	}
224 	topo_mod_free(mod, hbmdp->hbs, hbmdp->shbs * sizeof (md_hb_t));
225 
226 }
227