7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CDDL HEADER START
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The contents of this file are subject to the terms of the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Common Development and Distribution License (the "License").
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * You may not use this file except in compliance with the License.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * or http://www.opensolaris.org/os/licensing.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * See the License for the specific language governing permissions
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * and limitations under the License.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * When distributing Covered Code, include this CDDL HEADER in each
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If applicable, add the following below this CDDL HEADER, with the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * fields enclosed by brackets "[]" replaced with your own identifying
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * information: Portions Copyright [yyyy] [name of copyright owner]
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CDDL HEADER END
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/types.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sysmacros.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/ddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sunndi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/ddi_impldefs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/psm_types.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/smp_impldefs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/apic.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/processor.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/apix_irm_impl.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* global variable for static default limit for non-IRM drivers */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern int ddi_msix_alloc_limit;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Extern declarations */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_intr_op_t, int *);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Global variables for IRM pool configuration:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (1) apix_system_max_vectors -- this would limit the maximum
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * number of interrupt vectors that will be made avilable
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to the device drivers. The default value (-1) indicates
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * that all the available vectors could be used.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (2) apix_irm_cpu_factor -- This would specify the number of CPUs that
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * should be excluded from the global IRM pool of interrupt vectors.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * By default this would be zero, so vectors from all the CPUs
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * present will be factored into the IRM pool.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (3) apix_irm_reserve_fixed_vectors -- This would specify the number
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * of vectors that should be reserved for FIXED type interrupts and
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * exclude them from the IRM pool. The value can be one of the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * following:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 0 - no reservation (default)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * <n> - a positive number for the reserved cache
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * -1 - reserve the maximum needed
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (4) apix_irm_free_fixed_vectors -- This flag specifies if the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * vectors for FIXED type should be freed and added back
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to the IRM pool when ddi_intr_free() is called. The default
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is to add it back to the pool.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_system_max_vectors = -1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_cpu_factor = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_reserve_fixed_vectors = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_free_fixed_vector = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* info from APIX module for IRM configuration */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_info_t apix_irminfo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseskmutex_t apix_irm_lock; /* global mutex for apix_irm_* data */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesddi_irm_params_t apix_irm_params; /* IRM pool info */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_cache_size = 0; /* local cache for FIXED type requests */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_cpu_factor_available = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_max_cpus = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_cpus_used = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_fixed_intr_vectors_used;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern int ncpus;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* local data/functions */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int apix_irm_chk_apix();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_intr_op_t op, int *result);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_disable_intr(processorid_t);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid apix_irm_enable_intr(processorid_t);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint (*psm_intr_ops_saved)(dev_info_t *dip, ddi_intr_handle_impl_t *handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_intr_op_t op, int *result) = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint (*psm_disable_intr_saved)(processorid_t) = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid (*psm_enable_intr_saved)(processorid_t) = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_alloc_fixed(dev_info_t *, ddi_intr_handle_impl_t *, int *);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apix_irm_free_fixed(dev_info_t *, ddi_intr_handle_impl_t *, int *);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Initilaize IRM pool for APIC interrupts if the PSM module
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is of APIX type. This should be called only after PSM module
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is loaded and APIC interrupt system is initialized.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_init(void)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dev_info_t *dip;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int total_avail_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int cpus_used;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int cache_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* nothing to do if IRM is disabled */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!irm_enable)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Use root devinfo node to associate the IRM pool with it
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * as the pool is global to the system.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dip = ddi_root_node();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check if PSM module is initialized and it is APIX
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * module (which supports IRM functionality).
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((psm_intr_ops == NULL) || !apix_irm_chk_apix()) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* not an APIX module */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_CONT,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_init: APIX module not present"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Now, determine the IRM pool parameters based on the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * info from APIX module and global config variables.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apix_ncpus shows all the CPUs present in the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * system but not all of them may have been enabled
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (i.e. mp_startup() may not have been called yet).
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * So, use ncpus for IRM pool creation.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_irminfo.apix_ncpus > ncpus)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irminfo.apix_ncpus = ncpus;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* apply the CPU factor if possible */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apix_irm_cpu_factor > 0) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (apix_irminfo.apix_ncpus > apix_irm_cpu_factor)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpus_used = apix_irminfo.apix_ncpus - apix_irm_cpu_factor;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cpu_factor_available = apix_irm_cpu_factor;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpus_used = apix_irminfo.apix_ncpus;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cpus_used = apix_irm_max_cpus = cpus_used;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_CONT,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_init: %d CPUs used for IRM pool size", cpus_used));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases total_avail_vectors = cpus_used * apix_irminfo.apix_per_cpu_vectors -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irminfo.apix_vectors_allocated;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_fixed_intr_vectors_used = apix_irminfo.apix_vectors_allocated;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (total_avail_vectors <= 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* can not determine pool size */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_init: can not determine pool size"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* adjust the pool size as per the global config variable */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apix_system_max_vectors > 0) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (apix_system_max_vectors < total_avail_vectors))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases total_avail_vectors = apix_system_max_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* pre-reserve vectors (i.e. local cache) for FIXED type if needed */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_irm_reserve_fixed_vectors != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cache_size = apix_irm_reserve_fixed_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((cache_size == -1) ||
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (cache_size > apix_irminfo.apix_ioapic_max_vectors))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cache_size = apix_irminfo.apix_ioapic_max_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases total_avail_vectors -= cache_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cache_size = cache_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (total_avail_vectors <= 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_init: invalid config parameters!"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* IRM pool is used only for MSI/X interrupts */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_params.iparams_types = DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_params.iparams_total = total_avail_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ndi_irm_create(dip, &apix_irm_params,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases &apix_irm_pool_p) == NDI_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * re-direct psm_intr_ops to intercept FIXED
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupt allocation requests.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_intr_ops_saved = psm_intr_ops;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_intr_ops = apix_irm_intr_ops;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * re-direct psm_enable_intr()/psm_disable_intr() to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * intercept CPU offline/online requests.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_disable_intr_saved = psm_disable_intr;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_enable_intr_saved = psm_enable_intr;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_enable_intr = apix_irm_enable_intr;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_disable_intr = apix_irm_disable_intr;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_init(&apix_irm_lock, NULL, MUTEX_DRIVER, NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set default alloc limit for non-IRM drivers
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to DDI_MIN_MSIX_ALLOC (currently defined as 8).
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * NOTE: This is done here so that the limit of 8 vectors
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is applicable only with APIX module. For the old pcplusmp
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * implementation, the current default of 2 (i.e
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * DDI_DEFAULT_MSIX_ALLOC) is retained.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ddi_msix_alloc_limit < DDI_MIN_MSIX_ALLOC)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_msix_alloc_limit = DDI_MIN_MSIX_ALLOC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_init: ndi_irm_create() failed"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_pool_p = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check if the PSM module is "APIX" type which supports IRM feature.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Returns 0 if it is not an APIX module.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_chk_apix(void)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t info_hdl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_get_type_t type_info;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!psm_intr_ops)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases info_hdl.ih_private = &type_info;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases NULL)) != PSM_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* unknown type; assume not an APIX module */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (1);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * This function intercepts PSM_INTR_OP_* requests to deal with
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * IRM pool maintainance for FIXED type interrupts. The following
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * commands are intercepted and the rest are simply passed back to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the original psm_intr_ops function:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSM_INTR_OP_ALLOC_VECTORS
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSM_INTR_OP_FREE_VECTORS
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Return value is either PSM_SUCCESS or PSM_FAILURE.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_intr_op_t op, int *result)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch (op) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case PSM_INTR_OP_ALLOC_VECTORS:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (handle->ih_type == DDI_INTR_TYPE_FIXED)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apix_irm_alloc_fixed(dip, handle, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case PSM_INTR_OP_FREE_VECTORS:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (handle->ih_type == DDI_INTR_TYPE_FIXED)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apix_irm_free_fixed(dip, handle, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases default:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* pass the request to APIX */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((*psm_intr_ops_saved)(dip, handle, op, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Allocate a FIXED type interrupt. The procedure for this
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * operation is as follows:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 1) Check if this IRQ is shared (i.e. IRQ is already mapped
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * and a vector has been already allocated). If so, then no
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * new vector is needed and simply pass the request to APIX
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * and return.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 2) Check the local cache pool for an available vector. If
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the cache is not empty then take it from there and simply
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * pass the request to APIX and return.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 3) Otherwise, get a vector from the IRM pool by reducing the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * pool size by 1. If it is successful then pass the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * request to APIX module. Otherwise return PSM_FAILURE.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_alloc_fixed(dev_info_t *dip, ddi_intr_handle_impl_t *handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int *result)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ret;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check if this IRQ has been mapped (i.e. shared IRQ case)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * by doing PSM_INTR_OP_XLATE_VECTOR.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = (*psm_intr_ops_saved)(dip, handle, PSM_INTR_OP_XLATE_VECTOR,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases &vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ret == PSM_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_CONT,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_alloc_fixed: dip %p (%s) xlated vector 0x%x",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void *)dip, ddi_driver_name(dip), vector));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* (1) mapping already exists; pass the request to PSM */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((*psm_intr_ops_saved)(dip, handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_ALLOC_VECTORS, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* check the local cache for an available vector */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_enter(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_irm_cache_size) { /* cache is not empty */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases --apix_irm_cache_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_fixed_intr_vectors_used++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* (2) use the vector from the local cache */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((*psm_intr_ops_saved)(dip, handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_ALLOC_VECTORS, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* (3) get a vector from the IRM pool */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size = apix_irm_params.iparams_total - 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_CONT, "apix_irm_alloc_fixed: dip %p (%s) resize pool"
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases " from %x to %x\n", (void *)dip, ddi_driver_name(dip),
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_pool_p->ipool_totsz, new_pool_size));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ndi_irm_resize_pool(apix_irm_pool_p, new_pool_size) ==
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases NDI_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* update the pool size info */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_params.iparams_total = new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_fixed_intr_vectors_used++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((*psm_intr_ops_saved)(dip, handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_ALLOC_VECTORS, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Free up the FIXED type interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 1) If it is a shared vector then simply pass the request to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * APIX and return.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 2) Otherwise, if apix_irm_free_fixed_vector is not set then add the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * vector back to the IRM pool. Otherwise, keep it in the local cache.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_free_fixed(dev_info_t *dip, ddi_intr_handle_impl_t *handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int *result)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int shared;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ret;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* check if it is a shared vector */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = (*psm_intr_ops_saved)(dip, handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_GET_SHARED, &shared);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((ret == PSM_SUCCESS) && (shared > 0)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* (1) it is a shared vector; simply pass the request */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_CONT, "apix_irm_free_fixed: dip %p (%s) "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "shared %d\n", (void *)dip, ddi_driver_name(dip), shared));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((*psm_intr_ops_saved)(dip, handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_FREE_VECTORS, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = (*psm_intr_ops_saved)(dip, handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_FREE_VECTORS, result);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ret == PSM_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_enter(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_irm_free_fixed_vector) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* (2) add the vector back to IRM pool */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size = apix_irm_params.iparams_total + 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_CONT, "apix_irm_free_fixed: "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "dip %p (%s) resize pool from %x to %x\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void *)dip, ddi_driver_name(dip),
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_pool_p->ipool_totsz, new_pool_size));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ndi_irm_resize_pool(apix_irm_pool_p,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size) == NDI_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* update the pool size info */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_params.iparams_total = new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_free_fixed: failed to add"
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases " a vector to IRM pool");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* keep the vector in the local cache */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cache_size += 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_fixed_intr_vectors_used--;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ret);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Disable the CPU for interrupts. It is assumed that this is called to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * offline/disable the CPU so that no interrupts are allocated on
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * that CPU. For IRM perspective, the interrupt vectors on this
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CPU are to be excluded for any allocations.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If APIX module is successful in migrating all the vectors
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * from this CPU then reduce the IRM pool size to exclude the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupt vectors for that CPU.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_disable_intr(processorid_t id)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Interrupt disabling for Suspend/Resume */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpus[id].aci_status & APIC_CPU_SUSPEND)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((*psm_disable_intr_saved)(id));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_enter(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Don't remove the CPU from the IRM pool if we have CPU factor
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * available.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apix_irm_cpu_factor > 0) && (apix_irm_cpu_factor_available > 0)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cpu_factor_available--;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* can't disable if there is only one CPU used */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_irm_cpus_used == 1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Calculate the new size for the IRM pool */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size = apix_irm_params.iparams_total -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irminfo.apix_per_cpu_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Apply the max. limit */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_system_max_vectors > 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t max;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases max = apix_system_max_vectors -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_fixed_intr_vectors_used -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cache_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size = MIN(new_pool_size, max);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (new_pool_size == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN, "Invalid pool size 0 with "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_system_max_vectors = %d",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_system_max_vectors);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (new_pool_size != apix_irm_params.iparams_total) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* remove the CPU from the IRM pool */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ndi_irm_resize_pool(apix_irm_pool_p,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size) != NDI_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_disable_intr: failed to resize"
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases " the IRM pool"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* update the pool size info */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_params.iparams_total = new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* decrement the CPU count used by IRM pool */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cpus_used--;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Now, disable the CPU for interrupts.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((*psm_disable_intr_saved)(id) != PSM_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_IRM_DEBUG((CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "apix_irm_disable_intr: failed to disable CPU interrupts"
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases " for CPU#%d", id));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* decrement the CPU count enabled for interrupts */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_max_cpus--;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_SUCCESS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Enable the CPU for interrupts. It is assumed that this function is
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * called to enable/online the CPU so that interrupts could be assigned
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to it. If successful, add available vectors for that CPU to the IRM
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * pool if apix_irm_cpu_factor is already satisfied.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_irm_enable_intr(processorid_t id)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Interrupt enabling for Suspend/Resume */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpus[id].aci_status & APIC_CPU_SUSPEND) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (*psm_enable_intr_saved)(id);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_enter(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* enable the CPU for interrupts */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (*psm_enable_intr_saved)(id);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* increment the number of CPUs enabled for interrupts */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_max_cpus++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(apix_irminfo.apix_per_cpu_vectors > 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check if the apix_irm_cpu_factor is satisfied before.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If satisfied, add the CPU to IRM pool.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apix_irm_cpu_factor > 0) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (apix_irm_cpu_factor_available < apix_irm_cpu_factor)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Don't add the CPU to the IRM pool. Just update
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the available CPU factor.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cpu_factor_available++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Add the CPU to the IRM pool.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* increment the CPU count used by IRM */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cpus_used++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Calculate the new pool size */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size = apix_irm_params.iparams_total +
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irminfo.apix_per_cpu_vectors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Apply the max. limit */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_system_max_vectors > 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t max;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases max = apix_system_max_vectors -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_fixed_intr_vectors_used -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_cache_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size = MIN(new_pool_size, max);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (new_pool_size == apix_irm_params.iparams_total) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* no change to pool size */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (new_pool_size < apix_irm_params.iparams_total) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN, "new_pool_size %d is inconsistent "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "with irm_params.iparams_total %d",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases new_pool_size, apix_irm_params.iparams_total);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) ndi_irm_resize_pool(apix_irm_pool_p, new_pool_size);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* update the pool size info */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_irm_params.iparams_total = new_pool_size;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mutex_exit(&apix_irm_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}