xref: /onnv-gate/usr/src/uts/sun4u/opl/io/pcicmu/pcmu_ib.c (revision 11311:639e7bc0b42f)
11772Sjl139090 /*
21772Sjl139090  * CDDL HEADER START
31772Sjl139090  *
41772Sjl139090  * The contents of this file are subject to the terms of the
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * You may not use this file except in compliance with the License.
71772Sjl139090  *
81772Sjl139090  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91772Sjl139090  * or http://www.opensolaris.org/os/licensing.
101772Sjl139090  * See the License for the specific language governing permissions
111772Sjl139090  * and limitations under the License.
121772Sjl139090  *
131772Sjl139090  * When distributing Covered Code, include this CDDL HEADER in each
141772Sjl139090  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151772Sjl139090  * If applicable, add the following below this CDDL HEADER, with the
161772Sjl139090  * fields enclosed by brackets "[]" replaced with your own identifying
171772Sjl139090  * information: Portions Copyright [yyyy] [name of copyright owner]
181772Sjl139090  *
191772Sjl139090  * CDDL HEADER END
201772Sjl139090  */
21*11311SSurya.Prakki@Sun.COM 
221772Sjl139090 /*
23*11311SSurya.Prakki@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241772Sjl139090  * Use is subject to license terms.
251772Sjl139090  */
261772Sjl139090 
271772Sjl139090 /*
281772Sjl139090  * CMU-CH Interrupt Block
291772Sjl139090  */
301772Sjl139090 
311772Sjl139090 #include <sys/types.h>
321772Sjl139090 #include <sys/kmem.h>
331772Sjl139090 #include <sys/async.h>
341772Sjl139090 #include <sys/systm.h>
351772Sjl139090 #include <sys/spl.h>
361772Sjl139090 #include <sys/sunddi.h>
371772Sjl139090 #include <sys/machsystm.h>
381772Sjl139090 #include <sys/ddi_impldefs.h>
391772Sjl139090 #include <sys/pcicmu/pcicmu.h>
401772Sjl139090 
411772Sjl139090 static uint_t pcmu_ib_intr_reset(void *arg);
421772Sjl139090 
431772Sjl139090 extern uint64_t	xc_tick_jump_limit;
441772Sjl139090 
451772Sjl139090 void
pcmu_ib_create(pcmu_t * pcmu_p)461772Sjl139090 pcmu_ib_create(pcmu_t *pcmu_p)
471772Sjl139090 {
481772Sjl139090 	pcmu_ib_t *pib_p;
491772Sjl139090 	uintptr_t a;
501772Sjl139090 	int i;
511772Sjl139090 
521772Sjl139090 	/*
531772Sjl139090 	 * Allocate interrupt block state structure and link it to
541772Sjl139090 	 * the pci state structure.
551772Sjl139090 	 */
561772Sjl139090 	pib_p = kmem_zalloc(sizeof (pcmu_ib_t), KM_SLEEP);
571772Sjl139090 	pcmu_p->pcmu_ib_p = pib_p;
581772Sjl139090 	pib_p->pib_pcmu_p = pcmu_p;
591772Sjl139090 
601772Sjl139090 	a = pcmu_ib_setup(pib_p);
611772Sjl139090 
621772Sjl139090 	/*
631772Sjl139090 	 * Determine virtual addresses of interrupt mapping, clear and diag
641772Sjl139090 	 * registers that have common offsets.
651772Sjl139090 	 */
661772Sjl139090 	pib_p->pib_intr_retry_timer_reg =
676587Sjfrank 	    (uint64_t *)(a + PCMU_IB_INTR_RETRY_TIMER_OFFSET);
681772Sjl139090 	pib_p->pib_obio_intr_state_diag_reg =
696587Sjfrank 	    (uint64_t *)(a + PCMU_IB_OBIO_INTR_STATE_DIAG_REG);
701772Sjl139090 
711772Sjl139090 	PCMU_DBG2(PCMU_DBG_ATTACH, pcmu_p->pcmu_dip,
721772Sjl139090 	    "pcmu_ib_create: obio_imr=%x, obio_cir=%x\n",
731772Sjl139090 	    pib_p->pib_obio_intr_map_regs, pib_p->pib_obio_clear_intr_regs);
741772Sjl139090 	PCMU_DBG2(PCMU_DBG_ATTACH, pcmu_p->pcmu_dip,
751772Sjl139090 	    "pcmu_ib_create: retry_timer=%x, obio_diag=%x\n",
761772Sjl139090 	    pib_p->pib_intr_retry_timer_reg,
771772Sjl139090 	    pib_p->pib_obio_intr_state_diag_reg);
781772Sjl139090 
791772Sjl139090 	pib_p->pib_ino_lst = (pcmu_ib_ino_info_t *)NULL;
801772Sjl139090 	mutex_init(&pib_p->pib_intr_lock, NULL, MUTEX_DRIVER, NULL);
811772Sjl139090 	mutex_init(&pib_p->pib_ino_lst_mutex, NULL, MUTEX_DRIVER, NULL);
821772Sjl139090 
831772Sjl139090 	PCMU_DBG1(PCMU_DBG_ATTACH, pcmu_p->pcmu_dip,
841772Sjl139090 	    "pcmu_ib_create: numproxy=%x\n", pcmu_p->pcmu_numproxy);
851772Sjl139090 	for (i = 1; i <= pcmu_p->pcmu_numproxy; i++) {
861772Sjl139090 		set_intr_mapping_reg(pcmu_p->pcmu_id,
876587Sjfrank 		    (uint64_t *)pib_p->pib_upa_imr[i - 1], i);
881772Sjl139090 	}
891772Sjl139090 
901772Sjl139090 	pcmu_ib_configure(pib_p);
911772Sjl139090 	bus_func_register(BF_TYPE_RESINTR, pcmu_ib_intr_reset, pib_p);
921772Sjl139090 }
931772Sjl139090 
941772Sjl139090 void
pcmu_ib_destroy(pcmu_t * pcmu_p)951772Sjl139090 pcmu_ib_destroy(pcmu_t *pcmu_p)
961772Sjl139090 {
971772Sjl139090 	pcmu_ib_t *pib_p = pcmu_p->pcmu_ib_p;
981772Sjl139090 
991772Sjl139090 	PCMU_DBG0(PCMU_DBG_IB, pcmu_p->pcmu_dip, "pcmu_ib_destroy\n");
1001772Sjl139090 	bus_func_unregister(BF_TYPE_RESINTR, pcmu_ib_intr_reset, pib_p);
1011772Sjl139090 
1021772Sjl139090 	intr_dist_rem_weighted(pcmu_ib_intr_dist_all, pib_p);
1031772Sjl139090 	mutex_destroy(&pib_p->pib_ino_lst_mutex);
1041772Sjl139090 	mutex_destroy(&pib_p->pib_intr_lock);
1051772Sjl139090 
1061772Sjl139090 	pcmu_ib_free_ino_all(pib_p);
1071772Sjl139090 
1081772Sjl139090 	kmem_free(pib_p, sizeof (pcmu_ib_t));
1091772Sjl139090 	pcmu_p->pcmu_ib_p = NULL;
1101772Sjl139090 }
1111772Sjl139090 
1121772Sjl139090 void
pcmu_ib_configure(pcmu_ib_t * pib_p)1131772Sjl139090 pcmu_ib_configure(pcmu_ib_t *pib_p)
1141772Sjl139090 {
1151772Sjl139090 	*pib_p->pib_intr_retry_timer_reg = pcmu_intr_retry_intv;
1161772Sjl139090 }
1171772Sjl139090 
1181772Sjl139090 /*
1191772Sjl139090  * can only used for CMU-CH internal interrupts ue, pbm
1201772Sjl139090  */
1211772Sjl139090 void
pcmu_ib_intr_enable(pcmu_t * pcmu_p,pcmu_ib_ino_t ino)1221772Sjl139090 pcmu_ib_intr_enable(pcmu_t *pcmu_p, pcmu_ib_ino_t ino)
1231772Sjl139090 {
1241772Sjl139090 	pcmu_ib_t *pib_p = pcmu_p->pcmu_ib_p;
1251772Sjl139090 	pcmu_ib_mondo_t mondo = PCMU_IB_INO_TO_MONDO(pib_p, ino);
1261772Sjl139090 	volatile uint64_t *imr_p = ib_intr_map_reg_addr(pib_p, ino);
1271772Sjl139090 	uint_t cpu_id;
1281772Sjl139090 
1291772Sjl139090 	/*
1301772Sjl139090 	 * Determine the cpu for the interrupt.
1311772Sjl139090 	 */
1321772Sjl139090 	mutex_enter(&pib_p->pib_intr_lock);
1331772Sjl139090 	cpu_id = intr_dist_cpuid();
1341772Sjl139090 	cpu_id = u2u_translate_tgtid(pcmu_p, cpu_id, imr_p);
1351772Sjl139090 	PCMU_DBG2(PCMU_DBG_IB, pcmu_p->pcmu_dip,
1361772Sjl139090 	    "pcmu_ib_intr_enable: ino=%x cpu_id=%x\n", ino, cpu_id);
1371772Sjl139090 
1381772Sjl139090 	*imr_p = ib_get_map_reg(mondo, cpu_id);
1391772Sjl139090 	PCMU_IB_INO_INTR_CLEAR(ib_clear_intr_reg_addr(pib_p, ino));
1401772Sjl139090 	mutex_exit(&pib_p->pib_intr_lock);
1411772Sjl139090 }
1421772Sjl139090 
1431772Sjl139090 /*
1441772Sjl139090  * Disable the interrupt via its interrupt mapping register.
1451772Sjl139090  * Can only be used for internal interrupts: ue, pbm.
1461772Sjl139090  * If called under interrupt context, wait should be set to 0
1471772Sjl139090  */
1481772Sjl139090 void
pcmu_ib_intr_disable(pcmu_ib_t * pib_p,pcmu_ib_ino_t ino,int wait)1491772Sjl139090 pcmu_ib_intr_disable(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino, int wait)
1501772Sjl139090 {
1511772Sjl139090 	volatile uint64_t *imr_p = ib_intr_map_reg_addr(pib_p, ino);
1521772Sjl139090 	volatile uint64_t *state_reg_p = PCMU_IB_INO_INTR_STATE_REG(pib_p, ino);
1531772Sjl139090 	hrtime_t start_time;
1541772Sjl139090 	hrtime_t prev, curr, interval, jump;
1551772Sjl139090 	hrtime_t intr_timeout;
1561772Sjl139090 
1571772Sjl139090 	/* disable the interrupt */
1581772Sjl139090 	mutex_enter(&pib_p->pib_intr_lock);
1591772Sjl139090 	PCMU_IB_INO_INTR_OFF(imr_p);
1601772Sjl139090 	*imr_p;	/* flush previous write */
1611772Sjl139090 	mutex_exit(&pib_p->pib_intr_lock);
1621772Sjl139090 
1631772Sjl139090 	if (!wait)
1641772Sjl139090 		goto wait_done;
1651772Sjl139090 
1661772Sjl139090 	intr_timeout = pcmu_intrpend_timeout;
1671772Sjl139090 	jump = TICK_TO_NSEC(xc_tick_jump_limit);
1681772Sjl139090 	start_time = curr = gethrtime();
1691772Sjl139090 	/* busy wait if there is interrupt being processed */
1701772Sjl139090 	while (PCMU_IB_INO_INTR_PENDING(state_reg_p, ino) && !panicstr) {
1711772Sjl139090 		/*
1721772Sjl139090 		 * If we have a really large jump in hrtime, it is most
1731772Sjl139090 		 * probably because we entered the debugger (or OBP,
1741772Sjl139090 		 * in general). So, we adjust the timeout accordingly
1751772Sjl139090 		 * to prevent declaring an interrupt timeout. The
1761772Sjl139090 		 * master-interrupt mechanism in OBP should deliver
1771772Sjl139090 		 * the interrupts properly.
1781772Sjl139090 		 */
1791772Sjl139090 		prev = curr;
1801772Sjl139090 		curr = gethrtime();
1811772Sjl139090 		interval = curr - prev;
1821772Sjl139090 		if (interval > jump)
1831772Sjl139090 			intr_timeout += interval;
1841772Sjl139090 		if (curr - start_time > intr_timeout) {
1851772Sjl139090 			pcmu_pbm_t *pcbm_p = pib_p->pib_pcmu_p->pcmu_pcbm_p;
1861772Sjl139090 			cmn_err(CE_WARN,
1871772Sjl139090 			    "%s:%s: pcmu_ib_intr_disable timeout %x",
1881772Sjl139090 			    pcbm_p->pcbm_nameinst_str,
1891772Sjl139090 			    pcbm_p->pcbm_nameaddr_str, ino);
1901772Sjl139090 			break;
1911772Sjl139090 		}
1921772Sjl139090 	}
1931772Sjl139090 wait_done:
1941772Sjl139090 	PCMU_IB_INO_INTR_PEND(ib_clear_intr_reg_addr(pib_p, ino));
1951772Sjl139090 	u2u_ittrans_cleanup((u2u_ittrans_data_t *)
1961772Sjl139090 	    (PCMU_IB2CB(pib_p)->pcb_ittrans_cookie), imr_p);
1971772Sjl139090 }
1981772Sjl139090 
1991772Sjl139090 /* can only used for CMU-CH internal interrupts ue, pbm */
2001772Sjl139090 void
pcmu_ib_nintr_clear(pcmu_ib_t * pib_p,pcmu_ib_ino_t ino)2011772Sjl139090 pcmu_ib_nintr_clear(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino)
2021772Sjl139090 {
2031772Sjl139090 	uint64_t *clr_reg = ib_clear_intr_reg_addr(pib_p, ino);
2041772Sjl139090 	PCMU_IB_INO_INTR_CLEAR(clr_reg);
2051772Sjl139090 }
2061772Sjl139090 
2071772Sjl139090 /*
2081772Sjl139090  * distribute PBM and UPA interrupts. ino is set to 0 by caller if we
2091772Sjl139090  * are dealing with UPA interrupts (without inos).
2101772Sjl139090  */
2111772Sjl139090 void
pcmu_ib_intr_dist_nintr(pcmu_ib_t * pib_p,pcmu_ib_ino_t ino,volatile uint64_t * imr_p)2121772Sjl139090 pcmu_ib_intr_dist_nintr(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino,
2131772Sjl139090     volatile uint64_t *imr_p)
2141772Sjl139090 {
2151772Sjl139090 	volatile uint64_t imr = *imr_p;
2161772Sjl139090 	uint32_t cpu_id;
2171772Sjl139090 
2181772Sjl139090 	if (!PCMU_IB_INO_INTR_ISON(imr))
2191772Sjl139090 		return;
2201772Sjl139090 
2211772Sjl139090 	cpu_id = intr_dist_cpuid();
2221772Sjl139090 
2231772Sjl139090 	if (ino) {
2241772Sjl139090 		cpu_id = u2u_translate_tgtid(pib_p->pib_pcmu_p, cpu_id, imr_p);
2251772Sjl139090 	}
2261772Sjl139090 
2271772Sjl139090 	if (ib_map_reg_get_cpu(*imr_p) == cpu_id) {
2281772Sjl139090 		return;
2291772Sjl139090 	}
2301772Sjl139090 	*imr_p = ib_get_map_reg(PCMU_IB_IMR2MONDO(imr), cpu_id);
2311772Sjl139090 	imr = *imr_p;	/* flush previous write */
2321772Sjl139090 }
2331772Sjl139090 
2341772Sjl139090 static void
pcmu_ib_intr_dist(pcmu_ib_t * pib_p,pcmu_ib_ino_info_t * ino_p)2351772Sjl139090 pcmu_ib_intr_dist(pcmu_ib_t *pib_p, pcmu_ib_ino_info_t *ino_p)
2361772Sjl139090 {
2371772Sjl139090 	uint32_t cpu_id = ino_p->pino_cpuid;
2381772Sjl139090 	pcmu_ib_ino_t ino = ino_p->pino_ino;
2391772Sjl139090 	volatile uint64_t imr, *imr_p, *state_reg;
2401772Sjl139090 	hrtime_t start_time;
2411772Sjl139090 	hrtime_t prev, curr, interval, jump;
2421772Sjl139090 	hrtime_t intr_timeout;
2431772Sjl139090 
2441772Sjl139090 	ASSERT(MUTEX_HELD(&pib_p->pib_ino_lst_mutex));
2451772Sjl139090 	imr_p = ib_intr_map_reg_addr(pib_p, ino);
2461772Sjl139090 	state_reg = PCMU_IB_INO_INTR_STATE_REG(pib_p, ino);
2471772Sjl139090 
2481772Sjl139090 	/* disable interrupt, this could disrupt devices sharing our slot */
2491772Sjl139090 	PCMU_IB_INO_INTR_OFF(imr_p);
2501772Sjl139090 	imr = *imr_p;	/* flush previous write */
2511772Sjl139090 
2521772Sjl139090 	/* busy wait if there is interrupt being processed */
2531772Sjl139090 	intr_timeout = pcmu_intrpend_timeout;
2541772Sjl139090 	jump = TICK_TO_NSEC(xc_tick_jump_limit);
2551772Sjl139090 	start_time = curr = gethrtime();
2561772Sjl139090 	while (PCMU_IB_INO_INTR_PENDING(state_reg, ino) && !panicstr) {
2571772Sjl139090 		/*
2581772Sjl139090 		 * If we have a really large jump in hrtime, it is most
2591772Sjl139090 		 * probably because we entered the debugger (or OBP,
2601772Sjl139090 		 * in general). So, we adjust the timeout accordingly
2611772Sjl139090 		 * to prevent declaring an interrupt timeout. The
2621772Sjl139090 		 * master-interrupt mechanism in OBP should deliver
2631772Sjl139090 		 * the interrupts properly.
2641772Sjl139090 		 */
2651772Sjl139090 		prev = curr;
2661772Sjl139090 		curr = gethrtime();
2671772Sjl139090 		interval = curr - prev;
2681772Sjl139090 		if (interval > jump)
2691772Sjl139090 			intr_timeout += interval;
2701772Sjl139090 		if (curr - start_time > intr_timeout) {
2711772Sjl139090 			pcmu_pbm_t *pcbm_p = pib_p->pib_pcmu_p->pcmu_pcbm_p;
2721772Sjl139090 			cmn_err(CE_WARN,
2731772Sjl139090 			    "%s:%s: pcmu_ib_intr_dist(%p,%x) timeout",
2741772Sjl139090 			    pcbm_p->pcbm_nameinst_str,
2751772Sjl139090 			    pcbm_p->pcbm_nameaddr_str,
276*11311SSurya.Prakki@Sun.COM 			    (void *)imr_p, PCMU_IB_INO_TO_MONDO(pib_p, ino));
2771772Sjl139090 			break;
2781772Sjl139090 		}
2791772Sjl139090 	}
2801772Sjl139090 	cpu_id = u2u_translate_tgtid(pib_p->pib_pcmu_p, cpu_id, imr_p);
2811772Sjl139090 	*imr_p = ib_get_map_reg(PCMU_IB_IMR2MONDO(imr), cpu_id);
2821772Sjl139090 	imr = *imr_p;	/* flush previous write */
2831772Sjl139090 }
2841772Sjl139090 
2851772Sjl139090 /*
2861772Sjl139090  * Redistribute interrupts of the specified weight. The first call has a weight
2871772Sjl139090  * of weight_max, which can be used to trigger initialization for
2881772Sjl139090  * redistribution. The inos with weight [weight_max, inf.) should be processed
2891772Sjl139090  * on the "weight == weight_max" call.  This first call is followed by calls
2901772Sjl139090  * of decreasing weights, inos of that weight should be processed.  The final
2911772Sjl139090  * call specifies a weight of zero, this can be used to trigger processing of
2921772Sjl139090  * stragglers.
2931772Sjl139090  */
2941772Sjl139090 void
pcmu_ib_intr_dist_all(void * arg,int32_t weight_max,int32_t weight)2951772Sjl139090 pcmu_ib_intr_dist_all(void *arg, int32_t weight_max, int32_t weight)
2961772Sjl139090 {
2971772Sjl139090 	pcmu_ib_t *pib_p = (pcmu_ib_t *)arg;
2981772Sjl139090 	pcmu_ib_ino_info_t *ino_p;
2991772Sjl139090 	ih_t *ih_lst;
3001772Sjl139090 	int32_t dweight;
3011772Sjl139090 	int i;
3021772Sjl139090 
3031772Sjl139090 	mutex_enter(&pib_p->pib_ino_lst_mutex);
3041772Sjl139090 
3051772Sjl139090 	/* Perform special processing for first call of a redistribution. */
3061772Sjl139090 	if (weight == weight_max) {
3071772Sjl139090 		for (ino_p = pib_p->pib_ino_lst; ino_p;
3081772Sjl139090 		    ino_p = ino_p->pino_next) {
3091772Sjl139090 
3101772Sjl139090 			/*
3111772Sjl139090 			 * Clear pino_established of each ino on first call.
3121772Sjl139090 			 * The pino_established field may be used by a pci
3131772Sjl139090 			 * nexus driver's pcmu_intr_dist_cpuid implementation
3141772Sjl139090 			 * when detection of established pci slot-cpu binding
3151772Sjl139090 			 * for multi function pci cards.
3161772Sjl139090 			 */
3171772Sjl139090 			ino_p->pino_established = 0;
3181772Sjl139090 
3191772Sjl139090 			/*
3201772Sjl139090 			 * recompute the pino_intr_weight based on the device
3211772Sjl139090 			 * weight of all devinfo nodes sharing the ino (this
3221772Sjl139090 			 * will allow us to pick up new weights established by
3231772Sjl139090 			 * i_ddi_set_intr_weight()).
3241772Sjl139090 			 */
3251772Sjl139090 			ino_p->pino_intr_weight = 0;
3261772Sjl139090 			for (i = 0, ih_lst = ino_p->pino_ih_head;
3271772Sjl139090 			    i < ino_p->pino_ih_size;
3281772Sjl139090 			    i++, ih_lst = ih_lst->ih_next) {
3291772Sjl139090 				dweight = i_ddi_get_intr_weight(ih_lst->ih_dip);
3301772Sjl139090 				if (dweight > 0)
3311772Sjl139090 					ino_p->pino_intr_weight += dweight;
3321772Sjl139090 			}
3331772Sjl139090 		}
3341772Sjl139090 	}
3351772Sjl139090 
3361772Sjl139090 	for (ino_p = pib_p->pib_ino_lst; ino_p; ino_p = ino_p->pino_next) {
3371772Sjl139090 		/*
3381772Sjl139090 		 * Get the weight of the ino and determine if we are going to
3391772Sjl139090 		 * process call.  We wait until an pcmu_ib_intr_dist_all call of
3401772Sjl139090 		 * the proper weight occurs to support redistribution of all
3411772Sjl139090 		 * heavy weighted interrupts first (across all nexus driver
3421772Sjl139090 		 * instances).  This is done to ensure optimal
3431772Sjl139090 		 * INTR_WEIGHTED_DIST behavior.
3441772Sjl139090 		 */
3451772Sjl139090 		if ((weight == ino_p->pino_intr_weight) ||
3461772Sjl139090 		    ((weight >= weight_max) &&
3471772Sjl139090 		    (ino_p->pino_intr_weight >= weight_max))) {
3481772Sjl139090 			/* select cpuid to target and mark ino established */
3491772Sjl139090 			ino_p->pino_cpuid = pcmu_intr_dist_cpuid(pib_p, ino_p);
3501772Sjl139090 			ino_p->pino_established = 1;
3511772Sjl139090 
3521772Sjl139090 			/* Add device weight of ino devinfos to targeted cpu. */
3531772Sjl139090 			for (i = 0, ih_lst = ino_p->pino_ih_head;
3541772Sjl139090 			    i < ino_p->pino_ih_size;
3551772Sjl139090 			    i++, ih_lst = ih_lst->ih_next) {
3561772Sjl139090 				dweight = i_ddi_get_intr_weight(ih_lst->ih_dip);
3571772Sjl139090 				intr_dist_cpuid_add_device_weight(
3581772Sjl139090 				    ino_p->pino_cpuid, ih_lst->ih_dip, dweight);
3591772Sjl139090 			}
3601772Sjl139090 
3611772Sjl139090 			/* program the hardware */
3621772Sjl139090 			pcmu_ib_intr_dist(pib_p, ino_p);
3631772Sjl139090 		}
3641772Sjl139090 	}
3651772Sjl139090 	mutex_exit(&pib_p->pib_ino_lst_mutex);
3661772Sjl139090 }
3671772Sjl139090 
3681772Sjl139090 /*
3691772Sjl139090  * Reset interrupts to IDLE.  This function is called during
3701772Sjl139090  * panic handling after redistributing interrupts; it's needed to
3711772Sjl139090  * support dumping to network devices after 'sync' from OBP.
3721772Sjl139090  *
3731772Sjl139090  * N.B.  This routine runs in a context where all other threads
3741772Sjl139090  * are permanently suspended.
3751772Sjl139090  */
3761772Sjl139090 static uint_t
pcmu_ib_intr_reset(void * arg)3771772Sjl139090 pcmu_ib_intr_reset(void *arg)
3781772Sjl139090 {
3791772Sjl139090 	pcmu_ib_t *pib_p = (pcmu_ib_t *)arg;
3801772Sjl139090 	pcmu_ib_ino_t ino;
3811772Sjl139090 	uint64_t *clr_reg;
3821772Sjl139090 
3831772Sjl139090 	/*
3841772Sjl139090 	 * Note that we only actually care about interrupts that are
3851772Sjl139090 	 * potentially from network devices.
3861772Sjl139090 	 */
3871772Sjl139090 	for (ino = 0; ino <= pib_p->pib_max_ino; ino++) {
3881772Sjl139090 		clr_reg = ib_clear_intr_reg_addr(pib_p, ino);
3891772Sjl139090 		PCMU_IB_INO_INTR_CLEAR(clr_reg);
3901772Sjl139090 	}
3911772Sjl139090 	return (BF_NONE);
3921772Sjl139090 }
3931772Sjl139090 
3941772Sjl139090 void
pcmu_ib_suspend(pcmu_ib_t * pib_p)3951772Sjl139090 pcmu_ib_suspend(pcmu_ib_t *pib_p)
3961772Sjl139090 {
3971772Sjl139090 	pcmu_ib_ino_info_t *ip;
3981772Sjl139090 
3991772Sjl139090 	/* save ino_lst interrupts' mapping registers content */
4001772Sjl139090 	mutex_enter(&pib_p->pib_ino_lst_mutex);
4011772Sjl139090 	for (ip = pib_p->pib_ino_lst; ip; ip = ip->pino_next) {
4021772Sjl139090 		ip->pino_map_reg_save = *ip->pino_map_reg;
4031772Sjl139090 	}
4041772Sjl139090 	mutex_exit(&pib_p->pib_ino_lst_mutex);
4051772Sjl139090 }
4061772Sjl139090 
4071772Sjl139090 void
pcmu_ib_resume(pcmu_ib_t * pib_p)4081772Sjl139090 pcmu_ib_resume(pcmu_ib_t *pib_p)
4091772Sjl139090 {
4101772Sjl139090 	pcmu_ib_ino_info_t *ip;
4111772Sjl139090 
4121772Sjl139090 	/* restore ino_lst interrupts' mapping registers content */
4131772Sjl139090 	mutex_enter(&pib_p->pib_ino_lst_mutex);
4141772Sjl139090 	for (ip = pib_p->pib_ino_lst; ip; ip = ip->pino_next) {
4151772Sjl139090 		PCMU_IB_INO_INTR_CLEAR(ip->pino_clr_reg); /* set intr to idle */
4161772Sjl139090 		*ip->pino_map_reg = ip->pino_map_reg_save; /* restore IMR */
4171772Sjl139090 	}
4181772Sjl139090 	mutex_exit(&pib_p->pib_ino_lst_mutex);
4191772Sjl139090 }
4201772Sjl139090 
4211772Sjl139090 /*
4221772Sjl139090  * locate ino_info structure on pib_p->pib_ino_lst according to ino#
4231772Sjl139090  * returns NULL if not found.
4241772Sjl139090  */
4251772Sjl139090 pcmu_ib_ino_info_t *
pcmu_ib_locate_ino(pcmu_ib_t * pib_p,pcmu_ib_ino_t ino_num)4261772Sjl139090 pcmu_ib_locate_ino(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino_num)
4271772Sjl139090 {
4281772Sjl139090 	pcmu_ib_ino_info_t *ino_p = pib_p->pib_ino_lst;
4291772Sjl139090 	ASSERT(MUTEX_HELD(&pib_p->pib_ino_lst_mutex));
4301772Sjl139090 
4316587Sjfrank 	for (; ino_p && ino_p->pino_ino != ino_num; ino_p = ino_p->pino_next)
4326587Sjfrank 		;
4331772Sjl139090 	return (ino_p);
4341772Sjl139090 }
4351772Sjl139090 
4361772Sjl139090 #define	PCMU_IB_INO_TO_SLOT(ino)		\
4371772Sjl139090 	(PCMU_IB_IS_OBIO_INO(ino) ? 0xff : ((ino) & 0x1f) >> 2)
4381772Sjl139090 
4391772Sjl139090 pcmu_ib_ino_info_t *
pcmu_ib_new_ino(pcmu_ib_t * pib_p,pcmu_ib_ino_t ino_num,ih_t * ih_p)4401772Sjl139090 pcmu_ib_new_ino(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino_num, ih_t *ih_p)
4411772Sjl139090 {
4421772Sjl139090 	pcmu_ib_ino_info_t *ino_p = kmem_alloc(sizeof (pcmu_ib_ino_info_t),
4431772Sjl139090 	    KM_SLEEP);
4441772Sjl139090 	ino_p->pino_ino = ino_num;
4451772Sjl139090 	ino_p->pino_slot_no = PCMU_IB_INO_TO_SLOT(ino_num);
4461772Sjl139090 	ino_p->pino_ib_p = pib_p;
4471772Sjl139090 	ino_p->pino_clr_reg = ib_clear_intr_reg_addr(pib_p, ino_num);
4481772Sjl139090 	ino_p->pino_map_reg = ib_intr_map_reg_addr(pib_p, ino_num);
4491772Sjl139090 	ino_p->pino_unclaimed = 0;
4501772Sjl139090 
4511772Sjl139090 	/*
4521772Sjl139090 	 * cannot disable interrupt since we might share slot
4531772Sjl139090 	 * PCMU_IB_INO_INTR_OFF(ino_p->pino_map_reg);
4541772Sjl139090 	 */
4551772Sjl139090 
4561772Sjl139090 	ih_p->ih_next = ih_p;
4571772Sjl139090 	ino_p->pino_ih_head = ih_p;
4581772Sjl139090 	ino_p->pino_ih_tail = ih_p;
4591772Sjl139090 	ino_p->pino_ih_start = ih_p;
4601772Sjl139090 	ino_p->pino_ih_size = 1;
4611772Sjl139090 
4621772Sjl139090 	ino_p->pino_next = pib_p->pib_ino_lst;
4631772Sjl139090 	pib_p->pib_ino_lst = ino_p;
4641772Sjl139090 	return (ino_p);
4651772Sjl139090 }
4661772Sjl139090 
4671772Sjl139090 /* the ino_p is retrieved by previous call to pcmu_ib_locate_ino() */
4681772Sjl139090 void
pcmu_ib_delete_ino(pcmu_ib_t * pib_p,pcmu_ib_ino_info_t * ino_p)4691772Sjl139090 pcmu_ib_delete_ino(pcmu_ib_t *pib_p, pcmu_ib_ino_info_t *ino_p)
4701772Sjl139090 {
4711772Sjl139090 	pcmu_ib_ino_info_t *list = pib_p->pib_ino_lst;
4721772Sjl139090 	ASSERT(MUTEX_HELD(&pib_p->pib_ino_lst_mutex));
4731772Sjl139090 	if (list == ino_p) {
4741772Sjl139090 		pib_p->pib_ino_lst = list->pino_next;
4751772Sjl139090 	} else {
4766587Sjfrank 		for (; list->pino_next != ino_p; list = list->pino_next)
4776587Sjfrank 			;
4781772Sjl139090 		list->pino_next = ino_p->pino_next;
4791772Sjl139090 	}
4801772Sjl139090 }
4811772Sjl139090 
4821772Sjl139090 /* free all ino when we are detaching */
4831772Sjl139090 void
pcmu_ib_free_ino_all(pcmu_ib_t * pib_p)4841772Sjl139090 pcmu_ib_free_ino_all(pcmu_ib_t *pib_p)
4851772Sjl139090 {
4861772Sjl139090 	pcmu_ib_ino_info_t *tmp = pib_p->pib_ino_lst;
4871772Sjl139090 	pcmu_ib_ino_info_t *next = NULL;
4881772Sjl139090 	while (tmp) {
4891772Sjl139090 		next = tmp->pino_next;
4901772Sjl139090 		kmem_free(tmp, sizeof (pcmu_ib_ino_info_t));
4911772Sjl139090 		tmp = next;
4921772Sjl139090 	}
4931772Sjl139090 }
4941772Sjl139090 
4951772Sjl139090 void
pcmu_ib_ino_add_intr(pcmu_t * pcmu_p,pcmu_ib_ino_info_t * ino_p,ih_t * ih_p)4961772Sjl139090 pcmu_ib_ino_add_intr(pcmu_t *pcmu_p, pcmu_ib_ino_info_t *ino_p, ih_t *ih_p)
4971772Sjl139090 {
4981772Sjl139090 	pcmu_ib_ino_t ino = ino_p->pino_ino;
4991772Sjl139090 	pcmu_ib_t *pib_p = ino_p->pino_ib_p;
5001772Sjl139090 	volatile uint64_t *state_reg = PCMU_IB_INO_INTR_STATE_REG(pib_p, ino);
5011772Sjl139090 	hrtime_t start_time;
5021772Sjl139090 	hrtime_t prev, curr, interval, jump;
5031772Sjl139090 	hrtime_t intr_timeout;
5041772Sjl139090 
5051772Sjl139090 	ASSERT(pib_p == pcmu_p->pcmu_ib_p);
5061772Sjl139090 	ASSERT(MUTEX_HELD(&pib_p->pib_ino_lst_mutex));
5071772Sjl139090 
5081772Sjl139090 	/* disable interrupt, this could disrupt devices sharing our slot */
5091772Sjl139090 	PCMU_IB_INO_INTR_OFF(ino_p->pino_map_reg);
5101772Sjl139090 	*ino_p->pino_map_reg;
5111772Sjl139090 
5121772Sjl139090 	/* do NOT modify the link list until after the busy wait */
5131772Sjl139090 
5141772Sjl139090 	/*
5151772Sjl139090 	 * busy wait if there is interrupt being processed.
5161772Sjl139090 	 * either the pending state will be cleared by the interrupt wrapper
5171772Sjl139090 	 * or the interrupt will be marked as blocked indicating that it was
5181772Sjl139090 	 * jabbering.
5191772Sjl139090 	 */
5201772Sjl139090 	intr_timeout = pcmu_intrpend_timeout;
5211772Sjl139090 	jump = TICK_TO_NSEC(xc_tick_jump_limit);
5221772Sjl139090 	start_time = curr = gethrtime();
5231772Sjl139090 	while ((ino_p->pino_unclaimed <= pcmu_unclaimed_intr_max) &&
5246587Sjfrank 	    PCMU_IB_INO_INTR_PENDING(state_reg, ino) && !panicstr) {
5251772Sjl139090 		/*
5261772Sjl139090 		 * If we have a really large jump in hrtime, it is most
5271772Sjl139090 		 * probably because we entered the debugger (or OBP,
5281772Sjl139090 		 * in general). So, we adjust the timeout accordingly
5291772Sjl139090 		 * to prevent declaring an interrupt timeout. The
5301772Sjl139090 		 * master-interrupt mechanism in OBP should deliver
5311772Sjl139090 		 * the interrupts properly.
5321772Sjl139090 		 */
5331772Sjl139090 		prev = curr;
5341772Sjl139090 		curr = gethrtime();
5351772Sjl139090 		interval = curr - prev;
5361772Sjl139090 		if (interval > jump)
5371772Sjl139090 			intr_timeout += interval;
5381772Sjl139090 		if (curr - start_time > intr_timeout) {
5391772Sjl139090 			pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
5401772Sjl139090 			cmn_err(CE_WARN,
5411772Sjl139090 			    "%s:%s: pcmu_ib_ino_add_intr %x timeout",
5421772Sjl139090 			    pcbm_p->pcbm_nameinst_str,
5431772Sjl139090 			    pcbm_p->pcbm_nameaddr_str, ino);
5441772Sjl139090 			break;
5451772Sjl139090 		}
5461772Sjl139090 	}
5471772Sjl139090 
5481772Sjl139090 	/* link up pcmu_ispec_t portion of the ppd */
5491772Sjl139090 	ih_p->ih_next = ino_p->pino_ih_head;
5501772Sjl139090 	ino_p->pino_ih_tail->ih_next = ih_p;
5511772Sjl139090 	ino_p->pino_ih_tail = ih_p;
5521772Sjl139090 
5531772Sjl139090 	ino_p->pino_ih_start = ino_p->pino_ih_head;
5541772Sjl139090 	ino_p->pino_ih_size++;
5551772Sjl139090 
5561772Sjl139090 	/*
5571772Sjl139090 	 * if the interrupt was previously blocked (left in pending state)
5581772Sjl139090 	 * because of jabber we need to clear the pending state in case the
5591772Sjl139090 	 * jabber has gone away.
5601772Sjl139090 	 */
5611772Sjl139090 	if (ino_p->pino_unclaimed > pcmu_unclaimed_intr_max) {
5621772Sjl139090 		cmn_err(CE_WARN,
5631772Sjl139090 		    "%s%d: pcmu_ib_ino_add_intr: ino 0x%x has been unblocked",
5641772Sjl139090 		    ddi_driver_name(pcmu_p->pcmu_dip),
5651772Sjl139090 		    ddi_get_instance(pcmu_p->pcmu_dip),
5661772Sjl139090 		    ino_p->pino_ino);
5671772Sjl139090 		ino_p->pino_unclaimed = 0;
5681772Sjl139090 		PCMU_IB_INO_INTR_CLEAR(ino_p->pino_clr_reg);
5691772Sjl139090 	}
5701772Sjl139090 
5711772Sjl139090 	/* re-enable interrupt */
5721772Sjl139090 	PCMU_IB_INO_INTR_ON(ino_p->pino_map_reg);
5731772Sjl139090 	*ino_p->pino_map_reg;
5741772Sjl139090 }
5751772Sjl139090 
5761772Sjl139090 /*
5771772Sjl139090  * removes pcmu_ispec_t from the ino's link list.
5781772Sjl139090  * uses hardware mutex to lock out interrupt threads.
5791772Sjl139090  * Side effects: interrupt belongs to that ino is turned off on return.
5801772Sjl139090  * if we are sharing PCI slot with other inos, the caller needs
5811772Sjl139090  * to turn it back on.
5821772Sjl139090  */
5836587Sjfrank int
pcmu_ib_ino_rem_intr(pcmu_t * pcmu_p,pcmu_ib_ino_info_t * ino_p,ih_t * ih_p)5841772Sjl139090 pcmu_ib_ino_rem_intr(pcmu_t *pcmu_p, pcmu_ib_ino_info_t *ino_p, ih_t *ih_p)
5851772Sjl139090 {
5861772Sjl139090 	int i;
5871772Sjl139090 	pcmu_ib_ino_t ino = ino_p->pino_ino;
5881772Sjl139090 	ih_t *ih_lst = ino_p->pino_ih_head;
5891772Sjl139090 	volatile uint64_t *state_reg =
5906587Sjfrank 	    PCMU_IB_INO_INTR_STATE_REG(ino_p->pino_ib_p, ino);
5911772Sjl139090 	hrtime_t start_time;
5921772Sjl139090 	hrtime_t prev, curr, interval, jump;
5931772Sjl139090 	hrtime_t intr_timeout;
5941772Sjl139090 
5951772Sjl139090 	ASSERT(MUTEX_HELD(&ino_p->pino_ib_p->pib_ino_lst_mutex));
5961772Sjl139090 	/* disable interrupt, this could disrupt devices sharing our slot */
5971772Sjl139090 	PCMU_IB_INO_INTR_OFF(ino_p->pino_map_reg);
5981772Sjl139090 	*ino_p->pino_map_reg;
5991772Sjl139090 
6001772Sjl139090 	/* do NOT modify the link list until after the busy wait */
6011772Sjl139090 
6021772Sjl139090 	/*
6031772Sjl139090 	 * busy wait if there is interrupt being processed.
6041772Sjl139090 	 * either the pending state will be cleared by the interrupt wrapper
6051772Sjl139090 	 * or the interrupt will be marked as blocked indicating that it was
6061772Sjl139090 	 * jabbering.
6071772Sjl139090 	 */
6081772Sjl139090 	intr_timeout = pcmu_intrpend_timeout;
6091772Sjl139090 	jump = TICK_TO_NSEC(xc_tick_jump_limit);
6101772Sjl139090 	start_time = curr = gethrtime();
6111772Sjl139090 	while ((ino_p->pino_unclaimed <= pcmu_unclaimed_intr_max) &&
6126587Sjfrank 	    PCMU_IB_INO_INTR_PENDING(state_reg, ino) && !panicstr) {
6131772Sjl139090 		/*
6141772Sjl139090 		 * If we have a really large jump in hrtime, it is most
6151772Sjl139090 		 * probably because we entered the debugger (or OBP,
6161772Sjl139090 		 * in general). So, we adjust the timeout accordingly
6171772Sjl139090 		 * to prevent declaring an interrupt timeout. The
6181772Sjl139090 		 * master-interrupt mechanism in OBP should deliver
6191772Sjl139090 		 * the interrupts properly.
6201772Sjl139090 		 */
6211772Sjl139090 		prev = curr;
6221772Sjl139090 		curr = gethrtime();
6231772Sjl139090 		interval = curr - prev;
6241772Sjl139090 		if (interval > jump)
6251772Sjl139090 			intr_timeout += interval;
6261772Sjl139090 		if (curr - start_time > intr_timeout) {
6271772Sjl139090 			pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
6281772Sjl139090 			cmn_err(CE_WARN,
6291772Sjl139090 			    "%s:%s: pcmu_ib_ino_rem_intr %x timeout",
6301772Sjl139090 			    pcbm_p->pcbm_nameinst_str,
6311772Sjl139090 			    pcbm_p->pcbm_nameaddr_str, ino);
6326587Sjfrank 			PCMU_IB_INO_INTR_ON(ino_p->pino_map_reg);
6336587Sjfrank 			*ino_p->pino_map_reg;
6346587Sjfrank 			return (DDI_FAILURE);
6351772Sjl139090 		}
6361772Sjl139090 	}
6371772Sjl139090 
6381772Sjl139090 	if (ino_p->pino_ih_size == 1) {
6391772Sjl139090 		if (ih_lst != ih_p)
6401772Sjl139090 			goto not_found;
6411772Sjl139090 		/* no need to set head/tail as ino_p will be freed */
6421772Sjl139090 		goto reset;
6431772Sjl139090 	}
6441772Sjl139090 
6451772Sjl139090 	/*
6461772Sjl139090 	 * if the interrupt was previously blocked (left in pending state)
6471772Sjl139090 	 * because of jabber we need to clear the pending state in case the
6481772Sjl139090 	 * jabber has gone away.
6491772Sjl139090 	 */
6501772Sjl139090 	if (ino_p->pino_unclaimed > pcmu_unclaimed_intr_max) {
6511772Sjl139090 		cmn_err(CE_WARN,
6521772Sjl139090 		    "%s%d: pcmu_ib_ino_rem_intr: ino 0x%x has been unblocked",
6531772Sjl139090 		    ddi_driver_name(pcmu_p->pcmu_dip),
6541772Sjl139090 		    ddi_get_instance(pcmu_p->pcmu_dip),
6551772Sjl139090 		    ino_p->pino_ino);
6561772Sjl139090 		ino_p->pino_unclaimed = 0;
6571772Sjl139090 		PCMU_IB_INO_INTR_CLEAR(ino_p->pino_clr_reg);
6581772Sjl139090 	}
6591772Sjl139090 
6601772Sjl139090 	/* search the link list for ih_p */
6611772Sjl139090 	for (i = 0; (i < ino_p->pino_ih_size) && (ih_lst->ih_next != ih_p);
6626587Sjfrank 	    i++, ih_lst = ih_lst->ih_next)
6636587Sjfrank 		;
6641772Sjl139090 	if (ih_lst->ih_next != ih_p) {
6651772Sjl139090 		goto not_found;
6661772Sjl139090 	}
6671772Sjl139090 
6681772Sjl139090 	/* remove ih_p from the link list and maintain the head/tail */
6691772Sjl139090 	ih_lst->ih_next = ih_p->ih_next;
6701772Sjl139090 	if (ino_p->pino_ih_head == ih_p) {
6711772Sjl139090 		ino_p->pino_ih_head = ih_p->ih_next;
6721772Sjl139090 	}
6731772Sjl139090 	if (ino_p->pino_ih_tail == ih_p) {
6741772Sjl139090 		ino_p->pino_ih_tail = ih_lst;
6751772Sjl139090 	}
6761772Sjl139090 	ino_p->pino_ih_start = ino_p->pino_ih_head;
6771772Sjl139090 reset:
6781772Sjl139090 	if (ih_p->ih_config_handle) {
6791772Sjl139090 		pci_config_teardown(&ih_p->ih_config_handle);
6801772Sjl139090 	}
6811772Sjl139090 	kmem_free(ih_p, sizeof (ih_t));
6821772Sjl139090 	ino_p->pino_ih_size--;
6831772Sjl139090 
6846587Sjfrank 	return (DDI_SUCCESS);
6851772Sjl139090 not_found:
6861772Sjl139090 	PCMU_DBG2(PCMU_DBG_R_INTX, ino_p->pino_ib_p->pib_pcmu_p->pcmu_dip,
6871772Sjl139090 	    "ino_p=%x does not have ih_p=%x\n", ino_p, ih_p);
6886587Sjfrank 	return (DDI_SUCCESS);
6891772Sjl139090 }
6901772Sjl139090 
6911772Sjl139090 ih_t *
pcmu_ib_ino_locate_intr(pcmu_ib_ino_info_t * ino_p,dev_info_t * rdip,uint32_t inum)6921772Sjl139090 pcmu_ib_ino_locate_intr(pcmu_ib_ino_info_t *ino_p,
6931772Sjl139090     dev_info_t *rdip, uint32_t inum)
6941772Sjl139090 {
6951772Sjl139090 	ih_t *ih_lst = ino_p->pino_ih_head;
6961772Sjl139090 	int i;
6971772Sjl139090 	for (i = 0; i < ino_p->pino_ih_size; i++, ih_lst = ih_lst->ih_next) {
6981772Sjl139090 		if (ih_lst->ih_dip == rdip && ih_lst->ih_inum == inum) {
6991772Sjl139090 			return (ih_lst);
7001772Sjl139090 		}
7011772Sjl139090 	}
7021772Sjl139090 	return ((ih_t *)NULL);
7031772Sjl139090 }
7041772Sjl139090 
7051772Sjl139090 ih_t *
pcmu_ib_alloc_ih(dev_info_t * rdip,uint32_t inum,uint_t (* int_handler)(caddr_t int_handler_arg1,caddr_t int_handler_arg2),caddr_t int_handler_arg1,caddr_t int_handler_arg2)7061772Sjl139090 pcmu_ib_alloc_ih(dev_info_t *rdip, uint32_t inum,
7071772Sjl139090     uint_t (*int_handler)(caddr_t int_handler_arg1, caddr_t int_handler_arg2),
7081772Sjl139090     caddr_t int_handler_arg1,
7091772Sjl139090     caddr_t int_handler_arg2)
7101772Sjl139090 {
7111772Sjl139090 	ih_t *ih_p;
7121772Sjl139090 
7131772Sjl139090 	ih_p = kmem_alloc(sizeof (ih_t), KM_SLEEP);
7141772Sjl139090 	ih_p->ih_dip = rdip;
7151772Sjl139090 	ih_p->ih_inum = inum;
7161772Sjl139090 	ih_p->ih_intr_state = PCMU_INTR_STATE_DISABLE;
7171772Sjl139090 	ih_p->ih_handler = int_handler;
7181772Sjl139090 	ih_p->ih_handler_arg1 = int_handler_arg1;
7191772Sjl139090 	ih_p->ih_handler_arg2 = int_handler_arg2;
7201772Sjl139090 	ih_p->ih_config_handle = NULL;
7211772Sjl139090 	return (ih_p);
7221772Sjl139090 }
7231772Sjl139090 
7241772Sjl139090 int
pcmu_ib_update_intr_state(pcmu_t * pcmu_p,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp,uint_t new_intr_state)7251772Sjl139090 pcmu_ib_update_intr_state(pcmu_t *pcmu_p, dev_info_t *rdip,
7261772Sjl139090     ddi_intr_handle_impl_t *hdlp, uint_t new_intr_state)
7271772Sjl139090 {
7281772Sjl139090 	pcmu_ib_t		*pib_p = pcmu_p->pcmu_ib_p;
7291772Sjl139090 	pcmu_ib_ino_info_t	*ino_p;
7301772Sjl139090 	pcmu_ib_mondo_t	mondo;
7311772Sjl139090 	ih_t		*ih_p;
7321772Sjl139090 	int		ret = DDI_FAILURE;
7331772Sjl139090 
7341772Sjl139090 	mutex_enter(&pib_p->pib_ino_lst_mutex);
7351772Sjl139090 
7361772Sjl139090 	if ((mondo = PCMU_IB_INO_TO_MONDO(pcmu_p->pcmu_ib_p,
7371772Sjl139090 	    PCMU_IB_MONDO_TO_INO((int32_t)hdlp->ih_vector))) == 0) {
7381772Sjl139090 		mutex_exit(&pib_p->pib_ino_lst_mutex);
7391772Sjl139090 		return (ret);
7401772Sjl139090 	}
7411772Sjl139090 
7421772Sjl139090 	if (ino_p = pcmu_ib_locate_ino(pib_p, PCMU_IB_MONDO_TO_INO(mondo))) {
7431772Sjl139090 		if (ih_p = pcmu_ib_ino_locate_intr(ino_p,
7441772Sjl139090 		    rdip, hdlp->ih_inum)) {
7451772Sjl139090 			ih_p->ih_intr_state = new_intr_state;
7461772Sjl139090 			ret = DDI_SUCCESS;
7471772Sjl139090 		}
7481772Sjl139090 	}
7491772Sjl139090 	mutex_exit(&pib_p->pib_ino_lst_mutex);
7501772Sjl139090 	return (ret);
7511772Sjl139090 }
752