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 (c) 2010, Intel Corporation.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * All rights reserved.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/types.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/atomic.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/cmn_err.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/cpuvar.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/memlist.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/memlist_impl.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/note.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/obpdefs.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/synch.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sysmacros.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sunddi.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sunndi.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/x86_archext.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/machsystm.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/memnode.h> /* for lgrp_plat_node_cnt */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/psm_types.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpi/acpi.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpica.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpidev.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpidev_rsc.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpidev_dr.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpidev_impl.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct acpidev_dr_set_prop_arg {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t level;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t bdnum;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t cpu_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t mem_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t io_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t mod_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu};
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct acpidev_dr_device_remove_arg {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t level;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu};
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuextern int acpidev_options;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* User configurable option to enable/disable ACPI based DR operations. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint acpidev_dr_enable = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint acpidev_dr_hierarchy_name = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t acpidev_dr_max_segs_per_mem_device = ACPIDEV_DR_SEGS_PER_MEM_DEV;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t acpidev_dr_max_memlists_per_seg = ACPIDEV_DR_MEMLISTS_PER_SEG;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_TABLE_SRAT *acpidev_srat_tbl_ptr;
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_TABLE_SLIT *acpidev_slit_tbl_ptr;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* ACPI based DR operations are unsupported if zero. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int acpidev_dr_supported = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* Failed to initialize support of DR operations if non-zero. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int acpidev_dr_failed;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic volatile uint32_t acpidev_dr_boards;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic volatile uint32_t acpidev_dr_board_index;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic uint32_t acpidev_dr_max_cmp_per_board;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic uint32_t acpidev_dr_max_memory_per_board;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic uint32_t acpidev_dr_max_io_per_board;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic uint32_t acpidev_dr_memory_device_cnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_HANDLE *acpidev_dr_board_handles[ACPIDEV_DR_MAX_BOARDS];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* Lock to protect/block DR operations at runtime. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic kmutex_t acpidev_dr_lock;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic acpidev_dr_capacity_t acpidev_dr_capacities[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { /* Nehalem-EX */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu X86_VENDOR_Intel, 0x6, 0x2e, 0x2e, 0, UINT_MAX,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu B_TRUE, /* Hotplug capable */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu 1ULL << 30, /* Align on 1GB boundary */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { /* the last item is used to mark end of the table */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu UINT_MAX, UINT_MAX, UINT_MAX, 0, UINT_MAX, 0,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu B_FALSE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu 0,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu};
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS acpidev_dr_scan_topo(ACPI_HANDLE hdl, UINT32 lvl, void *arg,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic acpidev_dr_capacity_t *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_capacity(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_capacity_t *cp, *cp1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint_t vendor, family, model, step;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static acpidev_dr_capacity_t *acpidev_dr_capacity_curr = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_capacity_curr != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_capacity_curr);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kpreempt_disable();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu vendor = cpuid_getvendor(CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu family = cpuid_getfamily(CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu model = cpuid_getmodel(CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu step = cpuid_getstep(CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kpreempt_enable();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (cp = acpidev_dr_capacities; ; cp++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp < acpidev_dr_capacities +
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sizeof (acpidev_dr_capacities) / sizeof (*cp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether it reaches the last item of the table. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp->cpu_vendor == UINT_MAX && cp->cpu_family == UINT_MAX &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->cpu_model_min == UINT_MAX && cp->cpu_model_max == 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp->cpu_step_min == UINT_MAX && cp->cpu_step_max == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp->cpu_vendor == vendor && cp->cpu_family == family &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu model >= cp->cpu_model_min && model <= cp->cpu_model_max &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu step >= cp->cpu_step_min && step <= cp->cpu_step_max) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Assume all CPUs in system are homogeneous. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp1 = atomic_cas_ptr(&acpidev_dr_capacity_curr, NULL, cp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp1 == NULL || cp1 == cp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp1 != NULL && cp1 != cp) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (cp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_capable(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t flags1, flags2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_capacity_t *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Disable support of DR operations if:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 1) acpidev fails to initialize DR interfaces.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 2) ACPI based DR has been disabled by user.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 3) No DR capable devices have been detected.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 4) The system doesn't support DR operations.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 5) Some acpidev features have been disabled by user.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_failed != 0 || acpidev_dr_enable == 0 ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_supported == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags1 = ACPI_FEATURE_DEVCFG | ACPI_FEATURE_OSI_MODULE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags2 = ACPI_DEVCFG_CPU | ACPI_DEVCFG_MEMORY |
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_DEVCFG_CONTAINER | ACPI_DEVCFG_PCI;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpica_get_core_feature(flags1) != flags1 ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpica_get_devcfg_feature(flags2) != flags2) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "?acpidev: disable support of ACPI based DR because "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "some acpidev features have been disabled by user.\n");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_supported = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = acpidev_dr_get_capacity();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp == NULL || cp->hotplug_supported == B_FALSE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_boards(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_boards);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_io_units_per_board(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_max_io_per_board);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_mem_units_per_board(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_max_memory_per_board);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_cmp_units_per_board(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_max_cmp_per_board);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_cpu_units_per_cmp(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static int max_cnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (max_cnt == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kpreempt_disable();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu max_cnt = cpuid_get_ncpu_per_chip(CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kpreempt_enable();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (max_cnt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_segments_per_mem_device(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_max_segs_per_mem_device < 1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ACPIDEV_DR_SEGS_PER_MEM_DEV);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_max_segs_per_mem_device);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuint32_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_max_memlists_per_segment(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_max_memlists_per_seg < ACPIDEV_DR_MEMLISTS_PER_SEG) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ACPIDEV_DR_MEMLISTS_PER_SEG);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_max_memlists_per_seg);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_init(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_init(&acpidev_dr_lock, NULL, MUTEX_DRIVER, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_check_board_type(acpidev_data_handle_t dhdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct acpidev_dr_set_prop_arg *ap, char *objname)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_class_id == ACPIDEV_CLASS_ID_MEMORY) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Memory board should have only one memory device. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->cpu_id == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->mem_id == 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->io_id == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->mod_id == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdtype = ACPIDEV_MEMORY_BOARD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (dhdl->aod_class_id == ACPIDEV_CLASS_ID_PCI ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_class_id == ACPIDEV_CLASS_ID_PCIEX) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* IO board should have only one IO device. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->cpu_id == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->mem_id == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->io_id == 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap->mod_id == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdtype = ACPIDEV_IO_BOARD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (dhdl->aod_class_id == ACPIDEV_CLASS_ID_CONTAINER) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ap->mod_id == 1 && ap->mem_id == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdtype = ACPIDEV_CPU_BOARD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdtype = ACPIDEV_SYSTEM_BOARD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: unknown type of hotplug capable board %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Check for hotplug capable boards and create environment to support
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * ACPI based DR operations. No need to acquire lock here, it's called
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * from single-threaded context during boot.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_check(acpidev_walk_info_t *infop)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint_t cmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu boolean_t found = B_FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE phdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl, pdhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct acpidev_dr_set_prop_arg arg;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (infop == NULL ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop->awi_op_type != ACPIDEV_OP_BOOT_PROBE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: invalid parameter to acpidev_dr_check().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_capable() == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = infop->awi_data;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dhdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* This device has already been handled before. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPIDEV_DR_IS_PROCESSED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It implies that the device is hotplug capable if ACPI _EJ0 method
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * is available.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_IS_BOARD(dhdl) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_device_hotplug_capable(infop->awi_hdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_BOARD(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* All things are done if the device isn't hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_IS_BOARD(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether hardware topology is supported or not. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_dr_scan_topo(infop->awi_hdl, 0, NULL,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu NULL))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: hardware topology under %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "is unsupported for DR operations.", infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Generate board/index/port number for the hotplug capable board. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdnum = atomic_inc_32_nv(&acpidev_dr_boards) - 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_portid = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu phdl = infop->awi_hdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (ACPI_SUCCESS(AcpiGetParent(phdl, &phdl)) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu phdl != ACPI_ROOT_OBJECT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdhdl = acpidev_data_get_handle(phdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (pdhdl != NULL && ACPIDEV_DR_IS_BOARD(pdhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdidx = atomic_inc_32_nv(&pdhdl->aod_chidx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu found = B_TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (found == B_FALSE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdidx = atomic_inc_32_nv(&acpidev_dr_board_index);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdidx -= 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Found too many hotplug capable boards. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_bdnum >= ACPIDEV_DR_MAX_BOARDS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: too many hotplug capable boards, "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "max %d, found %d.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_MAX_BOARDS, dhdl->aod_bdnum + 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Scan all descendant devices to prepare info for DR operations. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bzero(&arg, sizeof (arg));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.bdnum = dhdl->aod_bdnum;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.level = infop->awi_level;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_dr_scan_topo(infop->awi_hdl, 0, &arg,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu NULL))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: failed to set DR properties "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "for descendants of %s.", infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Get type of the hotplug capable board. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_check_board_type(dhdl, &arg, infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Save ACPI handle of the hotplug capable board to speed up lookup
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * board handle if caching is enabled.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((acpidev_options & ACPIDEV_OUSER_NO_CACHE) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_board_handles[dhdl->aod_bdnum] = infop->awi_hdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Update system maximum DR capabilities. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmp = (arg.cpu_id + acpidev_dr_max_cpu_units_per_cmp() - 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmp /= acpidev_dr_max_cpu_units_per_cmp();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmp > acpidev_dr_max_cmp_per_board) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_max_cmp_per_board = cmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (arg.mem_id > acpidev_dr_max_memory_per_board) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_max_memory_per_board = arg.mem_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (arg.io_id > acpidev_dr_max_io_per_board) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_max_io_per_board = arg.io_id;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_initialize_memory_hotplug(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu caddr_t buf;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t cnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_capacity_t *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * We have already checked that the platform supports DR operations.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = acpidev_dr_get_capacity();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp != NULL && cp->hotplug_supported);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ISP2(cp->memory_alignment));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp->memory_alignment > MMU_PAGESIZE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mem_node_physalign = cp->memory_alignment;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Pre-populate memlist cache. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cnt = acpidev_dr_memory_device_cnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cnt *= acpidev_dr_max_segments_per_mem_device();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cnt *= acpidev_dr_max_memlists_per_segment();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cnt > ACPIDEV_DR_MAX_MEMLIST_ENTRIES) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: attempted to reserve too many "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "memlist entries (%u), max %u. Falling back to %u and "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "some memory hot add operations may fail.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cnt, ACPIDEV_DR_MAX_MEMLIST_ENTRIES,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_MAX_MEMLIST_ENTRIES);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cnt = ACPIDEV_DR_MAX_MEMLIST_ENTRIES;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cnt *= sizeof (struct memlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu buf = kmem_zalloc(cnt, KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu memlist_free_block(buf, cnt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Create pseudo DR control device node if the system is hotplug capable.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * No need to acquire lock, it's called from single-threaded context
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * during boot. pdip has been held by the caller.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_create_node(dev_info_t *pdip)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char unit[32];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *path;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *comps[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidr_sbd",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Disable support of DR operations if no hotplug capable board has
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * been detected.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_boards == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_supported = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_supported = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Don't create control device node if the system isn't hotplug capable.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_capable() == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Cache pointer to the ACPI SLIT table. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetTable(ACPI_SIG_SLIT, 1,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (ACPI_TABLE_HEADER **)&acpidev_slit_tbl_ptr))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_slit_tbl_ptr = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_srat_tbl_ptr == NULL || acpidev_slit_tbl_ptr == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lgrp_plat_node_cnt != 1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Disable support of CPU/memory DR operations if lgrp
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * is enabled but failed to cache SRAT/SLIT table
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * pointers.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get ACPI SRAT/SLIT table.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu plat_dr_disable_cpu();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu plat_dr_disable_memory();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_alloc_sleep(pdip, ACPIDEV_NODE_NAME_ACPIDR,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (pnode_t)DEVI_PSEUDO_NODEID, &dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Set "unit-address" device property. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) snprintf(unit, sizeof (unit), "%u", 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ndi_prop_update_string(DDI_DEV_T_NONE, dip,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_PROP_NAME_UNIT_ADDR, unit) != NDI_SUCCESS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "?acpidev: failed to set unit-address property for %s.\n",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ddi_pathname(dip, path));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(path, MAXPATHLEN);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) ddi_remove_child(dip, 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_failed = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Set "compatible" device property. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, OBP_COMPATIBLE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu comps, sizeof (comps) / sizeof (comps[0])) != NDI_SUCCESS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT, "?acpidev: failed to set compatible "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "property for %s.\n", ddi_pathname(dip, path));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(path, MAXPATHLEN);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) ddi_remove_child(dip, 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_failed = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) ndi_devi_bind_driver(dip, 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_initialize(dev_info_t *pdip)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_create_node(pdip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Initialize support of memory DR operations. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (plat_dr_support_memory()) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_initialize_memory_hotplug();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Mark the DR subsystem is ready for use. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu plat_dr_enable();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_find_board(ACPI_HANDLE hdl, uint_t lvl, void *ctx, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(lvl));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* No data handle available, not ready for DR operations. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_CTRL_DEPTH);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_BOARD(dhdl) && ACPIDEV_DR_IS_WORKING(dhdl) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdnum == (intptr_t)ctx) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(retval != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *(ACPI_HANDLE *)retval = hdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_CTRL_TERMINATE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_board_handle(uint_t board, ACPI_HANDLE *hdlp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE hdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdlp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdlp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_board_handle().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (board >= acpidev_dr_boards) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: board number %d is out of range, max %d.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu board, acpidev_dr_boards);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_FOUND);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Use cached handles if caching is enabled. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((acpidev_options & ACPIDEV_OUSER_NO_CACHE) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_board_handles[board] != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hdl = acpidev_dr_board_handles[board];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_dr_find_board(hdl, 1,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void *)(intptr_t)board, (void **)hdlp)) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *hdlp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: board %d doesn't exist.", board);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *hdlp = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_FOUND);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* All hotplug capable boards should exist under \_SB_. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_OBJECT_NAME_SB, &hdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get handle of %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_OBJECT_NAME_SB);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *hdlp = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiWalkNamespace(ACPI_TYPE_DEVICE, hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_MAX_ENUM_LEVELS - 1, acpidev_dr_find_board, NULL,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void *)(intptr_t)board, (void **)hdlp))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to find ACPI handle "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "for board %d.", board);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_NOT_FOUND;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (*hdlp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: board %d doesn't exist.", board);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_NOT_FOUND;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_board_type_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_board_type(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_board_type_t type = ACPIDEV_INVALID_BOARD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_board_type().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (type);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data associated with %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu type = dhdl->aod_bdtype;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (type);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_board_number(ACPI_HANDLE hdl, uint32_t *bnump)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || bnump == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_board_number().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data associated with %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *bnump = dhdl->aod_bdnum;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_board_name(ACPI_HANDLE hdl, char *buf, size_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *fmt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int count = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu size_t rlen = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE thdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdls[ACPIDEV_MAX_ENUM_LEVELS];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || buf == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_board_name().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Find ancestors of the device which are hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (thdl = hdl; thdl != NULL; ) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(thdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get data "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "associated with %p.", thdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_IS_BOARD(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* The board itself should be hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (count == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %p is "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "not hotplug capable.", thdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %p is "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "in the FAILED state.", thdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (count >= ACPIDEV_MAX_ENUM_LEVELS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: recursive level for hotplug "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "capable board is too deep.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdls[count] = dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu count++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_hierarchy_name == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu thdl = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPI_FAILURE(AcpiGetParent(thdl, &thdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu thdl = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Generate hierarchy board name for the board. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(count > 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (count--; count >= 0 && rlen < len; count--) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = dhdls[count];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (dhdl->aod_bdtype) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CPU_BOARD:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fmt = ACPIDEV_DR_CPU_BD_FMT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_MEMORY_BOARD:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fmt = ACPIDEV_DR_MEMORY_BD_FMT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_IO_BOARD:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fmt = ACPIDEV_DR_IO_BD_FMT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_SYSTEM_BOARD:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fmt = ACPIDEV_DR_SYSTEM_BD_FMT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_INVALID_BOARD:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid board type.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: unknown board type %u.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdtype);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Add "." before component name except first item. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rlen != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen += snprintf(buf + rlen, len - rlen, ".");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rlen < len) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen += snprintf(buf + rlen, len - rlen, fmt,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdidx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the buffer is sufficient. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rlen >= len) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: buffer length to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_board_name() is too small.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NO_MEMORY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_attachment_point(ACPI_HANDLE hdl, char *buf, size_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu size_t rlen;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || buf == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_attachment_point().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen = snprintf(buf, len, "/devices/%s/%s@%u:",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_NODE_NAME_ROOT, ACPIDEV_NODE_NAME_ACPIDR, 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rlen >= len) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: buffer to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_attachment_point() is too small.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NO_MEMORY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (acpidev_dr_get_board_name(hdl, buf + rlen, len - rlen));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Existence of ACPI _EJ0 method implies that the device is hotplug capable.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_hotplug_capable(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE ej0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetHandle(hdl, ACPIDEV_METHOD_NAME_EJ0, &ej0))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_has_edl(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE edl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetHandle(hdl, ACPIDEV_METHOD_NAME_EDL, &edl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_is_present(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int status;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu status = acpidev_query_device_status(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_check_device_present(status)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_is_powered(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int status;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Check device status returned by ACPI _STA method.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It implies that the device is powered if status is both PRESENT
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * and ENABLED.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu status = acpidev_query_device_status(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_check_device_enabled(status)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_mem_alignment(ACPI_HANDLE hdl, uint64_t *ap)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_capacity_t *cp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ap != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ap == NULL || hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_mem_alignment().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cp = acpidev_dr_get_capacity();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp == NULL || cp->hotplug_supported == B_FALSE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get memory alignment.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *ap = cp->memory_alignment;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Get the device property for the given name and store it into buf.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Returns the amount of data copied to buf if len is large enough to
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * hold all of the data. If len is not large enough, then the required
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * len would be returned and buf would not be modified. On any errors,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * -1 is returned and buf is not modified.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_get_regspec(ACPI_HANDLE hdl, boolean_t assigned,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_regspec_t **regpp, uint_t *cntp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int *valp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint_t count;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *propname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(regpp != NULL && cntp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || regpp == NULL || cntp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameters to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_get_regspec().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Set default return value. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *regpp = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *cntp = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data associated with %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if ((dip = acpidev_data_get_devinfo(dhdl)) == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get dip associated with %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_FOUND);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu propname = assigned ? "assigned-addresses" : "reg";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu propname, &valp, &count) != DDI_PROP_SUCCESS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to lookup device property %s.", propname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_FOUND);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (count % (sizeof (**regpp) / sizeof (int)) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: device property %s is invalid.", propname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ddi_prop_free(valp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *regpp = (acpidev_regspec_t *)valp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *cntp = count / (sizeof (**regpp) / sizeof (int));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_free_regspec(acpidev_regspec_t *regp, uint_t count)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(count));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (regp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ddi_prop_free(regp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Return values
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * . negative values on error
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * . size of data copied to buffer if it's bigger enough
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * . size of buffer needed if buffer is too small
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_getprop(ACPI_HANDLE hdl, char *name, caddr_t buf, size_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int rlen = -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (!ACPIDEV_DR_IS_WORKING(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strcmp(name, ACPIDEV_DR_PROP_PORTID) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len >= sizeof (uint32_t)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *(uint32_t *)(void *)buf = dhdl->aod_portid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen = sizeof (uint32_t);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strcmp(name, ACPIDEV_DR_PROP_BOARDNUM) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len >= sizeof (uint32_t)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *(uint32_t *)(void *)buf = dhdl->aod_bdnum;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen = sizeof (uint32_t);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strcmp(name, ACPIDEV_DR_PROP_DEVNAME) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (dhdl->aod_class_id) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_CPU:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len >= sizeof (ACPIDEV_NODE_NAME_CPU)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) strlcpy((char *)buf,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_NODE_NAME_CPU, len);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen = sizeof (ACPIDEV_NODE_NAME_CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_MEMORY:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len >= sizeof (ACPIDEV_NODE_NAME_MEMORY)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) strlcpy((char *)buf,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_NODE_NAME_MEMORY, len);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen = sizeof (ACPIDEV_NODE_NAME_MEMORY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_PCI:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_PCIEX:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len >= sizeof (ACPIDEV_NODE_NAME_PCI)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) strlcpy((char *)buf,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_NODE_NAME_PCI, len);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlen = sizeof (ACPIDEV_NODE_NAME_PCI);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rlen);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Figure out device class of the device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It only supports device classes which may be involved in DR operations.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_class_id_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_get_class(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT_TYPE type;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_DEVICE_INFO *infop;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_class_id_t id = ACPIDEV_CLASS_ID_INVALID;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static char *acpidev_id_cpu[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_HID_CPU,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static char *acpidev_id_mem[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_HID_MEMORY,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static char *acpidev_id_mod[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_HID_MODULE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static char *acpidev_id_pci[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_HID_PCI_HOSTBRIDGE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static char *acpidev_id_pciex[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_HID_PCIEX_HOSTBRIDGE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Figure out device type by checking ACPI object type. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetType(hdl, &type))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ACPIDEV_CLASS_ID_INVALID);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (type == ACPI_TYPE_PROCESSOR) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ACPIDEV_CLASS_ID_CPU);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (type != ACPI_TYPE_DEVICE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ACPIDEV_CLASS_ID_INVALID);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetObjectInfo(hdl, &infop))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ACPIDEV_CLASS_ID_INVALID);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Figure out device type by checking _HID and _CID. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_match_device_id(infop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_ARRAY_PARAM(acpidev_id_cpu))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu id = ACPIDEV_CLASS_ID_CPU;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (acpidev_match_device_id(infop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_ARRAY_PARAM(acpidev_id_mem))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu id = ACPIDEV_CLASS_ID_MEMORY;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (acpidev_match_device_id(infop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_ARRAY_PARAM(acpidev_id_mod))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu id = ACPIDEV_CLASS_ID_CONTAINER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (acpidev_match_device_id(infop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_ARRAY_PARAM(acpidev_id_pciex))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu id = ACPIDEV_CLASS_ID_PCIEX;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (acpidev_match_device_id(infop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_ARRAY_PARAM(acpidev_id_pci))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu id = ACPIDEV_CLASS_ID_PCI;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(infop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_get_memory_index(ACPI_HANDLE hdl, uint32_t *idxp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(idxp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle for %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (dhdl->aod_class_id != ACPIDEV_CLASS_ID_MEMORY) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %p is not a memory device.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *idxp = dhdl->aod_memidx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_is_board(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_is_board().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (!ACPIDEV_DR_IS_BOARD(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_walk_edl(ACPI_HANDLE hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_WALK_CALLBACK cb, void *arg, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT *obj;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_BUFFER buf;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *method = ACPIDEV_METHOD_NAME_EDL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cb != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || cb == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_edl().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu buf.Length = ACPI_ALLOCATE_BUFFER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiEvaluateObjectTyped(hdl, method, NULL, &buf,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_TYPE_PACKAGE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_NOT_FOUND) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to evaluate method %s under %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu method, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Validate the package structure. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu obj = buf.Pointer;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < obj->Package.Count; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (obj->Package.Elements[i].Type !=
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_TYPE_LOCAL_REFERENCE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: element %d in package "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "returned by %s of %s is not local reference.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i, method, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(buf.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (obj->Package.Elements[i].Reference.ActualType !=
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_TYPE_DEVICE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: element %d in package "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "returned by %s of %s doesn't refer to device.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i, method, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(buf.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < obj->Package.Count; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (obj->Package.Elements[i].Reference.Handle == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: handle of element %d in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "package returned by %s of %s is NULL.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i, method, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = (*cb)(obj->Package.Elements[i].Reference.Handle,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu UINT32_MAX, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_CTRL_DEPTH || rc == AE_CTRL_TERMINATE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(buf.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_walk_ejd(ACPI_HANDLE hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_WALK_CALLBACK cb, void *arg, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT *obj;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_BUFFER buf;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE chdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *method = ACPIDEV_METHOD_NAME_EJD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cb != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || cb == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_ejd().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu buf.Length = ACPI_ALLOCATE_BUFFER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiEvaluateObjectTyped(hdl, method, NULL, &buf,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_TYPE_STRING);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_NOT_FOUND) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to evaluate method %s under %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu method, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu obj = buf.Pointer;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(obj->String.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetHandle(NULL, obj->String.Pointer, &chdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: failed to get handle for %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu obj->String.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_ERROR;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = (*cb)(chdl, UINT32_MAX, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_CTRL_DEPTH || rc == AE_CTRL_TERMINATE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(buf.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Walk all child devices and special devices in the eject device list.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_walk_child(ACPI_HANDLE hdl, boolean_t init, uint_t max_lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_WALK_CALLBACK cb, void *arg, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cb != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || cb == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_child().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Walk the eject device list first when destroying.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * According to ACPI spec, devices in _EDL list must be handled first
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * when the ejecting device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (init == B_FALSE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_edl(hdl, cb, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to walk eject device list in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_child().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Walk all child ACPI DEVICE objects. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiWalkNamespace(ACPI_TYPE_DEVICE, hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu max_lvl, cb, NULL, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to walk DEVICE objects in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_child().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Walk all child ACPI PROCESSOR objects. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiWalkNamespace(ACPI_TYPE_PROCESSOR, hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu max_lvl, cb, NULL, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to walk PROCESSOR objects in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_child().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Walk the eject device list last when initializing.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (init == B_TRUE && ACPI_SUCCESS(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_edl(hdl, cb, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to walk eject device list in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_walk_child().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_walk_device(ACPI_HANDLE hdl, uint_t max_lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_WALK_CALLBACK cb, void *arg, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cb != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || cb == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_walk_device().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Walk the top object itself first. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = (*cb)(hdl, 0, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_CTRL_DEPTH || rc == AE_CTRL_TERMINATE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to handle top node %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "in acpidev_dr_walk_device().", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_child(hdl, B_TRUE, max_lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cb, arg, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to handle descendant nodes of %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "in acpidev_dr_walk_device().", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_no_support(ACPI_HANDLE hdl, UINT32 lvl, void *arg, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(arg, retval));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: device %s at level 0x%x is unsupported.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname, lvl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_set_prop(ACPI_HANDLE hdl, char *objname,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct acpidev_dr_set_prop_arg *ap, uint32_t lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_class_id_t clsid, uint_t *devid)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Create data handle first if it doesn't exist yet. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t rlvl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE phdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Compute level by walking ACPI namespace if it's a device
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * from the eject device list.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lvl == UINT32_MAX) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * AcpiGetParent() fails when it tries to get
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * the parent of the ACPI namespace root node.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (rlvl = 0, phdl = hdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_SUCCESS(AcpiGetParent(phdl, &phdl));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlvl++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (phdl == ACPI_ROOT_OBJECT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rlvl == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get level of %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rlvl = ap->level;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rlvl >= ACPIDEV_MAX_ENUM_LEVELS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: recursive level of %s is too deep.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_create_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_hdl = hdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_level = rlvl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to create data handle "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "for device %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NO_MEMORY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPIDEV_DR_IS_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The same device may be enumerated twice at most. Once as
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * child devices, another time from the eject device list.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_bdnum == ap->bdnum) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * A device has been enumerated more than once from
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * different paths. It's dangerous to support such
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * a topology. Disable support of DR operations.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: device %s has been "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "enumerated more than once for DR.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_failed = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Set properties for DR operations. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_class_id = clsid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_bdnum = ap->bdnum;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_portid = atomic_inc_32_nv(devid) - 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (clsid == ACPIDEV_CLASS_ID_MEMORY) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_memidx = acpidev_dr_memory_device_cnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dhdl->aod_memidx < ACPI_MEMNODE_DEVID_BOOT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_READY(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Verify whether the hardware topology is supported by the DR driver.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The ACPI specification is so flexible that for safety reasons, only
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * a few well defined topologies are supported.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Possible values of parameter lvl:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 0: the device is the board itself.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * UINT32_MAX: the device is from the _EDL list of the board.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * other: the device is a descendant of the board.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Return values:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * AE_OK: the topology is supported
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * AE_SUPPORT: the topology is unsupported
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * AE_ERROR: other errors
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_scan_topo(ACPI_HANDLE hdl, UINT32 lvl, void *arg, void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(retval));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_class_id_t cid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct acpidev_dr_set_prop_arg *ap = arg;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(lvl == 0 || lvl == 1 || lvl == UINT32_MAX);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Validate descendants of the hotplug capable board.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * lvl is zero if it's the hotplug capable board itself, otherwise
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * non-zero for descendants.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lvl != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Skip subtree if the device is hotplug capable.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It will be treated as another hotplug capable board.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_device_hotplug_capable(hdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_CTRL_DEPTH);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Don't support the _EDL list of a non-hotplug-capable device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_dr_device_has_edl(hdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: non-hotplug-capable "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "object %s has _EDL method.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cid = acpidev_dr_device_get_class(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (cid) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_CPU:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Don't support logical CPUs in the _EDL list. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lvl == UINT32_MAX) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: logical CPU %s in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "_EDL is unsupported.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_SUPPORT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Don't support logical CPUs with children. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ap->level++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_child(hdl, B_TRUE, 1,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_no_support, arg, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ap->level--;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_SUPPORT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: logical CPU %s has "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "child or dependent devices.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to scan "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "children of logical CPU %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_ERROR;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ap != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_set_prop(hdl, objname, ap, lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_CLASS_ID_CPU, &ap->cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_MEMORY:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Don't support memory devices with children. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ap->level++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_child(hdl, B_TRUE, 1,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_no_support, arg, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ap->level--;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == AE_SUPPORT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: memory device %s has child or "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "dependent devices.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to scan children of "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "memory device %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_ERROR;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ap != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_memory_device_cnt++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_set_prop(hdl, objname, ap, lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_CLASS_ID_MEMORY, &ap->mem_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_PCI:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_PCIEX:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Don't scan child/descendant devices of PCI/PCIex devices. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ap != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_set_prop(hdl, objname, ap, lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cid, &ap->io_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_CONTAINER:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Don't support module devices in the _EDL list. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lvl == UINT32_MAX) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: module device %s in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "_EDL is unsupported.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_SUPPORT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Don't support recurrence of module devices. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lvl > 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: recursion level of "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "module device %s is too deep.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_SUPPORT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ap->level++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_child(hdl, B_TRUE, 1,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_scan_topo, arg, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ap->level--;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(rc) && ap != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_set_prop(hdl, objname, ap, lvl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_CLASS_ID_CONTAINER, &ap->mod_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_INVALID:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*FALLTHROUGH*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: device %s is unsupported.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AE_SUPPORT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* Create walk information structures. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_create_walk_info(ACPI_HANDLE hdl, acpidev_data_handle_t dhdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname, acpidev_walk_info_t **infopp, acpidev_walk_info_t **cinfopp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE phdl = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *pdip = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t pdhdl, tdhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_walk_info_t *infop = NULL, *cinfop = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dhdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dhdl->aod_class_list != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(objname != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(infopp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cinfopp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetParent(hdl, &phdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get parent object of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdhdl = acpidev_data_get_handle(phdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (pdhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get data "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "associated with parent of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (pdhdl->aod_level >= ACPIDEV_MAX_ENUM_LEVELS - 1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: recursion level (%d) of %s is too deep.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdhdl->aod_level, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(pdhdl->aod_class_list != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (pdhdl->aod_class_list == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: class list for parent of %s is NULL.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Allocate a walk info structure for its parent. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop = acpidev_alloc_walk_info(ACPIDEV_OP_HOTPLUG_PROBE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdhdl->aod_level, phdl, dhdl->aod_class_list, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (infop == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to allocate walk info "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "structure for parent of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Get the parent dip if it's not ready yet. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (infop->awi_dip == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetParent(phdl, &phdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get parent of object %p.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu phdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tdhdl = acpidev_data_get_handle(phdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (tdhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get data "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "associated with object %p.", phdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdip = acpidev_data_get_devinfo(tdhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (pdip != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop->awi_dip = pdip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Give up if reaches the ACPI namespace root node. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (phdl == ACPI_ROOT_OBJECT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (infop->awi_dip == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get parent dip of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_walk_info(infop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Allocate a walk info for the child. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cinfop = acpidev_alloc_walk_info(ACPIDEV_OP_HOTPLUG_PROBE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop->awi_level + 1, hdl, NULL, infop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cinfop == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to allocate walk info "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "structure for %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_walk_info(infop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *infopp = infop;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *cinfopp = cinfop;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_probe_object(ACPI_HANDLE hdl, acpidev_data_handle_t dhdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int circ;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *pdip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS res;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT_TYPE type;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_class_list_t *it;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_walk_info_t *infop, *cinfop;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dhdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: hdl or dhdl is NULL in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_probe_object().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the device is of interest. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetType(hdl, &type)) ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu type > ACPI_TYPE_NS_NODE_MAX ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu BT_TEST(acpidev_object_type_mask, type) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: ACPI object %s is unsupported.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_class_list == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: class list is NULL in data associated with %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdip = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cinfop = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_create_walk_info(hdl, dhdl, objname, &infop, &cinfop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to create walk info structures for %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(infop != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(infop->awi_dip != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(infop->awi_class_list != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cinfop != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cinfop->awi_data == dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Lock the parent dip before touching children. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pdip = infop->awi_dip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_enter(pdip, &circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rw_enter(&acpidev_class_lock, RW_READER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Call pre-probe callback functions to prepare for probing. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (it = *(infop->awi_class_list); it != NULL; it = it->acl_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (it->acl_class->adc_pre_probe == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop->awi_class_curr = it->acl_class;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(it->acl_class->adc_pre_probe(infop))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: failed to pre-probe "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "device of type %s under %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu it->acl_class->adc_class_name, infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Call registered probe callback functions to probe devices. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (it = *(infop->awi_class_list); it != NULL; it = it->acl_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (it->acl_class->adc_probe == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cinfop->awi_class_curr = it->acl_class;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu res = it->acl_class->adc_probe(cinfop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(res)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = res;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to process object %s under %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname, infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Call post-probe callback functions to clean up. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (it = *(infop->awi_class_list); it != NULL; it = it->acl_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (it->acl_class->adc_post_probe == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu infop->awi_class_curr = it->acl_class;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(it->acl_class->adc_post_probe(infop))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: failed to post-probe "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "device of type %s under %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu it->acl_class->adc_class_name, infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rw_exit(&acpidev_class_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_exit(pdip, circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_walk_info(cinfop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_walk_info(infop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Some PCI/PCIex buses embedded in physical processors may be presented in
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * the eject device list instead of being presented as child devices.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * This function figures out such devices and create device nodes for them.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_probe_dependent(ACPI_HANDLE hdl, UINT32 lvl, void *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(retval));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int status;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE phdl, thdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(lvl == UINT32_MAX);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ctx != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu phdl = ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data associated with %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It should be treated as another board if device is hotplug capable.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPIDEV_DR_IS_BOARD(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (!ACPIDEV_DR_IS_WORKING(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: %s is unusable for DR operations.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Skip hdl if it's a descendant of phdl because it should have
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * already been handled when handling phdl itself.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (thdl = hdl; ACPI_SUCCESS(AcpiGetParent(thdl, &thdl)); ) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Return when reaches the phdl. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (thdl == phdl) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Break out when reaches the ACPI namespace root node. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (thdl == ACPI_ROOT_OBJECT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * No support of enumerating PCI/PCIex Host Bridge devices yet.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It will be enabled when PCI/PCIex Host Bridge hotplug is ready.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_class_id == ACPIDEV_CLASS_ID_PCI ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_class_id == ACPIDEV_CLASS_ID_PCIEX) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: PCI/PCIEX host bridge %s is "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "unsupported, skip it.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the device exists and has been enabled. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu status = acpidev_query_device_status(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!acpidev_check_device_enabled(status)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: object %s is disabled/absent "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "when trying to connect it.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Probe the device and its children. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_probe_object(hdl, dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to probe object %s in eject device list.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_insert(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int status, circ;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(acpidev_root_node() != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: parameter hdl to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_insert_insert() is NULL.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle associated with %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Validate that the object is hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_BOARD_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %s is not hotplug capable.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %s is in the FAILED "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "state, unusable for DR.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the device exists and has been enabled. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu status = acpidev_query_device_status(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!acpidev_check_device_enabled(status)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %s is disabled/absent "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "when trying to connect it.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_EXIST);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check that there's no device node created for object yet. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dip = acpidev_data_get_devinfo(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dip != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: device node for object %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "already exists when trying to connect it.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ALREADY_EXISTS);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Solaris has a limitation that all device nodes for PCI/PCIex host
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * bridges must exist directly under /devices.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Special care is needed here to deal with hot-adding PCI/PCIex host
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * bridges to avoid dead lock caused by ndi_devi_enter().
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Here the lock on ddi_root_node() is held first, which will break
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * the dead lock loop.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_enter(ddi_root_node(), &circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_probe_object(hdl, dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_edl(hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_dr_probe_dependent, hdl, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to create device "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "nodes for children of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: disable DR support for object %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "due to failure when creating device nodes for it.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_exit(ddi_root_node(), circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_remove_cb(ACPI_HANDLE hdl, UINT32 lvl, void *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **retval)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(lvl));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int status;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct acpidev_dr_device_remove_arg *argp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL && ctx != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL || ctx == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: parameter to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_remove_cb() is NULL.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu argp = (struct acpidev_dr_device_remove_arg *)ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle associated with %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Validate that the object is hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* It's the hotplug capable board itself if level is zero. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (argp->level == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_BOARD_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %s is not hotplug capable.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %s is unusable for DR.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* It's a device under the hotplug capable board. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Skip it if device itself is hotplug capable.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It will be treated as another hotplug capable board.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPIDEV_DR_IS_BOARD(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_IS_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %s is not hotplug capable.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %s is unusable for DR.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Skip the device if it hasn't been enabled at all. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu status = acpidev_data_get_status(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!acpidev_check_device_enabled(status)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dip = acpidev_data_get_devinfo(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dip == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get dev_info associated with %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* For safety, only handle supported device types when unconfiguring. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (dhdl->aod_class_id) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_CONTAINER:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*FALLTHROUGH*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_CPU:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*FALLTHROUGH*/
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case ACPIDEV_CLASS_ID_MEMORY:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %s (type %d) doesn't "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "support unconfiguration.", objname, dhdl->aod_class_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Destroy descendants first. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu argp->level++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_walk_child(hdl, B_FALSE, 1,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_device_remove_cb, ctx, retval);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu argp->level--;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to destroy descendants of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Untag dip and ACPI object before destroying the dip. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((dhdl->aod_iflag & ACPIDEV_ODF_DEVINFO_TAGGED) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_FAILURE(acpica_untag_devinfo(dip, hdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to untag object %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Mark the node as unusable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Destroy the node itself. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (e_ddi_branch_destroy(dip, NULL, 0) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((dhdl->aod_iflag & ACPIDEV_ODF_DEVINFO_TAGGED) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_FAILURE(acpica_tag_devinfo(dip, hdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to retag object %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Mark the node as unusable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) ddi_pathname(dip, path);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev: failed to remove node %s (%s).", path, objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(path, MAXPATHLEN);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Update status and information associated with the device. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_dip = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_iflag &= ~ACPIDEV_ODF_DEVINFO_CREATED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_iflag &= ~ACPIDEV_ODF_DEVINFO_TAGGED;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_class != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl->aod_class->adc_fini != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (*(dhdl->aod_class->adc_fini))(hdl, dhdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_class);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu atomic_dec_32(&(dhdl->aod_class->adc_refcnt));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_class = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_iflag &= ~ACPIDEV_ODF_STATUS_VALID;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl->aod_status = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_remove(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int circ;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *objname;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct acpidev_dr_device_remove_arg arg;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(acpidev_root_node() != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: parameter hdl to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_device_remove() is NULL.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname = acpidev_get_object_name(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle associated with %s.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Validate that the device is hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_BOARD_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %s is not hotplug capable.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %s is in the FAILED "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "state, unusable for DR.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Recursively destroy descendants under the top node.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * No need to undo what has been done if error happens, it will be
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * handled by DR driver.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Lock ddi_root_node() to avoid deadlock.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_enter(ddi_root_node(), &circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.level = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_device_remove_cb(hdl, 0, &arg, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(arg.level == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to destroy device "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "nodes for children of %s.", objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_WARN, "!acpidev: disable DR support for object %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "due to failure when destroying device nodes for it.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DR_SET_FAILED(dhdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ndi_devi_exit(ddi_root_node(), circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_free_object_name(objname);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_poweron(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle associated with %p.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the device is hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_BOARD_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %p is not hotplug capable.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %p is in the FAILED "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "state, unusable for DR.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_poweroff(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle associated with %p.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the device is hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_BOARD_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %p is not hotplug capable.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %p is in the FAILED "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "state, unusable for DR.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_eval_ej0(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to evaluate _EJ0 for object %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_device_check_status(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data handle associated with %p.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the device is hotplug capable. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_BOARD_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: object %p is not hotplug capable.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %p is in the FAILED "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "state, unusable for DR.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_lock_all(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&acpidev_dr_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_unlock_all(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&acpidev_dr_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_allocate_cpuid(ACPI_HANDLE hdl, processorid_t *idp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int rv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu processorid_t cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t procid, apicid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mach_cpu_add_arg_t arg;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t dhdl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(MUTEX_HELD(&cpu_lock));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: parameter hdl to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_allocate_cpuid() is NULL.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Validate that the device is ready for hotplug. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpica_get_devinfo(hdl, &dip))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get devinfo for object %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(dip != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dhdl = acpidev_data_get_handle(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (dhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get data associated with object %p",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ACPIDEV_DR_IS_READY(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: dip %p is not hotplug ready.", (void *)dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPIDEV_DR_IS_FAILED(dhdl)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: dip %p is in the FAILED state.", (void *)dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Query CPU relative information */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu apicid = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DDI_PROP_DONTPASS, ACPIDEV_PROP_NAME_LOCALAPIC_ID, UINT32_MAX);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu procid = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DDI_PROP_DONTPASS, ACPIDEV_PROP_NAME_PROCESSOR_ID, UINT32_MAX);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (procid == UINT32_MAX || apicid == UINT32_MAX || apicid == 255) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: dip %p is malformed, "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "procid(0x%x) or apicid(0x%x) is invalid.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void *)dip, procid, apicid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the CPU device is in offline state. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&(DEVI(dip)->devi_lock));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!DEVI_IS_DEVICE_OFFLINE(dip)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&DEVI(dip)->devi_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: dip %p isn't in offline state.", (void *)dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&DEVI(dip)->devi_lock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether the CPU already exists. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(acpica_get_cpu_id_by_object(hdl, &cpuid))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: dip %p already has CPU id(%d) assigned.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void *)dip, cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ALREADY_EXISTS);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Allocate cpuid for the CPU */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.arg.apic.apic_id = apicid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.arg.apic.proc_id = procid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (apicid >= 255) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.type = MACH_CPU_ARG_LOCAL_X2APIC;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arg.type = MACH_CPU_ARG_LOCAL_APIC;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = mach_cpu_add(&arg, &cpuid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rv != PSM_SUCCESS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to allocate cpu id for dip %p.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void *)dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_EXIST);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cpuid >= 0 && cpuid < NCPU && cpuid < max_ncpus);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (idp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *idp = cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_free_cpuid(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rv = AE_OK;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu processorid_t cpuid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(MUTEX_HELD(&cpu_lock));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: parameter hdl to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_free_cpuid() is NULL.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpica_get_cpu_id_by_object(hdl, &cpuid))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get cpuid for object %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = AE_NOT_EXIST;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (cpuid < 0 || cpuid > max_ncpus) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: cpuid(%d) of object %p is invalid.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cpuid, hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = AE_ERROR;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (mach_cpu_remove(cpuid) != PSM_SUCCESS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to free cpuid(%d) for object %p.",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cpuid, hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rv = AE_ERROR;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_latency(ACPI_HANDLE hdl, void **hdlpp,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t pxmid, uint32_t *slicntp, uchar_t **slipp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_BUFFER buf;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t i, pxmcnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uchar_t *valp, *sp, *ep;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Evaluate the ACPI _SLI method under the object. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu buf.Length = ACPI_ALLOCATE_BUFFER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiEvaluateObjectTyped(hdl, ACPIDEV_METHOD_NAME_SLI, NULL, &buf,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_TYPE_BUFFER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu valp = (uchar_t *)buf.Pointer;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (acpidev_slit_tbl_ptr->LocalityCount > pxmid) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pxmcnt = acpidev_slit_tbl_ptr->LocalityCount;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pxmcnt = pxmid + 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Validate data returned by the ACPI _SLI method.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Please refer to 6.2.14 "_SLI (System Locality Information)"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * in ACPI4.0 for data format returned by _SLI method.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (buf.Length != pxmcnt * 2 * sizeof (uchar_t)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: buffer length returned by _SLI method "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "under %p is invalid.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(buf.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (valp[pxmid] != ACPI_SLIT_SELF_LATENCY ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu valp[pxmid + pxmcnt] != ACPI_SLIT_SELF_LATENCY) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: local latency returned by _SLI method "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "under %p is not %u.", hdl, ACPI_SLIT_SELF_LATENCY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(buf.Pointer);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *slicntp = pxmcnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *slipp = (uchar_t *)buf.Pointer;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *hdlpp = buf.Pointer;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (rc != AE_NOT_FOUND) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to evaluate "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "_SLI method under object %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Return data from the ACPI SLIT table. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(acpidev_slit_tbl_ptr != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pxmcnt = acpidev_slit_tbl_ptr->LocalityCount;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (pxmid >= pxmcnt) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: proximity domain id "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "(%u) is too big, max %u.", pxmid, pxmcnt - 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *slicntp = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *slipp = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sp = AcpiOsAllocate(pxmcnt * 2 * sizeof (uchar_t));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ep = acpidev_slit_tbl_ptr->Entry;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < pxmcnt; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sp[i] = ep[pxmcnt * pxmid + i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sp[i + pxmcnt] = ep[pxmcnt * i + pxmid];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *slicntp = pxmcnt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *slipp = sp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *hdlpp = sp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Query NUMA information for the CPU device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It returns APIC id, Proximity id and latency information of the CPU device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_cpu_numa_info(cpu_t *cp, void **hdlpp, uint32_t *apicidp,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint32_t *pxmidp, uint32_t *slicntp, uchar_t **slipp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dev_info_t *dip = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_HANDLE hdl = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(cp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdlpp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(apicidp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(pxmidp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cp == NULL || hdlpp == NULL || apicidp == NULL || pxmidp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameters to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_cpu_numa_info().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *hdlpp = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *apicidp = UINT32_MAX;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *pxmidp = UINT32_MAX;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lgrp_plat_node_cnt == 1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(acpidev_slit_tbl_ptr != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Query APIC id and Proximity id from device properties. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpica_get_cpu_object_by_cpuid(cp->cpu_id, &hdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get ACPI object "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "for CPU(%d).", cp->cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpica_get_devinfo(hdl, &dip))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get device node "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "for CPU(%d).", cp->cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *apicidp = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_PROP_NAME_LOCALAPIC_ID, UINT32_MAX);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *pxmidp = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_PROP_NAME_PROXIMITY_ID, UINT32_MAX);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*apicidp == UINT32_MAX || *pxmidp == UINT32_MAX) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get local APIC id "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "or proximity id for CPU(%d).", cp->cpu_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT((slicntp && slipp) || (!slicntp && !slipp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (slicntp != NULL && slipp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_dr_get_latency(hdl, hdlpp, *pxmidp,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu slicntp, slipp))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_free_cpu_numa_info(void *hdlp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdlp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(hdlp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic ACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_mem_search_srat(struct memlist *ml, uint32_t *pxmidp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int len, off;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t start, end;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu boolean_t found = B_FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_SUBTABLE_HEADER *sp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_SRAT_MEM_AFFINITY *mp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ml != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(pxmidp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(acpidev_srat_tbl_ptr != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Search the static ACPI SRAT table for proximity domain. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sp = (ACPI_SUBTABLE_HEADER *)(acpidev_srat_tbl_ptr + 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu len = acpidev_srat_tbl_ptr->Header.Length;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu off = sizeof (*acpidev_srat_tbl_ptr);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (off < len) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (sp->Type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mp = (ACPI_SRAT_MEM_AFFINITY *)sp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((mp->Flags & ACPI_SRAT_MEM_ENABLED) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address >= mp->BaseAddress &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address <= mp->BaseAddress + mp->Length) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu found = B_TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu off += sp->Length;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sp = (ACPI_SUBTABLE_HEADER *)(((char *)sp) + sp->Length);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!found)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_FOUND);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Verify that all memory regions in the list belong to the same domain.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu start = mp->BaseAddress;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu end = mp->BaseAddress + mp->Length;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (ml) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ml->ml_address < start ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address + ml->ml_size > end) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: memory for hot-adding doesn't belong "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "to the same proximity domain.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml = ml->ml_next;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Query lgrp information for a memory device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It returns proximity domain id and latency information of the memory device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_get_mem_numa_info(ACPI_HANDLE hdl, struct memlist *ml,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **hdlpp, uint32_t *pxmidp, uint32_t *slicntp, uchar_t **slipp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(ml != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdlpp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(pxmidp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ml == NULL || hdlpp == NULL || pxmidp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameters to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_dr_get_mem_numa_info().");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_BAD_PARAMETER);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *pxmidp = UINT32_MAX;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (lgrp_plat_node_cnt == 1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_SUPPORT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_eval_pxm(hdl, pxmidp))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Try to get proximity domain id from SRAT table if failed to
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * evaluate ACPI _PXM method for memory device.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_dr_mem_search_srat(ml, pxmidp))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to get proximity domain id for "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "memory device %p.", hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT((slicntp && slipp) || (!slicntp && !slipp));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (slicntp != NULL && slipp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_dr_get_latency(hdl, hdlpp, *pxmidp,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu slicntp, slipp))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_ERROR);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_dr_free_mem_numa_info(void *hdlp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (hdlp != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu AcpiOsFree(hdlp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}