Mercurial > illumos > illumos-gate
view usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu_mdesc.c @ 3681:d93cfde2f771
6519375 refactored the mdesc code in cpu scheme, platform-cpu.so and chip.so into a single code base
6520142 sun4v motherboard/chip enums leaking memory
6520501 libtopo exports a set of errors associated with node methods
author | vn83148 |
---|---|
date | Mon, 19 Feb 2007 20:47:33 -0800 |
parents | usr/src/cmd/fm/schemes/cpu/sparc/cpu_mdesc.c@6338278a5e69 |
children | 1295bc02c435 |
line wrap: on
line source
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include <string.h> #include <umem.h> #include <sys/mdesc.h> #include <sys/fm/ldom.h> #include <cpu_mdesc.h> static void * cpu_alloc(size_t size) { return (umem_alloc(size, UMEM_DEFAULT)); } static void cpu_free(void *data, size_t size) { umem_free(data, size); } md_cpumap_t * cpu_find_cpumap(md_info_t *chip, uint32_t cpuid) { int i; md_cpumap_t *mcmp; for (i = 0, mcmp = chip->cpus; i < chip->ncpus; i++, mcmp++) { if (cpuid == mcmp->cpumap_pid) { return (mcmp); } } return (NULL); } int cpu_get_serialid_mdesc(md_info_t *chip, uint32_t cpuid, uint64_t *serialidp) { md_cpumap_t *mcmp; if ((mcmp = cpu_find_cpumap(chip, cpuid)) != NULL) { *serialidp = mcmp->cpumap_serialno; return (0); } return (-1); } static int cpu_n1_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip) { mde_cookie_t *listp; md_cpumap_t *mcmp; int i, num_nodes, idx; uint64_t x; num_nodes = md_node_count(mdp); listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * num_nodes); chip->ncpus = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, md_find_name(mdp, "cpu"), md_find_name(mdp, "fwd"), listp); topo_mod_dprintf(mod, "Found %d cpus\n", chip->ncpus); chip->cpus = topo_mod_zalloc(mod, chip->ncpus * sizeof (md_cpumap_t)); chip->nprocs = chip->ncpus; chip->procs = topo_mod_zalloc(mod, chip->nprocs * sizeof (md_proc_t)); for (idx = 0, mcmp = chip->cpus; idx < chip->ncpus; idx++, mcmp++) { if (md_get_prop_val(mdp, listp[idx], MD_STR_ID, &x) < 0) x = (uint64_t)-1; /* invalid value */ mcmp->cpumap_id = x; if (md_get_prop_val(mdp, listp[idx], MD_STR_PID, &x) < 0) x = mcmp->cpumap_id; mcmp->cpumap_pid = x; if (md_get_prop_val(mdp, listp[idx], MD_STR_CPU_SERIAL, &mcmp->cpumap_serialno) < 0) mcmp->cpumap_serialno = 0; /* * This PRI/MD has no indentity info. of the FRU. * Find if there is already an existing processor entry */ for (i = 0; i < chip->nprocs && chip->procs[i].serialno != 0; i++) { if (mcmp->cpumap_serialno == chip->procs[i].serialno) { break; } } if (i < chip->nprocs) { mcmp->cpumap_chipidx = i; if (chip->procs[i].serialno == 0) { chip->procs[i].serialno = mcmp->cpumap_serialno; topo_mod_dprintf(mod, "chip[%d] serial is %llx\n", i, chip->procs[i].serialno); } } } topo_mod_free(mod, listp, sizeof (mde_cookie_t) * num_nodes); return (0); } static int cpu_n2_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip) { mde_cookie_t *list1p, *list2p; md_cpumap_t *mcmp; md_proc_t *procp; md_fru_t *frup; int i, j, cnt; int nnode, ncomp, nproc, ncpu; char *str = NULL; uint64_t x, sn; nnode = md_node_count(mdp); list1p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode); /* Count the number of processors and strands */ ncomp = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, md_find_name(mdp, MD_STR_COMPONENT), md_find_name(mdp, "fwd"), list1p); if (ncomp <= 0) { topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode); return (-1); } for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) { if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 && str != NULL && strcmp(str, MD_STR_PROCESSOR) == 0) { nproc++; } if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 && str && strcmp(str, MD_STR_STRAND) == 0) { ncpu++; } } topo_mod_dprintf(mod, "Found %d procs and %d strands\n", nproc, ncpu); if (nproc == 0 || ncpu == 0) { topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode); return (-1); } /* Alloc processors and strand entries */ list2p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * 2 * ncpu); chip->nprocs = nproc; chip->procs = topo_mod_zalloc(mod, nproc * sizeof (md_proc_t)); chip->ncpus = ncpu; chip->cpus = topo_mod_zalloc(mod, ncpu * sizeof (md_cpumap_t)); /* Visit each processor node */ procp = chip->procs; mcmp = chip->cpus; for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) { if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) < 0 || str == NULL || strcmp(str, MD_STR_PROCESSOR)) continue; if (md_get_prop_val(mdp, list1p[i], MD_STR_SERIAL, &sn) < 0) { topo_mod_dprintf(mod, "Failed to get the serial number of proc[%d]\n", nproc); continue; } procp->serialno = sn; topo_mod_dprintf(mod, "proc %d : sn=%llx\n", nproc, sn); nproc++; /* Get all the strands below this proc */ cnt = md_scan_dag(mdp, list1p[i], md_find_name(mdp, MD_STR_COMPONENT), md_find_name(mdp, "fwd"), list2p); topo_mod_dprintf(mod, "proc[%llx]: Found %d fwd components\n", sn, cnt); if (cnt <= 0) { procp++; continue; } for (j = 0; j < cnt; j++) { /* Consider only the strand nodes */ if (md_get_prop_str(mdp, list2p[j], MD_STR_TYPE, &str) < 0 || str == NULL || strcmp(str, MD_STR_STRAND)) continue; ncpu++; if (md_get_prop_val(mdp, list2p[j], MD_STR_ID, &x) < 0) x = (uint64_t)-1; /* invalid value */ mcmp->cpumap_id = x; if (md_get_prop_val(mdp, list2p[j], MD_STR_PID, &x) < 0) x = mcmp->cpumap_id; mcmp->cpumap_pid = x; mcmp->cpumap_serialno = sn; mcmp->cpumap_chipidx = nproc - 1; mcmp++; } /* * To get the fru of this proc, follow the back arc up to * find the first node whose fru field is set */ cnt = md_scan_dag(mdp, list1p[i], md_find_name(mdp, MD_STR_COMPONENT), md_find_name(mdp, "back"), list2p); topo_mod_dprintf(mod, "proc[%d]: Found %d back components\n", nproc-1, cnt); if (cnt <= 0) { procp++; continue; } for (j = 0; j < cnt; j++) { /* test the fru field which must be positive number */ if ((md_get_prop_val(mdp, list2p[j], MD_STR_FRU, &x) == 0) && x > 0) break; } if (j < cnt) { /* Found the FRU node, get the fru identity */ topo_mod_dprintf(mod, "proc[%d] sn=%llx has a fru %d\n", nproc-1, procp->serialno, j); frup = topo_mod_zalloc(mod, sizeof (md_fru_t)); procp->fru = frup; if (!md_get_prop_str(mdp, list2p[j], MD_STR_NAC, &str)) frup->nac = topo_mod_strdup(mod, str); else frup->nac = topo_mod_strdup(mod, MD_FRU_DEF); if (!md_get_prop_str(mdp, list2p[j], MD_STR_PART, &str)) frup->part = topo_mod_strdup(mod, str); if (!md_get_prop_str(mdp, list2p[j], MD_STR_SERIAL, &str)) frup->serial = topo_mod_strdup(mod, str); if (!md_get_prop_str(mdp, list2p[j], MD_STR_DASH, &str)) frup->dash = topo_mod_strdup(mod, str); } else { topo_mod_dprintf(mod, "proc[%d] sn=%llx has no fru\n", i, procp->serialno); } procp++; } /* for i */ topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode); topo_mod_free(mod, list2p, sizeof (mde_cookie_t) * 2*chip->ncpus); return (0); } /* * Extract from the PRI the processor, strand and their fru identity */ int cpu_mdesc_init(topo_mod_t *mod, md_info_t *chip) { int rc = -1; md_t *mdp; ssize_t bufsiz = 0; uint64_t *bufp; ldom_hdl_t *lhp; /* get the PRI/MD */ if ((lhp = ldom_init(cpu_alloc, cpu_free)) == NULL) { return (topo_mod_seterrno(mod, EMOD_NOMEM)); } if ((bufsiz = ldom_get_core_md(lhp, &bufp)) <= 0) { topo_mod_dprintf(mod, "failed to get the PRI/MD\n"); ldom_fini(lhp); return (-1); } if ((mdp = md_init_intern(bufp, cpu_alloc, cpu_free)) == NULL || md_node_count(mdp) <= 0) { cpu_free(bufp, (size_t)bufsiz); ldom_fini(lhp); return (-1); } /* * N1 MD contains cpu nodes while N2 MD contains component nodes. */ if (md_find_name(mdp, MD_STR_COMPONENT) != MDE_INVAL_STR_COOKIE) { rc = cpu_n2_mdesc_init(mod, mdp, chip); } else if (md_find_name(mdp, MD_STR_CPU) != MDE_INVAL_STR_COOKIE) { rc = cpu_n1_mdesc_init(mod, mdp, chip); } else { topo_mod_dprintf(mod, "Unsupported PRI/MD\n"); rc = -1; } cpu_free(bufp, (size_t)bufsiz); (void) md_fini(mdp); ldom_fini(lhp); return (rc); } void cpu_mdesc_fini(topo_mod_t *mod, md_info_t *chip) { int i; md_proc_t *procp; md_fru_t *frup; if (chip->cpus != NULL) topo_mod_free(mod, chip->cpus, chip->ncpus * sizeof (md_cpumap_t)); if (chip->procs != NULL) { procp = chip->procs; for (i = 0; i < chip->nprocs; i++) { if ((frup = procp->fru) != NULL) { topo_mod_strfree(mod, frup->nac); topo_mod_strfree(mod, frup->serial); topo_mod_strfree(mod, frup->part); topo_mod_strfree(mod, frup->dash); topo_mod_free(mod, frup, sizeof (md_fru_t)); } procp++; } topo_mod_free(mod, chip->procs, chip->nprocs * sizeof (md_proc_t)); } }