11772Sjl139090 /*
21772Sjl139090 * CDDL HEADER START
31772Sjl139090 *
41772Sjl139090 * The contents of this file are subject to the terms of the
51772Sjl139090 * Common Development and Distribution License (the "License").
61772Sjl139090 * You may not use this file except in compliance with the License.
71772Sjl139090 *
81772Sjl139090 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91772Sjl139090 * or http://www.opensolaris.org/os/licensing.
101772Sjl139090 * See the License for the specific language governing permissions
111772Sjl139090 * and limitations under the License.
121772Sjl139090 *
131772Sjl139090 * When distributing Covered Code, include this CDDL HEADER in each
141772Sjl139090 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151772Sjl139090 * If applicable, add the following below this CDDL HEADER, with the
161772Sjl139090 * fields enclosed by brackets "[]" replaced with your own identifying
171772Sjl139090 * information: Portions Copyright [yyyy] [name of copyright owner]
181772Sjl139090 *
191772Sjl139090 * CDDL HEADER END
201772Sjl139090 */
211772Sjl139090
221772Sjl139090 /*
236297Sjl139090 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
241772Sjl139090 * Use is subject to license terms.
251772Sjl139090 */
261772Sjl139090
271772Sjl139090 #pragma ident "%Z%%M% %I% %E% SMI"
281772Sjl139090
291772Sjl139090 /*
301772Sjl139090 * OPL platform specific functions for
311772Sjl139090 * CPU/Memory error diagnosis engine.
321772Sjl139090 */
331772Sjl139090 #include <cmd_opl.h>
341772Sjl139090 #include <string.h>
351772Sjl139090 #include <errno.h>
362214Sav145390 #include <cmd_mem.h>
371772Sjl139090 #include <sys/fm/protocol.h>
381772Sjl139090 #include <sys/int_const.h>
391772Sjl139090
401794Sav145390 cmd_list_t *
opl_cpulist_insert(fmd_hdl_t * hdl,uint32_t cpuid,int flt_type)411794Sav145390 opl_cpulist_insert(fmd_hdl_t *hdl, uint32_t cpuid, int flt_type)
421772Sjl139090 {
431794Sav145390 opl_cpu_t *opl_cpu = NULL;
441794Sav145390 cmd_list_t *list_head = NULL;
455037Sjl139090 uint32_t c, s, sib_cpuid, base_cpuid;
461772Sjl139090
471772Sjl139090 switch (flt_type) {
481772Sjl139090 case IS_STRAND:
491794Sav145390 opl_cpu = fmd_hdl_alloc(hdl, sizeof (opl_cpu_t), FMD_SLEEP);
501794Sav145390 opl_cpu->oc_cpuid = cpuid;
511794Sav145390 cmd_list_append(&opl_cpu_list, opl_cpu);
521794Sav145390 list_head = &opl_cpu_list;
531772Sjl139090 break;
541772Sjl139090
551772Sjl139090 case IS_CORE:
561772Sjl139090 /*
575037Sjl139090 * Currently there are only two strands per core.
585037Sjl139090 * Xor the least significant bit to get the sibling strand
591772Sjl139090 */
601772Sjl139090 sib_cpuid = cpuid ^ 1;
611772Sjl139090 for (s = 0; s <= STRAND_UPPER_BOUND; s++) {
621794Sav145390 opl_cpu = fmd_hdl_alloc(hdl, sizeof (opl_cpu_t),
631772Sjl139090 FMD_SLEEP);
641772Sjl139090 if (s == 0) {
651794Sav145390 opl_cpu->oc_cpuid = cpuid;
661794Sav145390 cmd_list_append(&opl_cpu_list, opl_cpu);
671794Sav145390 list_head = &opl_cpu_list;
681772Sjl139090 } else {
691794Sav145390 opl_cpu->oc_cpuid = sib_cpuid;
701794Sav145390 cmd_list_insert_after(&opl_cpu_list,
711794Sav145390 list_head, opl_cpu);
721772Sjl139090 }
731772Sjl139090 }
741772Sjl139090 break;
751772Sjl139090
761772Sjl139090 case IS_CHIP:
771772Sjl139090 /*
785037Sjl139090 * Enumerate all the cpus/strands based on the max # of cores
795037Sjl139090 * within a chip and max # of strands within a core.
801772Sjl139090 */
815037Sjl139090 base_cpuid = (cpuid >> CHIPID_SHIFT) << CHIPID_SHIFT;
821772Sjl139090 for (c = 0; c <= CORE_UPPER_BOUND; c++) {
831794Sav145390 for (s = 0; s <= STRAND_UPPER_BOUND; s++) {
841794Sav145390 opl_cpu = fmd_hdl_alloc(hdl,
851794Sav145390 sizeof (opl_cpu_t), FMD_SLEEP);
865037Sjl139090 opl_cpu->oc_cpuid = base_cpuid |
875037Sjl139090 c << COREID_SHIFT | s;
881794Sav145390 if (c == 0 && s == 0) {
891794Sav145390 cmd_list_append(&opl_cpu_list, opl_cpu);
901794Sav145390 list_head = &opl_cpu_list;
915037Sjl139090 } else
921794Sav145390 cmd_list_insert_after(&opl_cpu_list,
931794Sav145390 list_head, opl_cpu);
941772Sjl139090 }
951772Sjl139090 }
961772Sjl139090 break;
971772Sjl139090
981772Sjl139090 default:
991794Sav145390 list_head = NULL;
1001772Sjl139090 break;
1011772Sjl139090 }
1021772Sjl139090
1031794Sav145390 return (list_head);
1041772Sjl139090 }
1051772Sjl139090
1061772Sjl139090 void
opl_cpulist_free(fmd_hdl_t * hdl,cmd_list_t * cpu_list)1071794Sav145390 opl_cpulist_free(fmd_hdl_t *hdl, cmd_list_t *cpu_list)
1081772Sjl139090 {
1091794Sav145390 opl_cpu_t *opl_cpu;
1101772Sjl139090
1111794Sav145390 fmd_hdl_debug(hdl,
1121794Sav145390 "Enter opl_cpulist_free for cpulist %llx\n", cpu_list);
1131794Sav145390
1142338Shueston while ((opl_cpu = cmd_list_next(cpu_list)) != NULL) {
1151794Sav145390 cmd_list_delete(cpu_list, opl_cpu);
1161794Sav145390 fmd_hdl_free(hdl, opl_cpu, sizeof (opl_cpu_t));
1171772Sjl139090 }
1181772Sjl139090 }
1191772Sjl139090
1201772Sjl139090 /*
1211772Sjl139090 * Based on "avg" function of eversholt
1221772Sjl139090 */
1231772Sjl139090 uint8_t
opl_avg(uint_t sum,uint_t cnt)1241772Sjl139090 opl_avg(uint_t sum, uint_t cnt)
1251772Sjl139090 {
1261772Sjl139090 unsigned long long s = sum * 10;
1271772Sjl139090
1281772Sjl139090 return ((s / cnt / 10) + (((s / cnt % 10) >= 5) ? 1 : 0));
1291772Sjl139090 }
1301772Sjl139090
1311772Sjl139090 /*
1321772Sjl139090 * This function builds the resource fmri page based on
1331772Sjl139090 * the kstat "cpu_fru" of the faulted cpu and cpuid
1341772Sjl139090 * using the "hc" scheme.
1351772Sjl139090 */
1361772Sjl139090 nvlist_t *
opl_cpursrc_create(fmd_hdl_t * hdl,uint32_t cpuid)1371794Sav145390 opl_cpursrc_create(fmd_hdl_t *hdl, uint32_t cpuid)
1381772Sjl139090 {
1391794Sav145390 nvlist_t *fmri;
1401772Sjl139090 char *frustr, *comp;
1412652Sav145390 int cmu_num;
1421772Sjl139090
1431794Sav145390 if ((errno = nvlist_alloc(&fmri, NV_UNIQUE_NAME, 0)) != 0)
1441772Sjl139090 return (NULL);
1451772Sjl139090
1463325Ssd77468 if ((frustr = cmd_cpu_getfrustr_by_id(hdl, cpuid)) == NULL) {
1471772Sjl139090 nvlist_free(fmri);
1481772Sjl139090 return (NULL);
1491772Sjl139090 }
1501772Sjl139090
1511772Sjl139090 /*
1522652Sav145390 * get the CMU # from cpu_fru for each model
1532652Sav145390 * exit with an error if we can not find one.
1541772Sjl139090 */
1552652Sav145390 if (strncmp(frustr, OPL_CPU_FRU_FMRI_DC,
1562652Sav145390 sizeof (OPL_CPU_FRU_FMRI_DC) - 1) == 0) {
1572652Sav145390 comp = frustr + sizeof (OPL_CPU_FRU_FMRI_DC) - 1;
1582652Sav145390 (void) sscanf(comp, "%2d", &cmu_num);
1592652Sav145390 } else if (strncmp(frustr, OPL_CPU_FRU_FMRI_FF1,
1602652Sav145390 sizeof (OPL_CPU_FRU_FMRI_FF1) - 1) == 0) {
1612652Sav145390 comp = frustr + sizeof (OPL_CPU_FRU_FMRI_FF1) - 1;
1622652Sav145390 (void) sscanf(comp, "%d", &cmu_num);
1632652Sav145390 cmu_num /= 2;
1642652Sav145390 } else if (strncmp(frustr, OPL_CPU_FRU_FMRI_FF2,
1652652Sav145390 sizeof (OPL_CPU_FRU_FMRI_FF2) - 1) == 0) {
1662652Sav145390 comp = frustr + sizeof (OPL_CPU_FRU_FMRI_FF2) - 1;
1672652Sav145390 (void) sscanf(comp, "%d", &cmu_num);
1682652Sav145390 cmu_num /= 2;
1696297Sjl139090 } else if (strncmp(frustr, OPL_CPU_FRU_FMRI_IKKAKU,
1706297Sjl139090 sizeof (OPL_CPU_FRU_FMRI_IKKAKU) - 1) == 0) {
1716297Sjl139090 cmu_num = 0;
1722652Sav145390 } else {
1732652Sav145390 CMD_STAT_BUMP(bad_cpu_asru);
1742652Sav145390 fmd_hdl_strfree(hdl, frustr);
1752652Sav145390 nvlist_free(fmri);
1762652Sav145390 return (NULL);
1772652Sav145390 }
1781772Sjl139090
1791794Sav145390 if (cmd_fmri_hc_set(hdl, fmri, FM_HC_SCHEME_VERSION, NULL, NULL,
1801794Sav145390 NPAIRS, "chassis", 0, "cmu", cmu_num, "chip",
1811794Sav145390 ((cpuid >> CHIPID_SHIFT) & CHIP_OR_CORE_MASK),
1821794Sav145390 "core", ((cpuid >> COREID_SHIFT) & CHIP_OR_CORE_MASK),
1831794Sav145390 "strand", (cpuid & STRAND_MASK)) != 0) {
1841772Sjl139090 fmd_hdl_strfree(hdl, frustr);
1851772Sjl139090 nvlist_free(fmri);
1861772Sjl139090 return (NULL);
1871772Sjl139090 }
1881772Sjl139090
1891772Sjl139090 fmd_hdl_strfree(hdl, frustr);
1901772Sjl139090 return (fmri);
1911772Sjl139090 }
1922214Sav145390
1932214Sav145390 nvlist_t *
opl_mem_fru_create(fmd_hdl_t * hdl,nvlist_t * nvl)1942214Sav145390 opl_mem_fru_create(fmd_hdl_t *hdl, nvlist_t *nvl)
1952214Sav145390 {
1962214Sav145390 nvlist_t *fmri;
1972214Sav145390 char *unum;
1982214Sav145390 char **serids;
1992214Sav145390 size_t nserids;
2002214Sav145390
2012214Sav145390
2022214Sav145390 if (nvlist_lookup_string(nvl, FM_FMRI_MEM_UNUM, &unum) != 0)
2032214Sav145390 return (NULL);
2042214Sav145390
2052214Sav145390 fmd_hdl_debug(hdl, "opl_mem_fru_create for mem %s\n", unum);
2062214Sav145390
207*6828Stsien if ((fmri = cmd_mem_fmri_create(unum, NULL, 0)) == NULL)
2082214Sav145390 return (NULL);
2092214Sav145390
2102214Sav145390 if ((nvlist_lookup_string_array(nvl, FM_FMRI_MEM_SERIAL_ID, &serids,
2112214Sav145390 &nserids)) == 0) {
2122214Sav145390 if ((nvlist_add_string_array(fmri, FM_FMRI_MEM_SERIAL_ID,
2132214Sav145390 serids, nserids)) != 0) {
2142214Sav145390 nvlist_free(fmri);
2152214Sav145390 return (NULL);
2162214Sav145390 }
2172214Sav145390 }
2182214Sav145390
2192214Sav145390 return (fmri);
2202214Sav145390 }
221