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