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