xref: /onnv-gate/usr/src/lib/fm/topo/modules/sun4v/hostbridge/hb_mdesc.c (revision 7850:168d612bb1e8)
15911Svn83148 /*
25911Svn83148  * CDDL HEADER START
35911Svn83148  *
45911Svn83148  * The contents of this file are subject to the terms of the
55911Svn83148  * Common Development and Distribution License (the "License").
65911Svn83148  * You may not use this file except in compliance with the License.
75911Svn83148  *
85911Svn83148  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95911Svn83148  * or http://www.opensolaris.org/os/licensing.
105911Svn83148  * See the License for the specific language governing permissions
115911Svn83148  * and limitations under the License.
125911Svn83148  *
135911Svn83148  * When distributing Covered Code, include this CDDL HEADER in each
145911Svn83148  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155911Svn83148  * If applicable, add the following below this CDDL HEADER, with the
165911Svn83148  * fields enclosed by brackets "[]" replaced with your own identifying
175911Svn83148  * information: Portions Copyright [yyyy] [name of copyright owner]
185911Svn83148  *
195911Svn83148  * CDDL HEADER END
205911Svn83148  */
215911Svn83148 
225911Svn83148 /*
235911Svn83148  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245911Svn83148  * Use is subject to license terms.
255911Svn83148  */
265911Svn83148 
275911Svn83148 #include <string.h>
285911Svn83148 #include <strings.h>
295911Svn83148 #include <umem.h>
305911Svn83148 #include <sys/mdesc.h>
315911Svn83148 #include <sys/systeminfo.h>
325911Svn83148 #include <sys/fm/ldom.h>
335911Svn83148 
345911Svn83148 #include <hb_mdesc.h>
355911Svn83148 
365911Svn83148 #include "hb_rcid.h"
375911Svn83148 
385911Svn83148 static void *
hb_alloc(size_t size)395911Svn83148 hb_alloc(size_t size)
405911Svn83148 {
415911Svn83148 	return (umem_alloc(size, UMEM_DEFAULT));
425911Svn83148 }
435911Svn83148 
445911Svn83148 static void
hb_free(void * data,size_t size)455911Svn83148 hb_free(void *data, size_t size)
465911Svn83148 {
475911Svn83148 	umem_free(data, size);
485911Svn83148 }
495911Svn83148 
505911Svn83148 /*
515911Svn83148  * hb_find_hb()
525911Svn83148  * Description:
535911Svn83148  *     Return the pointer of hostbridge entry
545911Svn83148  */
555911Svn83148 md_hb_t *
hb_find_hb(md_info_t * phbmd,int hbid)565911Svn83148 hb_find_hb(md_info_t *phbmd, int hbid) {
575911Svn83148 	int i;
585911Svn83148 	md_hb_t *phb;
595911Svn83148 
605911Svn83148 	/* search the processor based on the physical id */
615911Svn83148 	for (i = 0, phb = phbmd->hbs; i < phbmd->nhbs; i++, phb++) {
625911Svn83148 		if (phb->rcs != NULL && phb->id == hbid) {
635911Svn83148 			return (phb);
645911Svn83148 		}
655911Svn83148 	}
665911Svn83148 
675911Svn83148 	return (NULL);
685911Svn83148 }
695911Svn83148 
705911Svn83148 /*
715911Svn83148  * hb_rc_init()
725911Svn83148  * Description:
735911Svn83148  *     Read the hostbridge/pciexrc information from the MD
745911Svn83148  *     The hostbridge/pciexrc information is not specified in the PRI of
755911Svn83148  *     the existing sun4v platforms, the enumerator assumes there is only
765911Svn83148  *     one hostbridge and its physical id is 0. It will create all the
775911Svn83148  *     pciexrc nodes under the topo node hostbridge=0.
785911Svn83148  */
795911Svn83148 static int
hb_rc_init(topo_mod_t * mod,md_t * mdp,md_info_t * hbmdp)805911Svn83148 hb_rc_init(topo_mod_t *mod, md_t *mdp, md_info_t *hbmdp)
815911Svn83148 {
825911Svn83148 	int i, rc;
835911Svn83148 	int id, nnode, nio, nrcs;
845911Svn83148 	char *s = NULL;
855911Svn83148 	uint64_t x;
865911Svn83148 	mde_cookie_t *listp;
875911Svn83148 	md_hb_t *hbp;
885911Svn83148 	char platform[MAXNAMELEN];
895911Svn83148 
905911Svn83148 	bzero(hbmdp, sizeof (md_info_t));
915911Svn83148 	nnode = md_node_count(mdp);
925911Svn83148 	listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode);
935911Svn83148 
945911Svn83148 	/* find the pciex bus nodes */
955911Svn83148 	nio = md_scan_dag(mdp,
965911Svn83148 	    MDE_INVAL_ELEM_COOKIE,
975911Svn83148 	    md_find_name(mdp, MD_STR_IODEVICE),
985911Svn83148 	    md_find_name(mdp, "fwd"),
995911Svn83148 	    listp);
1005911Svn83148 	if (nio <= 0) {
1015911Svn83148 		topo_mod_dprintf(mod, "iodevice nodes not found\n");
1025911Svn83148 		topo_mod_free(mod, listp, sizeof (mde_cookie_t) * nnode);
1035911Svn83148 		return (-1);
1045911Svn83148 	}
1055911Svn83148 	topo_mod_dprintf(mod, "Found %d %s nodes\n", nio, MD_STR_IODEVICE);
1065911Svn83148 
1075911Svn83148 	for (i = 0, nrcs = 0; i < nio; i++) {
1085911Svn83148 		rc = md_get_prop_str(mdp, listp[i], MD_STR_DEVICE_TYPE, &s);
1095911Svn83148 		if ((rc == 0) && (s != NULL) && (strcmp(s, MD_STR_PCIEX) == 0))
1105911Svn83148 			nrcs++;
1115911Svn83148 	}
1125911Svn83148 	topo_mod_dprintf(mod, "Found %d pciex buses\n", nrcs);
1135911Svn83148 	if (nrcs == 0) {
1145911Svn83148 		topo_mod_dprintf(mod, "pciex nodes not found\n");
1155911Svn83148 		topo_mod_free(mod, listp, sizeof (mde_cookie_t) * nnode);
1165911Svn83148 		return (-1);
1175911Svn83148 	}
1185911Svn83148 
1195911Svn83148 	platform[0] = '\0';
1205911Svn83148 	(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
1215911Svn83148 
1225911Svn83148 	/*
1235911Svn83148 	 * All existing sun4v platforms have only one hostdridge.
1245911Svn83148 	 */
1255911Svn83148 	hbmdp->shbs = hbmdp->nhbs = 1;
1265911Svn83148 	hbp = topo_mod_zalloc(mod, sizeof (md_hb_t) * hbmdp->nhbs);
1275911Svn83148 	hbp->id = 0;
1285911Svn83148 	hbmdp->hbs = hbp;
1295911Svn83148 
1305911Svn83148 	hbp->srcs = nrcs;
1315911Svn83148 	hbp->rcs = topo_mod_zalloc(mod, sizeof (md_rc_t) * nrcs);
1325911Svn83148 	hbp->nrcs = 0;
1335911Svn83148 	for (i = 0, nrcs = 0; i < nio; i++) {
1345911Svn83148 		rc = md_get_prop_str(mdp, listp[i], MD_STR_DEVICE_TYPE, &s);
1355911Svn83148 		if ((rc != 0) || s == NULL || strcmp(s, MD_STR_PCIEX) != 0)
1365911Svn83148 			continue;
1375911Svn83148 
1385911Svn83148 		hbp->rcs[nrcs].id = -1;		/* invalidate the entry */
1395911Svn83148 
1405911Svn83148 		/* bus address */
1415911Svn83148 		if (md_get_prop_val(mdp, listp[i], MD_STR_CFGHDL, &x) < 0) {
1425911Svn83148 			nrcs++;
1435911Svn83148 			continue;
1445911Svn83148 		}
1455911Svn83148 		hbp->rcs[nrcs].cfg_handle = x;
1465911Svn83148 		topo_mod_dprintf(mod, "Found rc=%d ba=%llx\n", nrcs, x);
1475911Svn83148 
1485911Svn83148 		/* Assign the physical id of the pciexrc */
1495911Svn83148 		if ((id = hb_find_rc_pid(platform, x)) >= 0)
1505911Svn83148 			hbp->rcs[nrcs].id = id;
1515911Svn83148 		else
1525911Svn83148 			hbp->rcs[nrcs].id = hbp->nrcs;
1535911Svn83148 
1545911Svn83148 		nrcs++;
1555911Svn83148 		hbp->nrcs++;
1565911Svn83148 	}
1575911Svn83148 
1585911Svn83148 	topo_mod_free(mod, listp, sizeof (mde_cookie_t) * nnode);
1595911Svn83148 
1605911Svn83148 	return (0);
1615911Svn83148 }
1625911Svn83148 
1635911Svn83148 /*
1645911Svn83148  * Get the info. of the hb and rc from the PRI/MD
1655911Svn83148  */
1665911Svn83148 int
hb_mdesc_init(topo_mod_t * mod,md_info_t * phbmd)1675911Svn83148 hb_mdesc_init(topo_mod_t *mod, md_info_t *phbmd)
1685911Svn83148 {
1695911Svn83148 	int rc = -1;
1705911Svn83148 	md_t *mdp;
1715911Svn83148 	ssize_t bufsiz = 0;
1725911Svn83148 	uint64_t *bufp;
173*7850SVuong.Nguyen@Sun.COM 	uint32_t type = 0;
1745911Svn83148 	ldom_hdl_t *lhp;
1755911Svn83148 
1765911Svn83148 	/* get the PRI/MD */
1775911Svn83148 	if ((lhp = ldom_init(hb_alloc, hb_free)) == NULL) {
1785911Svn83148 		topo_mod_dprintf(mod, "ldom_init() failed\n");
1795911Svn83148 		return (topo_mod_seterrno(mod, EMOD_NOMEM));
1805911Svn83148 	}
181*7850SVuong.Nguyen@Sun.COM 
182*7850SVuong.Nguyen@Sun.COM 	(void) ldom_get_type(lhp, &type);
183*7850SVuong.Nguyen@Sun.COM 	if ((type & LDOM_TYPE_CONTROL) != 0) {
184*7850SVuong.Nguyen@Sun.COM 		bufsiz = ldom_get_core_md(lhp, &bufp);
185*7850SVuong.Nguyen@Sun.COM 	} else {
186*7850SVuong.Nguyen@Sun.COM 		bufsiz = ldom_get_local_md(lhp, &bufp);
187*7850SVuong.Nguyen@Sun.COM 	}
188*7850SVuong.Nguyen@Sun.COM 	if (bufsiz <= 0) {
1895911Svn83148 		topo_mod_dprintf(mod, "failed to get the PRI/MD\n");
1905911Svn83148 		ldom_fini(lhp);
1915911Svn83148 		return (-1);
1925911Svn83148 	}
1935911Svn83148 
1945911Svn83148 	if ((mdp = md_init_intern(bufp, hb_alloc, hb_free)) == NULL ||
1955911Svn83148 	    md_node_count(mdp) <= 0) {
1965911Svn83148 		hb_free(bufp, (size_t)bufsiz);
1975911Svn83148 		ldom_fini(lhp);
1985911Svn83148 		return (-1);
1995911Svn83148 	}
2005911Svn83148 
2015911Svn83148 	rc = hb_rc_init(mod, mdp, phbmd);
2025911Svn83148 
2035911Svn83148 	hb_free(bufp, (size_t)bufsiz);
2045911Svn83148 	(void) md_fini(mdp);
2055911Svn83148 	ldom_fini(lhp);
2065911Svn83148 
2075911Svn83148 	return (rc);
2085911Svn83148 }
2095911Svn83148 
2105911Svn83148 void
hb_mdesc_fini(topo_mod_t * mod,md_info_t * hbmdp)2115911Svn83148 hb_mdesc_fini(topo_mod_t *mod, md_info_t *hbmdp)
2125911Svn83148 {
2135911Svn83148 	int i;
2145911Svn83148 	md_hb_t *hbp;
2155911Svn83148 
2165911Svn83148 	if (hbmdp->hbs == NULL)
2175911Svn83148 		return;
2185911Svn83148 
2195911Svn83148 	for (i = 0, hbp = hbmdp->hbs; i < hbmdp->nhbs; i++, hbp++) {
2205911Svn83148 		if (hbp->rcs == NULL)
2215911Svn83148 			continue;
2225911Svn83148 		topo_mod_free(mod, hbp->rcs, hbp->srcs * sizeof (md_rc_t));
2235911Svn83148 	}
2245911Svn83148 	topo_mod_free(mod, hbmdp->hbs, hbmdp->shbs * sizeof (md_hb_t));
2255911Svn83148 
2265911Svn83148 }
227