1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * CPU support routines for DR 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/devops.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/poll.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/processor.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/mem_config.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/promif.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/x_call.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/membar.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/stack.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/spitregs.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 62*7c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/pte.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/mmu.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/x_call.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/cheetahregs.h> 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #include <sys/sbdpriv.h> 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate void 75*7c478bd9Sstevel@tonic-gate sbd_cpu_set_prop(sbd_cpu_unit_t *cp, dev_info_t *dip) 76*7c478bd9Sstevel@tonic-gate { 77*7c478bd9Sstevel@tonic-gate uint32_t clock_freq; 78*7c478bd9Sstevel@tonic-gate int ecache_size = 0; 79*7c478bd9Sstevel@tonic-gate char *cache_str = NULL; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* read in the CPU speed */ 82*7c478bd9Sstevel@tonic-gate clock_freq = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 83*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "clock-frequency", 0); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate ASSERT(clock_freq != 0); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * The ecache property string is not the same 89*7c478bd9Sstevel@tonic-gate * for all CPU implementations. 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate switch (cp->sbc_cpu_impl) { 92*7c478bd9Sstevel@tonic-gate case CHEETAH_IMPL: 93*7c478bd9Sstevel@tonic-gate case CHEETAH_PLUS_IMPL: 94*7c478bd9Sstevel@tonic-gate cache_str = "ecache-size"; 95*7c478bd9Sstevel@tonic-gate break; 96*7c478bd9Sstevel@tonic-gate case JAGUAR_IMPL: 97*7c478bd9Sstevel@tonic-gate cache_str = "l2-cache-size"; 98*7c478bd9Sstevel@tonic-gate break; 99*7c478bd9Sstevel@tonic-gate case PANTHER_IMPL: 100*7c478bd9Sstevel@tonic-gate cache_str = "l3-cache-size"; 101*7c478bd9Sstevel@tonic-gate break; 102*7c478bd9Sstevel@tonic-gate default: 103*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cpu implementation type " 104*7c478bd9Sstevel@tonic-gate "is an unknown %d value", cp->sbc_cpu_impl); 105*7c478bd9Sstevel@tonic-gate ASSERT(0); 106*7c478bd9Sstevel@tonic-gate break; 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate if (cache_str != NULL) { 110*7c478bd9Sstevel@tonic-gate /* read in the ecache size */ 111*7c478bd9Sstevel@tonic-gate ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 112*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, cache_str, 0); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * In the case the size is still 0, 117*7c478bd9Sstevel@tonic-gate * a zero value will be displayed running non-debug. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate ASSERT(ecache_size != 0); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* convert to the proper units */ 122*7c478bd9Sstevel@tonic-gate cp->sbc_speed = (clock_freq + 500000) / 1000000; 123*7c478bd9Sstevel@tonic-gate cp->sbc_ecache = ecache_size / (1024 * 1024); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate static void 127*7c478bd9Sstevel@tonic-gate sbd_fill_cpu_stat(sbd_cpu_unit_t *cp, dev_info_t *dip, sbd_cpu_stat_t *csp) 128*7c478bd9Sstevel@tonic-gate { 129*7c478bd9Sstevel@tonic-gate int namelen; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate bzero((caddr_t)csp, sizeof (*csp)); 132*7c478bd9Sstevel@tonic-gate csp->cs_type = cp->sbc_cm.sbdev_type; 133*7c478bd9Sstevel@tonic-gate csp->cs_unit = cp->sbc_cm.sbdev_unum; 134*7c478bd9Sstevel@tonic-gate namelen = sizeof (csp->cs_name); 135*7c478bd9Sstevel@tonic-gate (void) ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 136*7c478bd9Sstevel@tonic-gate OBP_DEVICETYPE, (caddr_t)csp->cs_name, &namelen); 137*7c478bd9Sstevel@tonic-gate csp->cs_busy = cp->sbc_cm.sbdev_busy; 138*7c478bd9Sstevel@tonic-gate csp->cs_time = cp->sbc_cm.sbdev_time; 139*7c478bd9Sstevel@tonic-gate csp->cs_ostate = cp->sbc_cm.sbdev_ostate; 140*7c478bd9Sstevel@tonic-gate csp->cs_cpuid = cp->sbc_cpu_id; 141*7c478bd9Sstevel@tonic-gate csp->cs_suspend = 0; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * If we have marked the cpu's condition previously 145*7c478bd9Sstevel@tonic-gate * then don't rewrite it 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate if (csp->cs_cond != SBD_COND_UNUSABLE) 148*7c478bd9Sstevel@tonic-gate csp->cs_cond = sbd_get_comp_cond(dip); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * If the speed and ecache properties have not been 152*7c478bd9Sstevel@tonic-gate * cached yet, read them in from the device tree. 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate if ((cp->sbc_speed == 0) || (cp->sbc_ecache == 0)) 155*7c478bd9Sstevel@tonic-gate sbd_cpu_set_prop(cp, dip); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* use the cached speed and ecache values */ 158*7c478bd9Sstevel@tonic-gate csp->cs_speed = cp->sbc_speed; 159*7c478bd9Sstevel@tonic-gate csp->cs_ecache = cp->sbc_ecache; 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate static void 163*7c478bd9Sstevel@tonic-gate sbd_fill_cmp_stat(sbd_cpu_stat_t *csp, int ncores, int impl, 164*7c478bd9Sstevel@tonic-gate sbd_cmp_stat_t *psp) 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate int core; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate ASSERT(csp && psp && (ncores >= 1)); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate bzero((caddr_t)psp, sizeof (*psp)); 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * Fill in the common status information based 174*7c478bd9Sstevel@tonic-gate * on the data for the first core. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate psp->ps_type = SBD_COMP_CMP; 177*7c478bd9Sstevel@tonic-gate psp->ps_unit = SBD_CMP_NUM(csp->cs_unit); 178*7c478bd9Sstevel@tonic-gate (void) strncpy(psp->ps_name, csp->cs_name, sizeof (psp->ps_name)); 179*7c478bd9Sstevel@tonic-gate psp->ps_cond = csp->cs_cond; 180*7c478bd9Sstevel@tonic-gate psp->ps_busy = csp->cs_busy; 181*7c478bd9Sstevel@tonic-gate psp->ps_time = csp->cs_time; 182*7c478bd9Sstevel@tonic-gate psp->ps_ostate = csp->cs_ostate; 183*7c478bd9Sstevel@tonic-gate psp->ps_suspend = csp->cs_suspend; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* CMP specific status data */ 186*7c478bd9Sstevel@tonic-gate *psp->ps_cpuid = csp->cs_cpuid; 187*7c478bd9Sstevel@tonic-gate psp->ps_ncores = 1; 188*7c478bd9Sstevel@tonic-gate psp->ps_speed = csp->cs_speed; 189*7c478bd9Sstevel@tonic-gate psp->ps_ecache = csp->cs_ecache; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* 192*7c478bd9Sstevel@tonic-gate * Walk through the data for the remaining cores. 193*7c478bd9Sstevel@tonic-gate * Make any adjustments to the common status data, 194*7c478bd9Sstevel@tonic-gate * or the shared CMP specific data if necessary. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate for (core = 1; core < ncores; core++) { 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * The following properties should be the same 200*7c478bd9Sstevel@tonic-gate * for all the cores of the CMP. 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate ASSERT(psp->ps_unit == SBD_CMP_NUM(csp[core].cs_unit)); 203*7c478bd9Sstevel@tonic-gate ASSERT(psp->ps_speed == csp[core].cs_speed); 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate psp->ps_cpuid[core] = csp[core].cs_cpuid; 206*7c478bd9Sstevel@tonic-gate psp->ps_ncores++; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * Jaguar has a split ecache, so the ecache 210*7c478bd9Sstevel@tonic-gate * for each core must be added together to 211*7c478bd9Sstevel@tonic-gate * get the total ecache for the whole chip. 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate if (IS_JAGUAR(impl)) { 214*7c478bd9Sstevel@tonic-gate psp->ps_ecache += csp[core].cs_ecache; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* adjust time if necessary */ 218*7c478bd9Sstevel@tonic-gate if (csp[core].cs_time > psp->ps_time) { 219*7c478bd9Sstevel@tonic-gate psp->ps_time = csp[core].cs_time; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate psp->ps_busy |= csp[core].cs_busy; 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* 225*7c478bd9Sstevel@tonic-gate * If any of the cores are configured, the 226*7c478bd9Sstevel@tonic-gate * entire CMP is marked as configured. 227*7c478bd9Sstevel@tonic-gate */ 228*7c478bd9Sstevel@tonic-gate if (csp[core].cs_ostate == SBD_STAT_CONFIGURED) { 229*7c478bd9Sstevel@tonic-gate psp->ps_ostate = csp[core].cs_ostate; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate int 235*7c478bd9Sstevel@tonic-gate sbd_cpu_flags(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp) 236*7c478bd9Sstevel@tonic-gate { 237*7c478bd9Sstevel@tonic-gate int cmp; 238*7c478bd9Sstevel@tonic-gate int ncpu; 239*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 240*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 241*7c478bd9Sstevel@tonic-gate sbd_cpu_stat_t cstat[MAX_CORES_PER_CMP]; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 244*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Grab the status lock before accessing the dip as we allow 248*7c478bd9Sstevel@tonic-gate * concurrent status and branch unconfigure and disconnect. 249*7c478bd9Sstevel@tonic-gate * 250*7c478bd9Sstevel@tonic-gate * The disconnect thread clears the present devset first 251*7c478bd9Sstevel@tonic-gate * and then destroys dips. It is possible that the status 252*7c478bd9Sstevel@tonic-gate * thread checks the present devset before they are cleared 253*7c478bd9Sstevel@tonic-gate * but accesses the dip after they are destroyed causing a 254*7c478bd9Sstevel@tonic-gate * panic. To prevent this, the status thread should check 255*7c478bd9Sstevel@tonic-gate * the present devset and access dips with status lock held. 256*7c478bd9Sstevel@tonic-gate * Similarly disconnect thread should clear the present devset 257*7c478bd9Sstevel@tonic-gate * and destroy dips with status lock held. 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate /* 262*7c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 263*7c478bd9Sstevel@tonic-gate */ 264*7c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * Treat every CPU as a CMP. In the case where the 268*7c478bd9Sstevel@tonic-gate * device is not a CMP, treat it as a CMP with only 269*7c478bd9Sstevel@tonic-gate * one core. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate for (cmp = ncpu = 0; cmp < MAX_CMP_UNITS_PER_BOARD; cmp++) { 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate int ncores; 274*7c478bd9Sstevel@tonic-gate int core; 275*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 276*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cp; 277*7c478bd9Sstevel@tonic-gate sbd_cmp_stat_t *psp; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CMP, cmp) == 0) 280*7c478bd9Sstevel@tonic-gate continue; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate ncores = 0; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate for (core = 0; core < MAX_CORES_PER_CMP; core++) { 285*7c478bd9Sstevel@tonic-gate int unit; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate unit = sbdp_portid_to_cpu_unit(cmp, core); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Check to make sure the cpu is in a state 291*7c478bd9Sstevel@tonic-gate * where its fully initialized. 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate if (SBD_DEVICE_STATE(sbp, SBD_COMP_CPU, unit) == 294*7c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY) 295*7c478bd9Sstevel@tonic-gate continue; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CMP)][unit]; 298*7c478bd9Sstevel@tonic-gate if (dip == NULL) 299*7c478bd9Sstevel@tonic-gate continue; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate cp = SBD_GET_BOARD_CPUUNIT(sbp, unit); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate sbd_fill_cpu_stat(cp, dip, &cstat[ncores++]); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (ncores == 0) 307*7c478bd9Sstevel@tonic-gate continue; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * Store the data to the outgoing array. If the 311*7c478bd9Sstevel@tonic-gate * device is a CMP, combine all the data for the 312*7c478bd9Sstevel@tonic-gate * cores into a single stat structure. 313*7c478bd9Sstevel@tonic-gate * 314*7c478bd9Sstevel@tonic-gate * The check for a CMP device uses the last core 315*7c478bd9Sstevel@tonic-gate * found, assuming that all cores will have the 316*7c478bd9Sstevel@tonic-gate * same implementation. 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate if (CPU_IMPL_IS_CMP(cp->sbc_cpu_impl)) { 319*7c478bd9Sstevel@tonic-gate psp = (sbd_cmp_stat_t *)dsp; 320*7c478bd9Sstevel@tonic-gate sbd_fill_cmp_stat(cstat, ncores, cp->sbc_cpu_impl, psp); 321*7c478bd9Sstevel@tonic-gate } else { 322*7c478bd9Sstevel@tonic-gate ASSERT(ncores == 1); 323*7c478bd9Sstevel@tonic-gate bcopy(cstat, dsp, sizeof (sbd_cpu_stat_t)); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate dsp++; 327*7c478bd9Sstevel@tonic-gate ncpu++; 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate return (ncpu); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate int 338*7c478bd9Sstevel@tonic-gate sbd_pre_release_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 339*7c478bd9Sstevel@tonic-gate { 340*7c478bd9Sstevel@tonic-gate int i, rv = 0, unit; 341*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 342*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 343*7c478bd9Sstevel@tonic-gate struct cpu *cpup; 344*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 345*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 346*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cp; 347*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_release_cpu"; 348*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 351*7c478bd9Sstevel@tonic-gate /* 352*7c478bd9Sstevel@tonic-gate * May have to juggle bootproc in release_component 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++, devlist++) { 357*7c478bd9Sstevel@tonic-gate dip = devlist->dv_dip; 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 360*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 361*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 362*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 363*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get cpuid for " 364*7c478bd9Sstevel@tonic-gate "dip (0x%p)", f, (void *)dip); 365*7c478bd9Sstevel@tonic-gate continue; 366*7c478bd9Sstevel@tonic-gate } else { 367*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 368*7c478bd9Sstevel@tonic-gate break; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 374*7c478bd9Sstevel@tonic-gate if (unit < 0) { 375*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 376*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 377*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get unit (cpu %d)", 378*7c478bd9Sstevel@tonic-gate f, cpuid); 379*7c478bd9Sstevel@tonic-gate continue; 380*7c478bd9Sstevel@tonic-gate } else { 381*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 382*7c478bd9Sstevel@tonic-gate break; 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate cp = SBD_GET_BOARD_CPUUNIT(sbp, unit); 387*7c478bd9Sstevel@tonic-gate cp->sbc_cpu_flags = cpu[cpuid]->cpu_flags; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate if (cpu_flagged_active(cp->sbc_cpu_flags)) { 390*7c478bd9Sstevel@tonic-gate int cpu_offline_flags = 0; 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) 393*7c478bd9Sstevel@tonic-gate cpu_offline_flags = CPU_FORCED; 394*7c478bd9Sstevel@tonic-gate PR_CPU("%s: offlining cpuid %d unit %d", f, 395*7c478bd9Sstevel@tonic-gate cpuid, unit); 396*7c478bd9Sstevel@tonic-gate if (cpu_offline(cpu[cpuid], cpu_offline_flags)) { 397*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 398*7c478bd9Sstevel@tonic-gate "%s: failed to offline cpu %d", 399*7c478bd9Sstevel@tonic-gate f, cpuid); 400*7c478bd9Sstevel@tonic-gate rv = -1; 401*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_OFFLINE); 402*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 403*7c478bd9Sstevel@tonic-gate cpup = cpu_get(cpuid); 404*7c478bd9Sstevel@tonic-gate if (cpup && disp_bound_threads(cpup, 0)) { 405*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sbd:%s: thread(s) " 406*7c478bd9Sstevel@tonic-gate "bound to cpu %d", 407*7c478bd9Sstevel@tonic-gate f, cpup->cpu_id); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate break; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (rv == 0) { 414*7c478bd9Sstevel@tonic-gate if (sbdp_release_component(hdp, dip)) { 415*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 416*7c478bd9Sstevel@tonic-gate break; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate if (rv) 421*7c478bd9Sstevel@tonic-gate break; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate if (rv) { 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * Need to unwind others since at this level (pre-release) 429*7c478bd9Sstevel@tonic-gate * the device state has not yet transitioned and failures 430*7c478bd9Sstevel@tonic-gate * will prevent us from reaching the "post" release 431*7c478bd9Sstevel@tonic-gate * function where states are normally transitioned. 432*7c478bd9Sstevel@tonic-gate */ 433*7c478bd9Sstevel@tonic-gate for (; i >= 0; i--, devlist--) { 434*7c478bd9Sstevel@tonic-gate dip = devlist->dv_dip; 435*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 436*7c478bd9Sstevel@tonic-gate if (unit < 0) { 437*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 438*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get unit for " 439*7c478bd9Sstevel@tonic-gate "dip (0x%p)", f, (void *)dip); 440*7c478bd9Sstevel@tonic-gate break; 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate (void) sbd_cancel_cpu(hp, unit); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_OFFLINE_CPU_PSEUDO_ERR, 447*7c478bd9Sstevel@tonic-gate hp->h_err, EIO, 448*7c478bd9Sstevel@tonic-gate ESBD_OFFLINE, 449*7c478bd9Sstevel@tonic-gate sbp->sb_cpupath[devnum - 1]); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate return (rv); 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate int 457*7c478bd9Sstevel@tonic-gate sbd_pre_attach_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 458*7c478bd9Sstevel@tonic-gate { 459*7c478bd9Sstevel@tonic-gate int i; 460*7c478bd9Sstevel@tonic-gate int unit; 461*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 462*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 463*7c478bd9Sstevel@tonic-gate sbd_istate_t dstate; 464*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 465*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_attach_cpu"; 466*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate PR_CPU("%s...\n", f); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++, devlist++) { 473*7c478bd9Sstevel@tonic-gate dip = devlist->dv_dip; 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate ASSERT(sbd_is_cmp_child(dip) || e_ddi_branch_held(dip)); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 478*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 479*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 480*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 481*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get cpuid for " 482*7c478bd9Sstevel@tonic-gate "dip (0x%p)", f, (void *)dip); 483*7c478bd9Sstevel@tonic-gate continue; 484*7c478bd9Sstevel@tonic-gate } else { 485*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 486*7c478bd9Sstevel@tonic-gate break; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 491*7c478bd9Sstevel@tonic-gate if (unit < 0) { 492*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 493*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 494*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get unit (cpu %d)", 495*7c478bd9Sstevel@tonic-gate f, cpuid); 496*7c478bd9Sstevel@tonic-gate continue; 497*7c478bd9Sstevel@tonic-gate } else { 498*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 499*7c478bd9Sstevel@tonic-gate break; 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate PR_CPU("%s: attach cpu-unit (%d.%d)\n", 504*7c478bd9Sstevel@tonic-gate f, sbp->sb_num, unit); 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate dstate = SBD_DEVICE_STATE(sbp, SBD_COMP_CPU, unit); 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate if (dstate == SBD_STATE_UNCONFIGURED) { 509*7c478bd9Sstevel@tonic-gate /* 510*7c478bd9Sstevel@tonic-gate * If we're coming from the UNCONFIGURED 511*7c478bd9Sstevel@tonic-gate * state then the cpu's sigblock will 512*7c478bd9Sstevel@tonic-gate * still be mapped in. Need to unmap it 513*7c478bd9Sstevel@tonic-gate * before continuing with attachment. 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate PR_CPU("%s: unmapping sigblk for cpu %d\n", 516*7c478bd9Sstevel@tonic-gate f, cpuid); 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate /* platform specific release of sigblk */ 519*7c478bd9Sstevel@tonic-gate CPU_SGN_MAPOUT(cpuid); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate return (0); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate int 532*7c478bd9Sstevel@tonic-gate sbd_post_attach_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate int i; 535*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 536*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 537*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 538*7c478bd9Sstevel@tonic-gate struct cpu *cp; 539*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 540*7c478bd9Sstevel@tonic-gate int err = ESBD_NOERROR; 541*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 542*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_attach_cpu"; 543*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cpup; 544*7c478bd9Sstevel@tonic-gate int unit; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate /* Startup and online newly-attached CPUs */ 549*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++, devlist++) { 550*7c478bd9Sstevel@tonic-gate dip = devlist->dv_dip; 551*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 552*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 553*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 554*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 555*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get cpuid for " 556*7c478bd9Sstevel@tonic-gate "dip (0x%p)", f, (void *)dip); 557*7c478bd9Sstevel@tonic-gate continue; 558*7c478bd9Sstevel@tonic-gate } else { 559*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 560*7c478bd9Sstevel@tonic-gate break; 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate cp = cpu_get(cpuid); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 567*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 568*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 569*7c478bd9Sstevel@tonic-gate "sbd:%s: cpu_get failed for cpu %d", 570*7c478bd9Sstevel@tonic-gate f, cpuid); 571*7c478bd9Sstevel@tonic-gate continue; 572*7c478bd9Sstevel@tonic-gate } else { 573*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_INTERNAL); 574*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 575*7c478bd9Sstevel@tonic-gate break; 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if (cpu_is_poweredoff(cp)) { 580*7c478bd9Sstevel@tonic-gate if (cpu_poweron(cp) != 0) { 581*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_CPUSTART); 582*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 583*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 584*7c478bd9Sstevel@tonic-gate "%s: failed to power-on cpu %d", 585*7c478bd9Sstevel@tonic-gate f, cpuid); 586*7c478bd9Sstevel@tonic-gate break; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_POWERON_CPU_PSEUDO_ERR, 589*7c478bd9Sstevel@tonic-gate ep, EIO, 590*7c478bd9Sstevel@tonic-gate ESBD_CPUSTOP, 591*7c478bd9Sstevel@tonic-gate sbp->sb_cpupath[i]); 592*7c478bd9Sstevel@tonic-gate PR_CPU("%s: cpu %d powered ON\n", f, cpuid); 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate if (cpu_is_offline(cp)) { 596*7c478bd9Sstevel@tonic-gate PR_CPU("%s: onlining cpu %d...\n", f, cpuid); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate if (cpu_online(cp) != 0) { 599*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_ONLINE); 600*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 601*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 602*7c478bd9Sstevel@tonic-gate "%s: failed to online cpu %d", 603*7c478bd9Sstevel@tonic-gate f, cp->cpu_id); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_ONLINE_CPU_PSEUDO_ERR, 606*7c478bd9Sstevel@tonic-gate ep, EIO, 607*7c478bd9Sstevel@tonic-gate ESBD_ONLINE, 608*7c478bd9Sstevel@tonic-gate sbp->sb_cpupath[i]); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate /* 612*7c478bd9Sstevel@tonic-gate * if there is no error mark the cpu as OK to use 613*7c478bd9Sstevel@tonic-gate */ 614*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) == 0) { 615*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 616*7c478bd9Sstevel@tonic-gate if (unit < 0) { 617*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 618*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 619*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get unit " 620*7c478bd9Sstevel@tonic-gate "(cpu %d)", f, cpuid); 621*7c478bd9Sstevel@tonic-gate continue; 622*7c478bd9Sstevel@tonic-gate } else { 623*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, 624*7c478bd9Sstevel@tonic-gate SBD_HD2ERR(hp)); 625*7c478bd9Sstevel@tonic-gate break; 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate cpup = SBD_GET_BOARD_CPUUNIT(sbp, unit); 629*7c478bd9Sstevel@tonic-gate cpup->sbc_cm.sbdev_cond = SBD_COND_OK; 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate if (err != ESBD_NOERROR) { 638*7c478bd9Sstevel@tonic-gate return (-1); 639*7c478bd9Sstevel@tonic-gate } else { 640*7c478bd9Sstevel@tonic-gate return (0); 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate int 645*7c478bd9Sstevel@tonic-gate sbd_pre_detach_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 646*7c478bd9Sstevel@tonic-gate { 647*7c478bd9Sstevel@tonic-gate int i; 648*7c478bd9Sstevel@tonic-gate int unit; 649*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 650*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 651*7c478bd9Sstevel@tonic-gate struct cpu *cpu; 652*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 653*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 654*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_detach_cpu"; 655*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 656*7c478bd9Sstevel@tonic-gate int rv = 0; 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate PR_CPU("%s...\n", f); 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++, devlist++) { 665*7c478bd9Sstevel@tonic-gate dip = devlist->dv_dip; 666*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 667*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 668*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 669*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 670*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get cpuid for " 671*7c478bd9Sstevel@tonic-gate "dip (0x%p)", f, (void *)dip); 672*7c478bd9Sstevel@tonic-gate continue; 673*7c478bd9Sstevel@tonic-gate } else { 674*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 675*7c478bd9Sstevel@tonic-gate break; 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate cpu = cpu_get(cpuid); 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate if (cpu == NULL) { 682*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 683*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 684*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get cpu %d", 685*7c478bd9Sstevel@tonic-gate f, cpuid); 686*7c478bd9Sstevel@tonic-gate continue; 687*7c478bd9Sstevel@tonic-gate } else { 688*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_INTERNAL); 689*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 690*7c478bd9Sstevel@tonic-gate break; 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 695*7c478bd9Sstevel@tonic-gate if (unit < 0) { 696*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 697*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 698*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get unit (cpu %d)", 699*7c478bd9Sstevel@tonic-gate f, cpuid); 700*7c478bd9Sstevel@tonic-gate continue; 701*7c478bd9Sstevel@tonic-gate } else { 702*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 703*7c478bd9Sstevel@tonic-gate break; 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate PR_CPU("%s: OS detach cpu-unit (%d.%d)\n", 708*7c478bd9Sstevel@tonic-gate f, sbp->sb_num, unit); 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate /* 711*7c478bd9Sstevel@tonic-gate * CPUs were offlined during Release. 712*7c478bd9Sstevel@tonic-gate */ 713*7c478bd9Sstevel@tonic-gate if (cpu_is_poweredoff(cpu)) { 714*7c478bd9Sstevel@tonic-gate PR_CPU("%s: cpu %d already powered OFF\n", f, cpuid); 715*7c478bd9Sstevel@tonic-gate continue; 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate if (cpu_is_offline(cpu)) { 719*7c478bd9Sstevel@tonic-gate int e; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate if (e = cpu_poweroff(cpu)) { 722*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 723*7c478bd9Sstevel@tonic-gate "%s: failed to power-off cpu %d " 724*7c478bd9Sstevel@tonic-gate "(errno %d)", 725*7c478bd9Sstevel@tonic-gate f, cpu->cpu_id, e); 726*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_CPUSTOP); 727*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate rv = -1; 730*7c478bd9Sstevel@tonic-gate break; 731*7c478bd9Sstevel@tonic-gate } else { 732*7c478bd9Sstevel@tonic-gate PR_CPU("%s: cpu %d powered OFF\n", 733*7c478bd9Sstevel@tonic-gate f, cpuid); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate } else { 736*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: cpu %d still active", 737*7c478bd9Sstevel@tonic-gate f, cpu->cpu_id); 738*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_BUSY); 739*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[i]); 740*7c478bd9Sstevel@tonic-gate rv = -1; 741*7c478bd9Sstevel@tonic-gate break; 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate return (rv); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate int 751*7c478bd9Sstevel@tonic-gate sbd_post_detach_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 752*7c478bd9Sstevel@tonic-gate { 753*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_detach_cpu"; 754*7c478bd9Sstevel@tonic-gate int i; 755*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 756*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 757*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 758*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 759*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 760*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cpup; 761*7c478bd9Sstevel@tonic-gate int unit; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate PR_CPU("%s...\n", f); 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate /* 766*7c478bd9Sstevel@tonic-gate * We should be holding the cpu_lock at this point, 767*7c478bd9Sstevel@tonic-gate * and should have blocked device tree changes. 768*7c478bd9Sstevel@tonic-gate */ 769*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++, devlist++) { 772*7c478bd9Sstevel@tonic-gate dip = devlist->dv_dip; 773*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 774*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 775*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 776*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 777*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 778*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get cpuid for " 779*7c478bd9Sstevel@tonic-gate "dip (0x%p)", f, (void *)dip); 780*7c478bd9Sstevel@tonic-gate continue; 781*7c478bd9Sstevel@tonic-gate } else { 782*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 783*7c478bd9Sstevel@tonic-gate break; 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate /* 787*7c478bd9Sstevel@tonic-gate * if there is no error mark the cpu as unusable 788*7c478bd9Sstevel@tonic-gate */ 789*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) == 0) { 790*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 791*7c478bd9Sstevel@tonic-gate if (unit < 0) { 792*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) { 793*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 794*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to get unit " 795*7c478bd9Sstevel@tonic-gate "(cpu %d)", f, cpuid); 796*7c478bd9Sstevel@tonic-gate continue; 797*7c478bd9Sstevel@tonic-gate } else { 798*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, 799*7c478bd9Sstevel@tonic-gate SBD_HD2ERR(hp)); 800*7c478bd9Sstevel@tonic-gate break; 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate cpup = SBD_GET_BOARD_CPUUNIT(sbp, unit); 804*7c478bd9Sstevel@tonic-gate cpup->sbc_cm.sbdev_cond = SBD_COND_UNUSABLE; 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate return (0); 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* 816*7c478bd9Sstevel@tonic-gate * Cancel previous release operation for cpu. For cpus this means simply 817*7c478bd9Sstevel@tonic-gate * bringing cpus that were offline back online. Note that they had to have been 818*7c478bd9Sstevel@tonic-gate * online at the time they were released. If attempting to power on or online 819*7c478bd9Sstevel@tonic-gate * a CPU fails, SBD_CPUERR_FATAL is returned to indicate that the CPU appears to 820*7c478bd9Sstevel@tonic-gate * be unsalvageable. If a CPU reaches an online or nointr state but can't be 821*7c478bd9Sstevel@tonic-gate * taken to a "lesser" state, SBD_CPUERR_RECOVERABLE is returned to indicate 822*7c478bd9Sstevel@tonic-gate * that it was not returned to its original state but appears to be functional. 823*7c478bd9Sstevel@tonic-gate * Note that the latter case can occur due to unexpected but non-erroneous CPU 824*7c478bd9Sstevel@tonic-gate * manipulation (e.g. by the "psradm" command) during the DR operation. 825*7c478bd9Sstevel@tonic-gate */ 826*7c478bd9Sstevel@tonic-gate int 827*7c478bd9Sstevel@tonic-gate sbd_cancel_cpu(sbd_handle_t *hp, int unit) 828*7c478bd9Sstevel@tonic-gate { 829*7c478bd9Sstevel@tonic-gate int rv = SBD_CPUERR_NONE; 830*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 831*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 832*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cp; 833*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_cancel_cpu"; 834*7c478bd9Sstevel@tonic-gate struct cpu *cpup; 835*7c478bd9Sstevel@tonic-gate int cpu_offline_flags = 0; 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate cp = SBD_GET_BOARD_CPUUNIT(sbp, unit); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * If CPU should remain off, nothing needs to be done. 843*7c478bd9Sstevel@tonic-gate */ 844*7c478bd9Sstevel@tonic-gate if (cpu_flagged_poweredoff(cp->sbc_cpu_flags)) 845*7c478bd9Sstevel@tonic-gate return (rv); 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) 848*7c478bd9Sstevel@tonic-gate cpu_offline_flags = CPU_FORCED; 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate /* 851*7c478bd9Sstevel@tonic-gate * CPU had been either offline, online, or set to no-intr. We 852*7c478bd9Sstevel@tonic-gate * will return a component to its original state that it was 853*7c478bd9Sstevel@tonic-gate * prior to the failed DR operation. There is a possible race 854*7c478bd9Sstevel@tonic-gate * condition between the calls to this function and re-obtaining 855*7c478bd9Sstevel@tonic-gate * the cpu_lock where a cpu state could change. Because of this 856*7c478bd9Sstevel@tonic-gate * we can't externally document that we are trying to roll cpus 857*7c478bd9Sstevel@tonic-gate * back to their original state, but we believe a best effort 858*7c478bd9Sstevel@tonic-gate * should be made. 859*7c478bd9Sstevel@tonic-gate */ 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 862*7c478bd9Sstevel@tonic-gate cpup = cpu[cp->sbc_cpu_id]; 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate /* 865*7c478bd9Sstevel@tonic-gate * The following will compare the cpu's current state with a 866*7c478bd9Sstevel@tonic-gate * snapshot of its state taken before the failed DR operation 867*7c478bd9Sstevel@tonic-gate * had started. 868*7c478bd9Sstevel@tonic-gate */ 869*7c478bd9Sstevel@tonic-gate /* POWEROFF */ 870*7c478bd9Sstevel@tonic-gate if (cpu_is_poweredoff(cpup)) { 871*7c478bd9Sstevel@tonic-gate if (cpu_poweron(cpup)) { 872*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 873*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to power-on cpu %d", 874*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 875*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_CPUSTART); 876*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[unit]); 877*7c478bd9Sstevel@tonic-gate rv = SBD_CPUERR_FATAL; 878*7c478bd9Sstevel@tonic-gate goto out; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_POWERON_CPU_PSEUDO_ERR, 881*7c478bd9Sstevel@tonic-gate hp->h_err, EIO, 882*7c478bd9Sstevel@tonic-gate ESBD_CPUSTART, 883*7c478bd9Sstevel@tonic-gate sbp->sb_cpupath[unit]); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* OFFLINE */ 887*7c478bd9Sstevel@tonic-gate if (cpu_is_offline(cpup)) { 888*7c478bd9Sstevel@tonic-gate if (cpu_flagged_offline(cp->sbc_cpu_flags)) { 889*7c478bd9Sstevel@tonic-gate PR_CPU("%s: leaving cpu %d OFFLINE\n", 890*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 891*7c478bd9Sstevel@tonic-gate } else if (cpu_online(cpup)) { 892*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 893*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to online cpu %d", 894*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 895*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_ONLINE); 896*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[unit]); 897*7c478bd9Sstevel@tonic-gate rv = SBD_CPUERR_FATAL; 898*7c478bd9Sstevel@tonic-gate goto out; 899*7c478bd9Sstevel@tonic-gate } else { 900*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_ONLINE_CPU_PSEUDO_ERR, 901*7c478bd9Sstevel@tonic-gate hp->h_err, EIO, 902*7c478bd9Sstevel@tonic-gate ESBD_ONLINE, 903*7c478bd9Sstevel@tonic-gate sbp->sb_cpupath[unit]); 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate /* ONLINE */ 908*7c478bd9Sstevel@tonic-gate if (cpu_is_online(cpup)) { 909*7c478bd9Sstevel@tonic-gate if (cpu_flagged_online(cp->sbc_cpu_flags)) { 910*7c478bd9Sstevel@tonic-gate PR_CPU("%s: setting cpu %d ONLINE\n", 911*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 912*7c478bd9Sstevel@tonic-gate } else if (cpu_flagged_offline(cp->sbc_cpu_flags)) { 913*7c478bd9Sstevel@tonic-gate if (cpu_offline(cpup, cpu_offline_flags)) { 914*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 915*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to offline" 916*7c478bd9Sstevel@tonic-gate " cpu %d", f, cp->sbc_cpu_id); 917*7c478bd9Sstevel@tonic-gate rv = SBD_CPUERR_RECOVERABLE; 918*7c478bd9Sstevel@tonic-gate goto out; 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate } else if (cpu_flagged_nointr(cp->sbc_cpu_flags)) { 921*7c478bd9Sstevel@tonic-gate if (cpu_intr_disable(cpup)) { 922*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: failed to " 923*7c478bd9Sstevel@tonic-gate "disable interrupts on cpu %d", 924*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 925*7c478bd9Sstevel@tonic-gate rv = SBD_CPUERR_RECOVERABLE; 926*7c478bd9Sstevel@tonic-gate } else { 927*7c478bd9Sstevel@tonic-gate PR_CPU("%s: setting cpu %d to NOINTR" 928*7c478bd9Sstevel@tonic-gate " (was online)\n", 929*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate goto out; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* NOINTR */ 936*7c478bd9Sstevel@tonic-gate if (cpu_is_nointr(cpup)) { 937*7c478bd9Sstevel@tonic-gate if (cpu_flagged_online(cp->sbc_cpu_flags)) { 938*7c478bd9Sstevel@tonic-gate cpu_intr_enable(cpup); 939*7c478bd9Sstevel@tonic-gate PR_CPU("%s: setting cpu %d ONLINE" 940*7c478bd9Sstevel@tonic-gate "(was nointr)\n", 941*7c478bd9Sstevel@tonic-gate f, cp->sbc_cpu_id); 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate if (cpu_flagged_offline(cp->sbc_cpu_flags)) { 944*7c478bd9Sstevel@tonic-gate if (cpu_offline(cpup, cpu_offline_flags)) { 945*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 946*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to offline" 947*7c478bd9Sstevel@tonic-gate " cpu %d", f, cp->sbc_cpu_id); 948*7c478bd9Sstevel@tonic-gate rv = SBD_CPUERR_RECOVERABLE; 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate } 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate out: 953*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate return (rv); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate int 959*7c478bd9Sstevel@tonic-gate sbd_connect_cpu(sbd_board_t *sbp, int unit) 960*7c478bd9Sstevel@tonic-gate { 961*7c478bd9Sstevel@tonic-gate int rv; 962*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 963*7c478bd9Sstevel@tonic-gate struct cpu *cpu; 964*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 965*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 966*7c478bd9Sstevel@tonic-gate extern kmutex_t cpu_lock; 967*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_connect_cpu"; 968*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * get dip for cpu just located in tree walk 972*7c478bd9Sstevel@tonic-gate */ 973*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, unit)) { 974*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CPU)][unit]; 975*7c478bd9Sstevel@tonic-gate if (dip == NULL) { 976*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 977*7c478bd9Sstevel@tonic-gate "sbd:%s: bad dip for cpu unit %d board %d", 978*7c478bd9Sstevel@tonic-gate f, unit, sbp->sb_num); 979*7c478bd9Sstevel@tonic-gate return (-1); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate PR_CPU("%s...\n", f); 982*7c478bd9Sstevel@tonic-gate } else { 983*7c478bd9Sstevel@tonic-gate return (0); 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate /* 987*7c478bd9Sstevel@tonic-gate * if sbd has attached this cpu, no need to bring 988*7c478bd9Sstevel@tonic-gate * it out of reset 989*7c478bd9Sstevel@tonic-gate */ 990*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_CPU, unit)) { 991*7c478bd9Sstevel@tonic-gate return (0); 992*7c478bd9Sstevel@tonic-gate } 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 997*7c478bd9Sstevel@tonic-gate if (cpuid == -1) { 998*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 999*7c478bd9Sstevel@tonic-gate return (-1); 1000*7c478bd9Sstevel@tonic-gate } 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate /* 1003*7c478bd9Sstevel@tonic-gate * if the cpu is already under Solaris control, 1004*7c478bd9Sstevel@tonic-gate * do not wake it up 1005*7c478bd9Sstevel@tonic-gate */ 1006*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 1007*7c478bd9Sstevel@tonic-gate cpu = cpu_get(cpuid); 1008*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 1009*7c478bd9Sstevel@tonic-gate if (cpu != NULL) { 1010*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1011*7c478bd9Sstevel@tonic-gate return (0); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate rv = sbdp_connect_cpu(hdp, dip, cpuid); 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate if (rv != 0) { 1017*7c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 0; 1018*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1019*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to wake up cpu unit %d board %d", 1020*7c478bd9Sstevel@tonic-gate f, unit, sbp->sb_num); 1021*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1022*7c478bd9Sstevel@tonic-gate return (rv); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate return (rv); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate int 1030*7c478bd9Sstevel@tonic-gate sbd_disconnect_cpu(sbd_handle_t *hp, int unit) 1031*7c478bd9Sstevel@tonic-gate { 1032*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1033*7c478bd9Sstevel@tonic-gate int rv; 1034*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 1035*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 1036*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cp; 1037*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 1038*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_disconnect_cpu"; 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate PR_CPU("%s...\n", f); 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate ASSERT((SBD_DEVICE_STATE(sbp, SBD_COMP_CPU, unit) == 1043*7c478bd9Sstevel@tonic-gate SBD_STATE_CONNECTED) || 1044*7c478bd9Sstevel@tonic-gate (SBD_DEVICE_STATE(sbp, SBD_COMP_CPU, unit) == 1045*7c478bd9Sstevel@tonic-gate SBD_STATE_UNCONFIGURED)); 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate cp = SBD_GET_BOARD_CPUUNIT(sbp, unit); 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate cpuid = cp->sbc_cpu_id; 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CPU)][unit]; 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate rv = sbdp_disconnect_cpu(hdp, dip, cpuid); 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate if (rv != 0) { 1058*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate return (rv); 1063*7c478bd9Sstevel@tonic-gate } 1064