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 #include <sys/errno.h> 2625cf1a30Sjl #include <sys/modctl.h> 2725cf1a30Sjl #include <sys/stat.h> 2825cf1a30Sjl #include <sys/kmem.h> 2925cf1a30Sjl #include <sys/ksynch.h> 3025cf1a30Sjl #include <sys/stream.h> 3125cf1a30Sjl #include <sys/stropts.h> 3225cf1a30Sjl #include <sys/termio.h> 3325cf1a30Sjl #include <sys/ddi.h> 3425cf1a30Sjl #include <sys/file.h> 3525cf1a30Sjl #include <sys/disp.h> 3625cf1a30Sjl #include <sys/sunddi.h> 3725cf1a30Sjl #include <sys/sunldi.h> 3825cf1a30Sjl #include <sys/sunndi.h> 3925cf1a30Sjl #include <sys/strsun.h> 4025cf1a30Sjl #include <sys/oplmsu/oplmsu.h> 4125cf1a30Sjl #include <sys/oplmsu/oplmsu_proto.h> 4225cf1a30Sjl 4325cf1a30Sjl /* 4425cf1a30Sjl * Link upper_path_table structure 4525cf1a30Sjl * 4625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 4725cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 4825cf1a30Sjl * -. uinst_t->u_lock : M 4925cf1a30Sjl * -. uinst_t->l_lock : A 5025cf1a30Sjl * -. uinst_t->c_lock : A 5125cf1a30Sjl */ 5225cf1a30Sjl void 5325cf1a30Sjl oplmsu_link_upath(upath_t *add_upath) 5425cf1a30Sjl { 5525cf1a30Sjl 5625cf1a30Sjl ASSERT(add_upath != NULL); 5725cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 5825cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 5925cf1a30Sjl 6025cf1a30Sjl if (oplmsu_uinst->first_upath == NULL) { 6125cf1a30Sjl oplmsu_uinst->first_upath = add_upath; 6225cf1a30Sjl add_upath->u_prev = NULL; 6325cf1a30Sjl } else { 6425cf1a30Sjl upath_t *last_upath; 6525cf1a30Sjl 6625cf1a30Sjl last_upath = oplmsu_uinst->last_upath; 6725cf1a30Sjl last_upath->u_next = add_upath; 6825cf1a30Sjl add_upath->u_prev = last_upath; 6925cf1a30Sjl } 7025cf1a30Sjl 7125cf1a30Sjl oplmsu_uinst->last_upath = add_upath; 7225cf1a30Sjl add_upath->u_next = NULL; 7325cf1a30Sjl } 7425cf1a30Sjl 7525cf1a30Sjl /* 7625cf1a30Sjl * Unlink upper_path_table structure 7725cf1a30Sjl * 7825cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 7925cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 8025cf1a30Sjl * -. uinst_t->u_lock : P 8125cf1a30Sjl * -. uinst_t->l_lock : P 8225cf1a30Sjl * -. uinst_t->c_lock : P 8325cf1a30Sjl */ 8425cf1a30Sjl void 8525cf1a30Sjl oplmsu_unlink_upath(upath_t *del_upath) 8625cf1a30Sjl { 8725cf1a30Sjl upath_t **first, **last; 8825cf1a30Sjl 8925cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 9025cf1a30Sjl 9125cf1a30Sjl first = &oplmsu_uinst->first_upath; 9225cf1a30Sjl last = &oplmsu_uinst->last_upath; 9325cf1a30Sjl 9425cf1a30Sjl if ((*first != del_upath) && (*last != del_upath)) { 9525cf1a30Sjl del_upath->u_prev->u_next = del_upath->u_next; 9625cf1a30Sjl del_upath->u_next->u_prev = del_upath->u_prev; 9725cf1a30Sjl } else { 9825cf1a30Sjl if (*first == del_upath) { 9925cf1a30Sjl *first = (*first)->u_next; 10025cf1a30Sjl if (*first) { 10125cf1a30Sjl (*first)->u_prev = NULL; 10225cf1a30Sjl } 10325cf1a30Sjl } 10425cf1a30Sjl 10525cf1a30Sjl if (*last == del_upath) { 10625cf1a30Sjl *last = (*last)->u_prev; 10725cf1a30Sjl if (*last) { 10825cf1a30Sjl (*last)->u_next = NULL; 10925cf1a30Sjl } 11025cf1a30Sjl } 11125cf1a30Sjl } 11225cf1a30Sjl 11325cf1a30Sjl del_upath->u_next = NULL; 11425cf1a30Sjl del_upath->u_prev = NULL; 11525cf1a30Sjl } 11625cf1a30Sjl 11725cf1a30Sjl /* 11825cf1a30Sjl * Link lower_path_table structure 11925cf1a30Sjl * 12025cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 12125cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 12225cf1a30Sjl * -. uinst_t->u_lock : A 12325cf1a30Sjl * -. uinst_t->l_lock : M 12425cf1a30Sjl * -. uinst_t->c_lock : A 12525cf1a30Sjl */ 12625cf1a30Sjl void 12725cf1a30Sjl oplmsu_link_lpath(lpath_t *add_lpath) 12825cf1a30Sjl { 12925cf1a30Sjl 13025cf1a30Sjl ASSERT(add_lpath != NULL); 13125cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 13225cf1a30Sjl 13325cf1a30Sjl if (oplmsu_uinst->first_lpath == NULL) { 13425cf1a30Sjl oplmsu_uinst->first_lpath = add_lpath; 13525cf1a30Sjl add_lpath->l_prev = NULL; 13625cf1a30Sjl } else { 13725cf1a30Sjl lpath_t *last_lpath; 13825cf1a30Sjl 13925cf1a30Sjl last_lpath = oplmsu_uinst->last_lpath; 14025cf1a30Sjl last_lpath->l_next = add_lpath; 14125cf1a30Sjl add_lpath->l_prev = last_lpath; 14225cf1a30Sjl } 14325cf1a30Sjl 14425cf1a30Sjl oplmsu_uinst->last_lpath = add_lpath; 14525cf1a30Sjl add_lpath->l_next = NULL; 14625cf1a30Sjl } 14725cf1a30Sjl 14825cf1a30Sjl /* 14925cf1a30Sjl * Unlink lower_path_table structure 15025cf1a30Sjl * 15125cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 15225cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 15325cf1a30Sjl * -. uinst_t->u_lock : P 15425cf1a30Sjl * -. uinst_t->l_lock : P 15525cf1a30Sjl * -. uinst_t->c_lock : P 15625cf1a30Sjl */ 15725cf1a30Sjl void 15825cf1a30Sjl oplmsu_unlink_lpath(lpath_t *del_lpath) 15925cf1a30Sjl { 16025cf1a30Sjl lpath_t **first, **last; 16125cf1a30Sjl 16225cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 16325cf1a30Sjl 16425cf1a30Sjl first = &oplmsu_uinst->first_lpath; 16525cf1a30Sjl last = &oplmsu_uinst->last_lpath; 16625cf1a30Sjl 16725cf1a30Sjl if ((*first != del_lpath) && (*last != del_lpath)) { 16825cf1a30Sjl del_lpath->l_prev->l_next = del_lpath->l_next; 16925cf1a30Sjl del_lpath->l_next->l_prev = del_lpath->l_prev; 17025cf1a30Sjl } else { 17125cf1a30Sjl if (*first == del_lpath) { 17225cf1a30Sjl *first = (*first)->l_next; 17325cf1a30Sjl if (*first) { 17425cf1a30Sjl (*first)->l_prev = NULL; 17525cf1a30Sjl } 17625cf1a30Sjl } 17725cf1a30Sjl 17825cf1a30Sjl if (*last == del_lpath) { 17925cf1a30Sjl *last = (*last)->l_prev; 18025cf1a30Sjl if (*last) { 18125cf1a30Sjl (*last)->l_next = NULL; 18225cf1a30Sjl } 18325cf1a30Sjl } 18425cf1a30Sjl } 18525cf1a30Sjl 18625cf1a30Sjl del_lpath->l_next = NULL; 18725cf1a30Sjl del_lpath->l_prev = NULL; 18825cf1a30Sjl } 18925cf1a30Sjl 19025cf1a30Sjl /* 19125cf1a30Sjl * Link msgb structure of high priority 19225cf1a30Sjl * 19325cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 19425cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 19525cf1a30Sjl * -. uinst_t->u_lock : A 19625cf1a30Sjl * -. uinst_t->l_lock : A [It depends on caller] 19725cf1a30Sjl * -. uinst_t->c_lock : A [It depends on caller] 19825cf1a30Sjl */ 19925cf1a30Sjl void 20025cf1a30Sjl oplmsu_link_high_primsg(mblk_t **first, mblk_t **last, mblk_t *add_msg) 20125cf1a30Sjl { 20225cf1a30Sjl 20325cf1a30Sjl ASSERT(add_msg != NULL); 20425cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 20525cf1a30Sjl 20625cf1a30Sjl if (*first == NULL) { 20725cf1a30Sjl *first = add_msg; 20825cf1a30Sjl add_msg->b_prev = NULL; 20925cf1a30Sjl } else { 21025cf1a30Sjl (*last)->b_next = add_msg; 21125cf1a30Sjl add_msg->b_prev = *last; 21225cf1a30Sjl } 21325cf1a30Sjl 21425cf1a30Sjl *last = add_msg; 21525cf1a30Sjl add_msg->b_next = NULL; 21625cf1a30Sjl } 21725cf1a30Sjl 21825cf1a30Sjl /* 21925cf1a30Sjl * Check whether lower path is usable by lower path info table address 22025cf1a30Sjl * 22125cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 22225cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 22325cf1a30Sjl * -. uinst_t->u_lock : A 22425cf1a30Sjl * -. uinst_t->l_lock : M 22525cf1a30Sjl * -. uinst_t->c_lock : P 22625cf1a30Sjl */ 22725cf1a30Sjl int 22825cf1a30Sjl oplmsu_check_lpath_usable(void) 22925cf1a30Sjl { 23025cf1a30Sjl lpath_t *lpath; 23125cf1a30Sjl int rval = SUCCESS; 23225cf1a30Sjl 23325cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 23425cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 23525cf1a30Sjl 23625cf1a30Sjl lpath = oplmsu_uinst->first_lpath; 23725cf1a30Sjl while (lpath) { 23825cf1a30Sjl if ((lpath->hndl_uqueue != NULL) || (lpath->hndl_mp != NULL)) { 23925cf1a30Sjl rval = BUSY; 24025cf1a30Sjl break; 24125cf1a30Sjl } 24225cf1a30Sjl lpath = lpath->l_next; 24325cf1a30Sjl } 24425cf1a30Sjl return (rval); 24525cf1a30Sjl } 24625cf1a30Sjl 24725cf1a30Sjl /* 24825cf1a30Sjl * Search upath_t by path number 24925cf1a30Sjl * 25025cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 25125cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 25225cf1a30Sjl * -. uinst_t->u_lock : M 25325cf1a30Sjl * -. uinst_t->l_lock : A 25425cf1a30Sjl * -. uinst_t->c_lock : P 25525cf1a30Sjl */ 25625cf1a30Sjl upath_t * 25725cf1a30Sjl oplmsu_search_upath_info(int path_no) 25825cf1a30Sjl { 25925cf1a30Sjl upath_t *upath; 26025cf1a30Sjl 26125cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 26225cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 26325cf1a30Sjl 26425cf1a30Sjl upath = oplmsu_uinst->first_upath; 26525cf1a30Sjl while (upath) { 26625cf1a30Sjl if (upath->path_no == path_no) { 26725cf1a30Sjl break; 26825cf1a30Sjl } 26925cf1a30Sjl upath = upath->u_next; 27025cf1a30Sjl } 27125cf1a30Sjl return (upath); 27225cf1a30Sjl } 27325cf1a30Sjl 27425cf1a30Sjl /* 27525cf1a30Sjl * Send M_IOCACK(or M_IOCNAK) message to stream 27625cf1a30Sjl * 27725cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 27825cf1a30Sjl * -. uinst_t->lock : P 27925cf1a30Sjl * -. uinst_t->u_lock : P 28025cf1a30Sjl * -. uinst_t->l_lock : P 28125cf1a30Sjl * -. uinst_t->c_lock : P 28225cf1a30Sjl */ 28325cf1a30Sjl void 28425cf1a30Sjl oplmsu_iocack(queue_t *q, mblk_t *mp, int errno) 28525cf1a30Sjl { 28625cf1a30Sjl struct iocblk *iocp = NULL; 28725cf1a30Sjl 28825cf1a30Sjl ASSERT(mp != NULL); 28925cf1a30Sjl 29025cf1a30Sjl iocp = (struct iocblk *)mp->b_rptr; 29125cf1a30Sjl iocp->ioc_error = errno; 29225cf1a30Sjl 29325cf1a30Sjl if (errno) { /* Error */ 29425cf1a30Sjl mp->b_datap->db_type = M_IOCNAK; 29525cf1a30Sjl iocp->ioc_rval = FAILURE; 29625cf1a30Sjl 29725cf1a30Sjl OPLMSU_TRACE(q, mp, MSU_TRC_UO); 29825cf1a30Sjl qreply(q, mp); 29925cf1a30Sjl } else { /* Good */ 30025cf1a30Sjl mp->b_datap->db_type = M_IOCACK; 30125cf1a30Sjl iocp->ioc_rval = SUCCESS; 30225cf1a30Sjl 30325cf1a30Sjl OPLMSU_TRACE(q, mp, MSU_TRC_UO); 30425cf1a30Sjl qreply(q, mp); 30525cf1a30Sjl } 30625cf1a30Sjl } 30725cf1a30Sjl 30825cf1a30Sjl /* 30925cf1a30Sjl * Delete all upath_t 31025cf1a30Sjl * 31125cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 31225cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 31325cf1a30Sjl * -. uinst_t->u_lock : M 31425cf1a30Sjl * -. uinst_t->l_lock : A 31525cf1a30Sjl * -. uinst_t->c_lock : A 31625cf1a30Sjl */ 31725cf1a30Sjl void 31825cf1a30Sjl oplmsu_delete_upath_info(void) 31925cf1a30Sjl { 32025cf1a30Sjl upath_t *upath, *next_upath; 32125cf1a30Sjl 32225cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 32325cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 32425cf1a30Sjl 32525cf1a30Sjl upath = oplmsu_uinst->first_upath; 32625cf1a30Sjl oplmsu_uinst->first_upath = NULL; 32725cf1a30Sjl oplmsu_uinst->last_upath = NULL; 32825cf1a30Sjl 32925cf1a30Sjl while (upath) { 33025cf1a30Sjl next_upath = upath->u_next; 33125cf1a30Sjl kmem_free(upath, sizeof (upath_t)); 33225cf1a30Sjl upath = next_upath; 33325cf1a30Sjl } 33425cf1a30Sjl } 33525cf1a30Sjl 33625cf1a30Sjl /* 33725cf1a30Sjl * Set queue and ioctl to lpath_t 33825cf1a30Sjl * 33925cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 34025cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 34125cf1a30Sjl * -. uinst_t->u_lock : A 34225cf1a30Sjl * -. uinst_t->l_lock : M 34325cf1a30Sjl * -. uinst_t->c_lock : P 34425cf1a30Sjl */ 34525cf1a30Sjl int 34625cf1a30Sjl oplmsu_set_ioctl_path(lpath_t *lpath, queue_t *hndl_queue, mblk_t *mp) 34725cf1a30Sjl { 34825cf1a30Sjl int rval = SUCCESS; 34925cf1a30Sjl 35025cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 35125cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 35225cf1a30Sjl 35325cf1a30Sjl if ((lpath->hndl_uqueue == NULL) && (lpath->hndl_mp == NULL) && 35425cf1a30Sjl (lpath->sw_flag == 0)) { 35525cf1a30Sjl if ((lpath->status == MSU_EXT_NOTUSED) || 35625cf1a30Sjl (lpath->status == MSU_EXT_ACTIVE_CANDIDATE) || 35725cf1a30Sjl (lpath->status == MSU_SETID_NU)) { 35825cf1a30Sjl if (hndl_queue == NULL) { 35925cf1a30Sjl lpath->hndl_uqueue = hndl_queue; 36025cf1a30Sjl } else { 36125cf1a30Sjl lpath->hndl_uqueue = WR(hndl_queue); 36225cf1a30Sjl } 36325cf1a30Sjl lpath->hndl_mp = mp; 36425cf1a30Sjl } else { 36525cf1a30Sjl rval = BUSY; 36625cf1a30Sjl } 36725cf1a30Sjl } else { 36825cf1a30Sjl rval = BUSY; 36925cf1a30Sjl } 37025cf1a30Sjl return (rval); 37125cf1a30Sjl } 37225cf1a30Sjl 37325cf1a30Sjl /* 37425cf1a30Sjl * Clear queue and ioctl to lpath_t 37525cf1a30Sjl * 37625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 37725cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 37825cf1a30Sjl * -. uinst_t->u_lock : A 37925cf1a30Sjl * -. uinst_t->l_lock : M 38025cf1a30Sjl * -. uinst_t->c_lock : P 38125cf1a30Sjl */ 38225cf1a30Sjl void 38325cf1a30Sjl oplmsu_clear_ioctl_path(lpath_t *lpath) 38425cf1a30Sjl { 38525cf1a30Sjl 38625cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 38725cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 38825cf1a30Sjl 38925cf1a30Sjl lpath->hndl_uqueue = NULL; 39025cf1a30Sjl lpath->hndl_mp = NULL; 39125cf1a30Sjl } 39225cf1a30Sjl 39325cf1a30Sjl /* 39425cf1a30Sjl * Get instanse status from status of upath_t 39525cf1a30Sjl * 39625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 39725cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 39825cf1a30Sjl * -. uinst_t->u_lock : M 39925cf1a30Sjl * -. uinst_t->l_lock : A 40025cf1a30Sjl * -. uinst_t->c_lock : P 40125cf1a30Sjl */ 40225cf1a30Sjl int 40325cf1a30Sjl oplmsu_get_inst_status(void) 40425cf1a30Sjl { 40525cf1a30Sjl upath_t *upath; 40625cf1a30Sjl int sts, pre_sts = INST_STAT_UNCONFIGURED; 40725cf1a30Sjl 40825cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 40925cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 41025cf1a30Sjl 41125cf1a30Sjl upath = oplmsu_uinst->first_upath; 41225cf1a30Sjl while (upath) { 41325cf1a30Sjl if (((upath->status == MSU_PSTAT_ACTIVE) && 41425cf1a30Sjl (upath->traditional_status == MSU_ACTIVE)) || 41525cf1a30Sjl ((upath->status == MSU_PSTAT_STANDBY) && 41625cf1a30Sjl (upath->traditional_status == MSU_STANDBY))) { 41725cf1a30Sjl sts = INST_STAT_ONLINE; 41825cf1a30Sjl } else if (((upath->status == MSU_PSTAT_STOP) && 41925cf1a30Sjl (upath->traditional_status == MSU_STOP)) || 42025cf1a30Sjl ((upath->status == MSU_PSTAT_FAIL) && 42125cf1a30Sjl (upath->traditional_status == MSU_FAIL))) { 42225cf1a30Sjl sts = INST_STAT_OFFLINE; 42325cf1a30Sjl } else if (((upath->status == MSU_PSTAT_DISCON) && 42425cf1a30Sjl (upath->traditional_status == MSU_DISCON)) || 42525cf1a30Sjl ((upath->status == MSU_PSTAT_EMPTY) && 42625cf1a30Sjl (upath->traditional_status == MSU_EMPTY))) { 42725cf1a30Sjl sts = INST_STAT_UNCONFIGURED; 42825cf1a30Sjl } else { 42925cf1a30Sjl sts = INST_STAT_BUSY; 43025cf1a30Sjl } 43125cf1a30Sjl 43225cf1a30Sjl if (pre_sts > sts) { 43325cf1a30Sjl pre_sts = sts; 43425cf1a30Sjl } 43525cf1a30Sjl upath = upath->u_next; 43625cf1a30Sjl } 43725cf1a30Sjl return (pre_sts); 43825cf1a30Sjl } 43925cf1a30Sjl 44025cf1a30Sjl /* 44125cf1a30Sjl * Search path of "online:standby" status 44225cf1a30Sjl * 44325cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 44425cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 44525cf1a30Sjl * -. uinst_t->u_lock : M 44625cf1a30Sjl * -. uinst_t->l_lock : A 44725cf1a30Sjl * -. uinst_t->c_lock : P 44825cf1a30Sjl */ 44925cf1a30Sjl upath_t * 45025cf1a30Sjl oplmsu_search_standby(void) 45125cf1a30Sjl { 45225cf1a30Sjl upath_t *upath, *altn_upath = NULL; 45325cf1a30Sjl int max_pathnum = UNDEFINED; 45425cf1a30Sjl 45525cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 45625cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 45725cf1a30Sjl 45825cf1a30Sjl upath = oplmsu_uinst->first_upath; 45925cf1a30Sjl while (upath) { 46025cf1a30Sjl if ((upath->status == MSU_PSTAT_STANDBY) && 46125cf1a30Sjl (upath->traditional_status == MSU_STANDBY) && 46225cf1a30Sjl (upath->lpath != NULL)) { 46325cf1a30Sjl if ((max_pathnum == UNDEFINED) || 46425cf1a30Sjl (max_pathnum > upath->path_no)) { 46525cf1a30Sjl max_pathnum = upath->path_no; 46625cf1a30Sjl altn_upath = upath; 46725cf1a30Sjl } 46825cf1a30Sjl } 46925cf1a30Sjl upath = upath->u_next; 47025cf1a30Sjl } 47125cf1a30Sjl return (altn_upath); 47225cf1a30Sjl } 47325cf1a30Sjl 47425cf1a30Sjl /* 47525cf1a30Sjl * Search path of "offline:stop" status, and minimum path number 47625cf1a30Sjl * 47725cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 47825cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 47925cf1a30Sjl * -. uinst_t->u_lock : M 48025cf1a30Sjl * -. uinst_t->l_lock : P 48125cf1a30Sjl * -. uinst_t->c_lock : P 48225cf1a30Sjl */ 48325cf1a30Sjl void 48425cf1a30Sjl oplmsu_search_min_stop_path(void) 48525cf1a30Sjl { 48625cf1a30Sjl upath_t *upath, *min_upath; 48725cf1a30Sjl lpath_t *lpath; 48825cf1a30Sjl int min_no = UNDEFINED; 48925cf1a30Sjl int active_flag = 0; 49025cf1a30Sjl 49125cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 49225cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 49325cf1a30Sjl 49425cf1a30Sjl upath = oplmsu_uinst->first_upath; 49525cf1a30Sjl while (upath) { 49625cf1a30Sjl if ((upath->status == MSU_PSTAT_ACTIVE) && 49725cf1a30Sjl (upath->traditional_status == MSU_ACTIVE)) { 49825cf1a30Sjl active_flag = 1; 49925cf1a30Sjl break; 50025cf1a30Sjl } else if ((upath->status == MSU_PSTAT_STOP) && 50125cf1a30Sjl (upath->traditional_status == MSU_STOP)) { 50225cf1a30Sjl if (upath->lpath != NULL) { 50325cf1a30Sjl if ((min_no == UNDEFINED) || 50425cf1a30Sjl (upath->path_no < min_no)) { 50525cf1a30Sjl lpath = upath->lpath; 50625cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 50725cf1a30Sjl if (lpath->status == MSU_EXT_NOTUSED) { 50825cf1a30Sjl min_upath = upath; 50925cf1a30Sjl min_no = upath->path_no; 51025cf1a30Sjl } 51125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 51225cf1a30Sjl } 51325cf1a30Sjl } 51425cf1a30Sjl } 51525cf1a30Sjl upath = upath->u_next; 51625cf1a30Sjl } 51725cf1a30Sjl 51825cf1a30Sjl if (active_flag == 0) { 51925cf1a30Sjl lpath = min_upath->lpath; 52025cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 52125cf1a30Sjl lpath->src_upath = NULL; 52225cf1a30Sjl lpath->status = MSU_EXT_ACTIVE_CANDIDATE; 52325cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 52425cf1a30Sjl } 52525cf1a30Sjl } 52625cf1a30Sjl 52725cf1a30Sjl /* 52825cf1a30Sjl * Get the total number of serial paths 52925cf1a30Sjl * 53025cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 53125cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 53225cf1a30Sjl * -. uinst_t->u_lock : M 53325cf1a30Sjl * -. uinst_t->l_lock : A 53425cf1a30Sjl * -. uinst_t->c_lock : A 53525cf1a30Sjl */ 53625cf1a30Sjl int 53725cf1a30Sjl oplmsu_get_pathnum(void) 53825cf1a30Sjl { 53925cf1a30Sjl upath_t *upath; 54025cf1a30Sjl int total_num = 0; 54125cf1a30Sjl 54225cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 54325cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 54425cf1a30Sjl 54525cf1a30Sjl if (oplmsu_uinst->first_upath != NULL) { 54625cf1a30Sjl upath = oplmsu_uinst->first_upath; 54725cf1a30Sjl while (upath) { 54825cf1a30Sjl total_num++; 54925cf1a30Sjl upath = upath->u_next; 55025cf1a30Sjl } 55125cf1a30Sjl } 55225cf1a30Sjl return (total_num); 55325cf1a30Sjl } 55425cf1a30Sjl 55525cf1a30Sjl /* 55625cf1a30Sjl * Put XOFF/ XON message on write queue 55725cf1a30Sjl * 55825cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 55925cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 56025cf1a30Sjl * -. uinst_t->u_lock : A 56125cf1a30Sjl * -. uinst_t->l_lock : A 56225cf1a30Sjl * -. uinst_t->c_lock : A 56325cf1a30Sjl */ 56425cf1a30Sjl int 56525cf1a30Sjl oplmsu_cmn_put_xoffxon(queue_t *queue, int data) 56625cf1a30Sjl { 56725cf1a30Sjl mblk_t *mp; 56825cf1a30Sjl int rval = SUCCESS; 56925cf1a30Sjl 57025cf1a30Sjl /* Send M_START */ 57125cf1a30Sjl if ((mp = allocb(0, BPRI_LO)) != NULL) { 57225cf1a30Sjl mp->b_datap->db_type = M_START; 573*07d06da5SSurya Prakki (void) putq(queue, mp); 57425cf1a30Sjl 57525cf1a30Sjl /* Send M_DATA(XOFF, XON) */ 57625cf1a30Sjl if ((mp = allocb(sizeof (int), BPRI_LO)) != NULL) { 57725cf1a30Sjl *(uint_t *)mp->b_rptr = data; 57825cf1a30Sjl mp->b_wptr = mp->b_rptr + sizeof (int); 579*07d06da5SSurya Prakki (void) putq(queue, mp); 58025cf1a30Sjl } else { 58125cf1a30Sjl rval = FAILURE; 58225cf1a30Sjl } 58325cf1a30Sjl } else { 58425cf1a30Sjl rval = FAILURE; 58525cf1a30Sjl } 58625cf1a30Sjl return (rval); 58725cf1a30Sjl } 58825cf1a30Sjl 58925cf1a30Sjl /* 59025cf1a30Sjl * Put XOFF message on write queue for all standby paths 59125cf1a30Sjl * 59225cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 59325cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 59425cf1a30Sjl * -. uinst_t->u_lock : M 59525cf1a30Sjl * -. uinst_t->l_lock : M 59625cf1a30Sjl * -. uinst_t->c_lock : P 59725cf1a30Sjl */ 59825cf1a30Sjl void 59925cf1a30Sjl oplmsu_cmn_putxoff_standby(void) 60025cf1a30Sjl { 60125cf1a30Sjl upath_t *upath; 60225cf1a30Sjl lpath_t *lpath; 60325cf1a30Sjl 60425cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 60525cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 60625cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 60725cf1a30Sjl 60825cf1a30Sjl upath = oplmsu_uinst->first_upath; 60925cf1a30Sjl while (upath) { 61025cf1a30Sjl lpath = upath->lpath; 61125cf1a30Sjl if ((upath->status != MSU_PSTAT_STANDBY) || 61225cf1a30Sjl (lpath == NULL)) { 61325cf1a30Sjl upath = upath->u_next; 61425cf1a30Sjl continue; 61525cf1a30Sjl } 61625cf1a30Sjl 61725cf1a30Sjl (void) oplmsu_cmn_put_xoffxon( 61825cf1a30Sjl WR(lpath->lower_queue), MSU_XOFF_4); 61925cf1a30Sjl upath = upath->u_next; 62025cf1a30Sjl } 62125cf1a30Sjl } 62225cf1a30Sjl 62325cf1a30Sjl /* 62425cf1a30Sjl * Set M_FLUSH message 62525cf1a30Sjl * 62625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 62725cf1a30Sjl * -. uinst_t->lock : A [RW_READER or RW_WRITER] 62825cf1a30Sjl * -. uinst_t->u_lock : A 62925cf1a30Sjl * -. uinst_t->l_lock : A 63025cf1a30Sjl * -. uinst_t->c_lock : A 63125cf1a30Sjl */ 63225cf1a30Sjl void 63325cf1a30Sjl oplmsu_cmn_set_mflush(mblk_t *mp) 63425cf1a30Sjl { 63525cf1a30Sjl 63625cf1a30Sjl mp->b_datap->db_type = M_FLUSH; 63725cf1a30Sjl *mp->b_rptr = FLUSHW; 63825cf1a30Sjl mp->b_wptr = mp->b_rptr + sizeof (char); 63925cf1a30Sjl } 64025cf1a30Sjl 64125cf1a30Sjl /* 64225cf1a30Sjl * Set status informations of upath_t 64325cf1a30Sjl * 64425cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 64525cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 64625cf1a30Sjl * -. uinst_t->u_lock : M 64725cf1a30Sjl * -. uinst_t->l_lock : A 64825cf1a30Sjl * -. uinst_t->c_lock : A 64925cf1a30Sjl */ 65025cf1a30Sjl void 65125cf1a30Sjl oplmsu_cmn_set_upath_sts(upath_t *upath, int sts, int prev_sts, 65225cf1a30Sjl ulong_t trad_sts) 65325cf1a30Sjl { 65425cf1a30Sjl 65525cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 65625cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 65725cf1a30Sjl 65825cf1a30Sjl upath->status = sts; 65925cf1a30Sjl upath->prev_status = prev_sts; 66025cf1a30Sjl upath->traditional_status = trad_sts; 66125cf1a30Sjl } 66225cf1a30Sjl 66325cf1a30Sjl /* 66425cf1a30Sjl * Allocate a message block 66525cf1a30Sjl * 66625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 66725cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 66825cf1a30Sjl * -. uinst_t->u_lock : A 66925cf1a30Sjl * -. uinst_t->l_lock : P 67025cf1a30Sjl * -. uinst_t->c_lock : P 67125cf1a30Sjl */ 67225cf1a30Sjl int 67325cf1a30Sjl oplmsu_cmn_allocmb(queue_t *q, mblk_t *mp, mblk_t **nmp, size_t size, 67425cf1a30Sjl int rw_flag) 67525cf1a30Sjl { 67625cf1a30Sjl int rval = SUCCESS; 67725cf1a30Sjl 67825cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 67925cf1a30Sjl 68025cf1a30Sjl if ((*nmp = (mblk_t *)allocb(size, BPRI_LO)) == NULL) { 68125cf1a30Sjl oplmsu_cmn_bufcall(q, mp, size, rw_flag); 68225cf1a30Sjl rval = FAILURE; 68325cf1a30Sjl } else { 68425cf1a30Sjl (*nmp)->b_wptr = (*nmp)->b_rptr + size; 68525cf1a30Sjl } 68625cf1a30Sjl return (rval); 68725cf1a30Sjl } 68825cf1a30Sjl 68925cf1a30Sjl /* 69025cf1a30Sjl * Copy a message 69125cf1a30Sjl * 69225cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 69325cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 69425cf1a30Sjl * -. uinst_t->u_lock : A 69525cf1a30Sjl * -. uinst_t->l_lock : P 69625cf1a30Sjl * -. uinst_t->c_lock : P 69725cf1a30Sjl */ 69825cf1a30Sjl int 69925cf1a30Sjl oplmsu_cmn_copymb(queue_t *q, mblk_t *mp, mblk_t **nmp, mblk_t *cmp, 70025cf1a30Sjl int rw_flag) 70125cf1a30Sjl { 70225cf1a30Sjl int rval = SUCCESS; 70325cf1a30Sjl 70425cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 70525cf1a30Sjl 70625cf1a30Sjl if ((*nmp = copymsg(cmp)) == NULL) { 70725cf1a30Sjl oplmsu_cmn_bufcall(q, mp, msgsize(cmp), rw_flag); 70825cf1a30Sjl rval = FAILURE; 70925cf1a30Sjl } 71025cf1a30Sjl return (rval); 71125cf1a30Sjl } 71225cf1a30Sjl 71325cf1a30Sjl /* 71425cf1a30Sjl * bufcall request 71525cf1a30Sjl * 71625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 71725cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 71825cf1a30Sjl * -. uinst_t->u_lock : A 71925cf1a30Sjl * -. uinst_t->l_lock : P 72025cf1a30Sjl * -. uinst_t->c_lock : P 72125cf1a30Sjl */ 72225cf1a30Sjl void 72325cf1a30Sjl oplmsu_cmn_bufcall(queue_t *q, mblk_t *mp, size_t size, int rw_flag) 72425cf1a30Sjl { 72525cf1a30Sjl 72625cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 72725cf1a30Sjl 72825cf1a30Sjl if (rw_flag == MSU_WRITE_SIDE) { 72925cf1a30Sjl ctrl_t *ctrl; 73025cf1a30Sjl 731*07d06da5SSurya Prakki (void) putbq(q, mp); 73225cf1a30Sjl 73325cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 73425cf1a30Sjl ctrl = (ctrl_t *)q->q_ptr; 73525cf1a30Sjl if (ctrl->wbuf_id != 0) { 73625cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 73725cf1a30Sjl return; 73825cf1a30Sjl } 73925cf1a30Sjl 74025cf1a30Sjl ctrl->wbuftbl->q = q; 74125cf1a30Sjl ctrl->wbuftbl->rw_flag = rw_flag; 74225cf1a30Sjl ctrl->wbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb, 74325cf1a30Sjl (void *)ctrl->wbuftbl); 74425cf1a30Sjl 74525cf1a30Sjl if (ctrl->wbuf_id == 0) { 74625cf1a30Sjl if (ctrl->wtout_id != 0) { 74725cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 74825cf1a30Sjl return; 74925cf1a30Sjl } 75025cf1a30Sjl 75125cf1a30Sjl ctrl->wtout_id = timeout(oplmsu_cmn_bufcb, 75225cf1a30Sjl (void *)ctrl->wbuftbl, drv_usectohz(MSU_TM_500MS)); 75325cf1a30Sjl } 75425cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 75525cf1a30Sjl } else if (rw_flag == MSU_READ_SIDE) { 75625cf1a30Sjl lpath_t *lpath; 75725cf1a30Sjl mblk_t *wrk_msg; 75825cf1a30Sjl 75925cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 76025cf1a30Sjl lpath = (lpath_t *)q->q_ptr; 76125cf1a30Sjl if (mp->b_datap->db_type >= QPCTL) { 76225cf1a30Sjl if (lpath->first_lpri_hi == NULL) { 76325cf1a30Sjl lpath->last_lpri_hi = mp; 76425cf1a30Sjl mp->b_next = NULL; 76525cf1a30Sjl } else { 76625cf1a30Sjl wrk_msg = lpath->first_lpri_hi; 76725cf1a30Sjl wrk_msg->b_prev = mp; 76825cf1a30Sjl mp->b_next = wrk_msg; 76925cf1a30Sjl } 77025cf1a30Sjl mp->b_prev = NULL; 77125cf1a30Sjl lpath->first_lpri_hi = mp; 77225cf1a30Sjl } else { 773*07d06da5SSurya Prakki (void) putbq(q, mp); 77425cf1a30Sjl } 77525cf1a30Sjl 77625cf1a30Sjl if (lpath->rbuf_id != 0) { 77725cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 77825cf1a30Sjl return; 77925cf1a30Sjl } 78025cf1a30Sjl 78125cf1a30Sjl lpath->rbuftbl->q = q; 78225cf1a30Sjl lpath->rbuftbl->rw_flag = rw_flag; 78325cf1a30Sjl lpath->rbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb, 78425cf1a30Sjl (void *)lpath->rbuftbl); 78525cf1a30Sjl 78625cf1a30Sjl if (lpath->rbuf_id == 0) { 78725cf1a30Sjl if (lpath->rtout_id != 0) { 78825cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 78925cf1a30Sjl return; 79025cf1a30Sjl } 79125cf1a30Sjl 79225cf1a30Sjl lpath->rtout_id = timeout(oplmsu_cmn_bufcb, 79325cf1a30Sjl (void *)lpath->rbuftbl, drv_usectohz(MSU_TM_500MS)); 79425cf1a30Sjl } 79525cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 79625cf1a30Sjl } 79725cf1a30Sjl } 79825cf1a30Sjl 79925cf1a30Sjl /* 80025cf1a30Sjl * Previous sequence for active path change 80125cf1a30Sjl * 80225cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 80325cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 80425cf1a30Sjl * -. uinst_t->u_lock : A 80525cf1a30Sjl * -. uinst_t->l_lock : P 80625cf1a30Sjl * -. uinst_t->c_lock : P 80725cf1a30Sjl */ 80825cf1a30Sjl int 80925cf1a30Sjl oplmsu_cmn_prechg(queue_t *q, mblk_t *mp, int rw_flag, mblk_t **term_mp, 81025cf1a30Sjl int *term_ioctl, int *term_stat) 81125cf1a30Sjl { 81225cf1a30Sjl 81325cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 81425cf1a30Sjl 81525cf1a30Sjl if (oplmsu_uinst->tcsets_p != NULL) { 81625cf1a30Sjl struct iocblk *iocp; 81725cf1a30Sjl 81825cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tcsets_p, 81925cf1a30Sjl rw_flag) == -1) { 82025cf1a30Sjl return (FAILURE); 82125cf1a30Sjl } 82225cf1a30Sjl 82325cf1a30Sjl iocp = (struct iocblk *)(*term_mp)->b_rptr; 82425cf1a30Sjl *term_ioctl = iocp->ioc_cmd; 82525cf1a30Sjl *term_stat = MSU_WTCS_ACK; 82625cf1a30Sjl } else if (oplmsu_uinst->tiocmset_p != NULL) { 82725cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p, 82825cf1a30Sjl rw_flag) == -1) { 82925cf1a30Sjl return (FAILURE); 83025cf1a30Sjl } 83125cf1a30Sjl 83225cf1a30Sjl *term_ioctl = TIOCMSET; 83325cf1a30Sjl *term_stat = MSU_WTMS_ACK; 83425cf1a30Sjl } else if (oplmsu_uinst->tiocspps_p != NULL) { 83525cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p, 83625cf1a30Sjl rw_flag) == -1) { 83725cf1a30Sjl return (FAILURE); 83825cf1a30Sjl } 83925cf1a30Sjl 84025cf1a30Sjl *term_ioctl = TIOCSPPS; 84125cf1a30Sjl *term_stat = MSU_WPPS_ACK; 84225cf1a30Sjl } else if (oplmsu_uinst->tiocswinsz_p != NULL) { 84325cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, 84425cf1a30Sjl oplmsu_uinst->tiocswinsz_p, rw_flag) == -1) { 84525cf1a30Sjl return (FAILURE); 84625cf1a30Sjl } 84725cf1a30Sjl 84825cf1a30Sjl *term_ioctl = TIOCSWINSZ; 84925cf1a30Sjl *term_stat = MSU_WWSZ_ACK; 85025cf1a30Sjl } else if (oplmsu_uinst->tiocssoftcar_p != NULL) { 85125cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, 85225cf1a30Sjl oplmsu_uinst->tiocssoftcar_p, rw_flag) == -1) { 85325cf1a30Sjl return (FAILURE); 85425cf1a30Sjl } 85525cf1a30Sjl 85625cf1a30Sjl *term_ioctl = TIOCSSOFTCAR; 85725cf1a30Sjl *term_stat = MSU_WCAR_ACK; 85825cf1a30Sjl } else { 85925cf1a30Sjl *term_stat = MSU_WPTH_CHG; 86025cf1a30Sjl *term_mp = NULL; 86125cf1a30Sjl } 86225cf1a30Sjl return (SUCCESS); 86325cf1a30Sjl } 86425cf1a30Sjl 86525cf1a30Sjl /* 86625cf1a30Sjl * Pick up termios to re-set 86725cf1a30Sjl * 86825cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 86925cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 87025cf1a30Sjl * -. uinst_t->u_lock : A 87125cf1a30Sjl * -. uinst_t->l_lock : A 87225cf1a30Sjl * -. uinst_t->c_lock : A 87325cf1a30Sjl */ 87425cf1a30Sjl int 87525cf1a30Sjl oplmsu_stop_prechg(mblk_t **term_mp, int *term_ioctl, int *term_stat) 87625cf1a30Sjl { 87725cf1a30Sjl 87825cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 87925cf1a30Sjl 88025cf1a30Sjl if (oplmsu_uinst->tcsets_p != NULL) { 88125cf1a30Sjl struct iocblk *iocp; 88225cf1a30Sjl 88325cf1a30Sjl if ((*term_mp = copymsg(oplmsu_uinst->tcsets_p)) == NULL) { 88425cf1a30Sjl return (FAILURE); 88525cf1a30Sjl } 88625cf1a30Sjl 88725cf1a30Sjl iocp = (struct iocblk *)(*term_mp)->b_rptr; 88825cf1a30Sjl *term_ioctl = iocp->ioc_cmd; 88925cf1a30Sjl *term_stat = MSU_WTCS_ACK; 89025cf1a30Sjl } else if (oplmsu_uinst->tiocmset_p != NULL) { 89125cf1a30Sjl if ((*term_mp = copymsg(oplmsu_uinst->tiocmset_p)) == NULL) { 89225cf1a30Sjl return (FAILURE); 89325cf1a30Sjl } 89425cf1a30Sjl 89525cf1a30Sjl *term_ioctl = TIOCMSET; 89625cf1a30Sjl *term_stat = MSU_WTMS_ACK; 89725cf1a30Sjl } else if (oplmsu_uinst->tiocspps_p != NULL) { 89825cf1a30Sjl if ((*term_mp = copymsg(oplmsu_uinst->tiocspps_p)) == NULL) { 89925cf1a30Sjl return (FAILURE); 90025cf1a30Sjl } 90125cf1a30Sjl 90225cf1a30Sjl *term_ioctl = TIOCSPPS; 90325cf1a30Sjl *term_stat = MSU_WPPS_ACK; 90425cf1a30Sjl } else if (oplmsu_uinst->tiocswinsz_p != NULL) { 90525cf1a30Sjl if ((*term_mp = copymsg(oplmsu_uinst->tiocswinsz_p)) == NULL) { 90625cf1a30Sjl return (FAILURE); 90725cf1a30Sjl } 90825cf1a30Sjl 90925cf1a30Sjl *term_ioctl = TIOCSWINSZ; 91025cf1a30Sjl *term_stat = MSU_WWSZ_ACK; 91125cf1a30Sjl } else if (oplmsu_uinst->tiocssoftcar_p != NULL) { 91225cf1a30Sjl if ((*term_mp = copymsg(oplmsu_uinst->tiocssoftcar_p)) 91325cf1a30Sjl == NULL) { 91425cf1a30Sjl return (FAILURE); 91525cf1a30Sjl } 91625cf1a30Sjl 91725cf1a30Sjl *term_ioctl = TIOCSSOFTCAR; 91825cf1a30Sjl *term_stat = MSU_WCAR_ACK; 91925cf1a30Sjl } else { 92025cf1a30Sjl *term_stat = MSU_WPTH_CHG; 92125cf1a30Sjl *term_mp = NULL; 92225cf1a30Sjl } 92325cf1a30Sjl return (SUCCESS); 92425cf1a30Sjl } 92525cf1a30Sjl 92625cf1a30Sjl /* 92725cf1a30Sjl * Previous sequence for active path change termio 92825cf1a30Sjl * 92925cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 93025cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 93125cf1a30Sjl * -. uinst_t->u_lock : A 93225cf1a30Sjl * -. uinst_t->l_lock : P 93325cf1a30Sjl * -. uinst_t->c_lock : P 93425cf1a30Sjl */ 93525cf1a30Sjl int 93625cf1a30Sjl oplmsu_cmn_prechg_termio(queue_t *q, mblk_t *mp, int rw_flag, int prev_flag, 93725cf1a30Sjl mblk_t **term_mp, int *term_stat) 93825cf1a30Sjl { 93925cf1a30Sjl 94025cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 94125cf1a30Sjl 94225cf1a30Sjl if ((prev_flag == MSU_TIOS_TCSETS) && 94325cf1a30Sjl (oplmsu_uinst->tiocmset_p != NULL)) { 94425cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p, 94525cf1a30Sjl rw_flag) == FAILURE) { 94625cf1a30Sjl return (FAILURE); 94725cf1a30Sjl } 94825cf1a30Sjl 94925cf1a30Sjl *term_stat = MSU_WTMS_ACK; 95025cf1a30Sjl } else if ((prev_flag <= MSU_TIOS_MSET) && 95125cf1a30Sjl (oplmsu_uinst->tiocspps_p != NULL)) { 95225cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p, 95325cf1a30Sjl rw_flag) == FAILURE) { 95425cf1a30Sjl return (FAILURE); 95525cf1a30Sjl } 95625cf1a30Sjl 95725cf1a30Sjl *term_stat = MSU_WPPS_ACK; 95825cf1a30Sjl } else if ((prev_flag <= MSU_TIOS_PPS) && 95925cf1a30Sjl (oplmsu_uinst->tiocswinsz_p != NULL)) { 96025cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, 96125cf1a30Sjl oplmsu_uinst->tiocswinsz_p, rw_flag) == FAILURE) { 96225cf1a30Sjl return (FAILURE); 96325cf1a30Sjl } 96425cf1a30Sjl 96525cf1a30Sjl *term_stat = MSU_WWSZ_ACK; 96625cf1a30Sjl } else if ((prev_flag <= MSU_TIOS_WINSZP) && 96725cf1a30Sjl (oplmsu_uinst->tiocssoftcar_p != NULL)) { 96825cf1a30Sjl if (oplmsu_cmn_copymb(q, mp, term_mp, 96925cf1a30Sjl oplmsu_uinst->tiocssoftcar_p, rw_flag) == FAILURE) { 97025cf1a30Sjl return (FAILURE); 97125cf1a30Sjl } 97225cf1a30Sjl 97325cf1a30Sjl *term_stat = MSU_WCAR_ACK; 97425cf1a30Sjl } else if (prev_flag <= MSU_TIOS_SOFTCAR) { 97525cf1a30Sjl *term_mp = NULL; 97625cf1a30Sjl *term_stat = MSU_WPTH_CHG; 97725cf1a30Sjl } 97825cf1a30Sjl return (SUCCESS); 97925cf1a30Sjl } 98025cf1a30Sjl 98125cf1a30Sjl /* 98225cf1a30Sjl * Pull up messages 98325cf1a30Sjl * 98425cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 98525cf1a30Sjl * -. uinst_t->lock : P 98625cf1a30Sjl * -. uinst_t->u_lock : P 98725cf1a30Sjl * -. uinst_t->l_lock : P 98825cf1a30Sjl * -. uinst_t->c_lock : P 98925cf1a30Sjl */ 99025cf1a30Sjl int 99125cf1a30Sjl oplmsu_cmn_pullup_msg(queue_t *q, mblk_t *mp) 99225cf1a30Sjl { 99325cf1a30Sjl mblk_t *nmp = NULL; 99425cf1a30Sjl 99525cf1a30Sjl if ((mp != NULL) && (mp->b_cont != NULL) && 99625cf1a30Sjl (mp->b_cont->b_cont != NULL)) { 99725cf1a30Sjl if ((nmp = msgpullup(mp->b_cont, -1)) == NULL) { 99825cf1a30Sjl oplmsu_iocack(q, mp, ENOSR); 99925cf1a30Sjl return (FAILURE); 100025cf1a30Sjl } else { 100125cf1a30Sjl freemsg(mp->b_cont); 100225cf1a30Sjl mp->b_cont = nmp; 100325cf1a30Sjl } 100425cf1a30Sjl } 100525cf1a30Sjl return (SUCCESS); 100625cf1a30Sjl } 100725cf1a30Sjl 100825cf1a30Sjl /* 100925cf1a30Sjl * Wake up flow control 101025cf1a30Sjl * 101125cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 101225cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 101325cf1a30Sjl * -. uinst_t->u_lock : P 101425cf1a30Sjl * -. uinst_t->l_lock : P 101525cf1a30Sjl * -. uinst_t->c_lock : P 101625cf1a30Sjl */ 101725cf1a30Sjl void 101825cf1a30Sjl oplmsu_cmn_wakeup(queue_t *q) 101925cf1a30Sjl { 102025cf1a30Sjl ctrl_t *ctrl; 102125cf1a30Sjl 102225cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 102325cf1a30Sjl 102425cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 102525cf1a30Sjl ctrl = (ctrl_t *)q->q_ptr; 102625cf1a30Sjl if (ctrl->sleep_flag == CV_SLEEP) { 102725cf1a30Sjl ctrl->sleep_flag = CV_WAKEUP; 102825cf1a30Sjl cv_signal(&ctrl->cvp); 102925cf1a30Sjl } 103025cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 103125cf1a30Sjl } 103225cf1a30Sjl 103325cf1a30Sjl /* 103425cf1a30Sjl * bufcall() and timeout() callback entry for read/write stream 103525cf1a30Sjl * 103625cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 103725cf1a30Sjl * -. uinst_t->lock : P 103825cf1a30Sjl * -. uinst_t->u_lock : P 103925cf1a30Sjl * -. uinst_t->l_lock : P 104025cf1a30Sjl * -. uinst_t->c_lock : P 104125cf1a30Sjl */ 104225cf1a30Sjl void 104325cf1a30Sjl oplmsu_cmn_bufcb(void *arg) 104425cf1a30Sjl { 104525cf1a30Sjl struct buf_tbl *buftbl = arg; 104625cf1a30Sjl lpath_t *lpath; 104725cf1a30Sjl ctrl_t *ctrl; 104825cf1a30Sjl queue_t *q; 104925cf1a30Sjl int lq_flag = 0; 105025cf1a30Sjl 105125cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_WRITER); 105225cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 105325cf1a30Sjl 105425cf1a30Sjl lpath = oplmsu_uinst->first_lpath; 105525cf1a30Sjl while (lpath) { 105625cf1a30Sjl if ((buftbl == lpath->rbuftbl) && 105725cf1a30Sjl (buftbl->rw_flag == MSU_READ_SIDE)) { 105825cf1a30Sjl if ((lpath->rbuf_id == 0) && (lpath->rtout_id == 0)) { 105925cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 106025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 106125cf1a30Sjl } else { 106225cf1a30Sjl q = lpath->rbuftbl->q; 106325cf1a30Sjl lpath->rbuftbl->q = NULL; 106425cf1a30Sjl lpath->rbuftbl->rw_flag = UNDEFINED; 106525cf1a30Sjl 106625cf1a30Sjl if (lpath->rbuf_id) { 106725cf1a30Sjl lpath->rbuf_id = 0; 106825cf1a30Sjl } else { 106925cf1a30Sjl lpath->rtout_id = 0; 107025cf1a30Sjl } 107125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 107225cf1a30Sjl 107325cf1a30Sjl if (oplmsu_queue_flag == 1) { 107425cf1a30Sjl lq_flag = 1; 107525cf1a30Sjl oplmsu_queue_flag = 0; 107625cf1a30Sjl } 107725cf1a30Sjl 107825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 107925cf1a30Sjl oplmsu_rcmn_high_qenable(q); 108025cf1a30Sjl 108125cf1a30Sjl if (lq_flag == 1) { 108225cf1a30Sjl rw_enter(&oplmsu_uinst->lock, 108325cf1a30Sjl RW_WRITER); 108425cf1a30Sjl oplmsu_queue_flag = 1; 108525cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 108625cf1a30Sjl } 108725cf1a30Sjl } 108825cf1a30Sjl return; 108925cf1a30Sjl } 109025cf1a30Sjl lpath = lpath->l_next; 109125cf1a30Sjl } 109225cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 109325cf1a30Sjl 109425cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 109525cf1a30Sjl if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) { 109625cf1a30Sjl if ((buftbl == ctrl->wbuftbl) && 109725cf1a30Sjl (buftbl->rw_flag == MSU_WRITE_SIDE)) { 109825cf1a30Sjl oplmsu_wbufcb_posthndl(ctrl); 109925cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 110025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 110125cf1a30Sjl return; 110225cf1a30Sjl } 110325cf1a30Sjl } 110425cf1a30Sjl 110525cf1a30Sjl if ((ctrl = oplmsu_uinst->meta_ctrl) != NULL) { 110625cf1a30Sjl if ((buftbl == ctrl->wbuftbl) && 110725cf1a30Sjl (buftbl->rw_flag == MSU_WRITE_SIDE)) { 110825cf1a30Sjl oplmsu_wbufcb_posthndl(ctrl); 110925cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 111025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 111125cf1a30Sjl return; 111225cf1a30Sjl } 111325cf1a30Sjl } 111425cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 111525cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 111625cf1a30Sjl } 111725cf1a30Sjl 111825cf1a30Sjl /* 111925cf1a30Sjl * bufcall() or timeout() callback post handling for write stream 112025cf1a30Sjl * 112125cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 112225cf1a30Sjl * -. uinst_t->lock : M [RW_WRITER] 112325cf1a30Sjl * -. uinst_t->u_lock : P 112425cf1a30Sjl * -. uinst_t->l_lock : P 112525cf1a30Sjl * -. uinst_t->c_lock : M 112625cf1a30Sjl */ 112725cf1a30Sjl void 112825cf1a30Sjl oplmsu_wbufcb_posthndl(ctrl_t *ctrl) 112925cf1a30Sjl { 113025cf1a30Sjl queue_t *q; 113125cf1a30Sjl int lq_flag = 0; 113225cf1a30Sjl 113325cf1a30Sjl ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 113425cf1a30Sjl ASSERT(MUTEX_HELD(&oplmsu_uinst->c_lock)); 113525cf1a30Sjl 113625cf1a30Sjl if ((ctrl->wbuf_id == 0) && (ctrl->wtout_id == 0)) { 113725cf1a30Sjl return; 113825cf1a30Sjl } 113925cf1a30Sjl 114025cf1a30Sjl q = ctrl->wbuftbl->q; 114125cf1a30Sjl ctrl->wbuftbl->q = NULL; 114225cf1a30Sjl ctrl->wbuftbl->rw_flag = UNDEFINED; 114325cf1a30Sjl if (ctrl->wbuf_id) { 114425cf1a30Sjl ctrl->wbuf_id = 0; 114525cf1a30Sjl } else { 114625cf1a30Sjl ctrl->wtout_id = 0; 114725cf1a30Sjl } 114825cf1a30Sjl 114925cf1a30Sjl if (oplmsu_queue_flag == 1) { 115025cf1a30Sjl lq_flag = 1; 115125cf1a30Sjl oplmsu_queue_flag = 0; 115225cf1a30Sjl } 115325cf1a30Sjl 115425cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 115525cf1a30Sjl oplmsu_wcmn_high_qenable(q, RW_WRITER); 115625cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 115725cf1a30Sjl 115825cf1a30Sjl if (lq_flag == 1) { 115925cf1a30Sjl oplmsu_queue_flag = 1; 116025cf1a30Sjl } 116125cf1a30Sjl } 116225cf1a30Sjl 116325cf1a30Sjl /* 116425cf1a30Sjl * COMMON FUNCTIONS FOR WRITE STREAM 116525cf1a30Sjl */ 116625cf1a30Sjl 116725cf1a30Sjl /* 116825cf1a30Sjl * Check control node and driver privilege 116925cf1a30Sjl * 117025cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 117125cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 117225cf1a30Sjl * -. uinst_t->u_lock : A 117325cf1a30Sjl * -. uinst_t->l_lock : A 117425cf1a30Sjl * -. uinst_t->c_lock : P 117525cf1a30Sjl */ 117625cf1a30Sjl int 117725cf1a30Sjl oplmsu_wcmn_chknode(queue_t *q, int node, mblk_t *mp) 117825cf1a30Sjl { 117925cf1a30Sjl struct iocblk *iocp; 118025cf1a30Sjl 118125cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 118225cf1a30Sjl 118325cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 118425cf1a30Sjl if (((ctrl_t *)q->q_ptr)->node_type != node) { 118525cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 118625cf1a30Sjl cmn_err(CE_WARN, "oplmsu: chk-node: ctrl node type = %d", node); 118725cf1a30Sjl return (EINVAL); 118825cf1a30Sjl } 118925cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 119025cf1a30Sjl 119125cf1a30Sjl /* Check super-user by oplmsu.conf */ 119225cf1a30Sjl if (oplmsu_check_su != 0) { 119325cf1a30Sjl iocp = (struct iocblk *)mp->b_rptr; 119425cf1a30Sjl if (drv_priv(iocp->ioc_cr) != 0) { 119525cf1a30Sjl cmn_err(CE_WARN, "oplmsu: chk-node: Permission denied"); 119625cf1a30Sjl return (EPERM); 119725cf1a30Sjl } 119825cf1a30Sjl } 119925cf1a30Sjl return (SUCCESS); 120025cf1a30Sjl } 120125cf1a30Sjl 120225cf1a30Sjl /* 120325cf1a30Sjl * Flush handle for write side stream 120425cf1a30Sjl * 120525cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 120625cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 120725cf1a30Sjl * -. uinst_t->u_lock : P 120825cf1a30Sjl * -. uinst_t->l_lock : P 120925cf1a30Sjl * -. uinst_t->c_lock : P 121025cf1a30Sjl */ 121125cf1a30Sjl void 121225cf1a30Sjl oplmsu_wcmn_flush_hndl(queue_t *q, mblk_t *mp, krw_t rw) 121325cf1a30Sjl { 121425cf1a30Sjl queue_t *dst_queue = NULL; 121525cf1a30Sjl 121625cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 121725cf1a30Sjl 121825cf1a30Sjl if (*mp->b_rptr & FLUSHW) { /* Write side */ 121925cf1a30Sjl flushq(q, FLUSHDATA); 122025cf1a30Sjl } 122125cf1a30Sjl 122225cf1a30Sjl dst_queue = oplmsu_uinst->lower_queue; 122325cf1a30Sjl if (dst_queue == NULL) { 122425cf1a30Sjl if (*mp->b_rptr & FLUSHR) { 122525cf1a30Sjl flushq(RD(q), FLUSHDATA); 122625cf1a30Sjl *mp->b_rptr &= ~FLUSHW; 122725cf1a30Sjl 122825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 122925cf1a30Sjl OPLMSU_TRACE(q, mp, MSU_TRC_UO); 123025cf1a30Sjl qreply(q, mp); 123125cf1a30Sjl rw_enter(&oplmsu_uinst->lock, rw); 123225cf1a30Sjl } else { 123325cf1a30Sjl freemsg(mp); 123425cf1a30Sjl } 123525cf1a30Sjl } else { 1236*07d06da5SSurya Prakki (void) putq(WR(dst_queue), mp); 123725cf1a30Sjl } 123825cf1a30Sjl } 123925cf1a30Sjl 124025cf1a30Sjl /* 124125cf1a30Sjl * Through message handle for write side stream 124225cf1a30Sjl * 124325cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 124425cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 124525cf1a30Sjl * -. uinst_t->u_lock : P 124625cf1a30Sjl * -. uinst_t->l_lock : P 124725cf1a30Sjl * -. uinst_t->c_lock : P 124825cf1a30Sjl */ 124925cf1a30Sjl int 125025cf1a30Sjl oplmsu_wcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag, krw_t rw) 125125cf1a30Sjl { 125225cf1a30Sjl queue_t *usr_queue = NULL, *dst_queue = NULL; 125325cf1a30Sjl ctrl_t *ctrl; 125425cf1a30Sjl 125525cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 125625cf1a30Sjl 125725cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 125825cf1a30Sjl if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) { 125925cf1a30Sjl usr_queue = ctrl->queue; 126025cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 126125cf1a30Sjl } else { 126225cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 126325cf1a30Sjl if (mp->b_datap->db_type == M_IOCTL) { 126425cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 126525cf1a30Sjl oplmsu_iocack(q, mp, ENODEV); 126625cf1a30Sjl rw_enter(&oplmsu_uinst->lock, rw); 126725cf1a30Sjl } else { 126825cf1a30Sjl freemsg(mp); 126925cf1a30Sjl } 127025cf1a30Sjl return (SUCCESS); 127125cf1a30Sjl } 127225cf1a30Sjl 127325cf1a30Sjl if (oplmsu_uinst->lower_queue != NULL) { 127425cf1a30Sjl dst_queue = WR(oplmsu_uinst->lower_queue); 127525cf1a30Sjl } else { 127625cf1a30Sjl cmn_err(CE_WARN, "!oplmsu: through-lwq: " 127725cf1a30Sjl "Active path doesn't exist"); 127825cf1a30Sjl 127925cf1a30Sjl if (mp->b_datap->db_type == M_IOCTL) { 128025cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 128125cf1a30Sjl oplmsu_iocack(q, mp, ENODEV); 128225cf1a30Sjl rw_enter(&oplmsu_uinst->lock, rw); 128325cf1a30Sjl } else { 128425cf1a30Sjl freemsg(mp); 128525cf1a30Sjl } 128625cf1a30Sjl return (SUCCESS); 128725cf1a30Sjl } 128825cf1a30Sjl 128925cf1a30Sjl if ((usr_queue == WR(q)) || (usr_queue == RD(q))) { 129025cf1a30Sjl if (pri_flag == MSU_HIGH) { 1291*07d06da5SSurya Prakki (void) putq(dst_queue, mp); 129225cf1a30Sjl } else { 129325cf1a30Sjl if (canput(dst_queue)) { 1294*07d06da5SSurya Prakki (void) putq(dst_queue, mp); 129525cf1a30Sjl } else { 129625cf1a30Sjl oplmsu_wcmn_norm_putbq(WR(q), mp, dst_queue); 129725cf1a30Sjl return (FAILURE); 129825cf1a30Sjl } 129925cf1a30Sjl } 130025cf1a30Sjl } else { 130125cf1a30Sjl cmn_err(CE_WARN, "oplmsu: through-lwq: " 130225cf1a30Sjl "Inappropriate message for this node"); 130325cf1a30Sjl 130425cf1a30Sjl if (mp->b_datap->db_type == M_IOCTL) { 130525cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 130625cf1a30Sjl oplmsu_iocack(q, mp, ENODEV); 130725cf1a30Sjl rw_enter(&oplmsu_uinst->lock, rw); 130825cf1a30Sjl } else { 130925cf1a30Sjl freemsg(mp); 131025cf1a30Sjl } 131125cf1a30Sjl } 131225cf1a30Sjl return (SUCCESS); 131325cf1a30Sjl } 131425cf1a30Sjl 131525cf1a30Sjl /* 131625cf1a30Sjl * Get high priority message from buffer for upper write stream 131725cf1a30Sjl * 131825cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 131925cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 132025cf1a30Sjl * -. uinst_t->u_lock : A 132125cf1a30Sjl * -. uinst_t->l_lock : A 132225cf1a30Sjl * -. uinst_t->c_lock : P 132325cf1a30Sjl */ 132425cf1a30Sjl mblk_t * 132525cf1a30Sjl oplmsu_wcmn_high_getq(queue_t *uwq) 132625cf1a30Sjl { 132725cf1a30Sjl mblk_t *mp; 132825cf1a30Sjl ctrl_t *ctrl; 132925cf1a30Sjl 133025cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 133125cf1a30Sjl 133225cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 133325cf1a30Sjl ctrl = (ctrl_t *)uwq->q_ptr; 133425cf1a30Sjl mp = ctrl->first_upri_hi; 133525cf1a30Sjl if (mp != NULL) { 133625cf1a30Sjl if (mp->b_next == NULL) { 133725cf1a30Sjl ctrl->first_upri_hi = NULL; 133825cf1a30Sjl ctrl->last_upri_hi = NULL; 133925cf1a30Sjl } else { 134025cf1a30Sjl ctrl->first_upri_hi = mp->b_next; 134125cf1a30Sjl mp->b_next->b_prev = NULL; 134225cf1a30Sjl mp->b_next = NULL; 134325cf1a30Sjl } 134425cf1a30Sjl mp->b_prev = NULL; 134525cf1a30Sjl } 134625cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 134725cf1a30Sjl return (mp); 134825cf1a30Sjl } 134925cf1a30Sjl 135025cf1a30Sjl /* 135125cf1a30Sjl * putbq() function for normal priority message of write stream 135225cf1a30Sjl * 135325cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 135425cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 135525cf1a30Sjl * -. uinst_t->u_lock : A 135625cf1a30Sjl * -. uinst_t->l_lock : P 135725cf1a30Sjl * -. uinst_t->c_lock : P 135825cf1a30Sjl */ 135925cf1a30Sjl void 136025cf1a30Sjl oplmsu_wcmn_norm_putbq(queue_t *uwq, mblk_t *mp, queue_t *dq) 136125cf1a30Sjl { 136225cf1a30Sjl lpath_t *lpath; 136325cf1a30Sjl 136425cf1a30Sjl ASSERT(mp != NULL); 136525cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 136625cf1a30Sjl 136725cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 136825cf1a30Sjl lpath = (lpath_t *)dq->q_ptr; 136925cf1a30Sjl lpath->uwq_flag = 1; 137025cf1a30Sjl lpath->uwq_queue = uwq; 137125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 1372*07d06da5SSurya Prakki (void) putbq(uwq, mp); 137325cf1a30Sjl } 137425cf1a30Sjl 137525cf1a30Sjl /* 137625cf1a30Sjl * Restart queuing for high priority message of write stream when flow control 137725cf1a30Sjl * failed 137825cf1a30Sjl * 137925cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 138025cf1a30Sjl * -. uinst_t->lock : M [RW_READER or RW_WRITER] 138125cf1a30Sjl * -. uinst_t->u_lock : P 138225cf1a30Sjl * -. uinst_t->l_lock : P 138325cf1a30Sjl * -. uinst_t->c_lock : P 138425cf1a30Sjl */ 138525cf1a30Sjl void 138625cf1a30Sjl oplmsu_wcmn_high_qenable(queue_t *q, krw_t rw) 138725cf1a30Sjl { 138825cf1a30Sjl mblk_t *mp; 138925cf1a30Sjl 139025cf1a30Sjl ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 139125cf1a30Sjl 139225cf1a30Sjl if (oplmsu_queue_flag == 1) { 139325cf1a30Sjl return; 139425cf1a30Sjl } 139525cf1a30Sjl 139625cf1a30Sjl /* Handle high priority message */ 139725cf1a30Sjl while (mp = oplmsu_wcmn_high_getq(WR(q))) { 139825cf1a30Sjl if (mp->b_datap->db_type & M_FLUSH) { 139925cf1a30Sjl oplmsu_wcmn_flush_hndl(q, mp, rw); 140025cf1a30Sjl continue; 140125cf1a30Sjl } 140225cf1a30Sjl 140325cf1a30Sjl if (oplmsu_wcmn_through_hndl(q, mp, MSU_HIGH, rw) == FAILURE) { 140425cf1a30Sjl return; 140525cf1a30Sjl } 140625cf1a30Sjl } 140725cf1a30Sjl qenable(WR(q)); /* enable upper write queue */ 140825cf1a30Sjl } 140925cf1a30Sjl 141025cf1a30Sjl /* 141125cf1a30Sjl * COMMON FUNCTIONS FOR READ STREAM 141225cf1a30Sjl */ 141325cf1a30Sjl 141425cf1a30Sjl /* 141525cf1a30Sjl * Flush handle for read side stream 141625cf1a30Sjl * 141725cf1a30Sjl * Requires lock ( M: mandatory P: prohibited A: allowed 141825cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 141925cf1a30Sjl * -. uinst_t->u_lock : P 142025cf1a30Sjl * -. uinst_t->l_lock : P 142125cf1a30Sjl * -. uinst_t->c_lock : P 142225cf1a30Sjl */ 142325cf1a30Sjl void 142425cf1a30Sjl oplmsu_rcmn_flush_hndl(queue_t *q, mblk_t *mp) 142525cf1a30Sjl { 142625cf1a30Sjl queue_t *dst_queue = NULL; 142725cf1a30Sjl ctrl_t *ctrl; 142825cf1a30Sjl 142925cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 143025cf1a30Sjl 143125cf1a30Sjl if (*mp->b_rptr & FLUSHR) { 143225cf1a30Sjl /* Remove only data messages from read queue */ 143325cf1a30Sjl flushq(q, FLUSHDATA); 143425cf1a30Sjl } 143525cf1a30Sjl 143625cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 143725cf1a30Sjl if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) { 143825cf1a30Sjl dst_queue = RD(ctrl->queue); 143925cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 144025cf1a30Sjl 144125cf1a30Sjl if (dst_queue != NULL) { 1442*07d06da5SSurya Prakki (void) putq(dst_queue, mp); 144325cf1a30Sjl } else { 144425cf1a30Sjl if (*mp->b_rptr & FLUSHW) { 144525cf1a30Sjl flushq(WR(q), FLUSHDATA); 144625cf1a30Sjl *mp->b_rptr &= ~FLUSHR; 144725cf1a30Sjl 144825cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 144925cf1a30Sjl OPLMSU_TRACE(q, mp, MSU_TRC_LO); 145025cf1a30Sjl qreply(q, mp); 145125cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_READER); 145225cf1a30Sjl } else { 145325cf1a30Sjl freemsg(mp); 145425cf1a30Sjl } 145525cf1a30Sjl } 145625cf1a30Sjl } else { 145725cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 145825cf1a30Sjl if (*mp->b_rptr & FLUSHW) { 145925cf1a30Sjl flushq(WR(q), FLUSHDATA); 146025cf1a30Sjl *mp->b_rptr &= ~FLUSHR; 146125cf1a30Sjl 146225cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 146325cf1a30Sjl OPLMSU_TRACE(q, mp, MSU_TRC_LO); 146425cf1a30Sjl qreply(q, mp); 146525cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_READER); 146625cf1a30Sjl } else { 146725cf1a30Sjl freemsg(mp); 146825cf1a30Sjl } 146925cf1a30Sjl } 147025cf1a30Sjl } 147125cf1a30Sjl 147225cf1a30Sjl /* 147325cf1a30Sjl * Through message handle for read side stream 147425cf1a30Sjl * 147525cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 147625cf1a30Sjl * -. uinst_t->lock : M [RW_READER] 147725cf1a30Sjl * -. uinst_t->u_lock : A 147825cf1a30Sjl * -. uinst_t->l_lock : P 147925cf1a30Sjl * -. uinst_t->c_lock : P 148025cf1a30Sjl */ 148125cf1a30Sjl int 148225cf1a30Sjl oplmsu_rcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag) 148325cf1a30Sjl { 148425cf1a30Sjl lpath_t *lpath; 148525cf1a30Sjl ctrl_t *ctrl; 148625cf1a30Sjl queue_t *dst_queue = NULL; 148725cf1a30Sjl int act_flag; 148825cf1a30Sjl 148925cf1a30Sjl ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 149025cf1a30Sjl 149125cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 149225cf1a30Sjl lpath = (lpath_t *)q->q_ptr; 149325cf1a30Sjl if (lpath->uinst != NULL) { 149425cf1a30Sjl act_flag = ACTIVE_RES; 149525cf1a30Sjl } else { 149625cf1a30Sjl act_flag = NOT_ACTIVE_RES; 149725cf1a30Sjl } 149825cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 149925cf1a30Sjl 150025cf1a30Sjl mutex_enter(&oplmsu_uinst->c_lock); 150125cf1a30Sjl if (((ctrl = oplmsu_uinst->user_ctrl) != NULL) && 150225cf1a30Sjl (((mp->b_datap->db_type == M_IOCACK) || 150325cf1a30Sjl (mp->b_datap->db_type == M_IOCNAK)) || (act_flag == ACTIVE_RES))) { 150425cf1a30Sjl dst_queue = RD(ctrl->queue); 150525cf1a30Sjl } else { 150625cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 150725cf1a30Sjl freemsg(mp); 150825cf1a30Sjl return (SUCCESS); 150925cf1a30Sjl } 151025cf1a30Sjl 151125cf1a30Sjl if (pri_flag == MSU_HIGH) { 1512*07d06da5SSurya Prakki (void) putq(dst_queue, mp); 151325cf1a30Sjl } else { 151425cf1a30Sjl if (canput(dst_queue)) { 1515*07d06da5SSurya Prakki (void) putq(dst_queue, mp); 151625cf1a30Sjl } else { 151725cf1a30Sjl /* 151825cf1a30Sjl * Place a normal priority message at the head of 151925cf1a30Sjl * read queue 152025cf1a30Sjl */ 152125cf1a30Sjl 152225cf1a30Sjl ctrl = (ctrl_t *)dst_queue->q_ptr; 152325cf1a30Sjl ctrl->lrq_flag = 1; 152425cf1a30Sjl ctrl->lrq_queue = q; 152525cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 1526*07d06da5SSurya Prakki (void) putbq(q, mp); 152725cf1a30Sjl return (FAILURE); 152825cf1a30Sjl } 152925cf1a30Sjl } 153025cf1a30Sjl mutex_exit(&oplmsu_uinst->c_lock); 153125cf1a30Sjl return (SUCCESS); 153225cf1a30Sjl } 153325cf1a30Sjl 153425cf1a30Sjl /* 153525cf1a30Sjl * Restart queuing for high priority message of read stream 153625cf1a30Sjl * when flow control failed 153725cf1a30Sjl * 153825cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 153925cf1a30Sjl * -. uinst_t->lock : P 154025cf1a30Sjl * -. uinst_t->u_lock : P 154125cf1a30Sjl * -. uinst_t->l_lock : P 154225cf1a30Sjl * -. uinst_t->c_lock : P 154325cf1a30Sjl */ 154425cf1a30Sjl void 154525cf1a30Sjl oplmsu_rcmn_high_qenable(queue_t *q) 154625cf1a30Sjl { 154725cf1a30Sjl mblk_t *mp; 154825cf1a30Sjl struct iocblk *iocp = NULL; 154925cf1a30Sjl lpath_t *lpath; 155025cf1a30Sjl int rval; 155125cf1a30Sjl 155225cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_READER); 155325cf1a30Sjl 155425cf1a30Sjl for (;;) { /* Handle high priority message */ 155525cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 155625cf1a30Sjl lpath = (lpath_t *)q->q_ptr; 155725cf1a30Sjl if ((mp = lpath->first_lpri_hi) == NULL) { 155825cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 155925cf1a30Sjl break; 156025cf1a30Sjl } 156125cf1a30Sjl 156225cf1a30Sjl if (mp->b_next == NULL) { 156325cf1a30Sjl lpath->first_lpri_hi = NULL; 156425cf1a30Sjl lpath->last_lpri_hi = NULL; 156525cf1a30Sjl } else { 156625cf1a30Sjl lpath->first_lpri_hi = mp->b_next; 156725cf1a30Sjl mp->b_next->b_prev = NULL; 156825cf1a30Sjl mp->b_next = NULL; 156925cf1a30Sjl } 157025cf1a30Sjl mp->b_prev = NULL; 157125cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 157225cf1a30Sjl 157325cf1a30Sjl rval = SUCCESS; 157425cf1a30Sjl switch (mp->b_datap->db_type) { 157525cf1a30Sjl case M_IOCACK : /* FALLTHRU */ 157625cf1a30Sjl case M_IOCNAK : 157725cf1a30Sjl iocp = (struct iocblk *)mp->b_rptr; 157825cf1a30Sjl switch (iocp->ioc_cmd) { 157925cf1a30Sjl case TCSETS : /* FALLTHRU */ 158025cf1a30Sjl case TCSETSW : /* FALLTHRU */ 158125cf1a30Sjl case TCSETSF : /* FALLTHRU */ 158225cf1a30Sjl case TIOCMSET : /* FALLTHRU */ 158325cf1a30Sjl case TIOCSPPS : /* FALLTHRU */ 158425cf1a30Sjl case TIOCSWINSZ : /* FALLTHRU */ 158525cf1a30Sjl case TIOCSSOFTCAR : 158625cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 158725cf1a30Sjl rval = oplmsu_lrioctl_termios(q, mp); 158825cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_WRITER); 158925cf1a30Sjl break; 159025cf1a30Sjl 159125cf1a30Sjl default : 159225cf1a30Sjl rval = oplmsu_rcmn_through_hndl( 159325cf1a30Sjl q, mp, MSU_HIGH); 159425cf1a30Sjl if (rval == FAILURE) { 159525cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 159625cf1a30Sjl return; 159725cf1a30Sjl } 159825cf1a30Sjl } 159925cf1a30Sjl break; 160025cf1a30Sjl 160125cf1a30Sjl case M_ERROR : 160225cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 160325cf1a30Sjl rval = oplmsu_lrmsg_error(q, mp); 160425cf1a30Sjl rw_enter(&oplmsu_uinst->lock, RW_WRITER); 160525cf1a30Sjl break; 160625cf1a30Sjl 160725cf1a30Sjl case M_FLUSH : 160825cf1a30Sjl oplmsu_rcmn_flush_hndl(q, mp); 160925cf1a30Sjl break; 161025cf1a30Sjl 161125cf1a30Sjl default : 161225cf1a30Sjl rval = oplmsu_rcmn_through_hndl(q, mp, MSU_HIGH); 161325cf1a30Sjl if (rval == FAILURE) { 161425cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 161525cf1a30Sjl return; 161625cf1a30Sjl } 161725cf1a30Sjl } 161825cf1a30Sjl 161925cf1a30Sjl if (rval == FAILURE) { 162025cf1a30Sjl break; 162125cf1a30Sjl } 162225cf1a30Sjl } 162325cf1a30Sjl 162425cf1a30Sjl rw_exit(&oplmsu_uinst->lock); 162525cf1a30Sjl qenable(q); /* Enable lower read queue */ 162625cf1a30Sjl } 162725cf1a30Sjl 162825cf1a30Sjl #ifdef DEBUG 162925cf1a30Sjl /* 163025cf1a30Sjl * Online trace 163125cf1a30Sjl * 163225cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 163325cf1a30Sjl * -. uinst_t->lock : P 163425cf1a30Sjl * -. uinst_t->u_lock : P 163525cf1a30Sjl * -. uinst_t->l_lock : P 163625cf1a30Sjl * -. uinst_t->c_lock : P 163725cf1a30Sjl */ 163825cf1a30Sjl void 163925cf1a30Sjl oplmsu_cmn_trace(queue_t *q, mblk_t *mp, int op) 164025cf1a30Sjl { 164125cf1a30Sjl struct iocblk *iocp; 164225cf1a30Sjl 164325cf1a30Sjl if ((op < MSU_TRC_UI) || (op > MSU_TRC_CLS)) { 164425cf1a30Sjl return; 164525cf1a30Sjl } 164625cf1a30Sjl 164725cf1a30Sjl mutex_enter(&oplmsu_ltrc_lock); 164825cf1a30Sjl 164925cf1a30Sjl if (oplmsu_debug_mode & MSU_DPRINT_ON) { 165025cf1a30Sjl oplmsu_cmn_msglog(mp, op); 165125cf1a30Sjl } 165225cf1a30Sjl 165325cf1a30Sjl /* Trace current counter */ 1654*07d06da5SSurya Prakki (void) drv_getparm(LBOLT, (void *)&oplmsu_ltrc_ccnt); 165525cf1a30Sjl 165625cf1a30Sjl if (oplmsu_ltrc_cur == oplmsu_ltrc_tail) { 165725cf1a30Sjl oplmsu_ltrc_cur = oplmsu_ltrc_top; 165825cf1a30Sjl } else { 165925cf1a30Sjl oplmsu_ltrc_cur++; 166025cf1a30Sjl } 166125cf1a30Sjl oplmsu_ltrc_cur->q = q; 166225cf1a30Sjl oplmsu_ltrc_cur->mp = mp; 166325cf1a30Sjl 166425cf1a30Sjl switch (op) { 166525cf1a30Sjl case MSU_TRC_UI : 166625cf1a30Sjl oplmsu_ltrc_cur->op[0] = 'u'; 166725cf1a30Sjl oplmsu_ltrc_cur->op[1] = 'i'; 166825cf1a30Sjl break; 166925cf1a30Sjl 167025cf1a30Sjl case MSU_TRC_UO : 167125cf1a30Sjl oplmsu_ltrc_cur->op[0] = 'u'; 167225cf1a30Sjl oplmsu_ltrc_cur->op[1] = 'o'; 167325cf1a30Sjl break; 167425cf1a30Sjl 167525cf1a30Sjl case MSU_TRC_LI : 167625cf1a30Sjl oplmsu_ltrc_cur->op[0] = 'l'; 167725cf1a30Sjl oplmsu_ltrc_cur->op[1] = 'i'; 167825cf1a30Sjl break; 167925cf1a30Sjl 168025cf1a30Sjl case MSU_TRC_LO : 168125cf1a30Sjl oplmsu_ltrc_cur->op[0] = 'l'; 168225cf1a30Sjl oplmsu_ltrc_cur->op[1] = 'o'; 168325cf1a30Sjl break; 168425cf1a30Sjl 168525cf1a30Sjl case MSU_TRC_OPN : 168625cf1a30Sjl oplmsu_ltrc_cur->op[0] = 'o'; 168725cf1a30Sjl oplmsu_ltrc_cur->op[1] = 'p'; 168825cf1a30Sjl break; 168925cf1a30Sjl 169025cf1a30Sjl case MSU_TRC_CLS : 169125cf1a30Sjl oplmsu_ltrc_cur->op[0] = 'c'; 169225cf1a30Sjl oplmsu_ltrc_cur->op[1] = 'l'; 169325cf1a30Sjl break; 169425cf1a30Sjl } 169525cf1a30Sjl 169625cf1a30Sjl if ((op == MSU_TRC_LI) || (op == MSU_TRC_LO)) { 169725cf1a30Sjl mutex_enter(&oplmsu_uinst->l_lock); 169825cf1a30Sjl oplmsu_ltrc_cur->pathno = ((lpath_t *)q->q_ptr)->path_no; 169925cf1a30Sjl mutex_exit(&oplmsu_uinst->l_lock); 170025cf1a30Sjl } else { 170125cf1a30Sjl oplmsu_ltrc_cur->pathno = 0; 170225cf1a30Sjl } 170325cf1a30Sjl 170425cf1a30Sjl if ((op == MSU_TRC_OPN) || (op == MSU_TRC_CLS)) { 170525cf1a30Sjl oplmsu_ltrc_cur->msg_type = 0; 170625cf1a30Sjl oplmsu_ltrc_cur->msg_cmd = 0; 170725cf1a30Sjl oplmsu_ltrc_cur->data = 0; 170825cf1a30Sjl 170925cf1a30Sjl switch ((ulong_t)mp) { 171025cf1a30Sjl case MSU_NODE_USER : 171125cf1a30Sjl oplmsu_ltrc_cur->data = MSU_TRC_USER; 171225cf1a30Sjl break; 171325cf1a30Sjl 171425cf1a30Sjl case MSU_NODE_META : 171525cf1a30Sjl oplmsu_ltrc_cur->data = MSU_TRC_META; 171625cf1a30Sjl break; 171725cf1a30Sjl } 171825cf1a30Sjl oplmsu_ltrc_cur->mp = NULL; 171925cf1a30Sjl } else { 172025cf1a30Sjl oplmsu_ltrc_cur->msg_type = mp->b_datap->db_type; 172125cf1a30Sjl iocp = (struct iocblk *)mp->b_rptr; 172225cf1a30Sjl oplmsu_ltrc_cur->msg_cmd = iocp->ioc_cmd; 172325cf1a30Sjl 172425cf1a30Sjl if ((mp->b_datap->db_type == M_IOCTL) || 172525cf1a30Sjl (mp->b_datap->db_type == M_IOCACK) || 172625cf1a30Sjl (mp->b_datap->db_type == M_IOCNAK)) { 172725cf1a30Sjl oplmsu_ltrc_cur->msg_cmd = iocp->ioc_cmd; 172825cf1a30Sjl 172925cf1a30Sjl if (mp->b_cont != NULL) { 173025cf1a30Sjl oplmsu_ltrc_cur->data = 173125cf1a30Sjl (ulong_t)mp->b_cont->b_rptr; 173225cf1a30Sjl } else { 173325cf1a30Sjl oplmsu_ltrc_cur->data = 0; 173425cf1a30Sjl } 173525cf1a30Sjl } else { 173625cf1a30Sjl oplmsu_ltrc_cur->msg_cmd = 0; 173725cf1a30Sjl 173825cf1a30Sjl if (mp->b_rptr == NULL) { 173925cf1a30Sjl oplmsu_ltrc_cur->data = 0; 174025cf1a30Sjl } else { 174125cf1a30Sjl oplmsu_ltrc_cur->data = *(ulong_t *)mp->b_rptr; 174225cf1a30Sjl } 174325cf1a30Sjl } 174425cf1a30Sjl } 174525cf1a30Sjl mutex_exit(&oplmsu_ltrc_lock); 174625cf1a30Sjl } 174725cf1a30Sjl 174825cf1a30Sjl /* 174925cf1a30Sjl * Display message log to console 175025cf1a30Sjl * 175125cf1a30Sjl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 175225cf1a30Sjl * -. uinst_t->lock : P 175325cf1a30Sjl * -. uinst_t->u_lock : P 175425cf1a30Sjl * -. uinst_t->l_lock : P 175525cf1a30Sjl * -. uinst_t->c_lock : P 175625cf1a30Sjl */ 175725cf1a30Sjl void 175825cf1a30Sjl oplmsu_cmn_msglog(mblk_t *mp, int direction) 175925cf1a30Sjl { 176025cf1a30Sjl uchar_t *cur = NULL; 176125cf1a30Sjl mblk_t *tmp_mp = NULL; 176225cf1a30Sjl ulong_t len; 176325cf1a30Sjl ulong_t line; 176425cf1a30Sjl ulong_t col; 176525cf1a30Sjl ulong_t row; 176625cf1a30Sjl ulong_t count; 176725cf1a30Sjl char buffer[70]; 176825cf1a30Sjl char *bufp; 176925cf1a30Sjl 177025cf1a30Sjl if (mp == NULL) { 177125cf1a30Sjl return; 177225cf1a30Sjl } 177325cf1a30Sjl 177425cf1a30Sjl switch (direction) { 177525cf1a30Sjl case 0: 177625cf1a30Sjl cmn_err(CE_NOTE, "!---------- Upper in --------"); 177725cf1a30Sjl break; 177825cf1a30Sjl 177925cf1a30Sjl case 1: 178025cf1a30Sjl cmn_err(CE_NOTE, "!---------- Upper out -------"); 178125cf1a30Sjl break; 178225cf1a30Sjl 178325cf1a30Sjl case 2: 178425cf1a30Sjl cmn_err(CE_NOTE, "!---------- Lower in --------"); 178525cf1a30Sjl break; 178625cf1a30Sjl 178725cf1a30Sjl case 3: 178825cf1a30Sjl cmn_err(CE_NOTE, "!---------- Lower out -------"); 178925cf1a30Sjl break; 179025cf1a30Sjl 179125cf1a30Sjl default: 179225cf1a30Sjl return; 179325cf1a30Sjl } 179425cf1a30Sjl 179525cf1a30Sjl for (tmp_mp = mp; tmp_mp; tmp_mp = tmp_mp->b_cont) { 179625cf1a30Sjl cmn_err(CE_NOTE, "!db_type = 0x%02x", tmp_mp->b_datap->db_type); 179725cf1a30Sjl 179825cf1a30Sjl len = tmp_mp->b_wptr - tmp_mp->b_rptr; 179925cf1a30Sjl line = (len + 31) / 32; 180025cf1a30Sjl cur = (uchar_t *)tmp_mp->b_rptr; 180125cf1a30Sjl count = 0; 180225cf1a30Sjl 180325cf1a30Sjl for (col = 0; col < line; col++) { 180425cf1a30Sjl bufp = buffer; 180525cf1a30Sjl 180625cf1a30Sjl for (row = 0; row < 32; row++) { 180725cf1a30Sjl if (row != 0 && (row % 8) == 0) { 180825cf1a30Sjl *bufp = ' '; 180925cf1a30Sjl bufp++; 181025cf1a30Sjl } 1811*07d06da5SSurya Prakki (void) sprintf(bufp, "%02x", *cur); 181225cf1a30Sjl bufp += 2; 181325cf1a30Sjl cur++; 181425cf1a30Sjl count++; 181525cf1a30Sjl 181625cf1a30Sjl if (count >= len) { 181725cf1a30Sjl break; 181825cf1a30Sjl } 181925cf1a30Sjl } 182025cf1a30Sjl *bufp = '\0'; 182125cf1a30Sjl cmn_err(CE_NOTE, "!%s", buffer); 182225cf1a30Sjl 182325cf1a30Sjl if (count >= len) { 182425cf1a30Sjl break; 182525cf1a30Sjl } 182625cf1a30Sjl } 182725cf1a30Sjl } 182825cf1a30Sjl } 182925cf1a30Sjl 183025cf1a30Sjl void 183125cf1a30Sjl oplmsu_cmn_prt_pathname(dev_info_t *dip) 183225cf1a30Sjl { 183325cf1a30Sjl char pathname[128]; 183425cf1a30Sjl char wrkbuf[128]; 183525cf1a30Sjl 1836*07d06da5SSurya Prakki (void) ddi_pathname(dip, wrkbuf); 183725cf1a30Sjl *(wrkbuf + strlen(wrkbuf)) = '\0'; 1838*07d06da5SSurya Prakki (void) sprintf(pathname, "/devices%s:%c", wrkbuf, 1839*07d06da5SSurya Prakki 'a'+ ddi_get_instance(dip)); 184025cf1a30Sjl 184125cf1a30Sjl DBG_PRINT((CE_NOTE, "oplmsu: debug-info: " 184225cf1a30Sjl "Active path change to path => %s", pathname)); 184325cf1a30Sjl } 184425cf1a30Sjl #endif 1845