1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006 23 */ 24 25 #include <sys/errno.h> 26 #include <sys/modctl.h> 27 #include <sys/stat.h> 28 #include <sys/kmem.h> 29 #include <sys/ksynch.h> 30 #include <sys/stream.h> 31 #include <sys/stropts.h> 32 #include <sys/termio.h> 33 #include <sys/ddi.h> 34 #include <sys/file.h> 35 #include <sys/disp.h> 36 #include <sys/sunddi.h> 37 #include <sys/sunldi.h> 38 #include <sys/sunndi.h> 39 #include <sys/strsun.h> 40 #include <sys/oplmsu/oplmsu.h> 41 #include <sys/oplmsu/oplmsu_proto.h> 42 43 /* 44 * Link upper_path_table structure 45 * 46 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 47 * -. uinst_t->lock : M [RW_WRITER] 48 * -. uinst_t->u_lock : M 49 * -. uinst_t->l_lock : A 50 * -. uinst_t->c_lock : A 51 */ 52 void 53 oplmsu_link_upath(upath_t *add_upath) 54 { 55 56 ASSERT(add_upath != NULL); 57 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 58 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 59 60 if (oplmsu_uinst->first_upath == NULL) { 61 oplmsu_uinst->first_upath = add_upath; 62 add_upath->u_prev = NULL; 63 } else { 64 upath_t *last_upath; 65 66 last_upath = oplmsu_uinst->last_upath; 67 last_upath->u_next = add_upath; 68 add_upath->u_prev = last_upath; 69 } 70 71 oplmsu_uinst->last_upath = add_upath; 72 add_upath->u_next = NULL; 73 } 74 75 /* 76 * Unlink upper_path_table structure 77 * 78 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 79 * -. uinst_t->lock : M [RW_WRITER] 80 * -. uinst_t->u_lock : P 81 * -. uinst_t->l_lock : P 82 * -. uinst_t->c_lock : P 83 */ 84 void 85 oplmsu_unlink_upath(upath_t *del_upath) 86 { 87 upath_t **first, **last; 88 89 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 90 91 first = &oplmsu_uinst->first_upath; 92 last = &oplmsu_uinst->last_upath; 93 94 if ((*first != del_upath) && (*last != del_upath)) { 95 del_upath->u_prev->u_next = del_upath->u_next; 96 del_upath->u_next->u_prev = del_upath->u_prev; 97 } else { 98 if (*first == del_upath) { 99 *first = (*first)->u_next; 100 if (*first) { 101 (*first)->u_prev = NULL; 102 } 103 } 104 105 if (*last == del_upath) { 106 *last = (*last)->u_prev; 107 if (*last) { 108 (*last)->u_next = NULL; 109 } 110 } 111 } 112 113 del_upath->u_next = NULL; 114 del_upath->u_prev = NULL; 115 } 116 117 /* 118 * Link lower_path_table structure 119 * 120 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 121 * -. uinst_t->lock : M [RW_WRITER] 122 * -. uinst_t->u_lock : A 123 * -. uinst_t->l_lock : M 124 * -. uinst_t->c_lock : A 125 */ 126 void 127 oplmsu_link_lpath(lpath_t *add_lpath) 128 { 129 130 ASSERT(add_lpath != NULL); 131 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 132 133 if (oplmsu_uinst->first_lpath == NULL) { 134 oplmsu_uinst->first_lpath = add_lpath; 135 add_lpath->l_prev = NULL; 136 } else { 137 lpath_t *last_lpath; 138 139 last_lpath = oplmsu_uinst->last_lpath; 140 last_lpath->l_next = add_lpath; 141 add_lpath->l_prev = last_lpath; 142 } 143 144 oplmsu_uinst->last_lpath = add_lpath; 145 add_lpath->l_next = NULL; 146 } 147 148 /* 149 * Unlink lower_path_table structure 150 * 151 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 152 * -. uinst_t->lock : M [RW_WRITER] 153 * -. uinst_t->u_lock : P 154 * -. uinst_t->l_lock : P 155 * -. uinst_t->c_lock : P 156 */ 157 void 158 oplmsu_unlink_lpath(lpath_t *del_lpath) 159 { 160 lpath_t **first, **last; 161 162 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 163 164 first = &oplmsu_uinst->first_lpath; 165 last = &oplmsu_uinst->last_lpath; 166 167 if ((*first != del_lpath) && (*last != del_lpath)) { 168 del_lpath->l_prev->l_next = del_lpath->l_next; 169 del_lpath->l_next->l_prev = del_lpath->l_prev; 170 } else { 171 if (*first == del_lpath) { 172 *first = (*first)->l_next; 173 if (*first) { 174 (*first)->l_prev = NULL; 175 } 176 } 177 178 if (*last == del_lpath) { 179 *last = (*last)->l_prev; 180 if (*last) { 181 (*last)->l_next = NULL; 182 } 183 } 184 } 185 186 del_lpath->l_next = NULL; 187 del_lpath->l_prev = NULL; 188 } 189 190 /* 191 * Link msgb structure of high priority 192 * 193 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 194 * -. uinst_t->lock : M [RW_READER] 195 * -. uinst_t->u_lock : A 196 * -. uinst_t->l_lock : A [It depends on caller] 197 * -. uinst_t->c_lock : A [It depends on caller] 198 */ 199 void 200 oplmsu_link_high_primsg(mblk_t **first, mblk_t **last, mblk_t *add_msg) 201 { 202 203 ASSERT(add_msg != NULL); 204 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 205 206 if (*first == NULL) { 207 *first = add_msg; 208 add_msg->b_prev = NULL; 209 } else { 210 (*last)->b_next = add_msg; 211 add_msg->b_prev = *last; 212 } 213 214 *last = add_msg; 215 add_msg->b_next = NULL; 216 } 217 218 /* 219 * Check whether lower path is usable by lower path info table address 220 * 221 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 222 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 223 * -. uinst_t->u_lock : A 224 * -. uinst_t->l_lock : M 225 * -. uinst_t->c_lock : P 226 */ 227 int 228 oplmsu_check_lpath_usable(void) 229 { 230 lpath_t *lpath; 231 int rval = SUCCESS; 232 233 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 234 ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 235 236 lpath = oplmsu_uinst->first_lpath; 237 while (lpath) { 238 if ((lpath->hndl_uqueue != NULL) || (lpath->hndl_mp != NULL)) { 239 rval = BUSY; 240 break; 241 } 242 lpath = lpath->l_next; 243 } 244 return (rval); 245 } 246 247 /* 248 * Search upath_t by path number 249 * 250 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 251 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 252 * -. uinst_t->u_lock : M 253 * -. uinst_t->l_lock : A 254 * -. uinst_t->c_lock : P 255 */ 256 upath_t * 257 oplmsu_search_upath_info(int path_no) 258 { 259 upath_t *upath; 260 261 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 262 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 263 264 upath = oplmsu_uinst->first_upath; 265 while (upath) { 266 if (upath->path_no == path_no) { 267 break; 268 } 269 upath = upath->u_next; 270 } 271 return (upath); 272 } 273 274 /* 275 * Send M_IOCACK(or M_IOCNAK) message to stream 276 * 277 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 278 * -. uinst_t->lock : P 279 * -. uinst_t->u_lock : P 280 * -. uinst_t->l_lock : P 281 * -. uinst_t->c_lock : P 282 */ 283 void 284 oplmsu_iocack(queue_t *q, mblk_t *mp, int errno) 285 { 286 struct iocblk *iocp = NULL; 287 288 ASSERT(mp != NULL); 289 290 iocp = (struct iocblk *)mp->b_rptr; 291 iocp->ioc_error = errno; 292 293 if (errno) { /* Error */ 294 mp->b_datap->db_type = M_IOCNAK; 295 iocp->ioc_rval = FAILURE; 296 297 OPLMSU_TRACE(q, mp, MSU_TRC_UO); 298 qreply(q, mp); 299 } else { /* Good */ 300 mp->b_datap->db_type = M_IOCACK; 301 iocp->ioc_rval = SUCCESS; 302 303 OPLMSU_TRACE(q, mp, MSU_TRC_UO); 304 qreply(q, mp); 305 } 306 } 307 308 /* 309 * Delete all upath_t 310 * 311 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 312 * -. uinst_t->lock : M [RW_WRITER] 313 * -. uinst_t->u_lock : M 314 * -. uinst_t->l_lock : A 315 * -. uinst_t->c_lock : A 316 */ 317 void 318 oplmsu_delete_upath_info(void) 319 { 320 upath_t *upath, *next_upath; 321 322 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 323 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 324 325 upath = oplmsu_uinst->first_upath; 326 oplmsu_uinst->first_upath = NULL; 327 oplmsu_uinst->last_upath = NULL; 328 329 while (upath) { 330 next_upath = upath->u_next; 331 kmem_free(upath, sizeof (upath_t)); 332 upath = next_upath; 333 } 334 } 335 336 /* 337 * Set queue and ioctl to lpath_t 338 * 339 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 340 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 341 * -. uinst_t->u_lock : A 342 * -. uinst_t->l_lock : M 343 * -. uinst_t->c_lock : P 344 */ 345 int 346 oplmsu_set_ioctl_path(lpath_t *lpath, queue_t *hndl_queue, mblk_t *mp) 347 { 348 int rval = SUCCESS; 349 350 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 351 ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 352 353 if ((lpath->hndl_uqueue == NULL) && (lpath->hndl_mp == NULL) && 354 (lpath->sw_flag == 0)) { 355 if ((lpath->status == MSU_EXT_NOTUSED) || 356 (lpath->status == MSU_EXT_ACTIVE_CANDIDATE) || 357 (lpath->status == MSU_SETID_NU)) { 358 if (hndl_queue == NULL) { 359 lpath->hndl_uqueue = hndl_queue; 360 } else { 361 lpath->hndl_uqueue = WR(hndl_queue); 362 } 363 lpath->hndl_mp = mp; 364 } else { 365 rval = BUSY; 366 } 367 } else { 368 rval = BUSY; 369 } 370 return (rval); 371 } 372 373 /* 374 * Clear queue and ioctl to lpath_t 375 * 376 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 377 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 378 * -. uinst_t->u_lock : A 379 * -. uinst_t->l_lock : M 380 * -. uinst_t->c_lock : P 381 */ 382 void 383 oplmsu_clear_ioctl_path(lpath_t *lpath) 384 { 385 386 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 387 ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 388 389 lpath->hndl_uqueue = NULL; 390 lpath->hndl_mp = NULL; 391 } 392 393 /* 394 * Get instanse status from status of upath_t 395 * 396 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 397 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 398 * -. uinst_t->u_lock : M 399 * -. uinst_t->l_lock : A 400 * -. uinst_t->c_lock : P 401 */ 402 int 403 oplmsu_get_inst_status(void) 404 { 405 upath_t *upath; 406 int sts, pre_sts = INST_STAT_UNCONFIGURED; 407 408 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 409 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 410 411 upath = oplmsu_uinst->first_upath; 412 while (upath) { 413 if (((upath->status == MSU_PSTAT_ACTIVE) && 414 (upath->traditional_status == MSU_ACTIVE)) || 415 ((upath->status == MSU_PSTAT_STANDBY) && 416 (upath->traditional_status == MSU_STANDBY))) { 417 sts = INST_STAT_ONLINE; 418 } else if (((upath->status == MSU_PSTAT_STOP) && 419 (upath->traditional_status == MSU_STOP)) || 420 ((upath->status == MSU_PSTAT_FAIL) && 421 (upath->traditional_status == MSU_FAIL))) { 422 sts = INST_STAT_OFFLINE; 423 } else if (((upath->status == MSU_PSTAT_DISCON) && 424 (upath->traditional_status == MSU_DISCON)) || 425 ((upath->status == MSU_PSTAT_EMPTY) && 426 (upath->traditional_status == MSU_EMPTY))) { 427 sts = INST_STAT_UNCONFIGURED; 428 } else { 429 sts = INST_STAT_BUSY; 430 } 431 432 if (pre_sts > sts) { 433 pre_sts = sts; 434 } 435 upath = upath->u_next; 436 } 437 return (pre_sts); 438 } 439 440 /* 441 * Search path of "online:standby" status 442 * 443 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 444 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 445 * -. uinst_t->u_lock : M 446 * -. uinst_t->l_lock : A 447 * -. uinst_t->c_lock : P 448 */ 449 upath_t * 450 oplmsu_search_standby(void) 451 { 452 upath_t *upath, *altn_upath = NULL; 453 int max_pathnum = UNDEFINED; 454 455 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 456 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 457 458 upath = oplmsu_uinst->first_upath; 459 while (upath) { 460 if ((upath->status == MSU_PSTAT_STANDBY) && 461 (upath->traditional_status == MSU_STANDBY) && 462 (upath->lpath != NULL)) { 463 if ((max_pathnum == UNDEFINED) || 464 (max_pathnum > upath->path_no)) { 465 max_pathnum = upath->path_no; 466 altn_upath = upath; 467 } 468 } 469 upath = upath->u_next; 470 } 471 return (altn_upath); 472 } 473 474 /* 475 * Search path of "offline:stop" status, and minimum path number 476 * 477 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 478 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 479 * -. uinst_t->u_lock : M 480 * -. uinst_t->l_lock : P 481 * -. uinst_t->c_lock : P 482 */ 483 void 484 oplmsu_search_min_stop_path(void) 485 { 486 upath_t *upath, *min_upath; 487 lpath_t *lpath; 488 int min_no = UNDEFINED; 489 int active_flag = 0; 490 491 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 492 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 493 494 upath = oplmsu_uinst->first_upath; 495 while (upath) { 496 if ((upath->status == MSU_PSTAT_ACTIVE) && 497 (upath->traditional_status == MSU_ACTIVE)) { 498 active_flag = 1; 499 break; 500 } else if ((upath->status == MSU_PSTAT_STOP) && 501 (upath->traditional_status == MSU_STOP)) { 502 if (upath->lpath != NULL) { 503 if ((min_no == UNDEFINED) || 504 (upath->path_no < min_no)) { 505 lpath = upath->lpath; 506 mutex_enter(&oplmsu_uinst->l_lock); 507 if (lpath->status == MSU_EXT_NOTUSED) { 508 min_upath = upath; 509 min_no = upath->path_no; 510 } 511 mutex_exit(&oplmsu_uinst->l_lock); 512 } 513 } 514 } 515 upath = upath->u_next; 516 } 517 518 if (active_flag == 0) { 519 lpath = min_upath->lpath; 520 mutex_enter(&oplmsu_uinst->l_lock); 521 lpath->src_upath = NULL; 522 lpath->status = MSU_EXT_ACTIVE_CANDIDATE; 523 mutex_exit(&oplmsu_uinst->l_lock); 524 } 525 } 526 527 /* 528 * Get the total number of serial paths 529 * 530 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 531 * -. uinst_t->lock : M [RW_WRITER] 532 * -. uinst_t->u_lock : M 533 * -. uinst_t->l_lock : A 534 * -. uinst_t->c_lock : A 535 */ 536 int 537 oplmsu_get_pathnum(void) 538 { 539 upath_t *upath; 540 int total_num = 0; 541 542 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 543 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 544 545 if (oplmsu_uinst->first_upath != NULL) { 546 upath = oplmsu_uinst->first_upath; 547 while (upath) { 548 total_num++; 549 upath = upath->u_next; 550 } 551 } 552 return (total_num); 553 } 554 555 /* 556 * Put XOFF/ XON message on write queue 557 * 558 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 559 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 560 * -. uinst_t->u_lock : A 561 * -. uinst_t->l_lock : A 562 * -. uinst_t->c_lock : A 563 */ 564 int 565 oplmsu_cmn_put_xoffxon(queue_t *queue, int data) 566 { 567 mblk_t *mp; 568 int rval = SUCCESS; 569 570 /* Send M_START */ 571 if ((mp = allocb(0, BPRI_LO)) != NULL) { 572 mp->b_datap->db_type = M_START; 573 (void) putq(queue, mp); 574 575 /* Send M_DATA(XOFF, XON) */ 576 if ((mp = allocb(sizeof (int), BPRI_LO)) != NULL) { 577 *(uint_t *)mp->b_rptr = data; 578 mp->b_wptr = mp->b_rptr + sizeof (int); 579 (void) putq(queue, mp); 580 } else { 581 rval = FAILURE; 582 } 583 } else { 584 rval = FAILURE; 585 } 586 return (rval); 587 } 588 589 /* 590 * Put XOFF message on write queue for all standby paths 591 * 592 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 593 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 594 * -. uinst_t->u_lock : M 595 * -. uinst_t->l_lock : M 596 * -. uinst_t->c_lock : P 597 */ 598 void 599 oplmsu_cmn_putxoff_standby(void) 600 { 601 upath_t *upath; 602 lpath_t *lpath; 603 604 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 605 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 606 ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock)); 607 608 upath = oplmsu_uinst->first_upath; 609 while (upath) { 610 lpath = upath->lpath; 611 if ((upath->status != MSU_PSTAT_STANDBY) || 612 (lpath == NULL)) { 613 upath = upath->u_next; 614 continue; 615 } 616 617 (void) oplmsu_cmn_put_xoffxon( 618 WR(lpath->lower_queue), MSU_XOFF_4); 619 upath = upath->u_next; 620 } 621 } 622 623 /* 624 * Set M_FLUSH message 625 * 626 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 627 * -. uinst_t->lock : A [RW_READER or RW_WRITER] 628 * -. uinst_t->u_lock : A 629 * -. uinst_t->l_lock : A 630 * -. uinst_t->c_lock : A 631 */ 632 void 633 oplmsu_cmn_set_mflush(mblk_t *mp) 634 { 635 636 mp->b_datap->db_type = M_FLUSH; 637 *mp->b_rptr = FLUSHW; 638 mp->b_wptr = mp->b_rptr + sizeof (char); 639 } 640 641 /* 642 * Set status informations of upath_t 643 * 644 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 645 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 646 * -. uinst_t->u_lock : M 647 * -. uinst_t->l_lock : A 648 * -. uinst_t->c_lock : A 649 */ 650 void 651 oplmsu_cmn_set_upath_sts(upath_t *upath, int sts, int prev_sts, 652 ulong_t trad_sts) 653 { 654 655 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 656 ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock)); 657 658 upath->status = sts; 659 upath->prev_status = prev_sts; 660 upath->traditional_status = trad_sts; 661 } 662 663 /* 664 * Allocate a message block 665 * 666 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 667 * -. uinst_t->lock : M [RW_READER] 668 * -. uinst_t->u_lock : A 669 * -. uinst_t->l_lock : P 670 * -. uinst_t->c_lock : P 671 */ 672 int 673 oplmsu_cmn_allocmb(queue_t *q, mblk_t *mp, mblk_t **nmp, size_t size, 674 int rw_flag) 675 { 676 int rval = SUCCESS; 677 678 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 679 680 if ((*nmp = (mblk_t *)allocb(size, BPRI_LO)) == NULL) { 681 oplmsu_cmn_bufcall(q, mp, size, rw_flag); 682 rval = FAILURE; 683 } else { 684 (*nmp)->b_wptr = (*nmp)->b_rptr + size; 685 } 686 return (rval); 687 } 688 689 /* 690 * Copy a message 691 * 692 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 693 * -. uinst_t->lock : M [RW_READER] 694 * -. uinst_t->u_lock : A 695 * -. uinst_t->l_lock : P 696 * -. uinst_t->c_lock : P 697 */ 698 int 699 oplmsu_cmn_copymb(queue_t *q, mblk_t *mp, mblk_t **nmp, mblk_t *cmp, 700 int rw_flag) 701 { 702 int rval = SUCCESS; 703 704 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 705 706 if ((*nmp = copymsg(cmp)) == NULL) { 707 oplmsu_cmn_bufcall(q, mp, msgsize(cmp), rw_flag); 708 rval = FAILURE; 709 } 710 return (rval); 711 } 712 713 /* 714 * bufcall request 715 * 716 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 717 * -. uinst_t->lock : M [RW_READER] 718 * -. uinst_t->u_lock : A 719 * -. uinst_t->l_lock : P 720 * -. uinst_t->c_lock : P 721 */ 722 void 723 oplmsu_cmn_bufcall(queue_t *q, mblk_t *mp, size_t size, int rw_flag) 724 { 725 726 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 727 728 if (rw_flag == MSU_WRITE_SIDE) { 729 ctrl_t *ctrl; 730 731 (void) putbq(q, mp); 732 733 mutex_enter(&oplmsu_uinst->c_lock); 734 ctrl = (ctrl_t *)q->q_ptr; 735 if (ctrl->wbuf_id != 0) { 736 mutex_exit(&oplmsu_uinst->c_lock); 737 return; 738 } 739 740 ctrl->wbuftbl->q = q; 741 ctrl->wbuftbl->rw_flag = rw_flag; 742 ctrl->wbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb, 743 (void *)ctrl->wbuftbl); 744 745 if (ctrl->wbuf_id == 0) { 746 if (ctrl->wtout_id != 0) { 747 mutex_exit(&oplmsu_uinst->c_lock); 748 return; 749 } 750 751 ctrl->wtout_id = timeout(oplmsu_cmn_bufcb, 752 (void *)ctrl->wbuftbl, drv_usectohz(MSU_TM_500MS)); 753 } 754 mutex_exit(&oplmsu_uinst->c_lock); 755 } else if (rw_flag == MSU_READ_SIDE) { 756 lpath_t *lpath; 757 mblk_t *wrk_msg; 758 759 mutex_enter(&oplmsu_uinst->l_lock); 760 lpath = (lpath_t *)q->q_ptr; 761 if (mp->b_datap->db_type >= QPCTL) { 762 if (lpath->first_lpri_hi == NULL) { 763 lpath->last_lpri_hi = mp; 764 mp->b_next = NULL; 765 } else { 766 wrk_msg = lpath->first_lpri_hi; 767 wrk_msg->b_prev = mp; 768 mp->b_next = wrk_msg; 769 } 770 mp->b_prev = NULL; 771 lpath->first_lpri_hi = mp; 772 } else { 773 (void) putbq(q, mp); 774 } 775 776 if (lpath->rbuf_id != 0) { 777 mutex_exit(&oplmsu_uinst->l_lock); 778 return; 779 } 780 781 lpath->rbuftbl->q = q; 782 lpath->rbuftbl->rw_flag = rw_flag; 783 lpath->rbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb, 784 (void *)lpath->rbuftbl); 785 786 if (lpath->rbuf_id == 0) { 787 if (lpath->rtout_id != 0) { 788 mutex_exit(&oplmsu_uinst->l_lock); 789 return; 790 } 791 792 lpath->rtout_id = timeout(oplmsu_cmn_bufcb, 793 (void *)lpath->rbuftbl, drv_usectohz(MSU_TM_500MS)); 794 } 795 mutex_exit(&oplmsu_uinst->l_lock); 796 } 797 } 798 799 /* 800 * Previous sequence for active path change 801 * 802 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 803 * -. uinst_t->lock : M [RW_READER] 804 * -. uinst_t->u_lock : A 805 * -. uinst_t->l_lock : P 806 * -. uinst_t->c_lock : P 807 */ 808 int 809 oplmsu_cmn_prechg(queue_t *q, mblk_t *mp, int rw_flag, mblk_t **term_mp, 810 int *term_ioctl, int *term_stat) 811 { 812 813 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 814 815 if (oplmsu_uinst->tcsets_p != NULL) { 816 struct iocblk *iocp; 817 818 if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tcsets_p, 819 rw_flag) == -1) { 820 return (FAILURE); 821 } 822 823 iocp = (struct iocblk *)(*term_mp)->b_rptr; 824 *term_ioctl = iocp->ioc_cmd; 825 *term_stat = MSU_WTCS_ACK; 826 } else if (oplmsu_uinst->tiocmset_p != NULL) { 827 if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p, 828 rw_flag) == -1) { 829 return (FAILURE); 830 } 831 832 *term_ioctl = TIOCMSET; 833 *term_stat = MSU_WTMS_ACK; 834 } else if (oplmsu_uinst->tiocspps_p != NULL) { 835 if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p, 836 rw_flag) == -1) { 837 return (FAILURE); 838 } 839 840 *term_ioctl = TIOCSPPS; 841 *term_stat = MSU_WPPS_ACK; 842 } else if (oplmsu_uinst->tiocswinsz_p != NULL) { 843 if (oplmsu_cmn_copymb(q, mp, term_mp, 844 oplmsu_uinst->tiocswinsz_p, rw_flag) == -1) { 845 return (FAILURE); 846 } 847 848 *term_ioctl = TIOCSWINSZ; 849 *term_stat = MSU_WWSZ_ACK; 850 } else if (oplmsu_uinst->tiocssoftcar_p != NULL) { 851 if (oplmsu_cmn_copymb(q, mp, term_mp, 852 oplmsu_uinst->tiocssoftcar_p, rw_flag) == -1) { 853 return (FAILURE); 854 } 855 856 *term_ioctl = TIOCSSOFTCAR; 857 *term_stat = MSU_WCAR_ACK; 858 } else { 859 *term_stat = MSU_WPTH_CHG; 860 *term_mp = NULL; 861 } 862 return (SUCCESS); 863 } 864 865 /* 866 * Pick up termios to re-set 867 * 868 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 869 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 870 * -. uinst_t->u_lock : A 871 * -. uinst_t->l_lock : A 872 * -. uinst_t->c_lock : A 873 */ 874 int 875 oplmsu_stop_prechg(mblk_t **term_mp, int *term_ioctl, int *term_stat) 876 { 877 878 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 879 880 if (oplmsu_uinst->tcsets_p != NULL) { 881 struct iocblk *iocp; 882 883 if ((*term_mp = copymsg(oplmsu_uinst->tcsets_p)) == NULL) { 884 return (FAILURE); 885 } 886 887 iocp = (struct iocblk *)(*term_mp)->b_rptr; 888 *term_ioctl = iocp->ioc_cmd; 889 *term_stat = MSU_WTCS_ACK; 890 } else if (oplmsu_uinst->tiocmset_p != NULL) { 891 if ((*term_mp = copymsg(oplmsu_uinst->tiocmset_p)) == NULL) { 892 return (FAILURE); 893 } 894 895 *term_ioctl = TIOCMSET; 896 *term_stat = MSU_WTMS_ACK; 897 } else if (oplmsu_uinst->tiocspps_p != NULL) { 898 if ((*term_mp = copymsg(oplmsu_uinst->tiocspps_p)) == NULL) { 899 return (FAILURE); 900 } 901 902 *term_ioctl = TIOCSPPS; 903 *term_stat = MSU_WPPS_ACK; 904 } else if (oplmsu_uinst->tiocswinsz_p != NULL) { 905 if ((*term_mp = copymsg(oplmsu_uinst->tiocswinsz_p)) == NULL) { 906 return (FAILURE); 907 } 908 909 *term_ioctl = TIOCSWINSZ; 910 *term_stat = MSU_WWSZ_ACK; 911 } else if (oplmsu_uinst->tiocssoftcar_p != NULL) { 912 if ((*term_mp = copymsg(oplmsu_uinst->tiocssoftcar_p)) 913 == NULL) { 914 return (FAILURE); 915 } 916 917 *term_ioctl = TIOCSSOFTCAR; 918 *term_stat = MSU_WCAR_ACK; 919 } else { 920 *term_stat = MSU_WPTH_CHG; 921 *term_mp = NULL; 922 } 923 return (SUCCESS); 924 } 925 926 /* 927 * Previous sequence for active path change termio 928 * 929 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 930 * -. uinst_t->lock : M [RW_READER] 931 * -. uinst_t->u_lock : A 932 * -. uinst_t->l_lock : P 933 * -. uinst_t->c_lock : P 934 */ 935 int 936 oplmsu_cmn_prechg_termio(queue_t *q, mblk_t *mp, int rw_flag, int prev_flag, 937 mblk_t **term_mp, int *term_stat) 938 { 939 940 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 941 942 if ((prev_flag == MSU_TIOS_TCSETS) && 943 (oplmsu_uinst->tiocmset_p != NULL)) { 944 if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p, 945 rw_flag) == FAILURE) { 946 return (FAILURE); 947 } 948 949 *term_stat = MSU_WTMS_ACK; 950 } else if ((prev_flag <= MSU_TIOS_MSET) && 951 (oplmsu_uinst->tiocspps_p != NULL)) { 952 if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p, 953 rw_flag) == FAILURE) { 954 return (FAILURE); 955 } 956 957 *term_stat = MSU_WPPS_ACK; 958 } else if ((prev_flag <= MSU_TIOS_PPS) && 959 (oplmsu_uinst->tiocswinsz_p != NULL)) { 960 if (oplmsu_cmn_copymb(q, mp, term_mp, 961 oplmsu_uinst->tiocswinsz_p, rw_flag) == FAILURE) { 962 return (FAILURE); 963 } 964 965 *term_stat = MSU_WWSZ_ACK; 966 } else if ((prev_flag <= MSU_TIOS_WINSZP) && 967 (oplmsu_uinst->tiocssoftcar_p != NULL)) { 968 if (oplmsu_cmn_copymb(q, mp, term_mp, 969 oplmsu_uinst->tiocssoftcar_p, rw_flag) == FAILURE) { 970 return (FAILURE); 971 } 972 973 *term_stat = MSU_WCAR_ACK; 974 } else if (prev_flag <= MSU_TIOS_SOFTCAR) { 975 *term_mp = NULL; 976 *term_stat = MSU_WPTH_CHG; 977 } 978 return (SUCCESS); 979 } 980 981 /* 982 * Pull up messages 983 * 984 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 985 * -. uinst_t->lock : P 986 * -. uinst_t->u_lock : P 987 * -. uinst_t->l_lock : P 988 * -. uinst_t->c_lock : P 989 */ 990 int 991 oplmsu_cmn_pullup_msg(queue_t *q, mblk_t *mp) 992 { 993 mblk_t *nmp = NULL; 994 995 if ((mp != NULL) && (mp->b_cont != NULL) && 996 (mp->b_cont->b_cont != NULL)) { 997 if ((nmp = msgpullup(mp->b_cont, -1)) == NULL) { 998 oplmsu_iocack(q, mp, ENOSR); 999 return (FAILURE); 1000 } else { 1001 freemsg(mp->b_cont); 1002 mp->b_cont = nmp; 1003 } 1004 } 1005 return (SUCCESS); 1006 } 1007 1008 /* 1009 * Wake up flow control 1010 * 1011 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1012 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1013 * -. uinst_t->u_lock : P 1014 * -. uinst_t->l_lock : P 1015 * -. uinst_t->c_lock : P 1016 */ 1017 void 1018 oplmsu_cmn_wakeup(queue_t *q) 1019 { 1020 ctrl_t *ctrl; 1021 1022 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1023 1024 mutex_enter(&oplmsu_uinst->c_lock); 1025 ctrl = (ctrl_t *)q->q_ptr; 1026 if (ctrl->sleep_flag == CV_SLEEP) { 1027 ctrl->sleep_flag = CV_WAKEUP; 1028 cv_signal(&ctrl->cvp); 1029 } 1030 mutex_exit(&oplmsu_uinst->c_lock); 1031 } 1032 1033 /* 1034 * bufcall() and timeout() callback entry for read/write stream 1035 * 1036 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1037 * -. uinst_t->lock : P 1038 * -. uinst_t->u_lock : P 1039 * -. uinst_t->l_lock : P 1040 * -. uinst_t->c_lock : P 1041 */ 1042 void 1043 oplmsu_cmn_bufcb(void *arg) 1044 { 1045 struct buf_tbl *buftbl = arg; 1046 lpath_t *lpath; 1047 ctrl_t *ctrl; 1048 queue_t *q; 1049 int lq_flag = 0; 1050 1051 rw_enter(&oplmsu_uinst->lock, RW_WRITER); 1052 mutex_enter(&oplmsu_uinst->l_lock); 1053 1054 lpath = oplmsu_uinst->first_lpath; 1055 while (lpath) { 1056 if ((buftbl == lpath->rbuftbl) && 1057 (buftbl->rw_flag == MSU_READ_SIDE)) { 1058 if ((lpath->rbuf_id == 0) && (lpath->rtout_id == 0)) { 1059 mutex_exit(&oplmsu_uinst->l_lock); 1060 rw_exit(&oplmsu_uinst->lock); 1061 } else { 1062 q = lpath->rbuftbl->q; 1063 lpath->rbuftbl->q = NULL; 1064 lpath->rbuftbl->rw_flag = UNDEFINED; 1065 1066 if (lpath->rbuf_id) { 1067 lpath->rbuf_id = 0; 1068 } else { 1069 lpath->rtout_id = 0; 1070 } 1071 mutex_exit(&oplmsu_uinst->l_lock); 1072 1073 if (oplmsu_queue_flag == 1) { 1074 lq_flag = 1; 1075 oplmsu_queue_flag = 0; 1076 } 1077 1078 rw_exit(&oplmsu_uinst->lock); 1079 oplmsu_rcmn_high_qenable(q); 1080 1081 if (lq_flag == 1) { 1082 rw_enter(&oplmsu_uinst->lock, 1083 RW_WRITER); 1084 oplmsu_queue_flag = 1; 1085 rw_exit(&oplmsu_uinst->lock); 1086 } 1087 } 1088 return; 1089 } 1090 lpath = lpath->l_next; 1091 } 1092 mutex_exit(&oplmsu_uinst->l_lock); 1093 1094 mutex_enter(&oplmsu_uinst->c_lock); 1095 if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) { 1096 if ((buftbl == ctrl->wbuftbl) && 1097 (buftbl->rw_flag == MSU_WRITE_SIDE)) { 1098 oplmsu_wbufcb_posthndl(ctrl); 1099 mutex_exit(&oplmsu_uinst->c_lock); 1100 rw_exit(&oplmsu_uinst->lock); 1101 return; 1102 } 1103 } 1104 1105 if ((ctrl = oplmsu_uinst->meta_ctrl) != NULL) { 1106 if ((buftbl == ctrl->wbuftbl) && 1107 (buftbl->rw_flag == MSU_WRITE_SIDE)) { 1108 oplmsu_wbufcb_posthndl(ctrl); 1109 mutex_exit(&oplmsu_uinst->c_lock); 1110 rw_exit(&oplmsu_uinst->lock); 1111 return; 1112 } 1113 } 1114 mutex_exit(&oplmsu_uinst->c_lock); 1115 rw_exit(&oplmsu_uinst->lock); 1116 } 1117 1118 /* 1119 * bufcall() or timeout() callback post handling for write stream 1120 * 1121 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1122 * -. uinst_t->lock : M [RW_WRITER] 1123 * -. uinst_t->u_lock : P 1124 * -. uinst_t->l_lock : P 1125 * -. uinst_t->c_lock : M 1126 */ 1127 void 1128 oplmsu_wbufcb_posthndl(ctrl_t *ctrl) 1129 { 1130 queue_t *q; 1131 int lq_flag = 0; 1132 1133 ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock)); 1134 ASSERT(MUTEX_HELD(&oplmsu_uinst->c_lock)); 1135 1136 if ((ctrl->wbuf_id == 0) && (ctrl->wtout_id == 0)) { 1137 return; 1138 } 1139 1140 q = ctrl->wbuftbl->q; 1141 ctrl->wbuftbl->q = NULL; 1142 ctrl->wbuftbl->rw_flag = UNDEFINED; 1143 if (ctrl->wbuf_id) { 1144 ctrl->wbuf_id = 0; 1145 } else { 1146 ctrl->wtout_id = 0; 1147 } 1148 1149 if (oplmsu_queue_flag == 1) { 1150 lq_flag = 1; 1151 oplmsu_queue_flag = 0; 1152 } 1153 1154 mutex_exit(&oplmsu_uinst->c_lock); 1155 oplmsu_wcmn_high_qenable(q, RW_WRITER); 1156 mutex_enter(&oplmsu_uinst->c_lock); 1157 1158 if (lq_flag == 1) { 1159 oplmsu_queue_flag = 1; 1160 } 1161 } 1162 1163 /* 1164 * COMMON FUNCTIONS FOR WRITE STREAM 1165 */ 1166 1167 /* 1168 * Check control node and driver privilege 1169 * 1170 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1171 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1172 * -. uinst_t->u_lock : A 1173 * -. uinst_t->l_lock : A 1174 * -. uinst_t->c_lock : P 1175 */ 1176 int 1177 oplmsu_wcmn_chknode(queue_t *q, int node, mblk_t *mp) 1178 { 1179 struct iocblk *iocp; 1180 1181 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1182 1183 mutex_enter(&oplmsu_uinst->c_lock); 1184 if (((ctrl_t *)q->q_ptr)->node_type != node) { 1185 mutex_exit(&oplmsu_uinst->c_lock); 1186 cmn_err(CE_WARN, "oplmsu: chk-node: ctrl node type = %d", node); 1187 return (EINVAL); 1188 } 1189 mutex_exit(&oplmsu_uinst->c_lock); 1190 1191 /* Check super-user by oplmsu.conf */ 1192 if (oplmsu_check_su != 0) { 1193 iocp = (struct iocblk *)mp->b_rptr; 1194 if (drv_priv(iocp->ioc_cr) != 0) { 1195 cmn_err(CE_WARN, "oplmsu: chk-node: Permission denied"); 1196 return (EPERM); 1197 } 1198 } 1199 return (SUCCESS); 1200 } 1201 1202 /* 1203 * Flush handle for write side stream 1204 * 1205 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1206 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1207 * -. uinst_t->u_lock : P 1208 * -. uinst_t->l_lock : P 1209 * -. uinst_t->c_lock : P 1210 */ 1211 void 1212 oplmsu_wcmn_flush_hndl(queue_t *q, mblk_t *mp, krw_t rw) 1213 { 1214 queue_t *dst_queue = NULL; 1215 1216 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1217 1218 if (*mp->b_rptr & FLUSHW) { /* Write side */ 1219 flushq(q, FLUSHDATA); 1220 } 1221 1222 dst_queue = oplmsu_uinst->lower_queue; 1223 if (dst_queue == NULL) { 1224 if (*mp->b_rptr & FLUSHR) { 1225 flushq(RD(q), FLUSHDATA); 1226 *mp->b_rptr &= ~FLUSHW; 1227 1228 rw_exit(&oplmsu_uinst->lock); 1229 OPLMSU_TRACE(q, mp, MSU_TRC_UO); 1230 qreply(q, mp); 1231 rw_enter(&oplmsu_uinst->lock, rw); 1232 } else { 1233 freemsg(mp); 1234 } 1235 } else { 1236 (void) putq(WR(dst_queue), mp); 1237 } 1238 } 1239 1240 /* 1241 * Through message handle for write side stream 1242 * 1243 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1244 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1245 * -. uinst_t->u_lock : P 1246 * -. uinst_t->l_lock : P 1247 * -. uinst_t->c_lock : P 1248 */ 1249 int 1250 oplmsu_wcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag, krw_t rw) 1251 { 1252 queue_t *usr_queue = NULL, *dst_queue = NULL; 1253 ctrl_t *ctrl; 1254 1255 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1256 1257 mutex_enter(&oplmsu_uinst->c_lock); 1258 if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) { 1259 usr_queue = ctrl->queue; 1260 mutex_exit(&oplmsu_uinst->c_lock); 1261 } else { 1262 mutex_exit(&oplmsu_uinst->c_lock); 1263 if (mp->b_datap->db_type == M_IOCTL) { 1264 rw_exit(&oplmsu_uinst->lock); 1265 oplmsu_iocack(q, mp, ENODEV); 1266 rw_enter(&oplmsu_uinst->lock, rw); 1267 } else { 1268 freemsg(mp); 1269 } 1270 return (SUCCESS); 1271 } 1272 1273 if (oplmsu_uinst->lower_queue != NULL) { 1274 dst_queue = WR(oplmsu_uinst->lower_queue); 1275 } else { 1276 cmn_err(CE_WARN, "!oplmsu: through-lwq: " 1277 "Active path doesn't exist"); 1278 1279 if (mp->b_datap->db_type == M_IOCTL) { 1280 rw_exit(&oplmsu_uinst->lock); 1281 oplmsu_iocack(q, mp, ENODEV); 1282 rw_enter(&oplmsu_uinst->lock, rw); 1283 } else { 1284 freemsg(mp); 1285 } 1286 return (SUCCESS); 1287 } 1288 1289 if ((usr_queue == WR(q)) || (usr_queue == RD(q))) { 1290 if (pri_flag == MSU_HIGH) { 1291 (void) putq(dst_queue, mp); 1292 } else { 1293 if (canput(dst_queue)) { 1294 (void) putq(dst_queue, mp); 1295 } else { 1296 oplmsu_wcmn_norm_putbq(WR(q), mp, dst_queue); 1297 return (FAILURE); 1298 } 1299 } 1300 } else { 1301 cmn_err(CE_WARN, "oplmsu: through-lwq: " 1302 "Inappropriate message for this node"); 1303 1304 if (mp->b_datap->db_type == M_IOCTL) { 1305 rw_exit(&oplmsu_uinst->lock); 1306 oplmsu_iocack(q, mp, ENODEV); 1307 rw_enter(&oplmsu_uinst->lock, rw); 1308 } else { 1309 freemsg(mp); 1310 } 1311 } 1312 return (SUCCESS); 1313 } 1314 1315 /* 1316 * Get high priority message from buffer for upper write stream 1317 * 1318 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1319 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1320 * -. uinst_t->u_lock : A 1321 * -. uinst_t->l_lock : A 1322 * -. uinst_t->c_lock : P 1323 */ 1324 mblk_t * 1325 oplmsu_wcmn_high_getq(queue_t *uwq) 1326 { 1327 mblk_t *mp; 1328 ctrl_t *ctrl; 1329 1330 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1331 1332 mutex_enter(&oplmsu_uinst->c_lock); 1333 ctrl = (ctrl_t *)uwq->q_ptr; 1334 mp = ctrl->first_upri_hi; 1335 if (mp != NULL) { 1336 if (mp->b_next == NULL) { 1337 ctrl->first_upri_hi = NULL; 1338 ctrl->last_upri_hi = NULL; 1339 } else { 1340 ctrl->first_upri_hi = mp->b_next; 1341 mp->b_next->b_prev = NULL; 1342 mp->b_next = NULL; 1343 } 1344 mp->b_prev = NULL; 1345 } 1346 mutex_exit(&oplmsu_uinst->c_lock); 1347 return (mp); 1348 } 1349 1350 /* 1351 * putbq() function for normal priority message of write stream 1352 * 1353 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1354 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1355 * -. uinst_t->u_lock : A 1356 * -. uinst_t->l_lock : P 1357 * -. uinst_t->c_lock : P 1358 */ 1359 void 1360 oplmsu_wcmn_norm_putbq(queue_t *uwq, mblk_t *mp, queue_t *dq) 1361 { 1362 lpath_t *lpath; 1363 1364 ASSERT(mp != NULL); 1365 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1366 1367 mutex_enter(&oplmsu_uinst->l_lock); 1368 lpath = (lpath_t *)dq->q_ptr; 1369 lpath->uwq_flag = 1; 1370 lpath->uwq_queue = uwq; 1371 mutex_exit(&oplmsu_uinst->l_lock); 1372 (void) putbq(uwq, mp); 1373 } 1374 1375 /* 1376 * Restart queuing for high priority message of write stream when flow control 1377 * failed 1378 * 1379 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1380 * -. uinst_t->lock : M [RW_READER or RW_WRITER] 1381 * -. uinst_t->u_lock : P 1382 * -. uinst_t->l_lock : P 1383 * -. uinst_t->c_lock : P 1384 */ 1385 void 1386 oplmsu_wcmn_high_qenable(queue_t *q, krw_t rw) 1387 { 1388 mblk_t *mp; 1389 1390 ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock)); 1391 1392 if (oplmsu_queue_flag == 1) { 1393 return; 1394 } 1395 1396 /* Handle high priority message */ 1397 while (mp = oplmsu_wcmn_high_getq(WR(q))) { 1398 if (mp->b_datap->db_type & M_FLUSH) { 1399 oplmsu_wcmn_flush_hndl(q, mp, rw); 1400 continue; 1401 } 1402 1403 if (oplmsu_wcmn_through_hndl(q, mp, MSU_HIGH, rw) == FAILURE) { 1404 return; 1405 } 1406 } 1407 qenable(WR(q)); /* enable upper write queue */ 1408 } 1409 1410 /* 1411 * COMMON FUNCTIONS FOR READ STREAM 1412 */ 1413 1414 /* 1415 * Flush handle for read side stream 1416 * 1417 * Requires lock ( M: mandatory P: prohibited A: allowed 1418 * -. uinst_t->lock : M [RW_READER] 1419 * -. uinst_t->u_lock : P 1420 * -. uinst_t->l_lock : P 1421 * -. uinst_t->c_lock : P 1422 */ 1423 void 1424 oplmsu_rcmn_flush_hndl(queue_t *q, mblk_t *mp) 1425 { 1426 queue_t *dst_queue = NULL; 1427 ctrl_t *ctrl; 1428 1429 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 1430 1431 if (*mp->b_rptr & FLUSHR) { 1432 /* Remove only data messages from read queue */ 1433 flushq(q, FLUSHDATA); 1434 } 1435 1436 mutex_enter(&oplmsu_uinst->c_lock); 1437 if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) { 1438 dst_queue = RD(ctrl->queue); 1439 mutex_exit(&oplmsu_uinst->c_lock); 1440 1441 if (dst_queue != NULL) { 1442 (void) putq(dst_queue, mp); 1443 } else { 1444 if (*mp->b_rptr & FLUSHW) { 1445 flushq(WR(q), FLUSHDATA); 1446 *mp->b_rptr &= ~FLUSHR; 1447 1448 rw_exit(&oplmsu_uinst->lock); 1449 OPLMSU_TRACE(q, mp, MSU_TRC_LO); 1450 qreply(q, mp); 1451 rw_enter(&oplmsu_uinst->lock, RW_READER); 1452 } else { 1453 freemsg(mp); 1454 } 1455 } 1456 } else { 1457 mutex_exit(&oplmsu_uinst->c_lock); 1458 if (*mp->b_rptr & FLUSHW) { 1459 flushq(WR(q), FLUSHDATA); 1460 *mp->b_rptr &= ~FLUSHR; 1461 1462 rw_exit(&oplmsu_uinst->lock); 1463 OPLMSU_TRACE(q, mp, MSU_TRC_LO); 1464 qreply(q, mp); 1465 rw_enter(&oplmsu_uinst->lock, RW_READER); 1466 } else { 1467 freemsg(mp); 1468 } 1469 } 1470 } 1471 1472 /* 1473 * Through message handle for read side stream 1474 * 1475 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1476 * -. uinst_t->lock : M [RW_READER] 1477 * -. uinst_t->u_lock : A 1478 * -. uinst_t->l_lock : P 1479 * -. uinst_t->c_lock : P 1480 */ 1481 int 1482 oplmsu_rcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag) 1483 { 1484 lpath_t *lpath; 1485 ctrl_t *ctrl; 1486 queue_t *dst_queue = NULL; 1487 int act_flag; 1488 1489 ASSERT(RW_READ_HELD(&oplmsu_uinst->lock)); 1490 1491 mutex_enter(&oplmsu_uinst->l_lock); 1492 lpath = (lpath_t *)q->q_ptr; 1493 if (lpath->uinst != NULL) { 1494 act_flag = ACTIVE_RES; 1495 } else { 1496 act_flag = NOT_ACTIVE_RES; 1497 } 1498 mutex_exit(&oplmsu_uinst->l_lock); 1499 1500 mutex_enter(&oplmsu_uinst->c_lock); 1501 if (((ctrl = oplmsu_uinst->user_ctrl) != NULL) && 1502 (((mp->b_datap->db_type == M_IOCACK) || 1503 (mp->b_datap->db_type == M_IOCNAK)) || (act_flag == ACTIVE_RES))) { 1504 dst_queue = RD(ctrl->queue); 1505 } else { 1506 mutex_exit(&oplmsu_uinst->c_lock); 1507 freemsg(mp); 1508 return (SUCCESS); 1509 } 1510 1511 if (pri_flag == MSU_HIGH) { 1512 (void) putq(dst_queue, mp); 1513 } else { 1514 if (canput(dst_queue)) { 1515 (void) putq(dst_queue, mp); 1516 } else { 1517 /* 1518 * Place a normal priority message at the head of 1519 * read queue 1520 */ 1521 1522 ctrl = (ctrl_t *)dst_queue->q_ptr; 1523 ctrl->lrq_flag = 1; 1524 ctrl->lrq_queue = q; 1525 mutex_exit(&oplmsu_uinst->c_lock); 1526 (void) putbq(q, mp); 1527 return (FAILURE); 1528 } 1529 } 1530 mutex_exit(&oplmsu_uinst->c_lock); 1531 return (SUCCESS); 1532 } 1533 1534 /* 1535 * Restart queuing for high priority message of read stream 1536 * when flow control failed 1537 * 1538 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1539 * -. uinst_t->lock : P 1540 * -. uinst_t->u_lock : P 1541 * -. uinst_t->l_lock : P 1542 * -. uinst_t->c_lock : P 1543 */ 1544 void 1545 oplmsu_rcmn_high_qenable(queue_t *q) 1546 { 1547 mblk_t *mp; 1548 struct iocblk *iocp = NULL; 1549 lpath_t *lpath; 1550 int rval; 1551 1552 rw_enter(&oplmsu_uinst->lock, RW_READER); 1553 1554 for (;;) { /* Handle high priority message */ 1555 mutex_enter(&oplmsu_uinst->l_lock); 1556 lpath = (lpath_t *)q->q_ptr; 1557 if ((mp = lpath->first_lpri_hi) == NULL) { 1558 mutex_exit(&oplmsu_uinst->l_lock); 1559 break; 1560 } 1561 1562 if (mp->b_next == NULL) { 1563 lpath->first_lpri_hi = NULL; 1564 lpath->last_lpri_hi = NULL; 1565 } else { 1566 lpath->first_lpri_hi = mp->b_next; 1567 mp->b_next->b_prev = NULL; 1568 mp->b_next = NULL; 1569 } 1570 mp->b_prev = NULL; 1571 mutex_exit(&oplmsu_uinst->l_lock); 1572 1573 rval = SUCCESS; 1574 switch (mp->b_datap->db_type) { 1575 case M_IOCACK : /* FALLTHRU */ 1576 case M_IOCNAK : 1577 iocp = (struct iocblk *)mp->b_rptr; 1578 switch (iocp->ioc_cmd) { 1579 case TCSETS : /* FALLTHRU */ 1580 case TCSETSW : /* FALLTHRU */ 1581 case TCSETSF : /* FALLTHRU */ 1582 case TIOCMSET : /* FALLTHRU */ 1583 case TIOCSPPS : /* FALLTHRU */ 1584 case TIOCSWINSZ : /* FALLTHRU */ 1585 case TIOCSSOFTCAR : 1586 rw_exit(&oplmsu_uinst->lock); 1587 rval = oplmsu_lrioctl_termios(q, mp); 1588 rw_enter(&oplmsu_uinst->lock, RW_WRITER); 1589 break; 1590 1591 default : 1592 rval = oplmsu_rcmn_through_hndl( 1593 q, mp, MSU_HIGH); 1594 if (rval == FAILURE) { 1595 rw_exit(&oplmsu_uinst->lock); 1596 return; 1597 } 1598 } 1599 break; 1600 1601 case M_ERROR : 1602 rw_exit(&oplmsu_uinst->lock); 1603 rval = oplmsu_lrmsg_error(q, mp); 1604 rw_enter(&oplmsu_uinst->lock, RW_WRITER); 1605 break; 1606 1607 case M_FLUSH : 1608 oplmsu_rcmn_flush_hndl(q, mp); 1609 break; 1610 1611 default : 1612 rval = oplmsu_rcmn_through_hndl(q, mp, MSU_HIGH); 1613 if (rval == FAILURE) { 1614 rw_exit(&oplmsu_uinst->lock); 1615 return; 1616 } 1617 } 1618 1619 if (rval == FAILURE) { 1620 break; 1621 } 1622 } 1623 1624 rw_exit(&oplmsu_uinst->lock); 1625 qenable(q); /* Enable lower read queue */ 1626 } 1627 1628 #ifdef DEBUG 1629 /* 1630 * Online trace 1631 * 1632 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1633 * -. uinst_t->lock : P 1634 * -. uinst_t->u_lock : P 1635 * -. uinst_t->l_lock : P 1636 * -. uinst_t->c_lock : P 1637 */ 1638 void 1639 oplmsu_cmn_trace(queue_t *q, mblk_t *mp, int op) 1640 { 1641 struct iocblk *iocp; 1642 1643 if ((op < MSU_TRC_UI) || (op > MSU_TRC_CLS)) { 1644 return; 1645 } 1646 1647 mutex_enter(&oplmsu_ltrc_lock); 1648 1649 if (oplmsu_debug_mode & MSU_DPRINT_ON) { 1650 oplmsu_cmn_msglog(mp, op); 1651 } 1652 1653 /* Trace current counter */ 1654 (void) drv_getparm(LBOLT, (void *)&oplmsu_ltrc_ccnt); 1655 1656 if (oplmsu_ltrc_cur == oplmsu_ltrc_tail) { 1657 oplmsu_ltrc_cur = oplmsu_ltrc_top; 1658 } else { 1659 oplmsu_ltrc_cur++; 1660 } 1661 oplmsu_ltrc_cur->q = q; 1662 oplmsu_ltrc_cur->mp = mp; 1663 1664 switch (op) { 1665 case MSU_TRC_UI : 1666 oplmsu_ltrc_cur->op[0] = 'u'; 1667 oplmsu_ltrc_cur->op[1] = 'i'; 1668 break; 1669 1670 case MSU_TRC_UO : 1671 oplmsu_ltrc_cur->op[0] = 'u'; 1672 oplmsu_ltrc_cur->op[1] = 'o'; 1673 break; 1674 1675 case MSU_TRC_LI : 1676 oplmsu_ltrc_cur->op[0] = 'l'; 1677 oplmsu_ltrc_cur->op[1] = 'i'; 1678 break; 1679 1680 case MSU_TRC_LO : 1681 oplmsu_ltrc_cur->op[0] = 'l'; 1682 oplmsu_ltrc_cur->op[1] = 'o'; 1683 break; 1684 1685 case MSU_TRC_OPN : 1686 oplmsu_ltrc_cur->op[0] = 'o'; 1687 oplmsu_ltrc_cur->op[1] = 'p'; 1688 break; 1689 1690 case MSU_TRC_CLS : 1691 oplmsu_ltrc_cur->op[0] = 'c'; 1692 oplmsu_ltrc_cur->op[1] = 'l'; 1693 break; 1694 } 1695 1696 if ((op == MSU_TRC_LI) || (op == MSU_TRC_LO)) { 1697 mutex_enter(&oplmsu_uinst->l_lock); 1698 oplmsu_ltrc_cur->pathno = ((lpath_t *)q->q_ptr)->path_no; 1699 mutex_exit(&oplmsu_uinst->l_lock); 1700 } else { 1701 oplmsu_ltrc_cur->pathno = 0; 1702 } 1703 1704 if ((op == MSU_TRC_OPN) || (op == MSU_TRC_CLS)) { 1705 oplmsu_ltrc_cur->msg_type = 0; 1706 oplmsu_ltrc_cur->msg_cmd = 0; 1707 oplmsu_ltrc_cur->data = 0; 1708 1709 switch ((ulong_t)mp) { 1710 case MSU_NODE_USER : 1711 oplmsu_ltrc_cur->data = MSU_TRC_USER; 1712 break; 1713 1714 case MSU_NODE_META : 1715 oplmsu_ltrc_cur->data = MSU_TRC_META; 1716 break; 1717 } 1718 oplmsu_ltrc_cur->mp = NULL; 1719 } else { 1720 oplmsu_ltrc_cur->msg_type = mp->b_datap->db_type; 1721 iocp = (struct iocblk *)mp->b_rptr; 1722 oplmsu_ltrc_cur->msg_cmd = iocp->ioc_cmd; 1723 1724 if ((mp->b_datap->db_type == M_IOCTL) || 1725 (mp->b_datap->db_type == M_IOCACK) || 1726 (mp->b_datap->db_type == M_IOCNAK)) { 1727 oplmsu_ltrc_cur->msg_cmd = iocp->ioc_cmd; 1728 1729 if (mp->b_cont != NULL) { 1730 oplmsu_ltrc_cur->data = 1731 (ulong_t)mp->b_cont->b_rptr; 1732 } else { 1733 oplmsu_ltrc_cur->data = 0; 1734 } 1735 } else { 1736 oplmsu_ltrc_cur->msg_cmd = 0; 1737 1738 if (mp->b_rptr == NULL) { 1739 oplmsu_ltrc_cur->data = 0; 1740 } else { 1741 oplmsu_ltrc_cur->data = *(ulong_t *)mp->b_rptr; 1742 } 1743 } 1744 } 1745 mutex_exit(&oplmsu_ltrc_lock); 1746 } 1747 1748 /* 1749 * Display message log to console 1750 * 1751 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed )) 1752 * -. uinst_t->lock : P 1753 * -. uinst_t->u_lock : P 1754 * -. uinst_t->l_lock : P 1755 * -. uinst_t->c_lock : P 1756 */ 1757 void 1758 oplmsu_cmn_msglog(mblk_t *mp, int direction) 1759 { 1760 uchar_t *cur = NULL; 1761 mblk_t *tmp_mp = NULL; 1762 ulong_t len; 1763 ulong_t line; 1764 ulong_t col; 1765 ulong_t row; 1766 ulong_t count; 1767 char buffer[70]; 1768 char *bufp; 1769 1770 if (mp == NULL) { 1771 return; 1772 } 1773 1774 switch (direction) { 1775 case 0: 1776 cmn_err(CE_NOTE, "!---------- Upper in --------"); 1777 break; 1778 1779 case 1: 1780 cmn_err(CE_NOTE, "!---------- Upper out -------"); 1781 break; 1782 1783 case 2: 1784 cmn_err(CE_NOTE, "!---------- Lower in --------"); 1785 break; 1786 1787 case 3: 1788 cmn_err(CE_NOTE, "!---------- Lower out -------"); 1789 break; 1790 1791 default: 1792 return; 1793 } 1794 1795 for (tmp_mp = mp; tmp_mp; tmp_mp = tmp_mp->b_cont) { 1796 cmn_err(CE_NOTE, "!db_type = 0x%02x", tmp_mp->b_datap->db_type); 1797 1798 len = tmp_mp->b_wptr - tmp_mp->b_rptr; 1799 line = (len + 31) / 32; 1800 cur = (uchar_t *)tmp_mp->b_rptr; 1801 count = 0; 1802 1803 for (col = 0; col < line; col++) { 1804 bufp = buffer; 1805 1806 for (row = 0; row < 32; row++) { 1807 if (row != 0 && (row % 8) == 0) { 1808 *bufp = ' '; 1809 bufp++; 1810 } 1811 (void) sprintf(bufp, "%02x", *cur); 1812 bufp += 2; 1813 cur++; 1814 count++; 1815 1816 if (count >= len) { 1817 break; 1818 } 1819 } 1820 *bufp = '\0'; 1821 cmn_err(CE_NOTE, "!%s", buffer); 1822 1823 if (count >= len) { 1824 break; 1825 } 1826 } 1827 } 1828 } 1829 1830 void 1831 oplmsu_cmn_prt_pathname(dev_info_t *dip) 1832 { 1833 char pathname[128]; 1834 char wrkbuf[128]; 1835 1836 (void) ddi_pathname(dip, wrkbuf); 1837 *(wrkbuf + strlen(wrkbuf)) = '\0'; 1838 (void) sprintf(pathname, "/devices%s:%c", wrkbuf, 1839 'a'+ ddi_get_instance(dip)); 1840 1841 DBG_PRINT((CE_NOTE, "oplmsu: debug-info: " 1842 "Active path change to path => %s", pathname)); 1843 } 1844 #endif 1845