rem: if (ret != DDI_SUCCESS) goto done;
add: if (ret != DDI_SUCCESS) { mutex_exit(&softsp->intr_poll_list_lock); goto done; }
context: sbus_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,    ddi_intr_handle_impl_t *hdlp){	struct sbus_soft_state *softsp = (struct sbus_soft_state *)	    ddi_get_soft_state(sbusp, ddi_get_instance(dip));	volatile uint64_t *mondo_vec_reg;	volatile uint64_t tmp_mondo_vec;	volatile uint64_t *intr_state_reg;	volatile uint64_t tmpreg;	/* HW flush reg */	uint_t start_bit;	int ino;	uint_t cpu_id;	struct sbus_wrapper_arg *sbus_arg;	struct sbus_intr_handler *intr_handler;	uint32_t slot;	/* Interrupt state machine reset flag */	int reset_ism_register = 1;	int ret = DDI_SUCCESS;	/* Check if we have a valid sbus slot address */	if (((slot = (uint_t)find_sbus_slot(dip, rdip)) >=	    MAX_SBUS_SLOT_ADDR) || (slot < (uint_t)0)) {		cmn_err(CE_WARN, "Invalid sbus slot 0x%x during add intr\n",		    slot);		return (DDI_FAILURE);	}	DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: sbus interrupt %d "	    "for device %s%d\n", hdlp->ih_vector, ddi_driver_name(rdip),	    ddi_get_instance(rdip)));	/* Xlate the interrupt */	if (sbus_xlate_intrs(dip, rdip, (uint32_t *)&hdlp->ih_vector,	    &hdlp->ih_pri, softsp->intr_mapping_ign) == DDI_FAILURE) {		cmn_err(CE_WARN, "Can't xlate SBUS devices %s interrupt.\n",		    ddi_driver_name(rdip));		return (DDI_FAILURE);	}	/* get the ino number */	ino = hdlp->ih_vector & SBUS_MAX_INO;	mondo_vec_reg = (softsp->intr_mapping_reg +	    ino_table[ino]->mapping_reg);	/*	 * This is an intermediate step in identifying	 * the exact bits which represent the device in the interrupt	 * state diagnostic register.	 */	if (ino > MAX_MONDO_EXTERNAL) {		start_bit = ino_table[ino]->diagreg_shift;		intr_state_reg = softsp->obio_intr_state;	} else {		start_bit = 16 * (ino >> 3) + 2 * (ino & 0x7);		intr_state_reg = softsp->sbus_intr_state;	}	/* Allocate a nexus interrupt data structure */	intr_handler = kmem_zalloc(sizeof (struct sbus_intr_handler), KM_SLEEP);	intr_handler->dip = rdip;	intr_handler->funcp = hdlp->ih_cb_func;	intr_handler->arg1 = hdlp->ih_cb_arg1;	intr_handler->arg2 = hdlp->ih_cb_arg2;	intr_handler->inum = hdlp->ih_inum;	DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: xlated interrupt 0x%x "	    "intr_handler 0x%x\n", hdlp->ih_vector, intr_handler));	/*	 * Grab this lock here. So it will protect the poll list.	 */	mutex_enter(&softsp->intr_poll_list_lock);	sbus_arg = softsp->intr_list[ino];	/* Check if we have a poll list to deal with */	if (sbus_arg) {		tmp_mondo_vec = *mondo_vec_reg;		tmp_mondo_vec &= ~INTERRUPT_VALID;		*mondo_vec_reg = tmp_mondo_vec;		tmpreg = *softsp->sbus_ctrl_reg;#ifdef	lint		tmpreg = tmpreg;#endif		DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr:sbus_arg exists "		    "0x%x\n", sbus_arg));		/*		 * Two bits per ino in the diagnostic register		 * indicate the status of its interrupt.		 * 0 - idle, 1 - transmit, 3 - pending.		 */		while (((*intr_state_reg >>		    start_bit) & 0x3) == INT_PENDING && !panicstr)			/* empty */;		intr_handler->next = sbus_arg->handler_list;		sbus_arg->handler_list = intr_handler;		reset_ism_register = 0;	} else {		sbus_arg = kmem_zalloc(sizeof (struct sbus_wrapper_arg),		    KM_SLEEP);		softsp->intr_list[ino] = sbus_arg;		sbus_arg->clear_reg = (softsp->clr_intr_reg +		    ino_table[ino]->clear_reg);		DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr:Ino 0x%x Interrupt "		    "clear reg: 0x%x\n", ino, sbus_arg->clear_reg));		sbus_arg->softsp = softsp;		sbus_arg->handler_list = intr_handler;		/*		 * No handler added yet in the interrupt vector		 * table for this ino.		 * Install the nexus interrupt wrapper in the		 * system. The wrapper will call the device		 * interrupt handler.		 */		DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,		    (ddi_intr_handler_t *)sbus_intr_wrapper,		    (caddr_t)sbus_arg, NULL);		ret = i_ddi_add_ivintr(hdlp);		/*		 * Restore original interrupt handler		 * and arguments in interrupt handle.		 */		DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, intr_handler->funcp,		    intr_handler->arg1, intr_handler->arg2);		if (ret != DDI_SUCCESS)		    goto done;		if ((slot >= EXT_SBUS_SLOTS) ||		    (softsp->intr_hndlr_cnt[slot] == 0)) {			cpu_id = intr_dist_cpuid();#ifdef	_STARFIRE			tmp_mondo_vec = pc_translate_tgtid(			    softsp->ittrans_cookie, cpu_id,				mondo_vec_reg) << IMR_TID_SHIFT;#else			tmp_mondo_vec =			    cpu_id << IMR_TID_SHIFT;			DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: initial "			    "mapping reg 0x%llx\n", tmp_mondo_vec));#endif	/* _STARFIRE */		} else {			/*			 * There is already a different			 * ino programmed at this IMR.			 * Just read the IMR out to get the			 * correct MID target.			 */			tmp_mondo_vec = *mondo_vec_reg;			tmp_mondo_vec &= ~INTERRUPT_VALID;			*mondo_vec_reg = tmp_mondo_vec;			DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: existing "			    "mapping reg 0x%llx\n", tmp_mondo_vec));		}		sbus_arg->pil = hdlp->ih_pri;		DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr:Alloc sbus_arg "		    "0x%x\n", sbus_arg));	}	softsp->intr_hndlr_cnt[slot]++;	mutex_exit(&softsp->intr_poll_list_lock);	/*	 * Program the ino vector accordingly.  This MUST be the	 * last thing we do.  Once we program the ino, the device	 * may begin to interrupt. Add this hardware interrupt to	 * the interrupt lists, and get the CPU to target it at.	 */	tmp_mondo_vec |= INTERRUPT_VALID;	DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: Ino 0x%x mapping reg: 0x%x "	    "Intr cntr %d\n", ino, mondo_vec_reg,	    softsp->intr_hndlr_cnt[slot]));	/* Force the interrupt state machine to idle. */	if (reset_ism_register) {		tmpreg = SBUS_INTR_IDLE;		*sbus_arg->clear_reg = tmpreg;	}	/* Store it in the hardware reg. */	*mondo_vec_reg = tmp_mondo_vec;	/* Flush store buffers */	tmpreg = *softsp->sbus_ctrl_reg;done:	return (ret);}