ddi_intr_irm.c revision d1b019ce281ee55ed1b22ff0a281dcdbc7e61e4e
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * CDDL HEADER START
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * The contents of this file are subject to the terms of the
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Common Development and Distribution License (the "License").
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * You may not use this file except in compliance with the License.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * or http://www.opensolaris.org/os/licensing.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * See the License for the specific language governing permissions
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * and limitations under the License.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * When distributing Covered Code, include this CDDL HEADER in each
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * If applicable, add the following below this CDDL HEADER, with the
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * fields enclosed by brackets "[]" replaced with your own identifying
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * information: Portions Copyright [yyyy] [name of copyright owner]
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * CDDL HEADER END
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Use is subject to license terms.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/note.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/sysmacros.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/types.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/param.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/systm.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/kmem.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/cmn_err.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/debug.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/ddi.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/sunndi.h>
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#include <sys/ndi_impldefs.h> /* include prototypes */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Interrupt Resource Management (IRM).
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#define DDI_IRM_BALANCE_DELAY (60) /* In seconds */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#define DDI_IRM_HAS_CB(c) ((c) && (c->cb_flags & DDI_CB_FLAG_INTR))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#define DDI_IRM_IS_REDUCIBLE(r) (((r->ireq_flags & DDI_IRM_FLAG_CALLBACK) && \
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (r->ireq_type == DDI_INTR_TYPE_MSIX)) || \
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (r->ireq_flags & DDI_IRM_FLAG_NEW))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWextern pri_t minclsyspri;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/* Global policies */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint irm_enable = 1;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWboolean_t irm_active = B_FALSE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint irm_default_policy = DDI_IRM_POLICY_LARGE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWuint_t irm_balance_delay = DDI_IRM_BALANCE_DELAY;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/* Global list of interrupt pools */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWkmutex_t irm_pools_lock;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWlist_t irm_pools_list;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/* Global debug tunables */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#ifdef DEBUG
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint irm_debug_policy = 0;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWuint_t irm_debug_size = 0;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#endif /* DEBUG */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void irm_balance_thread(ddi_irm_pool_t *);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void i_ddi_irm_balance(ddi_irm_pool_t *);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void i_ddi_irm_enqueue(ddi_irm_pool_t *, boolean_t);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void i_ddi_irm_reduce(ddi_irm_pool_t *pool);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic int i_ddi_irm_reduce_large(ddi_irm_pool_t *, int);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void i_ddi_irm_reduce_large_resort(ddi_irm_pool_t *);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic int i_ddi_irm_reduce_even(ddi_irm_pool_t *, int);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void i_ddi_irm_reduce_new(ddi_irm_pool_t *, int);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void i_ddi_irm_insertion_sort(list_t *, ddi_irm_req_t *);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic int i_ddi_irm_notify(ddi_irm_pool_t *, ddi_irm_req_t *);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * OS Initialization Routines
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * irm_init()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Initialize IRM subsystem before any drivers are attached.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWvoid
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWirm_init(void)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Do nothing if IRM is disabled */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!irm_enable)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Verify that the default balancing policy is valid */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!DDI_IRM_POLICY_VALID(irm_default_policy))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW irm_default_policy = DDI_IRM_POLICY_LARGE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Initialize the global list of interrupt pools */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_init(&irm_pools_lock, NULL, MUTEX_DRIVER, NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_create(&irm_pools_list, sizeof (ddi_irm_pool_t),
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW offsetof(ddi_irm_pool_t, ipool_link));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_poststartup()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * IRM is not activated until after the IO subsystem is initialized.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * When activated, per-pool balancing threads are spawned and a flag
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * is set so that all future pools will be activated when created.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * NOTE: the global variable 'irm_enable' disables IRM if zero.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWvoid
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_poststartup(void)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Do nothing if IRM is disabled */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!irm_enable)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the global list */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&irm_pools_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Activate all defined pools */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW for (pool_p = list_head(&irm_pools_list); pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p = list_next(&irm_pools_list, pool_p))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_thread = thread_create(NULL, 0,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW irm_balance_thread, pool_p, 0, &p0, TS_RUN, minclsyspri);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Set future pools to be active */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW irm_active = B_TRUE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Unlock the global list */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&irm_pools_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * NDI interfaces for creating/destroying IRM pools.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * ndi_irm_create()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Nexus interface to create an IRM pool. Create the new
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * pool and add it to the global list of interrupt pools.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWndi_irm_create(dev_info_t *dip, ddi_irm_params_t *paramsp,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t **pool_retp)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(dip != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(paramsp != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_retp != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(paramsp->iparams_total >= 1);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(paramsp->iparams_types != 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(paramsp->iparams_default >= 1);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "ndi_irm_create: dip %p\n", (void *)dip));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check if IRM is enabled */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!irm_enable)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate parameters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((dip == NULL) || (paramsp == NULL) || (pool_retp == NULL) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (paramsp->iparams_total < 1) || (paramsp->iparams_types == 0) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (paramsp->iparams_default < 1))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Allocate and initialize the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p = kmem_zalloc(sizeof (ddi_irm_pool_t), KM_SLEEP);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_owner = dip;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_policy = irm_default_policy;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_types = paramsp->iparams_types;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_totsz = paramsp->iparams_total;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_defsz = paramsp->iparams_default;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_create(&pool_p->ipool_req_list, sizeof (ddi_irm_req_t),
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW offsetof(ddi_irm_req_t, ireq_link));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_create(&pool_p->ipool_scratch_list, sizeof (ddi_irm_req_t),
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW offsetof(ddi_irm_req_t, ireq_scratch_link));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_init(&pool_p->ipool_cv, NULL, CV_DRIVER, NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_init(&pool_p->ipool_lock, NULL, MUTEX_DRIVER, NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_init(&pool_p->ipool_navail_lock, NULL, MUTEX_DRIVER, NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Add to global list of pools */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&irm_pools_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_insert_tail(&irm_pools_list, pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&irm_pools_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* If IRM is active, then activate the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (irm_active)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_thread = thread_create(NULL, 0,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW irm_balance_thread, pool_p, 0, &p0, TS_RUN, minclsyspri);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *pool_retp = pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * ndi_irm_destroy()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Nexus interface to destroy an IRM pool. Destroy the pool
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * and remove it from the global list of interrupt pools.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWndi_irm_destroy(ddi_irm_pool_t *pool_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p->ipool_resno == 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "ndi_irm_destroy: pool_p %p\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate parameters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (pool_p == NULL)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate that pool is empty */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (pool_p->ipool_resno != 0)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NDI_BUSY);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Remove the pool from the global list */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&irm_pools_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_remove(&irm_pools_list, pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&irm_pools_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Terminate the balancing thread */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (pool_p->ipool_thread &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (pool_p->ipool_flags & DDI_IRM_FLAG_ACTIVE)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_flags |= DDI_IRM_FLAG_EXIT;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_signal(&pool_p->ipool_cv);
d1b019ce281ee55ed1b22ff0a281dcdbc7e61e4eJustin Frank mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW thread_join(pool_p->ipool_thread->t_did);
d1b019ce281ee55ed1b22ff0a281dcdbc7e61e4eJustin Frank } else
d1b019ce281ee55ed1b22ff0a281dcdbc7e61e4eJustin Frank mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Destroy the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_destroy(&pool_p->ipool_cv);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_destroy(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_destroy(&pool_p->ipool_navail_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_destroy(&pool_p->ipool_req_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_destroy(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW kmem_free(pool_p, sizeof (ddi_irm_pool_t));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Insert/Modify/Remove Interrupt Requests
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_insert()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Insert a new request into an interrupt pool, and balance the pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_insert(dev_info_t *dip, int type, int count)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_cb_t *cb_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW devinfo_intr_t *intr_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t nreq, nmin, npartial;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW boolean_t irm_flag = B_FALSE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(dip != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(DDI_INTR_TYPE_FLAG_VALID(type));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(count > 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_insert: dip %p type %d count %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)dip, type, count));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate parameters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((dip == NULL) || (count < 1) || !DDI_INTR_TYPE_FLAG_VALID(type)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_insert: invalid args\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EINVAL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check for an existing request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (((intr_p = DEVI(dip)->devi_intr_p) != NULL) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (intr_p->devi_irm_req_p != NULL))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check for IRM support from the system */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((pool_p = i_ddi_intr_get_pool(dip, type)) == NULL) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_insert: not supported\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_ENOTSUP);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check for IRM support from the driver */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (((cb_p = DEVI(dip)->devi_cb_p) != NULL) && DDI_IRM_HAS_CB(cb_p) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (type == DDI_INTR_TYPE_MSIX))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW irm_flag = B_TRUE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Determine request size */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreq = (irm_flag) ? count : i_ddi_intr_get_current_navail(dip, type);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nmin = (irm_flag) ? 1 : nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW npartial = MIN(nreq, pool_p->ipool_defsz);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Allocate and initialize the request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = kmem_zalloc(sizeof (ddi_irm_req_t), KM_SLEEP);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_type = type;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_dip = dip;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_pool_p = pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_nreq = nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags = DDI_IRM_FLAG_NEW;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (DDI_IRM_HAS_CB(cb_p))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags |= DDI_IRM_FLAG_CALLBACK;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check for minimal fit before inserting */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((pool_p->ipool_minno + nmin) > pool_p->ipool_totsz) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cmn_err(CE_WARN, "%s%d: interrupt pool too full.\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_driver_name(dip), ddi_get_instance(dip));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW kmem_free(req_p, sizeof (ddi_irm_req_t));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EAGAIN);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Insert the request into the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno += nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno += nmin;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_insertion_sort(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Try to fulfill the request.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * If all the interrupts are available, and either the request
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * is static or the pool is active, then just take them directly.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * If only some of the interrupts are available, and the request
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * can receive future callbacks, then take some now but queue the
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * pool to be rebalanced later.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Otherwise, immediately rebalance the pool and wait.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((!irm_flag || (pool_p->ipool_flags & DDI_IRM_FLAG_ACTIVE)) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((pool_p->ipool_resno + nreq) <= pool_p->ipool_totsz)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_insert: "
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "request completely fulfilled.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno += nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail = nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags &= ~(DDI_IRM_FLAG_NEW);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else if (irm_flag &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((pool_p->ipool_resno + npartial) <= pool_p->ipool_totsz)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_insert: "
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "request partially fulfilled.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno += npartial;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail = npartial;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags &= ~(DDI_IRM_FLAG_NEW);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, B_FALSE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_insert: "
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "request needs immediate rebalance.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, B_TRUE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags &= ~(DDI_IRM_FLAG_NEW);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Fail if the request cannot be fulfilled at all */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_navail == 0) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cmn_err(CE_WARN, "%s%d: interrupt pool too full.\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_driver_name(dip), ddi_get_instance(dip));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno -= nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno -= nmin;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_remove(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW kmem_free(req_p, sizeof (ddi_irm_req_t));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EAGAIN);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Unlock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW intr_p->devi_irm_req_p = req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_modify()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Modify an existing request in an interrupt pool, and balance the pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_modify(dev_info_t *dip, int nreq)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW devinfo_intr_t *intr_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(dip != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_modify: dip %p nreq %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)dip, nreq));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate parameters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((dip == NULL) || (nreq < 1)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_modify: invalid args\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EINVAL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check that the operation is supported */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!(intr_p = DEVI(dip)->devi_intr_p) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW !(req_p = intr_p->devi_irm_req_p) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW !DDI_IRM_IS_REDUCIBLE(req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_modify: not supported\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_ENOTSUP);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate request size is not too large */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nreq > intr_p->devi_intr_sup_nintrs) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_modify: invalid args\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EINVAL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Modify request, but only if new size is different.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nreq != req_p->ireq_nreq) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p = req_p->ireq_pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Update pool and request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno -= req_p->ireq_nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno += nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_nreq = nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Re-sort request in the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_remove(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_insertion_sort(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Queue pool to be rebalanced */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, B_FALSE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Unlock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_remove()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Remove a request from an interrupt pool, and balance the pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWint
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_remove(dev_info_t *dip)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW devinfo_intr_t *intr_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t nmin;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(dip != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_remove: dip %p\n", (void *)dip));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate parameters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (dip == NULL) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_remove: invalid args\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EINVAL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check if the device has a request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!(intr_p = DEVI(dip)->devi_intr_p) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW !(req_p = intr_p->devi_irm_req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_modify: not found\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_EINVAL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p = req_p->ireq_pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Remove request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nmin = DDI_IRM_IS_REDUCIBLE(req_p) ? 1 : req_p->ireq_nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno -= nmin;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno -= req_p->ireq_nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno -= req_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_remove(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Queue pool to be rebalanced */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, B_FALSE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Unlock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Destroy the request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW intr_p->devi_irm_req_p = NULL;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW kmem_free(req_p, sizeof (ddi_irm_req_t));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_set_cb()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Change the callback flag for a request, in response to
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * a change in its callback registration. Then rebalance
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * the interrupt pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * NOTE: the request is not locked because the navail value
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * is not directly affected. The balancing thread may
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * modify the navail value in the background after it
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * locks the request itself.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWvoid
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_set_cb(dev_info_t *dip, boolean_t has_cb_flag)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW devinfo_intr_t *intr_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(dip != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_set_cb: dip %p has_cb_flag %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)dip, (int)has_cb_flag));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Validate parameters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (dip == NULL)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check for association with interrupt pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!(intr_p = DEVI(dip)->devi_intr_p) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW !(req_p = intr_p->devi_irm_req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_set_cb: not in pool\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p = req_p->ireq_pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Update the request and the pool
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (has_cb_flag) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Update pool statistics */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_type == DDI_INTR_TYPE_MSIX)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno -= (req_p->ireq_nreq - 1);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Update request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags |= DDI_IRM_FLAG_CALLBACK;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Rebalance in background */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, B_FALSE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Determine new request size */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreq = MIN(req_p->ireq_nreq, pool_p->ipool_defsz);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Update pool statistics */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno -= req_p->ireq_nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_reqno += nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_type == DDI_INTR_TYPE_MSIX) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno -= 1;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno += nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno -= req_p->ireq_nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_minno += nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Update request size, and re-sort in pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_nreq = nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_remove(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_insertion_sort(&pool_p->ipool_req_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Rebalance synchronously, before losing callback */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, B_TRUE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Remove callback flag */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_flags &= ~(DDI_IRM_FLAG_CALLBACK);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Unlock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Interrupt Pool Balancing
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * irm_balance_thread()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * One instance of this thread operates per each defined IRM pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * It does the initial activation of the pool, as well as balancing
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * any requests that were queued up before the pool was active.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Once active, it waits forever to service balance operations.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWirm_balance_thread(ddi_irm_pool_t *pool_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW clock_t interval, wakeup;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "irm_balance_thread: pool_p %p\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Perform initial balance if required */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (pool_p->ipool_reqno > pool_p->ipool_resno)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_balance(pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Activate the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_flags |= DDI_IRM_FLAG_ACTIVE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Main loop */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW for (;;) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Compute the delay interval */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW interval = drv_usectohz(irm_balance_delay * 1000000);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Sleep until queued */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_wait(&pool_p->ipool_cv, &pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "irm_balance_thread: signaled.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Wait one interval, or until there are waiters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((interval > 0) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW !(pool_p->ipool_flags & DDI_IRM_FLAG_WAITERS) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW !(pool_p->ipool_flags & DDI_IRM_FLAG_EXIT)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW wakeup = ddi_get_lbolt() + interval;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void) cv_timedwait(&pool_p->ipool_cv,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW &pool_p->ipool_lock, wakeup);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check if awakened to exit */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (pool_p->ipool_flags & DDI_IRM_FLAG_EXIT) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "irm_balance_thread: exiting...\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW thread_exit();
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Balance the pool */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_balance(pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Notify waiters */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (pool_p->ipool_flags & DDI_IRM_FLAG_WAITERS) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_broadcast(&pool_p->ipool_cv);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_flags &= ~(DDI_IRM_FLAG_WAITERS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Clear QUEUED condition */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_flags &= ~(DDI_IRM_FLAG_QUEUED);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_balance()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Balance a pool. The general algorithm is to first reset all
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * requests to their maximum size, use reduction algorithms to
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * solve any imbalance, and then notify affected drivers.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_balance(ddi_irm_pool_t *pool_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#ifdef DEBUG
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t debug_totsz = 0;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW int debug_policy = 0;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#endif /* DEBUG */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_balance: pool_p %p\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#ifdef DEBUG /* Adjust size and policy settings */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (irm_debug_size > pool_p->ipool_minno) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_balance: debug size %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW irm_debug_size));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW debug_totsz = pool_p->ipool_totsz;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_totsz = irm_debug_size;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (DDI_IRM_POLICY_VALID(irm_debug_policy)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_balance: debug policy %d\n", irm_debug_policy));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW debug_policy = pool_p->ipool_policy;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_policy = irm_debug_policy;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#endif /* DEBUG */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lock the availability lock */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_navail_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Put all of the reducible requests into a scratch list.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Reset each one of them to their maximum availability.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW for (req_p = list_head(&pool_p->ipool_req_list); req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(&pool_p->ipool_req_list, req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (DDI_IRM_IS_REDUCIBLE(req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno -= req_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_scratch = req_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail = req_p->ireq_nreq;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno += req_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_insert_tail(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Balance the requests */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_reduce(pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Unlock the availability lock */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_navail_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Process REMOVE notifications.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * If a driver fails to release interrupts: exclude it from
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * further processing, correct the resulting imbalance, and
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * start over again at the head of the scratch list.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (req_p) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((req_p->ireq_navail < req_p->ireq_scratch) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (i_ddi_irm_notify(pool_p, req_p) != DDI_SUCCESS)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_remove(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_navail_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_reduce(pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_navail_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Process ADD notifications.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * This is the last use of the scratch list, so empty it.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (req_p = list_remove_head(&pool_p->ipool_scratch_list)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_navail > req_p->ireq_scratch) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void) i_ddi_irm_notify(pool_p, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#ifdef DEBUG /* Restore size and policy settings */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (debug_totsz != 0)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_totsz = debug_totsz;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (debug_policy != 0)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_policy = debug_policy;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#endif /* DEBUG */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_reduce()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Use reduction algorithms to correct an imbalance in a pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_reduce(ddi_irm_pool_t *pool_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW int ret, imbalance;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(DDI_IRM_POLICY_VALID(pool_p->ipool_policy));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_reduce: pool_p %p\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Compute the imbalance. Do nothing if already balanced. */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((imbalance = pool_p->ipool_resno - pool_p->ipool_totsz) <= 0)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Reduce by policy */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW switch (pool_p->ipool_policy) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW case DDI_IRM_POLICY_LARGE:
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ret = i_ddi_irm_reduce_large(pool_p, imbalance);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW break;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW case DDI_IRM_POLICY_EVEN:
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ret = i_ddi_irm_reduce_even(pool_p, imbalance);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW break;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * If the policy based reductions failed, then
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * possibly reduce new requests as a last resort.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (ret != DDI_SUCCESS) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_reduce: policy reductions failed.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Compute remaining imbalance */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW imbalance = pool_p->ipool_resno - pool_p->ipool_totsz;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(imbalance > 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_reduce_new(pool_p, imbalance);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_enqueue()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Queue a pool to be balanced. Signals the balancing thread to wake
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * up and process the pool. If 'wait_flag' is true, then the current
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * thread becomes a waiter and blocks until the balance is completed.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_enqueue(ddi_irm_pool_t *pool_p, boolean_t wait_flag)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_enqueue: pool_p %p wait_flag %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p, (int)wait_flag));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Do nothing if pool is already balanced */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#ifndef DEBUG
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((pool_p->ipool_reqno == pool_p->ipool_resno)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#else
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((pool_p->ipool_reqno == pool_p->ipool_resno) && !irm_debug_size) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#endif /* DEBUG */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_enqueue: pool already balanced\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Avoid deadlocks when IRM is not active */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (!irm_active && wait_flag) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_enqueue: pool not active.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (wait_flag)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_flags |= DDI_IRM_FLAG_WAITERS;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (wait_flag || !(pool_p->ipool_flags & DDI_IRM_FLAG_QUEUED)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_flags |= DDI_IRM_FLAG_QUEUED;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_signal(&pool_p->ipool_cv);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_enqueue: pool queued.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (wait_flag) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_enqueue: waiting...\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cv_wait(&pool_p->ipool_cv, &pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Reduction Algorithms, Used For Balancing
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_reduce_large()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Algorithm for the DDI_IRM_POLICY_LARGE reduction policy.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * This algorithm generally reduces larger requests first, before
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * advancing to smaller requests. The scratch list is initially
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * sorted in descending order by current navail values, which are
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * maximized prior to reduction. This sorted order is preserved,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * but within a range of equally sized requests they are secondarily
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * sorted in ascending order by initial nreq value. The head of the
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * list is always selected for reduction, since it is the current
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * largest request. After being reduced, it is sorted further into
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * the list before the next iteration.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Optimizations in this algorithm include trying to reduce multiple
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * requests together if they are equally sized. And the algorithm
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * attempts to reduce in larger increments when possible to minimize
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * the total number of iterations.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic int
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_reduce_large(ddi_irm_pool_t *pool_p, int imbalance)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p, *next_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW int nreqs, reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(imbalance > 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_reduce_large: pool_p %p imbalance %d\n", (void *)pool_p,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW imbalance));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (imbalance > 0) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_next(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Fail if nothing is reducible */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_navail == 1) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_reduce_large: failure.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Count the number of equally sized requests */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreqs = 1;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (next_p && (req_p->ireq_navail == next_p->ireq_navail)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_next(&pool_p->ipool_scratch_list, next_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreqs++;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Try to reduce multiple requests together */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nreqs > 1) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (next_p) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = req_p->ireq_navail -
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (next_p->ireq_navail + 1);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = req_p->ireq_navail - 1;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((reduction * nreqs) > imbalance)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = imbalance / nreqs;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (reduction > 0) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (req_p && (req_p != next_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW imbalance -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW &pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW continue;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Or just reduce the current request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_next(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (next_p && (req_p->ireq_navail > next_p->ireq_navail)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = req_p->ireq_navail - next_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = MIN(reduction, imbalance);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = 1;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW imbalance -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Re-sort the scratch list if not yet finished */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (imbalance > 0) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_reduce_large_resort(pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_reduce_large_resort()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Helper function for i_ddi_irm_reduce_large(). Once a request
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * is reduced, this resorts it further down into the list as necessary.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_reduce_large_resort(ddi_irm_pool_t *pool_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p, *next_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_remove_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (next_p &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((next_p->ireq_navail > req_p->ireq_navail) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((next_p->ireq_navail == req_p->ireq_navail) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (next_p->ireq_nreq < req_p->ireq_nreq))))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_next(&pool_p->ipool_scratch_list, next_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_insert_before(&pool_p->ipool_scratch_list, next_p, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_reduce_even()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Algorithm for the DDI_IRM_POLICY_EVEN reduction policy.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * This algorithm reduces requests evenly, without giving a
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * specific preference to smaller or larger requests. Each
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * iteration reduces all reducible requests by the same amount
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * until the imbalance is corrected. Although when possible,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * it tries to avoid reducing requests below the threshold of
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * the interrupt pool's default allocation size.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * An optimization in this algorithm is to reduce the requests
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * in larger increments during each iteration, to minimize the
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * total number of iterations required.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic int
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_reduce_even(ddi_irm_pool_t *pool_p, int imbalance)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p, *last_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t nmin = pool_p->ipool_defsz;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t nreduce, reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(imbalance > 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "i_ddi_irm_reduce_even: pool_p %p imbalance %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p, imbalance));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while ((nmin > 0) && (imbalance > 0)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Count reducible requests */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreduce = 0;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW for (req_p = list_head(&pool_p->ipool_scratch_list); req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(&pool_p->ipool_scratch_list, req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_navail <= nmin)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW break;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW last_p = req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreduce++;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* If none are reducible, try a lower minimum */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nreduce == 0) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nmin--;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW continue;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Compute reduction */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nreduce < imbalance) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = last_p->ireq_navail - nmin;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((reduction * nreduce) > imbalance) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = imbalance / nreduce;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW reduction = 1;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Start at head of list, but skip excess */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (nreduce > imbalance) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreduce--;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Do reductions */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (req_p && (nreduce > 0)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW imbalance -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno -= reduction;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(&pool_p->ipool_scratch_list, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nreduce--;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nmin == 0) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_reduce_even: failure.\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_reduce_new()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Reduces new requests to zero. This is only used as a
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * last resort after another reduction algorithm failed.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_reduce_new(ddi_irm_pool_t *pool_p, int imbalance)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(pool_p != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(imbalance > 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(MUTEX_HELD(&pool_p->ipool_lock));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW for (req_p = list_head(&pool_p->ipool_scratch_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p && (imbalance > 0);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p = list_next(&pool_p->ipool_scratch_list, req_p)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(req_p->ireq_navail == 1);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_flags & DDI_IRM_FLAG_NEW) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail--;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno--;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW imbalance--;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Miscellaneous Helper Functions
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_intr_get_pool()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Get an IRM pool that supplies interrupts of a specified type.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Invokes a DDI_INTROP_GETPOOL to the bus nexus driver. Fails
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * if no pool exists.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWddi_irm_pool_t *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_intr_get_pool(dev_info_t *dip, int type)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW devinfo_intr_t *intr_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *req_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_intr_handle_impl_t hdl;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(dip != NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ASSERT(DDI_INTR_TYPE_FLAG_VALID(type));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (((intr_p = DEVI(dip)->devi_intr_p) != NULL) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((req_p = intr_p->devi_irm_req_p) != NULL) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((pool_p = req_p->ireq_pool_p) != NULL) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (pool_p->ipool_types & type)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW bzero(&hdl, sizeof (ddi_intr_handle_impl_t));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW hdl.ih_dip = dip;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW hdl.ih_type = type;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (i_ddi_intr_ops(dip, dip, DDI_INTROP_GETPOOL,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW &hdl, (void *)&pool_p) == DDI_SUCCESS)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (pool_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (NULL);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_insertion_sort()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Use the insertion sort method to insert a request into a list.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * The list is sorted in descending order by request size.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic void
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_insertion_sort(list_t *req_list, ddi_irm_req_t *req_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_req_t *next_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_head(req_list);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW while (next_p && (next_p->ireq_nreq > req_p->ireq_nreq))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW next_p = list_next(req_list, next_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW list_insert_before(req_list, next_p, req_p);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_notify()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * Notify a driver of changes to its interrupt request using the
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * generic callback mechanism. Checks for errors in processing.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWstatic int
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_notify(ddi_irm_pool_t *pool_p, ddi_irm_req_t *req_p)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_cb_action_t action;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_cb_t *cb_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW uint_t nintrs;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW int ret, count;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_notify: pool_p %p req_p %p\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)pool_p, (void *)req_p));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Do not notify new or unchanged requests */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((req_p->ireq_navail == req_p->ireq_scratch) ||
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (req_p->ireq_flags & DDI_IRM_FLAG_NEW))
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Determine action and count */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (req_p->ireq_navail > req_p->ireq_scratch) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW action = DDI_CB_INTR_ADD;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW count = req_p->ireq_navail - req_p->ireq_scratch;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_notify: adding %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW count));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW } else {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW action = DDI_CB_INTR_REMOVE;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW count = req_p->ireq_scratch - req_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_notify: removing %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW count));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Lookup driver callback */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if ((cb_p = DEVI(req_p->ireq_dip)->devi_cb_p) == NULL) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_WARN, "i_ddi_irm_notify: no callback!\n"));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Do callback */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ret = cb_p->cb_func(req_p->ireq_dip, action, (void *)(uintptr_t)count,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cb_p->cb_arg1, cb_p->cb_arg2);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Log callback errors */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (ret != DDI_SUCCESS) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cmn_err(CE_WARN, "%s%d: failed callback (action=%d, ret=%d)\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_driver_name(req_p->ireq_dip),
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_get_instance(req_p->ireq_dip), (int)action, ret);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Check if the driver exceeds its availability */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW nintrs = i_ddi_intr_get_current_nintrs(req_p->ireq_dip);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (nintrs > req_p->ireq_navail) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW cmn_err(CE_WARN, "%s%d: failed to release interrupts "
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW "(nintrs=%d, navail=%d).\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_driver_name(req_p->ireq_dip),
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_get_instance(req_p->ireq_dip), nintrs,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW pool_p->ipool_resno += (nintrs - req_p->ireq_navail);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_navail = nintrs;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_FAILURE);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW /* Update request */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW req_p->ireq_scratch = req_p->ireq_navail;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW return (DDI_SUCCESS);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW/*
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * i_ddi_irm_debug_balance()
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW *
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * A debug/test only routine to force the immediate,
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW * synchronous rebalancing of an interrupt pool.
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW */
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#ifdef DEBUG
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWvoid
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSWi_ddi_irm_debug_balance(dev_info_t *dip, boolean_t wait_flag)
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW{
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ddi_irm_pool_t *pool_p;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW int type;
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW DDI_INTR_IRMDBG((CE_CONT, "i_ddi_irm_debug_balance: dip %p wait %d\n",
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW (void *)dip, (int)wait_flag));
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW if (((type = i_ddi_intr_get_current_type(dip)) != 0) &&
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW ((pool_p = i_ddi_intr_get_pool(dip, type)) != NULL)) {
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_enter(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW i_ddi_irm_enqueue(pool_p, wait_flag);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW mutex_exit(&pool_p->ipool_lock);
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW }
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW}
5febcb4a56e199202aba97f9cf96d32cc0480a1fScott Carter, SD IOSW#endif