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