a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CDDL HEADER START
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The contents of this file are subject to the terms of the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Common Development and Distribution License (the "License").
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * You may not use this file except in compliance with the License.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * or http://www.opensolaris.org/os/licensing.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * See the License for the specific language governing permissions
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * and limitations under the License.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * When distributing Covered Code, include this CDDL HEADER in each
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * If applicable, add the following below this CDDL HEADER, with the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * fields enclosed by brackets "[]" replaced with your own identifying
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * information: Portions Copyright [yyyy] [name of copyright owner]
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CDDL HEADER END
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Use is subject to license terms.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright (c) 2010, Intel Corporation.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * All rights reserved.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CPU support routines for DR
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/note.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/debug.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/types.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/errno.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/dditypes.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/ddi.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sunddi.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sunndi.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/ndi_impldefs.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/kmem.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/processor.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/cpuvar.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/promif.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sysmacros.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/archsystm.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/machsystm.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/cpu_module.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/cmn_err.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/dr.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/dr_util.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* for the DR*INTERNAL_ERROR macros. see sys/dr.h. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic char *dr_ie_fmt = "dr_cpu.c %d";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_cpu_unit_is_sane(dr_board_t *bp, dr_cpu_unit_t *cp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#ifdef DEBUG
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp->sbc_cm.sbdev_bp == bp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp->sbc_cm.sbdev_type == SBD_COMP_CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(bp))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(cp))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#endif
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_errno2ecode(int error)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int rv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (error) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case EBUSY:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = ESBD_BUSY;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case EINVAL:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = ESBD_INVAL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case EALREADY:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = ESBD_ALREADY;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ENODEV:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = ESBD_NODEV;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ENOMEM:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = ESBD_NOMEM;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = ESBD_INVAL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * On x86, the "clock-frequency" and cache size device properties may be
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * unavailable before CPU starts. If they are unavailabe, just set them to zero.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_cpu_set_prop(dr_cpu_unit_t *cp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t clock_freq;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ecache_size = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *cache_str = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_get_dip(cp->sbc_cm.sbdev_id, &dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbc_cm.sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dip == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DR_DEV_INTERNAL_ERROR(&cp->sbc_cm);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* read in the CPU speed */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu clock_freq = (unsigned int)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DDI_PROP_DONTPASS, "clock-frequency", 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The ecache property string is not the same
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * for all CPU implementations.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (cp->sbc_cpu_impl) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case X86_CPU_IMPL_NEHALEM_EX:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cache_str = "l3-cache-size";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "Unknown cpu implementation=0x%x",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_impl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cache_str != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* read in the ecache size */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * If the property is not found in the CPU node,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * it has to be kept in the core or cmp node so
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * we just keep looking.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cache_str, 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* convert to the proper units */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_speed = (clock_freq + 500000) / 1000000;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_ecache = ecache_size / (1024 * 1024);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_init_cpu_unit(dr_cpu_unit_t *cp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_state_t new_state;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int impl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (DR_DEV_IS_ATTACHED(&cp->sbc_cm)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new_state = DR_STATE_CONFIGURED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cm.sbdev_cond = SBD_COND_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (DR_DEV_IS_PRESENT(&cp->sbc_cm)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new_state = DR_STATE_CONNECTED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cm.sbdev_cond = SBD_COND_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new_state = DR_STATE_EMPTY;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cm.sbdev_cond = SBD_COND_UNKNOWN;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (DR_DEV_IS_PRESENT(&cp->sbc_cm)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_cpu_get_id(cp->sbc_cm.sbdev_id, &cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbc_cm.sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new_state = DR_STATE_FATAL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto done;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_cpu_get_impl(cp->sbc_cm.sbdev_id, &impl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbc_cm.sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new_state = DR_STATE_FATAL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto done;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_id = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_impl = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto done;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_id = cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_impl = impl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* if true at init time, it must always be true */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(cp->sbc_cm.sbdev_bp, cp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((cpuid >= 0) && cpu[cpuid])
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_flags = cpu[cpuid]->cpu_flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->sbc_cpu_flags = P_OFFLINE | P_POWEROFF;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_set_prop(cp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudone:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* delay transition until fully initialized */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_device_transition(&cp->sbc_cm, new_state);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_pre_attach_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_pre_attach_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s...\n", f);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < devnum; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *up = (dr_cpu_unit_t *)devlist[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(hp->h_bd, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Print a console message for each attachment
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * point. For CMP devices, this means that only
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * one message should be printed, no matter how
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * many cores are actually present.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((up->sbc_cm.sbdev_unum % MAX_CORES_PER_CMP) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT, "OS configure %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up->sbc_cm.sbdev_path);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Block out status threads while creating
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * devinfo tree branches
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_lock_status(hp->h_bd);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_enter(ddi_root_node(), (int *)(&hp->h_ndi));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*ARGSUSED*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_attach_cpu(dr_handle_t *hp, dr_common_unit_t *cp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu processorid_t cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int rv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(MUTEX_HELD(&cpu_lock));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_configure(cp->sbdev_id, 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_cpu_get_id(cp->sbdev_id, &cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_unconfigure(cp->sbdev_id, DEVI_BRANCH_DESTROY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_clear(&err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if ((rv = cpu_configure(cpuid)) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, cp, dr_errno2ecode(rv));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_unconfigure(cp->sbdev_id, DEVI_BRANCH_DESTROY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_clear(&err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *up = (dr_cpu_unit_t *)cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up->sbc_cpu_id = cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * dr_post_attach_cpu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * sbd error policy: Does not stop on error. Processes all units in list.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_post_attach_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int errflag = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_post_attach_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s...\n", f);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Startup and online newly-attached CPUs */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < devnum; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *up = (dr_cpu_unit_t *)devlist[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct cpu *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(hp->h_bd, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = cpu_get(up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "%s: cpu_get failed for cpu %d",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_is_poweredoff(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_poweron(cp) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm, ESBD_CPUSTART);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu errflag = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: cpu %d powered ON\n", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_is_offline(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: onlining cpu %d...\n", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_online(cp) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm, ESBD_ONLINE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu errflag = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_exit(ddi_root_node(), hp->h_ndi);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_unlock_status(hp->h_bd);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (errflag)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * dr_pre_release_cpu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * sbd error policy: Stops on first error.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_pre_release_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int c, cix, i, lastoffline = -1, rv = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu processorid_t cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct cpu *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *up;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_devset_t devset;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_dev_stat_t *ds;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_pre_release_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int cpu_flags = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu devset = DR_DEVS_PRESENT(hp->h_bd);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* allocate status struct storage. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ds = (sbd_dev_stat_t *) kmem_zalloc(sizeof (sbd_dev_stat_t) *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu MAX_CPU_UNITS_PER_BOARD, KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cix = dr_cpu_status(hp, devset, ds);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < devnum; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up = (dr_cpu_unit_t *)devlist[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!DR_DEV_IS_ATTACHED(&up->sbc_cm)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(hp->h_bd, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * On x86 systems, some CPUs can't be unconfigured.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * For example, CPU0 can't be unconfigured because many other
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * components have a dependency on it.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * This check determines if a CPU is currently in use and
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * returns a "Device busy" error if so.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (c = 0; c < cix; c++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ds[c].d_cpu.cs_unit == up->sbc_cm.sbdev_unum) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ds[c].d_cpu.cs_busy) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ESBD_BUSY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (c < cix)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cpuid = up->sbc_cpu_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((cp = cpu_get(cpuid)) == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm, ESBD_OFFLINE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* used by dr_cancel_cpu during error flow */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up->sbc_cpu_flags = cp->cpu_flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (CPU_ACTIVE(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dr_cmd_flags(hp) & SBD_FLAG_FORCE)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cpu_flags = CPU_FORCED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: offlining cpu %d\n", f, cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_offline(cp, cpu_flags)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: failed to offline cpu %d\n", f,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm, ESBD_OFFLINE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (disp_bound_threads(cp, 0)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "%s: thread(s) bound "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "to cpu %d", f, cp->cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu lastoffline = i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!rv) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_release(up->sbc_cm.sbdev_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&up->sbc_cm.sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rv) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Need to unwind others since at this level (pre-release)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * the device state has not yet transitioned and failures
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * will prevent us from reaching the "post" release
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * function where states are normally transitioned.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = lastoffline; i >= 0; i--) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up = (dr_cpu_unit_t *)devlist[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) dr_cancel_cpu(up);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(ds, sizeof (sbd_dev_stat_t) * MAX_CPU_UNITS_PER_BOARD);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * dr_pre_detach_cpu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * sbd error policy: Stops on first error.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_pre_detach_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(hp))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int cpu_flags = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_pre_detach_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s...\n", f);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Block out status threads while destroying devinfo tree
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * branches
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_lock_status(hp->h_bd);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < devnum; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *up = (dr_cpu_unit_t *)devlist[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct cpu *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!DR_DEV_IS_ATTACHED(&up->sbc_cm)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(hp->h_bd, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = cpu_get(up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Print a console message for each attachment
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * point. For CMP devices, this means that only
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * one message should be printed, no matter how
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * many cores are actually present.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((up->sbc_cm.sbdev_unum % MAX_CORES_PER_CMP) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT, "OS unconfigure %s\n",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up->sbc_cm.sbdev_path);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CPUs were offlined during Release.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_is_poweredoff(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: cpu %d already powered OFF\n",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!cpu_is_offline(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dr_cmd_flags(hp) & SBD_FLAG_FORCE)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cpu_flags = CPU_FORCED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* cpu was onlined after release. Offline it again */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: offlining cpu %d\n", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_offline(cp, cpu_flags)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: failed to offline cpu %d\n",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm, ESBD_OFFLINE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (disp_bound_threads(cp, 0)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "%s: thread(s) bound "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "to cpu %d", f, cp->cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_poweroff(cp) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_WARN, &up->sbc_cm, ESBD_CPUSTOP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: cpu %d powered OFF\n", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuerr:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_unlock_status(hp->h_bd);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*ARGSUSED*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_detach_cpu(dr_handle_t *hp, dr_common_unit_t *cp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu processorid_t cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int rv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *up = (dr_cpu_unit_t *)cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(MUTEX_HELD(&cpu_lock));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!DR_DEV_IS_ATTACHED(&up->sbc_cm)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_cpu_get_id(cp->sbdev_id, &cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if ((rv = cpu_unconfigure(cpuid)) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_dev_err(CE_IGNORE, cp, dr_errno2ecode(rv));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_unconfigure(cp->sbdev_id, DEVI_BRANCH_DESTROY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up->sbc_cpu_id = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*ARGSUSED1*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_post_detach_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_post_detach_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s...\n", f);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hp->h_ndi = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_unlock_status(hp->h_bd);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_fill_cpu_stat(dr_cpu_unit_t *cp, drmach_status_t *pstat, sbd_cpu_stat_t *csp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp && pstat && csp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Fill in the common status information */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bzero((caddr_t)csp, sizeof (*csp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_type = cp->sbc_cm.sbdev_type;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_unit = cp->sbc_cm.sbdev_unum;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) strlcpy(csp->cs_name, pstat->type, sizeof (csp->cs_name));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_cond = cp->sbc_cm.sbdev_cond;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_busy = cp->sbc_cm.sbdev_busy | pstat->busy;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_time = cp->sbc_cm.sbdev_time;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_ostate = cp->sbc_cm.sbdev_ostate;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_suspend = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* CPU specific status data */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_cpuid = cp->sbc_cpu_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * If the speed and ecache properties have not been
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * cached yet, read them in from the device tree.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((cp->sbc_speed == 0) || (cp->sbc_ecache == 0))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_set_prop(cp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* use the cached speed and ecache values */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_speed = cp->sbc_speed;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_ecache = cp->sbc_ecache;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!cpu_get(csp->cs_cpuid)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* ostate must be UNCONFIGURED */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu csp->cs_cm.c_ostate = SBD_STAT_UNCONFIGURED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*ARGSUSED2*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_fill_cmp_stat(sbd_cpu_stat_t *csp, int ncores, int impl, sbd_cmp_stat_t *psp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int core;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(csp && psp && (ncores >= 1));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bzero((caddr_t)psp, sizeof (*psp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Fill in the common status information based
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * on the data for the first core.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_type = SBD_COMP_CMP;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_unit = DR_UNUM2SBD_UNUM(csp->cs_unit, SBD_COMP_CMP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) strlcpy(psp->ps_name, csp->cs_name, sizeof (psp->ps_name));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_cond = csp->cs_cond;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_busy = csp->cs_busy;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_time = csp->cs_time;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_ostate = csp->cs_ostate;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_suspend = csp->cs_suspend;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* CMP specific status data */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *psp->ps_cpuid = csp->cs_cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_ncores = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_speed = csp->cs_speed;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_ecache = csp->cs_ecache;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Walk through the data for the remaining cores.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Make any adjustments to the common status data,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * or the shared CMP specific data if necessary.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (core = 1; core < ncores; core++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The following properties should be the same
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * for all the cores of the CMP.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(psp->ps_unit == DR_UNUM2SBD_UNUM(csp[core].cs_unit,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu SBD_COMP_CMP));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (csp[core].cs_speed > psp->ps_speed)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_speed = csp[core].cs_speed;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (csp[core].cs_ecache > psp->ps_ecache)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_ecache = csp[core].cs_ecache;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_cpuid[core] = csp[core].cs_cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_ncores++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* adjust time if necessary */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (csp[core].cs_time > psp->ps_time) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_time = csp[core].cs_time;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_busy |= csp[core].cs_busy;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * If any of the cores are configured, the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * entire CMP is marked as configured.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (csp[core].cs_ostate == SBD_STAT_CONFIGURED) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp->ps_ostate = csp[core].cs_ostate;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_cpu_status(dr_handle_t *hp, dr_devset_t devset, sbd_dev_stat_t *dsp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int cmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int core;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ncpu;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_board_t *bp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_cpu_stat_t *cstat;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int impl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bp = hp->h_bd;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ncpu = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu devset &= DR_DEVS_PRESENT(bp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cstat = kmem_zalloc(sizeof (sbd_cpu_stat_t) * MAX_CORES_PER_CMP,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Treat every CPU as a CMP. In the case where the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * device is not a CMP, treat it as a CMP with only
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * one core.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (cmp = 0; cmp < MAX_CMP_UNITS_PER_BOARD; cmp++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ncores;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_cpu_unit_t *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu drmach_status_t pstat;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_cmp_stat_t *psp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((devset & DEVSET(SBD_COMP_CMP, cmp)) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ncores = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (core = 0; core < MAX_CORES_PER_CMP; core++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = dr_get_cpu_unit(bp, DR_CMP_CORE_UNUM(cmp, core));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp->sbc_cm.sbdev_state == DR_STATE_EMPTY) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* present, but not fully initialized */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(hp->h_bd, cp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* skip if not present */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp->sbc_cm.sbdev_id == (drmachid_t)0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* fetch platform status */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_status(cp->sbc_cm.sbdev_id, &pstat);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&cp->sbc_cm.sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_fill_cpu_stat(cp, &pstat, &cstat[ncores++]);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * We should set impl here because the last core
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * found might be EMPTY or not present.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu impl = cp->sbc_cpu_impl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ncores == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Store the data to the outgoing array. If the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * device is a CMP, combine all the data for the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * cores into a single stat structure.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The check for a CMP device uses the last core
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * found, assuming that all cores will have the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * same implementation.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (CPU_IMPL_IS_CMP(impl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu psp = (sbd_cmp_stat_t *)dsp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_fill_cmp_stat(cstat, ncores, impl, psp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ncores == 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bcopy(cstat, dsp, sizeof (sbd_cpu_stat_t));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dsp++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ncpu++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(cstat, sizeof (sbd_cpu_stat_t) * MAX_CORES_PER_CMP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ncpu);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Cancel previous release operation for cpu.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * For cpus this means simply bringing cpus that
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * were offline back online. Note that they had
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * to have been online at the time there were
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * released.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_cancel_cpu(dr_cpu_unit_t *up)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int rv = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_cancel_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(up->sbc_cm.sbdev_bp, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_flagged_active(up->sbc_cpu_flags)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct cpu *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CPU had been online, go ahead
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * bring it back online.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: bringing cpu %d back ONLINE\n", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = cpu[up->sbc_cpu_id];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_is_poweredoff(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_poweron(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "%s: failed to power-on "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "cpu %d", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rv == 0 && cpu_is_offline(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_online(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "%s: failed to online cpu %d",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rv == 0 && cpu_is_online(cp)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_flagged_nointr(up->sbc_cpu_flags)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cpu_intr_disable(cp) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "%s: failed to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "disable interrupts on cpu %d", f,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&cpu_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_disconnect_cpu(dr_cpu_unit_t *up)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static fn_t f = "dr_disconnect_cpu";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s...\n", f);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT((up->sbc_cm.sbdev_state == DR_STATE_CONNECTED) ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (up->sbc_cm.sbdev_state == DR_STATE_UNCONFIGURED));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dr_cpu_unit_is_sane(up->sbc_cm.sbdev_bp, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (up->sbc_cm.sbdev_state == DR_STATE_CONNECTED) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Cpus were never brought in and so are still
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * effectively disconnected, so nothing to do here.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PR_CPU("%s: cpu %d never brought in\n", f, up->sbc_cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = drmach_cpu_disconnect(up->sbc_cm.sbdev_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (err == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DRERR_SET_C(&up->sbc_cm.sbdev_error, &err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*NOTREACHED*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}