125cf1a30Sjl /* 225cf1a30Sjl * CDDL HEADER START 325cf1a30Sjl * 425cf1a30Sjl * The contents of this file are subject to the terms of the 525cf1a30Sjl * Common Development and Distribution License (the "License"). 625cf1a30Sjl * You may not use this file except in compliance with the License. 725cf1a30Sjl * 825cf1a30Sjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 925cf1a30Sjl * or http://www.opensolaris.org/os/licensing. 1025cf1a30Sjl * See the License for the specific language governing permissions 1125cf1a30Sjl * and limitations under the License. 1225cf1a30Sjl * 1325cf1a30Sjl * When distributing Covered Code, include this CDDL HEADER in each 1425cf1a30Sjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1525cf1a30Sjl * If applicable, add the following below this CDDL HEADER, with the 1625cf1a30Sjl * fields enclosed by brackets "[]" replaced with your own identifying 1725cf1a30Sjl * information: Portions Copyright [yyyy] [name of copyright owner] 1825cf1a30Sjl * 1925cf1a30Sjl * CDDL HEADER END 2025cf1a30Sjl */ 2125cf1a30Sjl /* 2225cf1a30Sjl * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006 2325cf1a30Sjl */ 2425cf1a30Sjl 2525cf1a30Sjl #pragma ident "%Z%%M% %I% %E% SMI" 2625cf1a30Sjl 2725cf1a30Sjl #include <sys/errno.h> 2825cf1a30Sjl #include <sys/modctl.h> 2925cf1a30Sjl #include <sys/stat.h> 3025cf1a30Sjl #include <sys/kmem.h> 3125cf1a30Sjl #include <sys/ksynch.h> 3225cf1a30Sjl #include <sys/stream.h> 3325cf1a30Sjl #include <sys/stropts.h> 3425cf1a30Sjl #include <sys/termio.h> 3525cf1a30Sjl #include <sys/ddi.h> 3625cf1a30Sjl #include <sys/file.h> 3725cf1a30Sjl #include <sys/disp.h> 3825cf1a30Sjl #include <sys/sunddi.h> 3925cf1a30Sjl #include <sys/sunldi.h> 4025cf1a30Sjl #include <sys/sunndi.h> 4125cf1a30Sjl #include <sys/prom_plat.h> 4225cf1a30Sjl #include <sys/oplmsu/oplmsu.h> 4325cf1a30Sjl #include <sys/oplmsu/oplmsu_proto.h> 4425cf1a30Sjl 4525cf1a30Sjl /* 4625cf1a30Sjl * LOWER READ SERVICE PROCEDURE 4725cf1a30Sjl */ 4825cf1a30Sjl 4925cf1a30Sjl /* termios ioctl response received */ 5025cf1a30Sjl int 5125cf1a30Sjl oplmsu_lrioctl_termios(queue_t *lrq, mblk_t *mp) 5225cf1a30Sjl { 5325cf1a30Sjl upath_t *upath, *altn_upath = NULL, *stp_upath = NULL; 5425cf1a30Sjl lpath_t *lpath, *altn_lpath = NULL, *stp_lpath = NULL; 5525cf1a30Sjl struct iocblk *iocp, *temp_iocp = NULL; 5625cf1a30Sjl mblk_t *hndl_mp, *nmp = NULL, *fmp = NULL; 5725cf1a30Sjl queue_t *dst_queue; 5825cf1a30Sjl int term_ioctl, term_stat, sts; 5925cf1a30Sjl int ack_flag, termio_flag, chkflag; 6025cf1a30Sjl ulong_t trad_sts; 6125cf1a30Sjl 6225cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_READER); 6325cf1a30Sjl iocp = (struct iocblk *)mp->b_rptr; 6425cf1a30Sjl 6525cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 6625cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 6725cf1a30Sjl lpath = (lpath_t *)lrq->q_ptr; 6825cf1a30Sjl hndl_mp = lpath->hndl_mp; 6925cf1a30Sjl 7025cf1a30Sjl upath = oplmsu_search_upath_info(lpath->path_no); 7125cf1a30Sjl trad_sts = upath->traditional_status; 7225cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 7325cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 7425cf1a30Sjl 7525cf1a30Sjl if (((iocp->ioc_cmd == TCSETS) && (trad_sts == MSU_WTCS_ACK)) || 7625cf1a30Sjl ((iocp->ioc_cmd == TCSETSW) && (trad_sts == MSU_WTCS_ACK)) || 7725cf1a30Sjl ((iocp->ioc_cmd == TCSETSF) && (trad_sts == MSU_WTCS_ACK)) || 7825cf1a30Sjl ((iocp->ioc_cmd == TIOCMSET) && (trad_sts == MSU_WTMS_ACK)) || 7925cf1a30Sjl ((iocp->ioc_cmd == TIOCSPPS) && (trad_sts == MSU_WPPS_ACK)) || 8025cf1a30Sjl ((iocp->ioc_cmd == TIOCSWINSZ) && (trad_sts == MSU_WWSZ_ACK)) || 8125cf1a30Sjl ((iocp->ioc_cmd == TIOCSSOFTCAR) && (trad_sts == MSU_WCAR_ACK))) { 8225cf1a30Sjl if (mp->b_datap->db_type == M_IOCACK) { 8325cf1a30Sjl ack_flag = ACK_RES; 8425cf1a30Sjl } else { 8525cf1a30Sjl ack_flag = NAK_RES; 8625cf1a30Sjl } 8725cf1a30Sjl } else { 8825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 8925cf1a30Sjl freemsg(mp); 9025cf1a30Sjl cmn_err(CE_WARN, "oplmsu: lr-termios: " 9125cf1a30Sjl "Status of path is improper"); 9225cf1a30Sjl return (SUCCESS); 9325cf1a30Sjl } 9425cf1a30Sjl 9525cf1a30Sjl switch (trad_sts) { 9625cf1a30Sjl case MSU_WTCS_ACK : 9725cf1a30Sjl termio_flag = MSU_TIOS_TCSETS; 9825cf1a30Sjl break; 9925cf1a30Sjl 10025cf1a30Sjl case MSU_WTMS_ACK : 10125cf1a30Sjl termio_flag = MSU_TIOS_MSET; 10225cf1a30Sjl break; 10325cf1a30Sjl 10425cf1a30Sjl case MSU_WPPS_ACK : 10525cf1a30Sjl termio_flag = MSU_TIOS_PPS; 10625cf1a30Sjl break; 10725cf1a30Sjl 10825cf1a30Sjl case MSU_WWSZ_ACK : 10925cf1a30Sjl termio_flag = MSU_TIOS_WINSZP; 11025cf1a30Sjl break; 11125cf1a30Sjl 11225cf1a30Sjl case MSU_WCAR_ACK : 11325cf1a30Sjl termio_flag = MSU_TIOS_SOFTCAR; 11425cf1a30Sjl break; 11525cf1a30Sjl 11625cf1a30Sjl default : 11725cf1a30Sjl termio_flag = MSU_TIOS_END; 11825cf1a30Sjl break; 11925cf1a30Sjl } 12025cf1a30Sjl 12125cf1a30Sjl if (hndl_mp == NULL) { 12225cf1a30Sjl switch (trad_sts) { 12325cf1a30Sjl case MSU_WTCS_ACK : /* FALLTHRU */ 12425cf1a30Sjl case MSU_WTMS_ACK : /* FALLTHRU */ 12525cf1a30Sjl case MSU_WPPS_ACK : /* FALLTHRU */ 12625cf1a30Sjl case MSU_WWSZ_ACK : /* FALLTHRU */ 12725cf1a30Sjl case MSU_WCAR_ACK : 12825cf1a30Sjl chkflag = MSU_CMD_STOP; 12925cf1a30Sjl break; 13025cf1a30Sjl 13125cf1a30Sjl default : 13225cf1a30Sjl chkflag = FAILURE; 13325cf1a30Sjl break; 13425cf1a30Sjl } 13525cf1a30Sjl } else { 13625cf1a30Sjl /* xoff/xon received */ 13725cf1a30Sjl if (hndl_mp->b_datap->db_type == M_DATA) { 13825cf1a30Sjl chkflag = MSU_CMD_ACTIVE; 13925cf1a30Sjl } else { /* Normal termios */ 14025cf1a30Sjl temp_iocp = (struct iocblk *)hndl_mp->b_rptr; 14125cf1a30Sjl chkflag = temp_iocp->ioc_cmd; 14225cf1a30Sjl } 14325cf1a30Sjl } 14425cf1a30Sjl 14525cf1a30Sjl if ((chkflag == MSU_CMD_ACTIVE) || (chkflag == MSU_CMD_STOP)) { 14625cf1a30Sjl if (ack_flag == ACK_RES) { /* M_IOCACK received */ 14725cf1a30Sjl ctrl_t *ctrl; 14825cf1a30Sjl 14925cf1a30Sjl if (oplmsu_cmn_prechg_termio(lrq, mp, MSU_READ_SIDE, 15025cf1a30Sjl termio_flag, &nmp, &term_stat) == FAILURE) { 15125cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 15225cf1a30Sjl return (FAILURE); 15325cf1a30Sjl } 15425cf1a30Sjl 15525cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 15625cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 15725cf1a30Sjl if (term_stat != MSU_WPTH_CHG) { 15825cf1a30Sjl upath->traditional_status = term_stat; 15925cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 16025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 16125cf1a30Sjl freemsg(mp); 16225cf1a30Sjl 16325cf1a30Sjl OPLMSU_TRACE(RD(lrq), nmp, MSU_TRC_LO); 16425cf1a30Sjl 16525cf1a30Sjl /* Continue sending termios ioctls */ 16625cf1a30Sjl qreply(RD(lrq), nmp); 16725cf1a30Sjl return (SUCCESS); 16825cf1a30Sjl } 16925cf1a30Sjl freemsg(mp); 17025cf1a30Sjl 17125cf1a30Sjl /* Change status of new active path */ 17225cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_ACTIVE, 17325cf1a30Sjl upath->status, MSU_ACTIVE); 17425cf1a30Sjl 17525cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 17625cf1a30Sjl lpath->uinst = oplmsu_uinst; 17725cf1a30Sjl dst_queue = lpath->hndl_uqueue; 17825cf1a30Sjl 17925cf1a30Sjl ctrl = oplmsu_uinst->user_ctrl; 18025cf1a30Sjl if ((chkflag == MSU_CMD_ACTIVE) && (hndl_mp != NULL)) { 18125cf1a30Sjl /* Put a message(M_DATA) on a queue */ 18225cf1a30Sjl if (ctrl != NULL) { 18325cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 18425cf1a30Sjl putq(RD(ctrl->queue), hndl_mp); 18525cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 18625cf1a30Sjl } 18725cf1a30Sjl } 18825cf1a30Sjl 18925cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 19025cf1a30Sjl stp_upath = lpath->src_upath; 19125cf1a30Sjl lpath->src_upath = NULL; 19225cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 19325cf1a30Sjl 19425cf1a30Sjl /* Notify of the active path changing */ 19525cf1a30Sjl prom_opl_switch_console(upath->ser_devcb.lsb); 19625cf1a30Sjl 19725cf1a30Sjl /* Send XON to notify active path */ 19825cf1a30Sjl (void) oplmsu_cmn_put_xoffxon(WR(lrq), MSU_XON_4); 19925cf1a30Sjl 20025cf1a30Sjl stp_lpath = stp_upath->lpath; 20125cf1a30Sjl stp_lpath->uinst = NULL; 20225cf1a30Sjl oplmsu_clear_ioctl_path(stp_lpath); 20325cf1a30Sjl stp_lpath->src_upath = NULL; 20425cf1a30Sjl stp_lpath->status = MSU_EXT_NOTUSED; 20525cf1a30Sjl 20625cf1a30Sjl /* Change status of stopped or old-active path */ 20725cf1a30Sjl if (chkflag == MSU_CMD_STOP) { 20825cf1a30Sjl sts = MSU_PSTAT_STOP; 20925cf1a30Sjl trad_sts = MSU_STOP; 21025cf1a30Sjl } else { /* == MSU_CMD_ACTIVE */ 21125cf1a30Sjl sts = MSU_PSTAT_STANDBY; 21225cf1a30Sjl trad_sts = MSU_STANDBY; 21325cf1a30Sjl } 21425cf1a30Sjl oplmsu_cmn_set_upath_sts(stp_upath, sts, 21525cf1a30Sjl stp_upath->status, trad_sts); 21625cf1a30Sjl 21725cf1a30Sjl /* Send XOFF to notify all standby paths */ 21825cf1a30Sjl oplmsu_cmn_putxoff_standby(); 21925cf1a30Sjl oplmsu_uinst->lower_queue = lrq; 22025cf1a30Sjl oplmsu_uinst->inst_status = oplmsu_get_inst_status(); 22125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 22225cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 22325cf1a30Sjl 22425cf1a30Sjl /* Change active path of user node */ 22525cf1a30Sjl if (ctrl != NULL) { 22625cf1a30Sjl queue_t *temp_queue; 22725cf1a30Sjl 22825cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 22925cf1a30Sjl temp_queue = WR(ctrl->queue); 23025cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 23125cf1a30Sjl 23225cf1a30Sjl /* Reschedule a queue for service */ 23325cf1a30Sjl enableok(temp_queue); 23425cf1a30Sjl 23525cf1a30Sjl oplmsu_queue_flag = 0; 23625cf1a30Sjl oplmsu_wcmn_high_qenable(temp_queue, RW_WRITER); 23725cf1a30Sjl } 23825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 23925cf1a30Sjl 24025cf1a30Sjl if (nmp != NULL) { 24125cf1a30Sjl freemsg(nmp); 24225cf1a30Sjl } 24325cf1a30Sjl 24425cf1a30Sjl /* Wake up oplmsu_config_stop */ 24525cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 24625cf1a30Sjl if (stp_lpath->sw_flag) { 24725cf1a30Sjl stp_lpath->sw_flag = 0; 24825cf1a30Sjl cv_signal(&stp_lpath->sw_cv); 24925cf1a30Sjl } 25025cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 25125cf1a30Sjl return (SUCCESS); 25225cf1a30Sjl } else { /* M_IOCNAK received */ 25325cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 25425cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 25525cf1a30Sjl if ((chkflag == MSU_CMD_ACTIVE) && 25625cf1a30Sjl (lpath->hndl_uqueue == NULL)) { 25725cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 25825cf1a30Sjl stp_upath = lpath->src_upath; 25925cf1a30Sjl lpath->src_upath = NULL; 26025cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 26125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 26225cf1a30Sjl 26325cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, 26425cf1a30Sjl MSU_PSTAT_STANDBY, upath->status, 26525cf1a30Sjl MSU_STANDBY); 26625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 26725cf1a30Sjl 26825cf1a30Sjl if (hndl_mp != NULL) { 26925cf1a30Sjl freemsg(hndl_mp); 27025cf1a30Sjl } 27125cf1a30Sjl 27225cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 27325cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 27425cf1a30Sjl oplmsu_uinst->inst_status = 27525cf1a30Sjl oplmsu_get_inst_status(); 27625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 27725cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 27825cf1a30Sjl return (SUCCESS); 27925cf1a30Sjl } else if ((chkflag == MSU_CMD_STOP) && 28025cf1a30Sjl (lpath->src_upath != NULL) && 28125cf1a30Sjl (lpath->src_upath->lpath->sw_flag)) { 28225cf1a30Sjl /* MSU_CMD_STOP for active path */ 28325cf1a30Sjl 28425cf1a30Sjl dst_queue = RD(lpath->hndl_uqueue); 28525cf1a30Sjl stp_upath = lpath->src_upath; 28625cf1a30Sjl 28725cf1a30Sjl /* Search alternate path from standby paths */ 28825cf1a30Sjl altn_upath = oplmsu_search_standby(); 28925cf1a30Sjl if (altn_upath == NULL) { 29025cf1a30Sjl altn_upath = upath; 29125cf1a30Sjl } 29225cf1a30Sjl 29325cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 29425cf1a30Sjl if (oplmsu_cmn_allocmb(lrq, mp, &fmp, 29525cf1a30Sjl sizeof (char), MSU_READ_SIDE) == FAILURE) { 29625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 29725cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 29825cf1a30Sjl return (FAILURE); 29925cf1a30Sjl } 30025cf1a30Sjl 30125cf1a30Sjl if (oplmsu_cmn_prechg(lrq, mp, MSU_READ_SIDE, 30225cf1a30Sjl &nmp, &term_ioctl, &term_stat) == FAILURE) { 30325cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 30425cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 30525cf1a30Sjl freeb(fmp); 30625cf1a30Sjl return (FAILURE); 30725cf1a30Sjl } 30825cf1a30Sjl 30925cf1a30Sjl altn_upath->traditional_status = term_stat; 31025cf1a30Sjl altn_lpath = altn_upath->lpath; 31125cf1a30Sjl 31225cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 31325cf1a30Sjl altn_lpath->hndl_mp = hndl_mp; 31425cf1a30Sjl altn_lpath->hndl_uqueue = dst_queue; 31525cf1a30Sjl altn_lpath->src_upath = stp_upath; 31625cf1a30Sjl altn_lpath->status = MSU_EXT_VOID; 31725cf1a30Sjl dst_queue = RD(altn_lpath->lower_queue); 31825cf1a30Sjl 31925cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL, 32025cf1a30Sjl upath->status, MSU_FAIL); 32125cf1a30Sjl 32225cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 32325cf1a30Sjl lpath->src_upath = NULL; 32425cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 32525cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 32625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 32725cf1a30Sjl 32825cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 32925cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 33025cf1a30Sjl oplmsu_uinst->inst_status = 33125cf1a30Sjl oplmsu_get_inst_status(); 33225cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 33325cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 33425cf1a30Sjl freemsg(mp); 33525cf1a30Sjl oplmsu_cmn_set_mflush(fmp); 33625cf1a30Sjl 33725cf1a30Sjl OPLMSU_TRACE(dst_queue, fmp, MSU_TRC_LO); 33825cf1a30Sjl qreply(dst_queue, fmp); 33925cf1a30Sjl 34025cf1a30Sjl OPLMSU_TRACE(dst_queue, nmp, MSU_TRC_LO); 34125cf1a30Sjl qreply(dst_queue, nmp); 34225cf1a30Sjl return (SUCCESS); 34325cf1a30Sjl } 34425cf1a30Sjl } 34525cf1a30Sjl } else if ((chkflag == TCSETS) || (chkflag == TCSETSW) || 34625cf1a30Sjl (chkflag == TCSETSF) || (chkflag == TIOCMSET) || 34725cf1a30Sjl (chkflag == TIOCSPPS) || (chkflag == TIOCSWINSZ) || 34825cf1a30Sjl (chkflag == TIOCSSOFTCAR)) { 34925cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 35025cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 35125cf1a30Sjl 35225cf1a30Sjl if ((ack_flag == ACK_RES) && 35325cf1a30Sjl (lpath->hndl_uqueue != NULL)) { /* M_IOCACK received */ 35425cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 35525cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 35625cf1a30Sjl if (oplmsu_cmn_copymb(lrq, mp, &nmp, hndl_mp, 35725cf1a30Sjl MSU_READ_SIDE) == FAILURE) { 35825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 35925cf1a30Sjl return (FAILURE); 36025cf1a30Sjl } 36125cf1a30Sjl 36225cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 36325cf1a30Sjl switch (chkflag) { 36425cf1a30Sjl case TCSETS : /* FALLTHRU */ 36525cf1a30Sjl case TCSETSW : /* FALLTHRU */ 36625cf1a30Sjl case TCSETSF : 36725cf1a30Sjl if (oplmsu_uinst->tcsets_p != NULL) { 36825cf1a30Sjl freemsg(oplmsu_uinst->tcsets_p); 36925cf1a30Sjl } 37025cf1a30Sjl oplmsu_uinst->tcsets_p = nmp; 37125cf1a30Sjl break; 37225cf1a30Sjl 37325cf1a30Sjl case TIOCMSET : 37425cf1a30Sjl if (oplmsu_uinst->tiocmset_p != NULL) { 37525cf1a30Sjl freemsg(oplmsu_uinst->tiocmset_p); 37625cf1a30Sjl } 37725cf1a30Sjl oplmsu_uinst->tiocmset_p = nmp; 37825cf1a30Sjl break; 37925cf1a30Sjl 38025cf1a30Sjl case TIOCSPPS : 38125cf1a30Sjl if (oplmsu_uinst->tiocspps_p != NULL) { 38225cf1a30Sjl freemsg(oplmsu_uinst->tiocspps_p); 38325cf1a30Sjl } 38425cf1a30Sjl oplmsu_uinst->tiocspps_p = nmp; 38525cf1a30Sjl break; 38625cf1a30Sjl 38725cf1a30Sjl case TIOCSWINSZ : 38825cf1a30Sjl if (oplmsu_uinst->tiocswinsz_p != NULL) { 38925cf1a30Sjl freemsg(oplmsu_uinst->tiocswinsz_p); 39025cf1a30Sjl } 39125cf1a30Sjl oplmsu_uinst->tiocswinsz_p = nmp; 39225cf1a30Sjl break; 39325cf1a30Sjl 39425cf1a30Sjl case TIOCSSOFTCAR : 39525cf1a30Sjl if (oplmsu_uinst->tiocssoftcar_p != NULL) { 39625cf1a30Sjl freemsg(oplmsu_uinst->tiocssoftcar_p); 39725cf1a30Sjl } 39825cf1a30Sjl oplmsu_uinst->tiocssoftcar_p = nmp; 39925cf1a30Sjl break; 40025cf1a30Sjl } 40125cf1a30Sjl 40225cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 40325cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 40425cf1a30Sjl upath->traditional_status = lpath->status; 40525cf1a30Sjl nmp = lpath->hndl_mp; 40625cf1a30Sjl nmp->b_datap->db_type = M_IOCACK; 40725cf1a30Sjl dst_queue = RD(lpath->hndl_uqueue); 40825cf1a30Sjl bcopy(mp->b_rptr, nmp->b_rptr, sizeof (struct iocblk)); 40925cf1a30Sjl 41025cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 41125cf1a30Sjl lpath->src_upath = NULL; 41225cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 41325cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 41425cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 41525cf1a30Sjl freemsg(mp); 41625cf1a30Sjl putq(dst_queue, nmp); 41725cf1a30Sjl 41825cf1a30Sjl /* Check sleep flag and wake up thread */ 41925cf1a30Sjl oplmsu_cmn_wakeup(dst_queue); 42025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 42125cf1a30Sjl return (SUCCESS); 42225cf1a30Sjl } else if ((ack_flag == NAK_RES) && 42325cf1a30Sjl (lpath->hndl_uqueue != NULL)) { /* M_IOCNAK received */ 42425cf1a30Sjl upath->traditional_status = lpath->status; 42525cf1a30Sjl 42625cf1a30Sjl nmp = lpath->hndl_mp; 42725cf1a30Sjl nmp->b_datap->db_type = M_IOCNAK; 42825cf1a30Sjl dst_queue = RD(lpath->hndl_uqueue); 42925cf1a30Sjl 43025cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 43125cf1a30Sjl lpath->src_upath = NULL; 43225cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 43325cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 43425cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 43525cf1a30Sjl freemsg(mp); 43625cf1a30Sjl putq(dst_queue, nmp); 43725cf1a30Sjl 43825cf1a30Sjl /* Check sleep flag and wake up thread */ 43925cf1a30Sjl oplmsu_cmn_wakeup(dst_queue); 44025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 44125cf1a30Sjl return (SUCCESS); 44225cf1a30Sjl } 44325cf1a30Sjl } 44425cf1a30Sjl 44525cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 44625cf1a30Sjl switch (upath->status) { 44725cf1a30Sjl case MSU_PSTAT_FAIL : 44825cf1a30Sjl upath->traditional_status = MSU_FAIL; 44925cf1a30Sjl break; 45025cf1a30Sjl 45125cf1a30Sjl case MSU_PSTAT_STOP : 45225cf1a30Sjl upath->traditional_status = MSU_STOP; 45325cf1a30Sjl break; 45425cf1a30Sjl 45525cf1a30Sjl case MSU_PSTAT_STANDBY : 45625cf1a30Sjl upath->traditional_status = MSU_STANDBY; 45725cf1a30Sjl break; 45825cf1a30Sjl 45925cf1a30Sjl case MSU_PSTAT_ACTIVE : 46025cf1a30Sjl upath->traditional_status = MSU_ACTIVE; 46125cf1a30Sjl break; 46225cf1a30Sjl } 46325cf1a30Sjl 46425cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 46525cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 46625cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 46725cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 46825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 46925cf1a30Sjl freemsg(mp); 47025cf1a30Sjl return (SUCCESS); 47125cf1a30Sjl } 47225cf1a30Sjl 47325cf1a30Sjl /* M_ERROR or M_HANGUP response received */ 47425cf1a30Sjl int 47525cf1a30Sjl oplmsu_lrmsg_error(queue_t *lrq, mblk_t *mp) 47625cf1a30Sjl { 47725cf1a30Sjl upath_t *upath, *altn_upath = NULL; 47825cf1a30Sjl lpath_t *lpath, *altn_lpath = NULL; 47925cf1a30Sjl mblk_t *nmp = NULL, *fmp = NULL; 48025cf1a30Sjl queue_t *dst_queue = NULL; 48125cf1a30Sjl ctrl_t *ctrl; 48225cf1a30Sjl int term_stat, term_ioctl; 48325cf1a30Sjl 48425cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_READER); 48525cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 48625cf1a30Sjl ctrl = oplmsu_uinst->user_ctrl; 48725cf1a30Sjl if (ctrl != NULL) { 48825cf1a30Sjl dst_queue = RD(ctrl->queue); 48925cf1a30Sjl } 49025cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 49125cf1a30Sjl 49225cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 49325cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 49425cf1a30Sjl lpath = (lpath_t *)lrq->q_ptr; 49525cf1a30Sjl upath = oplmsu_search_upath_info(lpath->path_no); 49625cf1a30Sjl 497*c2c6897eSraghuram if (upath == NULL) { 498*c2c6897eSraghuram mutex_exit(&oplmsu_uinst->l_lock); 499*c2c6897eSraghuram mutex_exit(&oplmsu_uinst->u_lock); 500*c2c6897eSraghuram rw_exit(&oplmsu_uinst->lock); 501*c2c6897eSraghuram freemsg(mp); 502*c2c6897eSraghuram return (SUCCESS); 503*c2c6897eSraghuram } 504*c2c6897eSraghuram 50525cf1a30Sjl if ((lpath->status == MSU_LINK_NU) || 50625cf1a30Sjl (lpath->status == MSU_SETID_NU) || 50725cf1a30Sjl (upath->traditional_status == MSU_WSTR_ACK) || 50825cf1a30Sjl (upath->traditional_status == MSU_WTCS_ACK) || 50925cf1a30Sjl (upath->traditional_status == MSU_WTMS_ACK) || 51025cf1a30Sjl (upath->traditional_status == MSU_WPPS_ACK) || 51125cf1a30Sjl (upath->traditional_status == MSU_WWSZ_ACK) || 51225cf1a30Sjl (upath->traditional_status == MSU_WCAR_ACK) || 51325cf1a30Sjl (upath->traditional_status == MSU_WSTP_ACK) || 51425cf1a30Sjl (upath->traditional_status == MSU_WPTH_CHG)) { 51525cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 51625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 51725cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 51825cf1a30Sjl freemsg(mp); 51925cf1a30Sjl } else if ((upath->traditional_status == MSU_MAKE_INST) || 52025cf1a30Sjl (upath->traditional_status == MSU_STOP) || 52125cf1a30Sjl (upath->traditional_status == MSU_STANDBY) || 52225cf1a30Sjl (upath->traditional_status == MSU_SETID) || 52325cf1a30Sjl (upath->traditional_status == MSU_LINK)) { 52425cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL, upath->status, 52525cf1a30Sjl MSU_FAIL); 52625cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 52725cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 52825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 52925cf1a30Sjl freemsg(mp); 53025cf1a30Sjl } else if (upath->traditional_status == MSU_FAIL) { 53125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 53225cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 53325cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 53425cf1a30Sjl freemsg(mp); 53525cf1a30Sjl } else if (upath->traditional_status == MSU_ACTIVE) { 53625cf1a30Sjl altn_upath = oplmsu_search_standby(); 53725cf1a30Sjl if (altn_upath == NULL) { 53825cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL, 53925cf1a30Sjl upath->status, MSU_FAIL); 54025cf1a30Sjl 54125cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 54225cf1a30Sjl lpath->src_upath = NULL; 54325cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 54425cf1a30Sjl lpath->uinst = NULL; 54525cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 54625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 54725cf1a30Sjl 54825cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 54925cf1a30Sjl oplmsu_uinst->lower_queue = NULL; 55025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 55125cf1a30Sjl freemsg(mp); 55225cf1a30Sjl return (SUCCESS); 55325cf1a30Sjl } 55425cf1a30Sjl 55525cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 55625cf1a30Sjl if (oplmsu_cmn_allocmb(lrq, mp, &fmp, sizeof (char), 55725cf1a30Sjl MSU_READ_SIDE) == FAILURE) { 55825cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 55925cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 56025cf1a30Sjl return (FAILURE); 56125cf1a30Sjl } 56225cf1a30Sjl 56325cf1a30Sjl if (oplmsu_cmn_prechg(lrq, mp, MSU_READ_SIDE, &nmp, &term_ioctl, 56425cf1a30Sjl &term_stat) == FAILURE) { 56525cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 56625cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 56725cf1a30Sjl freeb(fmp); 56825cf1a30Sjl return (FAILURE); 56925cf1a30Sjl } 57025cf1a30Sjl 57125cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL, 57225cf1a30Sjl upath->status, MSU_FAIL); 57325cf1a30Sjl 57425cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 57525cf1a30Sjl lpath->uinst = NULL; 57625cf1a30Sjl 57725cf1a30Sjl altn_upath->traditional_status = term_stat; 57825cf1a30Sjl altn_lpath = altn_upath->lpath; 57925cf1a30Sjl 58025cf1a30Sjl altn_lpath->hndl_mp = NULL; 58125cf1a30Sjl altn_lpath->hndl_uqueue = NULL; 58225cf1a30Sjl altn_lpath->src_upath = upath; 58325cf1a30Sjl altn_lpath->status = MSU_EXT_VOID; 58425cf1a30Sjl dst_queue = RD(altn_lpath->lower_queue); 58525cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 58625cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 58725cf1a30Sjl 58825cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 58925cf1a30Sjl oplmsu_uinst->lower_queue = NULL; 59025cf1a30Sjl oplmsu_cmn_set_mflush(fmp); 59125cf1a30Sjl 59225cf1a30Sjl if (ctrl != NULL) { 59325cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 59425cf1a30Sjl noenable(WR(ctrl->queue)); 59525cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 59625cf1a30Sjl 59725cf1a30Sjl oplmsu_queue_flag = 1; 59825cf1a30Sjl } 59925cf1a30Sjl 60025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 60125cf1a30Sjl freemsg(mp); 60225cf1a30Sjl 60325cf1a30Sjl OPLMSU_TRACE(dst_queue, fmp, MSU_TRC_LO); 60425cf1a30Sjl qreply(dst_queue, fmp); 60525cf1a30Sjl OPLMSU_TRACE(dst_queue, nmp, MSU_TRC_LO); 60625cf1a30Sjl qreply(dst_queue, nmp); 60725cf1a30Sjl } 60825cf1a30Sjl return (SUCCESS); 60925cf1a30Sjl } 61025cf1a30Sjl 61125cf1a30Sjl /* M_DATA[xoff/xon] was received from serial port */ 61225cf1a30Sjl int 61325cf1a30Sjl oplmsu_lrdata_xoffxon(queue_t *lrq, mblk_t *mp) 61425cf1a30Sjl { 61525cf1a30Sjl upath_t *upath, *stp_upath = NULL; 61625cf1a30Sjl lpath_t *lpath, *stp_lpath = NULL; 61725cf1a30Sjl mblk_t *nmp = NULL, *fmp = NULL; 61825cf1a30Sjl ctrl_t *ctrl; 61925cf1a30Sjl int term_stat, term_ioctl; 62025cf1a30Sjl 62125cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_READER); 62225cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 62325cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 62425cf1a30Sjl 62525cf1a30Sjl if (oplmsu_uinst->lower_queue != NULL) { 62625cf1a30Sjl /* Get lower path of active status */ 62725cf1a30Sjl stp_lpath = (lpath_t *)oplmsu_uinst->lower_queue->q_ptr; 62825cf1a30Sjl if (stp_lpath != NULL) { 62925cf1a30Sjl stp_upath = 63025cf1a30Sjl oplmsu_search_upath_info(stp_lpath->path_no); 63125cf1a30Sjl } 63225cf1a30Sjl } 63325cf1a30Sjl 63425cf1a30Sjl lpath = (lpath_t *)lrq->q_ptr; 63525cf1a30Sjl upath = oplmsu_search_upath_info(lpath->path_no); 63625cf1a30Sjl 637*c2c6897eSraghuram if (upath == NULL) { 638*c2c6897eSraghuram mutex_exit(&oplmsu_uinst->l_lock); 639*c2c6897eSraghuram mutex_exit(&oplmsu_uinst->u_lock); 640*c2c6897eSraghuram rw_exit(&oplmsu_uinst->lock); 641*c2c6897eSraghuram freemsg(mp); 642*c2c6897eSraghuram return (SUCCESS); 643*c2c6897eSraghuram } 644*c2c6897eSraghuram 64525cf1a30Sjl if ((stp_upath != NULL) && (stp_upath != upath)) { 64625cf1a30Sjl if ((stp_upath->status != MSU_PSTAT_ACTIVE) || 64725cf1a30Sjl (stp_upath->traditional_status != MSU_ACTIVE)) { 64825cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 64925cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 65025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 65125cf1a30Sjl putbq(lrq, mp); 65225cf1a30Sjl return (FAILURE); 65325cf1a30Sjl } 65425cf1a30Sjl } 65525cf1a30Sjl 65625cf1a30Sjl if ((upath->status == MSU_PSTAT_ACTIVE) && 65725cf1a30Sjl ((upath->traditional_status == MSU_ACTIVE) || 65825cf1a30Sjl (upath->traditional_status == MSU_WTCS_ACK) || 65925cf1a30Sjl (upath->traditional_status == MSU_WTMS_ACK) || 66025cf1a30Sjl (upath->traditional_status == MSU_WPPS_ACK) || 66125cf1a30Sjl (upath->traditional_status == MSU_WWSZ_ACK) || 66225cf1a30Sjl (upath->traditional_status == MSU_WCAR_ACK))) { 66325cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 66425cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 66525cf1a30Sjl oplmsu_rcmn_through_hndl(lrq, mp, MSU_NORM); 66625cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 66725cf1a30Sjl return (SUCCESS); 66825cf1a30Sjl } else if ((upath->status != MSU_PSTAT_STANDBY) || 66925cf1a30Sjl (upath->traditional_status != MSU_STANDBY)) { 67025cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 67125cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 67225cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 67325cf1a30Sjl freemsg(mp); 67425cf1a30Sjl cmn_err(CE_WARN, "oplmsu: lr-xoffxon: " 67525cf1a30Sjl "Can't change to specified path"); 67625cf1a30Sjl return (SUCCESS); 67725cf1a30Sjl } 67825cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 67925cf1a30Sjl 68025cf1a30Sjl if (oplmsu_cmn_allocmb(lrq, mp, &fmp, sizeof (char), MSU_READ_SIDE) == 68125cf1a30Sjl FAILURE) { 68225cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 68325cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 68425cf1a30Sjl return (FAILURE); 68525cf1a30Sjl } 68625cf1a30Sjl 68725cf1a30Sjl if (oplmsu_cmn_prechg(lrq, mp, MSU_READ_SIDE, &nmp, &term_ioctl, 68825cf1a30Sjl &term_stat) == FAILURE) { 68925cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 69025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 69125cf1a30Sjl freeb(fmp); 69225cf1a30Sjl return (FAILURE); 69325cf1a30Sjl } 69425cf1a30Sjl 69525cf1a30Sjl oplmsu_cmn_set_mflush(fmp); 69625cf1a30Sjl upath->traditional_status = term_stat; 69725cf1a30Sjl 69825cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 69925cf1a30Sjl lpath->hndl_mp = mp; 70025cf1a30Sjl lpath->hndl_uqueue = NULL; 70125cf1a30Sjl lpath->src_upath = stp_upath; 70225cf1a30Sjl lpath->status = MSU_EXT_VOID; 70325cf1a30Sjl 70425cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 70525cf1a30Sjl ctrl = oplmsu_uinst->user_ctrl; 70625cf1a30Sjl if (term_stat != MSU_WPTH_CHG) { 70725cf1a30Sjl /* 70825cf1a30Sjl * Send termios to new active path and wait response 70925cf1a30Sjl */ 71025cf1a30Sjl if (ctrl != NULL) { 71125cf1a30Sjl noenable(WR(ctrl->queue)); 71225cf1a30Sjl } 71325cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 71425cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 71525cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 71625cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 71725cf1a30Sjl 71825cf1a30Sjl OPLMSU_TRACE(RD(lrq), fmp, MSU_TRC_LO); 71925cf1a30Sjl qreply(RD(lrq), fmp); 72025cf1a30Sjl OPLMSU_TRACE(RD(lrq), nmp, MSU_TRC_LO); 72125cf1a30Sjl qreply(RD(lrq), nmp); 72225cf1a30Sjl } else { 72325cf1a30Sjl /* 72425cf1a30Sjl * No termios messages are received. Change active path. 72525cf1a30Sjl */ 72625cf1a30Sjl 72725cf1a30Sjl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_ACTIVE, upath->status, 72825cf1a30Sjl MSU_ACTIVE); 72925cf1a30Sjl 73025cf1a30Sjl lpath->uinst = oplmsu_uinst; 73125cf1a30Sjl lpath->src_upath = NULL; 73225cf1a30Sjl lpath->status = MSU_EXT_NOTUSED; 73325cf1a30Sjl 73425cf1a30Sjl /* Notify of the active path changing */ 73525cf1a30Sjl prom_opl_switch_console(upath->ser_devcb.lsb); 73625cf1a30Sjl 73725cf1a30Sjl putq(WR(lrq), fmp); 73825cf1a30Sjl 73925cf1a30Sjl /* Send XON to notify active path */ 74025cf1a30Sjl (void) oplmsu_cmn_put_xoffxon(WR(lrq), MSU_XON_4); 74125cf1a30Sjl 74225cf1a30Sjl if (lpath->hndl_mp != NULL) { 74325cf1a30Sjl /* Put a message(M_DATA) on a queue */ 74425cf1a30Sjl if (ctrl != NULL) { 74525cf1a30Sjl putq(RD(ctrl->queue), lpath->hndl_mp); 74625cf1a30Sjl } 74725cf1a30Sjl } 74825cf1a30Sjl 74925cf1a30Sjl oplmsu_clear_ioctl_path(lpath); 75025cf1a30Sjl 75125cf1a30Sjl if (ctrl != NULL) { 75225cf1a30Sjl noenable(WR(ctrl->queue)); 75325cf1a30Sjl } 75425cf1a30Sjl 75525cf1a30Sjl if ((stp_upath != NULL) && (stp_lpath != NULL)) { 75625cf1a30Sjl /* Change the status of stop path */ 75725cf1a30Sjl oplmsu_cmn_set_upath_sts(stp_upath, MSU_PSTAT_STANDBY, 75825cf1a30Sjl stp_upath->status, MSU_STANDBY); 75925cf1a30Sjl 76025cf1a30Sjl oplmsu_clear_ioctl_path(stp_lpath); 76125cf1a30Sjl stp_lpath->uinst = NULL; 76225cf1a30Sjl stp_lpath->src_upath = NULL; 76325cf1a30Sjl stp_lpath->status = MSU_EXT_NOTUSED; 76425cf1a30Sjl } 76525cf1a30Sjl #ifdef DEBUG 76625cf1a30Sjl oplmsu_cmn_prt_pathname(upath->ser_devcb.dip); 76725cf1a30Sjl #endif 76825cf1a30Sjl /* Send XOFF to notify all standby paths */ 76925cf1a30Sjl oplmsu_cmn_putxoff_standby(); 77025cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 77125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 77225cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 77325cf1a30Sjl 77425cf1a30Sjl OPLMSU_RWLOCK_UPGRADE(); 77525cf1a30Sjl mutex_enter(&oplmsu_uinst->u_lock); 77625cf1a30Sjl oplmsu_uinst->lower_queue = lrq; 77725cf1a30Sjl oplmsu_uinst->inst_status = oplmsu_get_inst_status(); 77825cf1a30Sjl mutex_exit(&oplmsu_uinst->u_lock); 77925cf1a30Sjl 78025cf1a30Sjl if (ctrl != NULL) { 78125cf1a30Sjl queue_t *temp_queue; 78225cf1a30Sjl 78325cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 78425cf1a30Sjl temp_queue = WR(ctrl->queue); 78525cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 78625cf1a30Sjl 78725cf1a30Sjl /* Reschedule a queue for service */ 78825cf1a30Sjl enableok(temp_queue); 78925cf1a30Sjl 79025cf1a30Sjl oplmsu_queue_flag = 0; 79125cf1a30Sjl oplmsu_wcmn_high_qenable(temp_queue, RW_WRITER); 79225cf1a30Sjl } 79325cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 79425cf1a30Sjl } 79525cf1a30Sjl return (SUCCESS); 79625cf1a30Sjl } 797