tzmon.c revision 044802ffd0b6258ef2221463b41121e8df53782f
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * CDDL HEADER START
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The contents of this file are subject to the terms of the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Common Development and Distribution License (the "License").
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * You may not use this file except in compliance with the License.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * or http://www.opensolaris.org/os/licensing.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * See the License for the specific language governing permissions
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * and limitations under the License.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * When distributing Covered Code, include this CDDL HEADER in each
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If applicable, add the following below this CDDL HEADER, with the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * fields enclosed by brackets "[]" replaced with your own identifying
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * information: Portions Copyright [yyyy] [name of copyright owner]
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * CDDL HEADER END
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
40c61268017ed628fcfb89162250c59130d14824Mike Christensen * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Use is subject to license terms.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Solaris x86 ACPI ThermalZone Monitor
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#pragma ident "%Z%%M% %I% %E% SMI"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/errno.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/conf.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/modctl.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/open.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/stat.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/ddi.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/sunddi.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/ksynch.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/uadmin.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/acpi/acpi.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/acpica.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/sdt.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include "tzmon.h"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define TZMON_ENUM_TRIP_POINTS 1
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define TZMON_ENUM_DEV_LISTS 2
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define TZMON_ENUM_ALL (TZMON_ENUM_TRIP_POINTS | TZMON_ENUM_DEV_LISTS)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * TZ_TASKQ_NAME_LEN is precisely the length of the string "AcpiThermalMonitor"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * plus a two-digit instance number plus a NULL. If the taskq name is changed
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * (particularly if it is lengthened), then this value needs to change.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define TZ_TASKQ_NAME_LEN 21
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Kelvin to Celsius conversion
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The formula for converting degrees Kelvin to degrees Celsius is
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * C = K - 273.15 (we round to 273.2). The unit for thermal zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * temperatures is tenths of a degree Kelvin. Use tenth of a degree
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * to convert, then make a whole number out of it.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define K_TO_C(temp) (((temp) - 2732) / 10)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* cb_ops or dev_ops forward declarations */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int tzmon_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen void *arg, void **result);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int tzmon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int tzmon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* other forward declarations */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_notify_zone(ACPI_HANDLE obj, UINT32 val, void *ctx);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_eval_int(ACPI_HANDLE obj, char *method, int *rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic thermal_zone_t *tzmon_alloc_zone();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_free_zone_list();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_discard_buffers(thermal_zone_t *tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_enumerate_zone(ACPI_HANDLE obj, thermal_zone_t *tzp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int enum_flag);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ACPI_STATUS tzmon_zone_callback(ACPI_HANDLE obj, UINT32 nest,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen void *ctx, void **rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_find_zones(void);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_monitor(void *ctx);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_set_power_device(ACPI_HANDLE dev, int on_off);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_set_power(ACPI_BUFFER devlist, int on_off);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void tzmon_eval_zone(thermal_zone_t *tzp);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensenstatic void tzmon_do_shutdown(void);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenextern void halt(char *);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic struct cb_ops tzmon_cb_ops = {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no open routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no close routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* not a block driver */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no print routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no dump routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no read routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no write routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no ioctl routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no devmap routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no mmap routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* no segmap routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nochpoll, /* no chpoll routine */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ddi_prop_op,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen 0, /* not a STREAMS driver */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen D_NEW | D_MP, /* safe for multi-thread/multi-processor */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen};
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic struct dev_ops tzmon_ops = {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DEVO_REV, /* devo_rev */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen 0, /* devo_refcnt */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_getinfo, /* devo_getinfo */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nulldev, /* devo_identify */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nulldev, /* devo_probe */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_attach, /* devo_attach */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_detach, /* devo_detach */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nodev, /* devo_reset */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen &tzmon_cb_ops, /* devo_cb_ops */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (struct bus_ops *)0, /* devo_bus_ops */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen NULL, /* devo_power */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen};
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenextern struct mod_ops mod_driverops;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic struct modldrv modldrv = {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen &mod_driverops,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "ACPI Thermal Zone Monitor %I%",
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen &tzmon_ops,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen};
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic struct modlinkage modlinkage = {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen MODREV_1, /* MODREV_1 indicated by manual */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void *)&modldrv,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen NULL, /* termination of list of linkage structures */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen};
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* globals for this module */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic dev_info_t *tzmon_dip;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic thermal_zone_t *zone_list;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int zone_count;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic kmutex_t zone_list_lock;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic kcondvar_t zone_list_condvar;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * _init, _info, and _fini support loading and unloading the driver.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen_init(void)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (mod_install(&modlinkage));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen_info(struct modinfo *modinfop)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (mod_info(&modlinkage, modinfop));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen_fini(void)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (mod_remove(&modlinkage));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (cmd != DDI_ATTACH)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_FAILURE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzmon_dip != NULL)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_FAILURE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Check to see if ACPI CA services are available
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (AcpiSubsystemStatus() != AE_OK)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_FAILURE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_init(&zone_list_lock, NULL, MUTEX_DRIVER, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cv_init(&zone_list_condvar, NULL, CV_DRIVER, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_find_zones();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (zone_count < 1) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_destroy(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cv_destroy(&zone_list_condvar);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_FAILURE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ddi_create_minor_node(dip, ddi_get_name(dip), S_IFCHR, 0,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DDI_PSEUDO, 0) == DDI_FAILURE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_free_zone_list();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_destroy(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cv_destroy(&zone_list_condvar);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_FAILURE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_dip = dip;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ddi_report_dev(dip);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_SUCCESS);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*ARGSUSED*/
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int error;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen switch (infocmd) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen case DDI_INFO_DEVT2DEVINFO:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *result = tzmon_dip;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzmon_dip == NULL)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen error = DDI_FAILURE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen else
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen error = DDI_SUCCESS;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen case DDI_INFO_DEVT2INSTANCE:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *result = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen error = DDI_SUCCESS;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen default:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *result = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen error = DDI_FAILURE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (error);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen thermal_zone_t *tzp = zone_list;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (cmd != DDI_DETACH)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_FAILURE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* free allocated thermal zone name(s) */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen while (tzp != NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen AcpiOsFree(tzp->zone_name);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp = tzp->next;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* discard zone list assets */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_free_zone_list();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ddi_remove_minor_node(dip, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_dip = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_destroy(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cv_destroy(&zone_list_condvar);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DDI_SUCCESS);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_notify_zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Thermal zone notification handler.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_notify_zone(ACPI_HANDLE obj, UINT32 val, void *ctx)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen thermal_zone_t *tzp = (thermal_zone_t *)ctx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen switch (val) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen case 0x80: /* Thermal Zone status changed */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_zone(tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen case 0x81: /* Thermal Zone trip points changed */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_enumerate_zone(obj, tzp, TZMON_ENUM_TRIP_POINTS);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen case 0x82: /* Device Lists changed */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_enumerate_zone(obj, tzp, TZMON_ENUM_DEV_LISTS);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen case 0x83: /* Thermal Relationship Table changed */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* not handling _TRT objects, so not handling this event */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_CONT, "?tzmon: thermal relationship table changed");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen default:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_eval_int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Evaluate the object/method as an integer.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_eval_int(ACPI_HANDLE obj, char *method, int *rv)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (acpica_eval_int(obj, method, rv) != AE_OK)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *rv = -1;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_alloc_zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Allocate memory for the zone structure and initialize it lock mutex.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic thermal_zone_t *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_alloc_zone()
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen thermal_zone_t *tzp;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp = kmem_zalloc(sizeof (thermal_zone_t), KM_SLEEP);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_init(&tzp->lock, NULL, MUTEX_DRIVER, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_free_zone_list
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Free the zone list, either because attach failed or detach initiated.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_free_zone_list()
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen thermal_zone_t *tzp = zone_list;
40c61268017ed628fcfb89162250c59130d14824Mike Christensen
40c61268017ed628fcfb89162250c59130d14824Mike Christensen while (tzp != NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen thermal_zone_t *next;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Remove the notify handler for the zone. Not much to
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * do if this fails (since we are on our way out), so
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * just ignore failure.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) AcpiRemoveNotifyHandler(tzp->obj, ACPI_DEVICE_NOTIFY,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_notify_zone);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Shut down monitor thread, if running */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->taskq != NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->polling_period = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cv_broadcast(&zone_list_condvar);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Drop mutex to allow the thread to run */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ddi_taskq_destroy(tzp->taskq);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_discard_buffers(tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&tzp->lock);
40c61268017ed628fcfb89162250c59130d14824Mike Christensen mutex_destroy(&tzp->lock);
40c61268017ed628fcfb89162250c59130d14824Mike Christensen
40c61268017ed628fcfb89162250c59130d14824Mike Christensen next = tzp->next;
40c61268017ed628fcfb89162250c59130d14824Mike Christensen kmem_free(tzp, sizeof (thermal_zone_t));
40c61268017ed628fcfb89162250c59130d14824Mike Christensen tzp = next;
40c61268017ed628fcfb89162250c59130d14824Mike Christensen }
40c61268017ed628fcfb89162250c59130d14824Mike Christensen}
40c61268017ed628fcfb89162250c59130d14824Mike Christensen
40c61268017ed628fcfb89162250c59130d14824Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_discard_buffers(thermal_zone_t *tzp)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen int level;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen for (level = 0; level < TZ_NUM_LEVELS; level++) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen if (tzp->al[level].Pointer != NULL)
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen AcpiOsFree(tzp->al[level].Pointer);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen }
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen if (tzp->psl.Pointer != NULL)
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen AcpiOsFree(tzp->psl.Pointer);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen}
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_enumerate_zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Enumerates the contents of a thermal zone and updates passed-in
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * thermal_zone or creates a new one if tzp is NULL. Newly-created
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * zones are linked into the global zone_list.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_enumerate_zone(ACPI_HANDLE obj, thermal_zone_t *tzp, int enum_flag)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_STATUS status;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_BUFFER zone_name;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int level;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int instance;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char abuf[5];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Newly-created zones and existing zones both require
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * some individual attention.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* New zone required */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp = tzmon_alloc_zone();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->next = zone_list;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen zone_list = tzp;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * It is exceedingly unlikely that instance will exceed 99.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * However, if it does, this will cause problems when
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * creating the taskq for this thermal zone.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen instance = zone_count;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen zone_count++;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&zone_list_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->obj = obj;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Set to a low level. Will get set to the actual
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * current power level when the thread monitor polls
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the current temperature.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->current_level = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Get the zone name in case we need to display it later */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen zone_name.Length = ACPI_ALLOCATE_BUFFER;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen zone_name.Pointer = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen status = AcpiGetName(obj, ACPI_FULL_PATHNAME, &zone_name);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(status == AE_OK);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->zone_name = zone_name.Pointer;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen status = AcpiInstallNotifyHandler(obj, ACPI_DEVICE_NOTIFY,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_notify_zone, (void *)tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(status == AE_OK);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Existing zone - toss out allocated items */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(tzp->obj == obj);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (enum_flag & TZMON_ENUM_DEV_LISTS)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_discard_buffers(tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (enum_flag & TZMON_ENUM_TRIP_POINTS) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (level = 0; level < TZ_NUM_LEVELS; level++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) snprintf(abuf, 5, "_AC%d", level);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, abuf, &tzp->ac[level]);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_CRT", &tzp->crt);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_HOT", &tzp->hot);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_PSV", &tzp->psv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (enum_flag & TZMON_ENUM_DEV_LISTS) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (level = 0; level < TZ_NUM_LEVELS; level++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->ac[level] == -1) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->al[level].Length = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->al[level].Pointer = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) snprintf(abuf, 5, "_AL%d", level);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->al[level].Length = ACPI_ALLOCATE_BUFFER;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->al[level].Pointer = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (AcpiEvaluateObject(obj, abuf, NULL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen &tzp->al[level]) != AE_OK) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "tzmon: error "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "evaluating _AL object");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->al[level].Length = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->al[level].Pointer = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->psl.Length = ACPI_ALLOCATE_BUFFER;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->psl.Pointer = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) AcpiEvaluateObject(obj, "_PSL", NULL, &tzp->psl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_TC1", &tzp->tc1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_TC2", &tzp->tc2);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_TSP", &tzp->tsp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(obj, "_TZP", &tzp->tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->tzp == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->polling_period = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->tzp < 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->polling_period = TZ_DEFAULT_PERIOD;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen else
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->polling_period = tzp->tzp/10;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* start monitor thread if needed */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->taskq == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char taskq_name[TZ_TASKQ_NAME_LEN];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) snprintf(taskq_name, TZ_TASKQ_NAME_LEN,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "AcpiThermalMonitor%02d", instance);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->taskq = ddi_taskq_create(tzmon_dip,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen taskq_name, 1, TASKQ_DEFAULTPRI, 0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->taskq == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->polling_period = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "tzmon: could not create"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " monitor thread - monitor by notify only");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ddi_taskq_dispatch(tzp->taskq,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_monitor, tzp, DDI_SLEEP);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_zone_callback
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Enumerate the thermal zone if it has a _TMP (current thermal zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * operating temperature) method.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*ARGSUSED*/
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ACPI_STATUS
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_zone_callback(ACPI_HANDLE obj, UINT32 nest, void *ctx, void **rv)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_HANDLE tmpobj;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * We get both ThermalZone() and Scope(\_TZ) objects here;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * look for _TMP (without which a zone is invalid) to pick
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * between them (and ignore invalid zones)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (AcpiGetHandle(obj, "_TMP", &tmpobj) == AE_OK) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_enumerate_zone(obj, NULL, TZMON_ENUM_ALL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (AE_OK);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_find_zones
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Find all of the thermal zones by calling a ACPICA function that
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * walks the ACPI namespace and invokes a callback for each thermal
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * object found.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_find_zones()
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_STATUS status;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int retval;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen status = AcpiWalkNamespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen 8, tzmon_zone_callback, NULL, (void **)&retval);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(status == AE_OK);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_monitor
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Run as a separate thread, this wakes according to polling period and
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * checks particular objects in the thermal zone. One instance per
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * thermal zone.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_monitor(void *ctx)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen thermal_zone_t *tzp = (thermal_zone_t *)ctx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen clock_t ticks;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen do {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Check out the zone */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_zone(tzp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Go back to sleep */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ticks = drv_usectohz(tzp->polling_period * 1000000);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ticks > 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) cv_timedwait(&zone_list_condvar, &tzp->lock,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ddi_get_lbolt() + ticks);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } while (ticks > 0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_set_power_device
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_set_power_device(ACPI_HANDLE dev, int on_off)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_BUFFER rb;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_OBJECT *pr0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_STATUS status;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rb.Length = ACPI_ALLOCATE_BUFFER;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rb.Pointer = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen status = AcpiEvaluateObject(dev, "_PR0", NULL, &rb);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (status != AE_OK) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "tzmon: can not set power");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen pr0 = ((ACPI_OBJECT *)rb.Pointer);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (pr0->Type != ACPI_TYPE_PACKAGE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "tzmon: can not set power");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen AcpiOsFree(rb.Pointer);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 0; i < pr0->Package.Count; i++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen status = AcpiEvaluateObject(
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen pr0->Package.Elements[i].Reference.Handle,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen on_off ? "_ON" : "_OFF", NULL, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (status != AE_OK) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "tz_set_pwr_dev: failed to set %d\n",
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen i);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen AcpiOsFree(rb.Pointer);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_set_power
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Turn on or turn off all devices in the supplied list.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_set_power(ACPI_BUFFER devlist, int on_off)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ACPI_OBJECT *devs;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen devs = ((ACPI_OBJECT *)devlist.Pointer);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (devs->Type != ACPI_TYPE_PACKAGE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "tzmon: can not set power");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 0; i < devs->Package.Count; i++)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_set_power_device(
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen devs->Package.Elements[i].Reference.Handle, on_off);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_eval_zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Evaluate the current conditions within the thermal zone.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_eval_zone(thermal_zone_t *tzp)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int tmp, new_level, level;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* get the current temperature from ACPI */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_eval_int(tzp->obj, "_TMP", &tmp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DTRACE_PROBE1(tzmon_tz_temp, int, tmp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* _HOT handling */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->hot > 0 && tmp >= tzp->hot) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "tzmon: Thermal zone (%s) is too hot (%d C); "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "initiating shutdown\n",
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (char *)tzp->zone_name, K_TO_C(tmp));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_do_shutdown();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* _CRT handling */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->crt > 0 && tmp >= tzp->crt) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "tzmon: Thermal zone (%s) is critically hot (%d C); "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "initiating rapid shutdown\n",
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (char *)tzp->zone_name, K_TO_C(tmp));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* shut down (fairly) immediately */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mdboot(A_REBOOT, AD_HALT, NULL, B_FALSE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * use the temperature to determine whether the thermal zone
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * is at a new active cooling threshold level
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (level = 0, new_level = -1; level < TZ_NUM_LEVELS; level++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->ac[level] >= 0 && (tmp >= tzp->ac[level])) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen new_level = level;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * if the active cooling threshold has changed, turn off the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * devices associated with the old one and turn on the new one
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (tzp->current_level != new_level) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((tzp->current_level >= 0) &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (tzp->al[tzp->current_level].Length != 0))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_set_power(tzp->al[tzp->current_level], 0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((new_level >= 0) &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (tzp->al[new_level].Length != 0))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzmon_set_power(tzp->al[new_level], 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tzp->current_level = new_level;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&tzp->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * tzmon_do_shutdown
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Initiates shutdown by sending a SIGPWR signal to init.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentzmon_do_shutdown(void)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen proc_t *initpp;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&pidlock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen initpp = prfind(P_INITPID);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&pidlock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* if we can't find init, just halt */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (initpp == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mdboot(A_REBOOT, AD_HALT, NULL, B_FALSE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* graceful shutdown with inittab and all getting involved */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen psignal(initpp, SIGPWR);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen