xref: /onnv-gate/usr/src/uts/sun4u/opl/io/oplmsu/oplmsu_ioctl_uwp.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 /*
231772Sjl139090  * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
241772Sjl139090  */
251772Sjl139090 
261772Sjl139090 #include <sys/errno.h>
271772Sjl139090 #include <sys/modctl.h>
281772Sjl139090 #include <sys/stat.h>
291772Sjl139090 #include <sys/kmem.h>
301772Sjl139090 #include <sys/ksynch.h>
311772Sjl139090 #include <sys/stream.h>
321772Sjl139090 #include <sys/stropts.h>
331772Sjl139090 #include <sys/termio.h>
341772Sjl139090 #include <sys/ddi.h>
351772Sjl139090 #include <sys/file.h>
361772Sjl139090 #include <sys/disp.h>
371772Sjl139090 #include <sys/sunddi.h>
381772Sjl139090 #include <sys/sunldi.h>
391772Sjl139090 #include <sys/sunndi.h>
401772Sjl139090 #include <sys/oplmsu/oplmsu.h>
411772Sjl139090 #include <sys/oplmsu/oplmsu_proto.h>
421772Sjl139090 
431772Sjl139090 /*
441772Sjl139090  *	UPPER WRITE SERVICE PROCEDURE
451772Sjl139090  */
461772Sjl139090 
471772Sjl139090 /* I_PLINK ioctl command received */
481772Sjl139090 int
oplmsu_uwioctl_iplink(queue_t * uwq,mblk_t * mp)491772Sjl139090 oplmsu_uwioctl_iplink(queue_t *uwq, mblk_t *mp)
501772Sjl139090 {
511772Sjl139090 	struct linkblk	*lbp;
521772Sjl139090 	lpath_t		*lpath;
531772Sjl139090 	int		ncode;
541772Sjl139090 
551772Sjl139090 	if (mp == NULL) {
561772Sjl139090 		return (EINVAL);
571772Sjl139090 	}
581772Sjl139090 
591772Sjl139090 	if ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) <
601772Sjl139090 	    sizeof (struct linkblk)) {
611772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-iplink: Invalid data length");
621772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
631772Sjl139090 		return (EINVAL);
641772Sjl139090 	}
651772Sjl139090 
661772Sjl139090 	lbp = (struct linkblk *)mp->b_cont->b_rptr;
671772Sjl139090 	rw_enter(&oplmsu_uinst->lock, RW_WRITER);
681772Sjl139090 
691772Sjl139090 	/*
701772Sjl139090 	 * Check whether this is called by super-user privilege.
711772Sjl139090 	 *   uwq => Queue of meta control node
721772Sjl139090 	 */
731772Sjl139090 
741772Sjl139090 	ncode = oplmsu_wcmn_chknode(uwq, MSU_NODE_META, mp);
751772Sjl139090 	if (ncode != SUCCESS) {
761772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
771772Sjl139090 		oplmsu_iocack(uwq, mp, ncode);
781772Sjl139090 		return (ncode);
791772Sjl139090 	}
801772Sjl139090 
811772Sjl139090 	/* Allocate kernel memory for lpath_t */
821772Sjl139090 	lpath = (lpath_t *)kmem_zalloc(sizeof (lpath_t), KM_NOSLEEP);
831772Sjl139090 	if (lpath == NULL) {
841772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
851772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-iplink: "
861772Sjl139090 		    "Failed to allocate kernel memory");
871772Sjl139090 		oplmsu_iocack(uwq, mp, ENOMEM);
881772Sjl139090 		return (ENOMEM);
891772Sjl139090 	}
901772Sjl139090 
911772Sjl139090 	/*
921772Sjl139090 	 * Initialize members of lpath_t
931772Sjl139090 	 */
941772Sjl139090 
951772Sjl139090 	lpath->rbuftbl =
961772Sjl139090 	    (struct buf_tbl *)kmem_zalloc(sizeof (struct buf_tbl), KM_NOSLEEP);
971772Sjl139090 	if (lpath->rbuftbl == NULL) {
981772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
991772Sjl139090 		kmem_free(lpath, sizeof (lpath_t));
1001772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-iplink: "
1011772Sjl139090 		    "Failed to allocate kernel memory");
1021772Sjl139090 		oplmsu_iocack(uwq, mp, ENOMEM);
1031772Sjl139090 		return (ENOMEM);
1041772Sjl139090 	}
1051772Sjl139090 
1061772Sjl139090 	cv_init(&lpath->sw_cv, "oplmsu lpath condvar", CV_DRIVER, NULL);
1071772Sjl139090 	lpath->src_upath = NULL;
1081772Sjl139090 	lpath->status = MSU_EXT_NOTUSED;
1091772Sjl139090 	lpath->lower_queue = lbp->l_qbot;	/* Set lower queue pointer */
1101772Sjl139090 	lpath->link_id = lbp->l_index;		/* Set Link-ID */
1111772Sjl139090 	lpath->path_no = UNDEFINED;		/* Set initial path number */
1121772Sjl139090 	lpath->abt_char = oplmsu_uinst->abts;	/* Set abort character seq */
1131772Sjl139090 
1141772Sjl139090 	WR(lpath->lower_queue)->q_ptr = lpath;
1151772Sjl139090 	RD(lpath->lower_queue)->q_ptr = lpath;
1161772Sjl139090 
1171772Sjl139090 	oplmsu_link_lpath(lpath);	/* Link lpath_t */
1181772Sjl139090 	rw_exit(&oplmsu_uinst->lock);
1191772Sjl139090 	oplmsu_iocack(uwq, mp, 0);
1201772Sjl139090 	return (SUCCESS);
1211772Sjl139090 }
1221772Sjl139090 
1231772Sjl139090 /* I_PUNLINK ioctl command received */
1241772Sjl139090 int
oplmsu_uwioctl_ipunlink(queue_t * uwq,mblk_t * mp)1251772Sjl139090 oplmsu_uwioctl_ipunlink(queue_t *uwq, mblk_t *mp)
1261772Sjl139090 {
1271772Sjl139090 	struct linkblk	*lbp;
1281772Sjl139090 	upath_t		*upath;
1291772Sjl139090 	lpath_t		*lpath;
1301772Sjl139090 	mblk_t		*hmp = NULL, *next_hmp = NULL;
1311772Sjl139090 	bufcall_id_t	rbuf_id;
1321772Sjl139090 	timeout_id_t	rtout_id;
1331772Sjl139090 	int		ncode;
1341772Sjl139090 	int		use_flag;
1351772Sjl139090 
1361772Sjl139090 	if (mp == NULL) {
1371772Sjl139090 		return (EINVAL);
1381772Sjl139090 	}
1391772Sjl139090 
1401772Sjl139090 	if ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) <
1411772Sjl139090 	    sizeof (struct linkblk)) {
1421772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-ipunlink: Invalid data length");
1431772Sjl139090 		oplmsu_iocack(uwq, mp, ENOSR);
1441772Sjl139090 		return (ENOSR);
1451772Sjl139090 	}
1461772Sjl139090 
1471772Sjl139090 	lbp = (struct linkblk *)mp->b_cont->b_rptr;
1481772Sjl139090 	rw_enter(&oplmsu_uinst->lock, RW_WRITER);
1491772Sjl139090 
1501772Sjl139090 	/*
1511772Sjl139090 	 * Check whether this is called by super-user privilege.
1521772Sjl139090 	 *   uwq => Queue of meta control node
1531772Sjl139090 	 */
1541772Sjl139090 
1551772Sjl139090 	ncode = oplmsu_wcmn_chknode(uwq, MSU_NODE_META, mp);
1561772Sjl139090 	if (ncode != SUCCESS) {
1571772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
1581772Sjl139090 		oplmsu_iocack(uwq, mp, ncode);
1591772Sjl139090 		return (ncode);
1601772Sjl139090 	}
1611772Sjl139090 
1621772Sjl139090 	mutex_enter(&oplmsu_uinst->u_lock);
1631772Sjl139090 	mutex_enter(&oplmsu_uinst->l_lock);
1641772Sjl139090 
1651772Sjl139090 	/*
1661772Sjl139090 	 * Search for a corresponding lower path information table to
1671772Sjl139090 	 * lbp->l_qbot from the lower queue address.
1681772Sjl139090 	 */
1691772Sjl139090 
1701772Sjl139090 	lpath = oplmsu_uinst->first_lpath;
1711772Sjl139090 	while (lpath) {
1721772Sjl139090 		if ((lpath->lower_queue == RD(lbp->l_qbot)) ||
1731772Sjl139090 		    (lpath->lower_queue == WR(lbp->l_qbot))) {
1741772Sjl139090 			break;
1751772Sjl139090 		}
1761772Sjl139090 		lpath = lpath->l_next;
1771772Sjl139090 	}
1781772Sjl139090 
1791772Sjl139090 	if (lpath == NULL) {
1801772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
1811772Sjl139090 		mutex_exit(&oplmsu_uinst->u_lock);
1821772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
1831772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-ipunlink: "
1841772Sjl139090 		    "Proper lpath_t doesn't find");
1851772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
1861772Sjl139090 		return (EINVAL);
1871772Sjl139090 	}
1881772Sjl139090 
1891772Sjl139090 	/* lpath_t come into the busy status */
1901772Sjl139090 	use_flag = oplmsu_set_ioctl_path(lpath, uwq, NULL);
1911772Sjl139090 	if (use_flag == BUSY) {
1921772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
1931772Sjl139090 		mutex_exit(&oplmsu_uinst->u_lock);
1941772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
1951772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-ipunlink: "
1961772Sjl139090 		    "Other processing is using lower path");
1971772Sjl139090 		oplmsu_iocack(uwq, mp, EBUSY);
1981772Sjl139090 		return (EBUSY);
1991772Sjl139090 	}
2001772Sjl139090 
2011772Sjl139090 	/* upath_t is retrieved by using the path number */
2021772Sjl139090 	upath = oplmsu_search_upath_info(lpath->path_no);
2031772Sjl139090 	if (upath != NULL) {	/* When the upath_t exists */
2041772Sjl139090 		switch (upath->status) {
2051772Sjl139090 		case MSU_PSTAT_STOP :	/* FALLTHRU */
2061772Sjl139090 		case MSU_PSTAT_FAIL :
2071772Sjl139090 			/*
2081772Sjl139090 			 * When traditional_status is MSU_SETID, the path
2091772Sjl139090 			 * status is changed into the state of disconnect.
2101772Sjl139090 			 */
2111772Sjl139090 
2121772Sjl139090 			if (upath->traditional_status == MSU_SETID) {
2131772Sjl139090 				oplmsu_cmn_set_upath_sts(upath,
2141772Sjl139090 				    MSU_PSTAT_DISCON, upath->status,
2151772Sjl139090 				    MSU_DISCON);
2161772Sjl139090 				upath->lpath = NULL;
2171772Sjl139090 				break;
2181772Sjl139090 			}
2191772Sjl139090 
2201772Sjl139090 			/*
2211772Sjl139090 			 * When traditional_status isn't MSU_SETID,
2221772Sjl139090 			 * the error is reported.
2231772Sjl139090 			 */
2241772Sjl139090 
2251772Sjl139090 		default :
2261772Sjl139090 			/*
2271772Sjl139090 			 * When upath->status isn't MSU_PSTAT_STOP or
2281772Sjl139090 			 * MSU_PSTAT_FAIL, the error is reported.
2291772Sjl139090 			 */
2301772Sjl139090 
2311772Sjl139090 			oplmsu_clear_ioctl_path(lpath);
2321772Sjl139090 			mutex_exit(&oplmsu_uinst->l_lock);
2331772Sjl139090 			cmn_err(CE_WARN, "oplmsu: uw-ipunlink: "
2341772Sjl139090 			    "trad_status = %lx", upath->traditional_status);
2351772Sjl139090 			cmn_err(CE_WARN, "oplmsu: uw-ipunlink: "
2361772Sjl139090 			    "status = %d", upath->status);
2371772Sjl139090 			mutex_exit(&oplmsu_uinst->u_lock);
2381772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
2391772Sjl139090 			oplmsu_iocack(uwq, mp, EINVAL);
2401772Sjl139090 			return (EINVAL);
2411772Sjl139090 		}
2421772Sjl139090 	} else {
2431772Sjl139090 		/*
2441772Sjl139090 		 * This pattern is no upper info table before config_add or
2451772Sjl139090 		 * after config_del.
2461772Sjl139090 		 */
2471772Sjl139090 
2481772Sjl139090 		/*
2491772Sjl139090 		 * When the upper path table doesn't exist, path is deleted
2501772Sjl139090 		 * with config_del/config_add ioctl processed.
2511772Sjl139090 		 */
2521772Sjl139090 
2531772Sjl139090 		if ((lpath->status != MSU_LINK_NU) &&
2541772Sjl139090 		    (lpath->status != MSU_SETID_NU)) {
2551772Sjl139090 			oplmsu_clear_ioctl_path(lpath);
2561772Sjl139090 			mutex_exit(&oplmsu_uinst->l_lock);
2571772Sjl139090 			mutex_exit(&oplmsu_uinst->u_lock);
2581772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
2591772Sjl139090 			oplmsu_iocack(uwq, mp, EINVAL);
2601772Sjl139090 			return (EINVAL);
2611772Sjl139090 		}
2621772Sjl139090 	}
2631772Sjl139090 
2641772Sjl139090 	oplmsu_uinst->inst_status = oplmsu_get_inst_status();
2651772Sjl139090 	oplmsu_clear_ioctl_path(lpath);
2661772Sjl139090 
2671772Sjl139090 	/* Free high priority message */
2681772Sjl139090 	if (lpath->first_lpri_hi != NULL) {
2691772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-ipunlink: "
2701772Sjl139090 		    "Free high-priority message by unlinking lower path");
2711772Sjl139090 
2721772Sjl139090 		for (hmp = lpath->first_lpri_hi; hmp; ) {
2731772Sjl139090 			next_hmp = hmp->b_next;
2741772Sjl139090 			freemsg(hmp);
2751772Sjl139090 			hmp = next_hmp;
2761772Sjl139090 		}
2771772Sjl139090 		lpath->first_lpri_hi = NULL;
2781772Sjl139090 		lpath->last_lpri_hi = NULL;
2791772Sjl139090 	}
2801772Sjl139090 
2811772Sjl139090 	rbuf_id = lpath->rbuf_id;
2821772Sjl139090 	rtout_id = lpath->rtout_id;
2831772Sjl139090 	lpath->rbuf_id = 0;
2841772Sjl139090 	lpath->rtout_id = 0;
2851772Sjl139090 
2861772Sjl139090 	kmem_free(lpath->rbuftbl, sizeof (struct buf_tbl));
2871772Sjl139090 	lpath->rbuftbl = NULL;
2881772Sjl139090 	cv_destroy(&lpath->sw_cv);
2891772Sjl139090 	oplmsu_unlink_lpath(lpath);
2901772Sjl139090 	kmem_free(lpath, sizeof (lpath_t));
2911772Sjl139090 
2921772Sjl139090 	mutex_exit(&oplmsu_uinst->l_lock);
2931772Sjl139090 	mutex_exit(&oplmsu_uinst->u_lock);
2941772Sjl139090 	rw_exit(&oplmsu_uinst->lock);
2951772Sjl139090 
2961772Sjl139090 	if (rbuf_id != 0) {
2971772Sjl139090 		unbufcall(rbuf_id);
2981772Sjl139090 	}
2991772Sjl139090 
3001772Sjl139090 	if (rtout_id != 0) {
301*11311SSurya.Prakki@Sun.COM 		(void) untimeout(rtout_id);
3021772Sjl139090 	}
3031772Sjl139090 	oplmsu_iocack(uwq, mp, 0);
3041772Sjl139090 	return (SUCCESS);
3051772Sjl139090 }
3061772Sjl139090 
3071772Sjl139090 /* termio ioctl command received */
3081772Sjl139090 int
oplmsu_uwioctl_termios(queue_t * uwq,mblk_t * mp)3091772Sjl139090 oplmsu_uwioctl_termios(queue_t *uwq, mblk_t *mp)
3101772Sjl139090 {
3111772Sjl139090 	struct iocblk	*iocp = NULL;
3121772Sjl139090 	queue_t		*dst_queue;
3131772Sjl139090 	upath_t		*upath = NULL;
3141772Sjl139090 	lpath_t		*lpath = NULL;
3151772Sjl139090 	mblk_t		*nmp = NULL;
3161772Sjl139090 	ctrl_t		*ctrl;
3171772Sjl139090 	int		term_stat;
3181772Sjl139090 	int		use_flag;
3191772Sjl139090 
3201772Sjl139090 	if (mp == NULL) {
3211772Sjl139090 		return (EINVAL);
3221772Sjl139090 	}
3231772Sjl139090 
3241772Sjl139090 	if (mp->b_cont == NULL) {
3251772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-termios: "
3261772Sjl139090 		    "b_cont data block is NULL");
3271772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
3281772Sjl139090 		return (FAILURE);
3291772Sjl139090 	}
3301772Sjl139090 
3311772Sjl139090 	if (mp->b_cont->b_rptr == NULL) {
3321772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-termios: "
3331772Sjl139090 		    "b_rptr data pointer is NULL");
3341772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
3351772Sjl139090 		return (EINVAL);
3361772Sjl139090 	}
3371772Sjl139090 
3381772Sjl139090 	iocp = (struct iocblk *)mp->b_rptr;
3391772Sjl139090 	rw_enter(&oplmsu_uinst->lock, RW_READER);
3401772Sjl139090 
3411772Sjl139090 	/*
3421772Sjl139090 	 * Check control node type
3431772Sjl139090 	 *   uwq : Queue of user control node
3441772Sjl139090 	 */
3451772Sjl139090 
3461772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
3471772Sjl139090 	ctrl = (ctrl_t *)uwq->q_ptr;
3481772Sjl139090 	if (ctrl != NULL) {
3491772Sjl139090 		if (ctrl->node_type != MSU_NODE_USER) {
3501772Sjl139090 			mutex_exit(&oplmsu_uinst->c_lock);
3511772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
3521772Sjl139090 			cmn_err(CE_WARN, "oplmsu: uw-termios: "
3531772Sjl139090 			    "ctrl node type = %d", ctrl->node_type);
3541772Sjl139090 			oplmsu_iocack(uwq, mp, EINVAL);
3551772Sjl139090 			return (EINVAL);
3561772Sjl139090 		}
3571772Sjl139090 	}
3581772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
3591772Sjl139090 
3601772Sjl139090 	switch (iocp->ioc_cmd) {
3611772Sjl139090 	case TCSETS :	/* FALLTHRU */
3621772Sjl139090 	case TCSETSW :	/* FALLTHRU */
3631772Sjl139090 	case TCSETSF :
3641772Sjl139090 		term_stat = MSU_WTCS_ACK;
3651772Sjl139090 		break;
3661772Sjl139090 
3671772Sjl139090 	case TIOCMSET :
3681772Sjl139090 		term_stat = MSU_WTMS_ACK;
3691772Sjl139090 		break;
3701772Sjl139090 
3711772Sjl139090 	case TIOCSPPS :
3721772Sjl139090 		term_stat = MSU_WPPS_ACK;
3731772Sjl139090 		break;
3741772Sjl139090 
3751772Sjl139090 	case TIOCSWINSZ :
3761772Sjl139090 		term_stat = MSU_WWSZ_ACK;
3771772Sjl139090 		break;
3781772Sjl139090 
3791772Sjl139090 	case TIOCSSOFTCAR :
3801772Sjl139090 		term_stat = MSU_WCAR_ACK;
3811772Sjl139090 		break;
3821772Sjl139090 
3831772Sjl139090 	default :
3841772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
3851772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-termios: ioctl mismatch");
3861772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
3871772Sjl139090 		return (EINVAL);
3881772Sjl139090 	}
3891772Sjl139090 
3901772Sjl139090 	if (oplmsu_uinst->lower_queue == NULL) {
3911772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
3921772Sjl139090 		cmn_err(CE_WARN, "!oplmsu: uw-termios: "
3931772Sjl139090 		    "Active path doesn't exist");
3941772Sjl139090 		oplmsu_iocack(uwq, mp, ENODEV);
3951772Sjl139090 		return (FAILURE);
3961772Sjl139090 	}
3971772Sjl139090 
3981772Sjl139090 	lpath = oplmsu_uinst->lower_queue->q_ptr;
3991772Sjl139090 	if (lpath == NULL) {
4001772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
4011772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-termios: "
4021772Sjl139090 		    "Proper lpath_t doesn't exist");
4031772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
4041772Sjl139090 		return (EINVAL);
4051772Sjl139090 	}
4061772Sjl139090 
4071772Sjl139090 	if (oplmsu_cmn_copymb(uwq, mp, &nmp, mp, MSU_WRITE_SIDE) == FAILURE) {
4081772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
4091772Sjl139090 		return (FAILURE);
4101772Sjl139090 	}
4111772Sjl139090 
4121772Sjl139090 	mutex_enter(&oplmsu_uinst->u_lock);
4131772Sjl139090 	mutex_enter(&oplmsu_uinst->l_lock);
4141772Sjl139090 
4151772Sjl139090 	upath = oplmsu_search_upath_info(lpath->path_no);
4161772Sjl139090 	if (upath == NULL) {
4171772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
4181772Sjl139090 		mutex_exit(&oplmsu_uinst->u_lock);
4191772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
4201772Sjl139090 		cmn_err(CE_WARN, "oplmsu: uw-termios: "
4211772Sjl139090 		    "Proper upath_t doesn't find");
4221772Sjl139090 		oplmsu_iocack(uwq, mp, EINVAL);
4231772Sjl139090 		return (EINVAL);
4241772Sjl139090 	}
4251772Sjl139090 
4261772Sjl139090 	/* Set ioctl command to lower path info table */
4271772Sjl139090 	use_flag = oplmsu_set_ioctl_path(lpath, uwq, mp);
4281772Sjl139090 	if (use_flag == BUSY) {
4291772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
4301772Sjl139090 		mutex_exit(&oplmsu_uinst->u_lock);
4311772Sjl139090 		freemsg(nmp);
4321772Sjl139090 
4331772Sjl139090 		if (ctrl != NULL) {
4341772Sjl139090 			mutex_enter(&oplmsu_uinst->c_lock);
4351772Sjl139090 			ctrl->wait_queue = uwq;
4361772Sjl139090 			mutex_exit(&oplmsu_uinst->c_lock);
4371772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
4381772Sjl139090 
439*11311SSurya.Prakki@Sun.COM 			(void) putbq(uwq, mp);
4401772Sjl139090 			return (SUCCESS);
4411772Sjl139090 		} else {
4421772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
4431772Sjl139090 			oplmsu_iocack(uwq, mp, EBUSY);
4441772Sjl139090 			return (EBUSY);
4451772Sjl139090 		}
4461772Sjl139090 	}
4471772Sjl139090 
4481772Sjl139090 	/* Set destination queue (active path) */
4491772Sjl139090 	dst_queue = WR(oplmsu_uinst->lower_queue);
4501772Sjl139090 	if (canput(dst_queue)) {
4511772Sjl139090 		lpath->src_upath = NULL;
4521772Sjl139090 		lpath->status = upath->traditional_status;
4531772Sjl139090 		upath->traditional_status = term_stat;
4541772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
4551772Sjl139090 		mutex_exit(&oplmsu_uinst->u_lock);
4561772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
4571772Sjl139090 
458*11311SSurya.Prakki@Sun.COM 		(void) putq(dst_queue, nmp);
4591772Sjl139090 		return (SUCCESS);
4601772Sjl139090 	} else {
4611772Sjl139090 		oplmsu_clear_ioctl_path(lpath);
4621772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
4631772Sjl139090 		mutex_exit(&oplmsu_uinst->u_lock);
4641772Sjl139090 
4651772Sjl139090 		freemsg(nmp);
4661772Sjl139090 		oplmsu_wcmn_norm_putbq(WR(uwq), mp, dst_queue);
4671772Sjl139090 		rw_exit(&oplmsu_uinst->lock);
4681772Sjl139090 		return (FAILURE);
4691772Sjl139090 	}
4701772Sjl139090 }
471