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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/conf.h> 27 #include <sys/file.h> 28 #include <sys/ddi.h> 29 #include <sys/sunddi.h> 30 #include <sys/scsi/scsi.h> 31 #include <sys/scsi/adapters/scsi_vhci.h> 32 #include <sys/scsi/adapters/scsi_vhci_tpgs.h> 33 34 /* 35 * External function definitions 36 */ 37 extern void vhci_mpapi_update_tpg_data(struct scsi_address *, char *); 38 39 40 41 static int vhci_tpgs_inquiry(struct scsi_address *ap, struct buf *bp, 42 int *mode); 43 static int vhci_tpgs_page83(struct scsi_address *ap, struct buf *bp, 44 int *rel_tgt_port, int *tgt_port, int *lu); 45 static void print_buf(char *buf, int buf_size); 46 static int vhci_tpgs_report_target_groups(struct scsi_address *ap, 47 struct buf *bp, int rel_tgt_port, int tgt_port, int *pstate, 48 int *preferred); 49 50 int 51 vhci_tpgs_set_target_groups(struct scsi_address *ap, int set_state, 52 int tpg_id) 53 { 54 struct scsi_pkt *pkt; 55 struct buf *bp; 56 int len, rval, ss = SCSI_SENSE_UNKNOWN; 57 char *bufp; 58 struct scsi_extended_sense *sns; 59 60 len = 8; 61 62 bp = getrbuf(KM_NOSLEEP); 63 if (bp == NULL) { 64 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_set_target_groups: " 65 " failed getrbuf")); 66 return (1); 67 } 68 69 bufp = kmem_zalloc(len, KM_NOSLEEP); 70 if (bufp == NULL) { 71 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_set_target_groups: " 72 "request packet allocation for %d failed....", len)); 73 freerbuf(bp); 74 return (1); 75 } 76 77 bp->b_un.b_addr = bufp; 78 bp->b_flags = B_READ; 79 bp->b_bcount = len; 80 bp->b_resid = 0; 81 82 bufp[4] = (0x0f & set_state); 83 bufp[6] = (0xff00 & tpg_id) >> 8; 84 bufp[7] = (0x00ff & tpg_id); 85 86 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP5, 87 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 88 89 if (pkt == NULL) { 90 VHCI_DEBUG(1, (CE_NOTE, NULL, 91 "!vhci_tpgs_set_target_groups: scsi_init_pkt error\n")); 92 freerbuf(bp); 93 kmem_free((void *)bufp, len); 94 return (1); 95 } 96 97 /* 98 * Sends 1 TPG descriptor only. Hence Parameter list length pkt_cdbp[9] 99 * is set to 8 bytes - Refer SPC3 for details. 100 */ 101 pkt->pkt_cdbp[0] = SCMD_MAINTENANCE_OUT; 102 pkt->pkt_cdbp[1] = SSVC_ACTION_SET_TARGET_PORT_GROUPS; 103 pkt->pkt_cdbp[9] = 8; 104 pkt->pkt_time = 90; 105 106 VHCI_DEBUG(1, (CE_NOTE, NULL, 107 "!vhci_tpgs_set_target_groups: sending set target port group:" 108 " cdb[0/1/6/7/8/9]: %x/%x/%x/%x/%x/%x\n", pkt->pkt_cdbp[0], 109 pkt->pkt_cdbp[1], pkt->pkt_cdbp[6], pkt->pkt_cdbp[7], 110 pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); 111 112 #ifdef DEBUG 113 print_buf(bufp, len); 114 #endif 115 rval = vhci_do_scsi_cmd(pkt); 116 117 if (rval == 0) { 118 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_set_target_groups:" 119 " vhci_do_scsi_cmd failed\n")); 120 freerbuf(bp); 121 kmem_free((void *)bufp, len); 122 scsi_destroy_pkt(pkt); 123 return (-1); 124 } else if ((pkt->pkt_reason == CMD_CMPLT) && 125 (SCBP_C(pkt) == STATUS_CHECK) && 126 (pkt->pkt_state & STATE_ARQ_DONE)) { 127 sns = &(((struct scsi_arq_status *)(uintptr_t) 128 (pkt->pkt_scbp))->sts_sensedata); 129 130 if ((sns->es_key == KEY_UNIT_ATTENTION) && 131 (sns->es_add_code == STD_SCSI_ASC_STATE_CHG) && 132 (sns->es_qual_code == STD_SCSI_ASCQ_STATE_CHG_SUCC)) { 133 ss = SCSI_SENSE_STATE_CHANGED; 134 VHCI_DEBUG(4, (CE_NOTE, NULL, 135 "!vhci_tpgs_set_target_groups:" 136 " sense:%x, add_code: %x, qual_code:%x" 137 " sense:%x\n", sns->es_key, sns->es_add_code, 138 sns->es_qual_code, ss)); 139 } else if ((sns->es_key == KEY_ILLEGAL_REQUEST) && 140 (sns->es_add_code == STD_SCSI_ASC_INVAL_PARAM_LIST)) { 141 ss = SCSI_SENSE_NOFAILOVER; 142 VHCI_DEBUG(1, (CE_NOTE, NULL, 143 "!vhci_tpgs_set_target_groups:" 144 " sense:%x, add_code: %x, qual_code:%x" 145 " sense:%x\n", sns->es_key, sns->es_add_code, 146 sns->es_qual_code, ss)); 147 } else if ((sns->es_key == KEY_ILLEGAL_REQUEST) && 148 (sns->es_add_code == STD_SCSI_ASC_INVAL_CMD_OPCODE)) { 149 ss = SCSI_SENSE_NOFAILOVER; 150 VHCI_DEBUG(1, (CE_NOTE, NULL, 151 "!vhci_tpgs_set_target_groups:" 152 " sense_key:%x, add_code: %x, qual_code:%x" 153 " sense:%x\n", sns->es_key, sns->es_add_code, 154 sns->es_qual_code, rval)); 155 } else { 156 /* 157 * At this point sns data may be for power-on-reset 158 * UNIT ATTN hardware errors, vendor unqiue sense etc. 159 * For all these cases, sense is unknown. 160 */ 161 ss = SCSI_SENSE_NOFAILOVER; 162 VHCI_DEBUG(1, (CE_NOTE, NULL, 163 "!vhci_tpgs_set_target_groups: " 164 " sense UNKNOWN: sense key:%x, ASC:%x, ASCQ:%x\n", 165 sns->es_key, sns->es_add_code, sns->es_qual_code)); 166 } 167 168 if (ss == SCSI_SENSE_STATE_CHANGED) { 169 freerbuf(bp); 170 kmem_free((void *)bufp, len); 171 scsi_destroy_pkt(pkt); 172 return (0); 173 } 174 } 175 176 freerbuf(bp); 177 kmem_free((void *)bufp, len); 178 scsi_destroy_pkt(pkt); 179 return (1); 180 } 181 182 /* 183 * get the failover mode, ownership and if it has extended failover 184 * capability. The mode(bits5-4/byte5) is defined as implicit, explicit, or 185 * both. The state is defined as online-optimized(0h), 186 * online-nonoptimized(1h), standby(2h), offline(3h), 187 * and transitioning(fh). Currently, there is online, 188 * standby, and offline(defined in sunmdi.h). 189 * Online-nonoptimized will be a mode of secondary 190 * and an ownership of online. Thought about using a different mode but 191 * it appears the states are really for the states for secondary mode. 192 * We currently have IS_ONLINING, IS_OFFLINING - should we have TRANSITIONING 193 * to mean from online-optimized to online-nonoptimized or does onlining 194 * cover this? 195 */ 196 /* ARGSUSED */ 197 int 198 vhci_tpgs_get_target_fo_mode(struct scsi_device *sd, int *mode, 199 int *state, int *xlf_capable, int *preferred) 200 { 201 int retval = 0; 202 struct buf *bp; 203 struct scsi_address *ap; 204 int lu = 0, rel_tgt_port = 0, tgt_port = 0x0; 205 206 VHCI_DEBUG(6, (CE_NOTE, NULL, 207 "!vhci_tpgs_get_target_fo_mode: enter\n")); 208 *mode = *state = *xlf_capable = 0; 209 bp = getrbuf(KM_NOSLEEP); 210 if (bp == NULL) { 211 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_get_target_fo_mode: " 212 " failed getrbuf\n")); 213 return (1); 214 } 215 216 ap = &sd->sd_address; 217 if (vhci_tpgs_inquiry(ap, bp, mode)) { 218 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_get_target_fo_mode: " 219 " failed vhci_tpgs_inquiry\n")); 220 retval = 1; 221 } else if (vhci_tpgs_page83(ap, bp, &rel_tgt_port, &tgt_port, &lu)) { 222 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_get_target_fo_mode: " 223 " failed vhci_tpgs_page83\n")); 224 retval = 1; 225 } else if (vhci_tpgs_report_target_groups(ap, bp, rel_tgt_port, 226 tgt_port, state, preferred)) { 227 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_get_target_fo_mode: " 228 " failed vhci_tpgs_report_target_groups\n")); 229 retval = 1; 230 } 231 232 freerbuf(bp); 233 if (retval == 0) { 234 VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_tpgs_get_target_fo_mode: " 235 "SUCCESS\n")); 236 } 237 return (retval); 238 } 239 240 static int 241 vhci_tpgs_inquiry(struct scsi_address *ap, struct buf *bp, int *mode) 242 { 243 struct scsi_pkt *pkt; 244 struct scsi_inquiry inq; 245 int retval; 246 247 *mode = 0; 248 bp->b_un.b_addr = (caddr_t)&inq; 249 bp->b_flags = B_READ; 250 bp->b_bcount = sizeof (inq); 251 bp->b_resid = 0; 252 253 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 254 sizeof (struct scsi_arq_status), 0, 0, SLEEP_FUNC, NULL); 255 pkt->pkt_cdbp[0] = SCMD_INQUIRY; 256 pkt->pkt_cdbp[4] = sizeof (inq); 257 pkt->pkt_time = 60; 258 259 retval = vhci_do_scsi_cmd(pkt); 260 scsi_destroy_pkt(pkt); 261 if (retval == 0) { 262 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_inquiry: Failure" 263 " returned from vhci_do_scsi_cmd")); 264 return (1); 265 } 266 267 if (inq.inq_tpgs == TPGS_FAILOVER_NONE) { 268 VHCI_DEBUG(1, (CE_WARN, NULL, 269 "!vhci_tpgs_inquiry: zero tpgs_bits")); 270 return (1); 271 } 272 retval = 0; 273 if (inq.inq_tpgs == TPGS_FAILOVER_IMPLICIT) { 274 *mode = SCSI_IMPLICIT_FAILOVER; 275 } else if (inq.inq_tpgs == TPGS_FAILOVER_EXPLICIT) { 276 *mode = SCSI_EXPLICIT_FAILOVER; 277 } else if (inq.inq_tpgs == TPGS_FAILOVER_BOTH) { 278 *mode = SCSI_BOTH_FAILOVER; 279 } else { 280 VHCI_DEBUG(1, (CE_WARN, NULL, 281 "!vhci_tpgs_inquiry: Illegal mode returned: %x mode: %x", 282 inq.inq_tpgs, *mode)); 283 retval = 1; 284 } 285 286 return (retval); 287 } 288 289 static int 290 vhci_tpgs_page83(struct scsi_address *ap, struct buf *bp, 291 int *rel_tgt_port, int *tgt_port, int *lu) 292 { 293 char *ptr, *end; 294 struct scsi_pkt *pkt; 295 char *bufp; 296 unsigned int buf_len, rx_bsize; 297 298 /* 299 * lets start the buf size with 512 bytes. If this 300 * if found to be insufficient, we can allocate 301 * appropriate size in the next iteration. 302 */ 303 buf_len = 512; 304 305 once_again: 306 bufp = kmem_zalloc(buf_len, KM_NOSLEEP); 307 if (bufp == NULL) { 308 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_page83: " 309 "request packet allocation for %d failed....", 310 buf_len)); 311 return (1); 312 } 313 314 315 bp->b_un.b_addr = bufp; 316 bp->b_flags = B_READ; 317 bp->b_bcount = buf_len; 318 bp->b_resid = 0; 319 320 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 321 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 322 if (pkt == NULL) { 323 VHCI_DEBUG(1, (CE_WARN, NULL, 324 "!vhci_tpgs_page83: Failure returned from scsi_init_pkt")); 325 kmem_free((void *)bufp, buf_len); 326 return (1); 327 } 328 329 pkt->pkt_cdbp[0] = SCMD_INQUIRY; 330 pkt->pkt_cdbp[1] = 0x1; 331 pkt->pkt_cdbp[2] = 0x83; 332 pkt->pkt_cdbp[3] = (unsigned char)((buf_len >> 8) & 0xff); 333 pkt->pkt_cdbp[4] = (unsigned char)(buf_len & 0xff); 334 pkt->pkt_time = 90; 335 336 if (vhci_do_scsi_cmd(pkt) == 0) { 337 VHCI_DEBUG(1, (CE_NOTE, NULL, 338 "!vhci_tpgs_page83: vhci_do_scsi_cmd failed\n")); 339 kmem_free((void *)bufp, buf_len); 340 scsi_destroy_pkt(pkt); 341 return (1); 342 } 343 344 /* 345 * Now lets check if the size that was provided was 346 * sufficient. If not, allocate the appropriate size 347 * and retry the command again. 348 */ 349 rx_bsize = (((bufp[2] & 0xff) << 8) | (bufp[3] & 0xff)); 350 rx_bsize += 4; 351 if (rx_bsize > buf_len) { 352 /* 353 * Need to allocate more buf and retry again 354 */ 355 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_page83: " 356 "bufsize: %d greater than allocated buf: %d\n", 357 rx_bsize, buf_len)); 358 VHCI_DEBUG(1, (CE_NOTE, NULL, "Retrying for size %d\n", 359 rx_bsize)); 360 kmem_free((void *)bufp, buf_len); 361 buf_len = (unsigned int)(rx_bsize); 362 goto once_again; 363 } 364 365 ptr = bufp; 366 ptr += 4; /* identification descriptor 0 */ 367 end = bufp + rx_bsize; 368 while (ptr < end) { 369 VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_tpgs_page83: " 370 "desc[1/4/5/6/7]:%x %x %x %x %x\n", 371 ptr[1], ptr[4], ptr[5], ptr[6], ptr[7])); 372 if ((ptr[1] & 0x0f) == 0x04) { 373 *rel_tgt_port = 0; 374 *rel_tgt_port |= ((ptr[6] & 0xff) << 8); 375 *rel_tgt_port |= (ptr[7] & 0xff); 376 VHCI_DEBUG(1, (CE_NOTE, NULL, 377 "!vhci_tpgs_page83: relative target port: %x\n", 378 *rel_tgt_port)); 379 } else if ((ptr[1] & 0x0f) == 0x05) { 380 *tgt_port = 0; 381 *tgt_port = ((ptr[6] & 0xff) << 8); 382 *tgt_port |= (ptr[7] & 0xff); 383 VHCI_DEBUG(1, (CE_NOTE, NULL, 384 "!vhci_tpgs_page83: target port: %x\n", *tgt_port)); 385 } else if ((ptr[1] & 0x0f) == 0x06) { 386 *lu = 0; 387 *lu |= ((ptr[6] & 0xff)<< 8); 388 *lu |= (ptr[7] & 0xff); 389 VHCI_DEBUG(1, (CE_NOTE, NULL, 390 "!vhci_tpgs_page83: logical unit: %x\n", *lu)); 391 } 392 ptr += ptr[3] + 4; /* next identification descriptor */ 393 } 394 kmem_free((void *)bufp, buf_len); 395 scsi_destroy_pkt(pkt); 396 return (0); 397 } 398 399 #ifdef DEBUG 400 static void 401 print_buf(char *buf, int buf_size) 402 { 403 int i = 0, j; 404 int loop, left; 405 406 loop = buf_size / 8; 407 left = buf_size % 8; 408 409 VHCI_DEBUG(4, (CE_NOTE, NULL, "!buf_size: %x loop: %x left: %x", 410 buf_size, loop, left)); 411 412 for (j = 0; j < loop; j++) { 413 VHCI_DEBUG(4, (CE_NOTE, NULL, 414 "!buf[%d-%d]: %x %x %x %x %x %x %x %x", 415 i, i + 7, buf[i], buf[i+1], buf[i+2], buf[i+3], 416 buf[i+4], buf[i+5], buf[i+6], buf[i+7])); 417 i += 8; 418 } 419 420 if (left) { 421 VHCI_DEBUG(4, (CE_CONT, NULL, 422 "NOTICE: buf[%d-%d]:", i, i + left)); 423 for (j = 0; j < left; j++) { 424 VHCI_DEBUG(4, (CE_CONT, NULL, " %x", buf[i + j])); 425 } 426 VHCI_DEBUG(4, (CE_CONT, NULL, "\n")); 427 } 428 } 429 #endif 430 431 static int 432 vhci_tpgs_report_target_groups(struct scsi_address *ap, struct buf *bp, 433 int rel_tgt_port, int tgt_port, int *pstate, int *preferred) 434 { 435 struct scsi_pkt *pkt; 436 char *ptr, *end, *bufp, *mpapi_ptr; 437 unsigned int rtpg_len = 0; 438 unsigned int l_tgt_port = 0, tpgs_state = 0; 439 unsigned int tgt_port_cnt = 0, lr_tgt_port = 0; 440 int i, len; 441 442 /* 443 * Start with buffer size of 512. 444 * If this is found to be insufficient, required size 445 * will be allocated and the command will be retried. 446 */ 447 len = 512; 448 449 try_again: 450 bufp = kmem_zalloc(len, KM_NOSLEEP); 451 if (bufp == NULL) { 452 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_report_target_groups:" 453 " request packet allocation for %d failed....", len)); 454 return (1); 455 } 456 457 bp->b_un.b_addr = bufp; 458 bp->b_flags = B_READ; 459 bp->b_bcount = len; 460 bp->b_resid = 0; 461 462 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP5, 463 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 464 465 if (pkt == NULL) { 466 VHCI_DEBUG(1, (CE_NOTE, NULL, 467 "!vhci_tpgs_report_target_groups: scsi_init_pkt error\n")); 468 kmem_free((void *)bufp, len); 469 return (1); 470 } 471 472 pkt->pkt_cdbp[0] = SCMD_MAINTENANCE_IN; 473 pkt->pkt_cdbp[1] = SSVC_ACTION_GET_TARGET_PORT_GROUPS; 474 pkt->pkt_cdbp[6] = ((len >> 24) & 0xff); 475 pkt->pkt_cdbp[7] = ((len >> 16) & 0xff); 476 pkt->pkt_cdbp[8] = ((len >> 8) & 0xff); 477 pkt->pkt_cdbp[9] = len & 0xff; 478 pkt->pkt_time = 90; 479 480 VHCI_DEBUG(6, (CE_NOTE, NULL, 481 "!vhci_tpgs_report_target_groups: sending target port group:" 482 " cdb[6/7/8/9]: %x/%x/%x/%x\n", pkt->pkt_cdbp[6], 483 pkt->pkt_cdbp[7], pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); 484 if (vhci_do_scsi_cmd(pkt) == 0) { 485 VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_tpgs_report_target_groups:" 486 " vhci_do_scsi_cmd failed\n")); 487 kmem_free((void *)bufp, len); 488 scsi_destroy_pkt(pkt); 489 return (1); 490 } 491 ptr = bufp; 492 VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_tpgs_report_target_groups:" 493 " returned from target" 494 " port group: buf[0/1/2/3]: %x/%x/%x/%x\n", 495 ptr[0], ptr[1], ptr[2], ptr[3])); 496 rtpg_len = (unsigned int)((0xff & ptr[0]) << 24); 497 rtpg_len |= (unsigned int)((0xff & ptr[1]) << 16); 498 rtpg_len |= (unsigned int)((0xff & ptr[2]) << 8); 499 rtpg_len |= (unsigned int)(0xff & ptr[3]); 500 rtpg_len += 4; 501 if (rtpg_len > len) { 502 VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_tpgs_report_target_groups:" 503 " bufsize: %d greater than allocated buf: %d\n", 504 rtpg_len, len)); 505 VHCI_DEBUG(4, (CE_NOTE, NULL, "Retrying for size %d\n", 506 rtpg_len)); 507 kmem_free((void *)bufp, len); 508 len = (unsigned int)(rtpg_len + 1); 509 goto try_again; 510 } 511 #ifdef DEBUG 512 print_buf(bufp, rtpg_len); 513 #endif 514 end = ptr + rtpg_len; 515 ptr += 4; 516 while (ptr < end) { 517 mpapi_ptr = ptr; 518 l_tgt_port = ((ptr[2] & 0xff) << 8) + (ptr[3] & 0xff); 519 tpgs_state = ptr[0] & 0x0f; 520 tgt_port_cnt = (ptr[7] & 0xff); 521 VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_tpgs_report_tgt_groups:" 522 " tpgs state: %x" 523 " tgt_group: %x count: %x\n", tpgs_state, 524 l_tgt_port, tgt_port_cnt)); 525 ptr += 8; 526 for (i = 0; i < tgt_port_cnt; i++) { 527 lr_tgt_port = 0; 528 lr_tgt_port |= ((ptr[2] & 0Xff) << 8); 529 lr_tgt_port |= (ptr[3] & 0xff); 530 531 if ((lr_tgt_port == rel_tgt_port) && 532 (l_tgt_port == tgt_port)) { 533 VHCI_DEBUG(4, (CE_NOTE, NULL, 534 "!vhci_tpgs_report_tgt_groups:" 535 " found tgt_port: %x rel_tgt_port:%x" 536 " tpgs_state: %x\n", tgt_port, rel_tgt_port, 537 tpgs_state)); 538 /* 539 * once we have the preferred flag 540 * and a non-optimized state flag 541 * we will get preferred flag from the 542 * report target groups 543 */ 544 if (tpgs_state == STD_ACTIVE_OPTIMIZED) { 545 *pstate = STD_ACTIVE_OPTIMIZED; 546 *preferred = PCLASS_PREFERRED; 547 } else if (tpgs_state == 548 STD_ACTIVE_NONOPTIMIZED) { 549 *pstate = STD_ACTIVE_NONOPTIMIZED; 550 *preferred = PCLASS_NONPREFERRED; 551 } else if (tpgs_state == STD_STANDBY) { 552 *pstate = STD_STANDBY; 553 *preferred = PCLASS_NONPREFERRED; 554 } else { 555 *pstate = STD_UNAVAILABLE; 556 *preferred = PCLASS_NONPREFERRED; 557 } 558 vhci_mpapi_update_tpg_data(ap, mpapi_ptr); 559 kmem_free((void *)bufp, len); 560 scsi_destroy_pkt(pkt); 561 return (0); 562 } 563 VHCI_DEBUG(4, (CE_NOTE, NULL, 564 "!vhci_tpgs_report_tgt_groups:" 565 " tgt_port: %x rel_tgt_port:%x\n", tgt_port, 566 rel_tgt_port)); 567 ptr += 4; 568 } 569 } 570 *pstate = SCSI_PATH_INACTIVE; 571 *preferred = PCLASS_NONPREFERRED; 572 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_report_tgt_groups: " 573 "NO rel_TGTPRT MATCH!!! Assigning Default: state: %x " 574 "preferred: %d\n", *pstate, *preferred)); 575 kmem_free((void *)bufp, len); 576 scsi_destroy_pkt(pkt); 577 return (1); 578 } 579