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 pkt->pkt_cdbp[0] = SCMD_INQUIRY; 263 pkt->pkt_cdbp[4] = sizeof (inq); 264 pkt->pkt_time = 60; 265 266 retval = vhci_do_scsi_cmd(pkt); 267 scsi_destroy_pkt(pkt); 268 if (retval == 0) { 269 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_inquiry: Failure" 270 " returned from vhci_do_scsi_cmd")); 271 return (1); 272 } 273 274 if (inq.inq_tpgs == TPGS_FAILOVER_NONE) { 275 VHCI_DEBUG(1, (CE_WARN, NULL, 276 "!vhci_tpgs_inquiry: zero tpgs_bits")); 277 return (1); 278 } 279 retval = 0; 280 if (inq.inq_tpgs == TPGS_FAILOVER_IMPLICIT) { 281 *mode = SCSI_IMPLICIT_FAILOVER; 282 } else if (inq.inq_tpgs == TPGS_FAILOVER_EXPLICIT) { 283 *mode = SCSI_EXPLICIT_FAILOVER; 284 } else if (inq.inq_tpgs == TPGS_FAILOVER_BOTH) { 285 *mode = SCSI_BOTH_FAILOVER; 286 } else { 287 VHCI_DEBUG(1, (CE_WARN, NULL, 288 "!vhci_tpgs_inquiry: Illegal mode returned: %x mode: %x", 289 inq.inq_tpgs, *mode)); 290 retval = 1; 291 } 292 293 return (retval); 294 } 295 296 static int 297 vhci_tpgs_page83(struct scsi_address *ap, struct buf *bp, 298 int *rel_tgt_port, int *tgt_port, int *lu) 299 { 300 char *ptr, *end; 301 struct scsi_pkt *pkt; 302 char *bufp; 303 unsigned int buf_len, rx_bsize; 304 305 /* 306 * lets start the buf size with 512 bytes. If this 307 * if found to be insufficient, we can allocate 308 * appropriate size in the next iteration. 309 */ 310 buf_len = 512; 311 312 once_again: 313 bufp = kmem_zalloc(buf_len, KM_NOSLEEP); 314 if (bufp == NULL) { 315 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_page83: " 316 "request packet allocation for %d failed....", 317 buf_len)); 318 return (1); 319 } 320 321 322 bp->b_un.b_addr = bufp; 323 bp->b_flags = B_READ; 324 bp->b_bcount = buf_len; 325 bp->b_resid = 0; 326 327 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 328 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 329 if (pkt == NULL) { 330 VHCI_DEBUG(1, (CE_WARN, NULL, 331 "!vhci_tpgs_page83: Failure returned from scsi_init_pkt")); 332 kmem_free((void *)bufp, buf_len); 333 return (1); 334 } 335 336 pkt->pkt_cdbp[0] = SCMD_INQUIRY; 337 pkt->pkt_cdbp[1] = 0x1; 338 pkt->pkt_cdbp[2] = 0x83; 339 pkt->pkt_cdbp[3] = (unsigned char)((buf_len >> 8) & 0xff); 340 pkt->pkt_cdbp[4] = (unsigned char)(buf_len & 0xff); 341 pkt->pkt_time = 90; 342 343 if (vhci_do_scsi_cmd(pkt) == 0) { 344 VHCI_DEBUG(1, (CE_NOTE, NULL, 345 "!vhci_tpgs_page83: vhci_do_scsi_cmd failed\n")); 346 kmem_free((void *)bufp, buf_len); 347 scsi_destroy_pkt(pkt); 348 return (1); 349 } 350 351 /* 352 * Now lets check if the size that was provided was 353 * sufficient. If not, allocate the appropriate size 354 * and retry the command again. 355 */ 356 rx_bsize = (((bufp[2] & 0xff) << 8) | (bufp[3] & 0xff)); 357 rx_bsize += 4; 358 if (rx_bsize > buf_len) { 359 /* 360 * Need to allocate more buf and retry again 361 */ 362 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_page83: " 363 "bufsize: %d greater than allocated buf: %d\n", 364 rx_bsize, buf_len)); 365 VHCI_DEBUG(1, (CE_NOTE, NULL, "Retrying for size %d\n", 366 rx_bsize)); 367 kmem_free((void *)bufp, buf_len); 368 buf_len = (unsigned int)(rx_bsize); 369 goto once_again; 370 } 371 372 ptr = bufp; 373 ptr += 4; /* identification descriptor 0 */ 374 end = bufp + rx_bsize; 375 while (ptr < end) { 376 VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_tpgs_page83: " 377 "desc[1/4/5/6/7]:%x %x %x %x %x\n", 378 ptr[1], ptr[4], ptr[5], ptr[6], ptr[7])); 379 if ((ptr[1] & 0x0f) == 0x04) { 380 *rel_tgt_port = 0; 381 *rel_tgt_port |= ((ptr[6] & 0xff) << 8); 382 *rel_tgt_port |= (ptr[7] & 0xff); 383 VHCI_DEBUG(1, (CE_NOTE, NULL, 384 "!vhci_tpgs_page83: relative target port: %x\n", 385 *rel_tgt_port)); 386 } else if ((ptr[1] & 0x0f) == 0x05) { 387 *tgt_port = 0; 388 *tgt_port = ((ptr[6] & 0xff) << 8); 389 *tgt_port |= (ptr[7] & 0xff); 390 VHCI_DEBUG(1, (CE_NOTE, NULL, 391 "!vhci_tpgs_page83: target port: %x\n", *tgt_port)); 392 } else if ((ptr[1] & 0x0f) == 0x06) { 393 *lu = 0; 394 *lu |= ((ptr[6] & 0xff)<< 8); 395 *lu |= (ptr[7] & 0xff); 396 VHCI_DEBUG(1, (CE_NOTE, NULL, 397 "!vhci_tpgs_page83: logical unit: %x\n", *lu)); 398 } 399 ptr += ptr[3] + 4; /* next identification descriptor */ 400 } 401 kmem_free((void *)bufp, buf_len); 402 scsi_destroy_pkt(pkt); 403 return (0); 404 } 405 406 #ifdef DEBUG 407 static void 408 print_buf(char *buf, int buf_size) 409 { 410 int i = 0, j; 411 int loop, left; 412 413 loop = buf_size / 8; 414 left = buf_size % 8; 415 416 VHCI_DEBUG(4, (CE_NOTE, NULL, "!buf_size: %x loop: %x left: %x", 417 buf_size, loop, left)); 418 419 for (j = 0; j < loop; j++) { 420 VHCI_DEBUG(4, (CE_NOTE, NULL, 421 "!buf[%d-%d]: %x %x %x %x %x %x %x %x", 422 i, i + 7, buf[i], buf[i+1], buf[i+2], buf[i+3], 423 buf[i+4], buf[i+5], buf[i+6], buf[i+7])); 424 i += 8; 425 } 426 427 if (left) { 428 VHCI_DEBUG(4, (CE_CONT, NULL, 429 "NOTICE: buf[%d-%d]:", i, i + left)); 430 for (j = 0; j < left; j++) { 431 VHCI_DEBUG(4, (CE_CONT, NULL, " %x", buf[i + j])); 432 } 433 VHCI_DEBUG(4, (CE_CONT, NULL, "\n")); 434 } 435 } 436 #endif 437 438 static int 439 vhci_tpgs_report_target_groups(struct scsi_address *ap, struct buf *bp, 440 int rel_tgt_port, int tgt_port, int *pstate, int *preferred) 441 { 442 struct scsi_pkt *pkt; 443 char *ptr, *end, *bufp, *mpapi_ptr; 444 unsigned int rtpg_len = 0; 445 unsigned int l_tgt_port = 0, tpgs_state = 0; 446 unsigned int tgt_port_cnt = 0, lr_tgt_port = 0; 447 int i, len; 448 449 /* 450 * Start with buffer size of 512. 451 * If this is found to be insufficient, required size 452 * will be allocated and the command will be retried. 453 */ 454 len = 512; 455 456 try_again: 457 bufp = kmem_zalloc(len, KM_NOSLEEP); 458 if (bufp == NULL) { 459 VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_tpgs_report_target_groups:" 460 " request packet allocation for %d failed....", len)); 461 return (1); 462 } 463 464 bp->b_un.b_addr = bufp; 465 bp->b_flags = B_READ; 466 bp->b_bcount = len; 467 bp->b_resid = 0; 468 469 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP5, 470 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 471 472 if (pkt == NULL) { 473 VHCI_DEBUG(1, (CE_NOTE, NULL, 474 "!vhci_tpgs_report_target_groups: scsi_init_pkt error\n")); 475 kmem_free((void *)bufp, len); 476 return (1); 477 } 478 479 pkt->pkt_cdbp[0] = SCMD_MAINTENANCE_IN; 480 pkt->pkt_cdbp[1] = SSVC_ACTION_GET_TARGET_PORT_GROUPS; 481 pkt->pkt_cdbp[6] = ((len >> 24) & 0xff); 482 pkt->pkt_cdbp[7] = ((len >> 16) & 0xff); 483 pkt->pkt_cdbp[8] = ((len >> 8) & 0xff); 484 pkt->pkt_cdbp[9] = len & 0xff; 485 pkt->pkt_time = 90; 486 487 VHCI_DEBUG(6, (CE_NOTE, NULL, 488 "!vhci_tpgs_report_target_groups: sending target port group:" 489 " cdb[6/7/8/9]: %x/%x/%x/%x\n", pkt->pkt_cdbp[6], 490 pkt->pkt_cdbp[7], pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); 491 if (vhci_do_scsi_cmd(pkt) == 0) { 492 VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_tpgs_report_target_groups:" 493 " vhci_do_scsi_cmd failed\n")); 494 kmem_free((void *)bufp, len); 495 scsi_destroy_pkt(pkt); 496 return (1); 497 } 498 ptr = bufp; 499 VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_tpgs_report_target_groups:" 500 " returned from target" 501 " port group: buf[0/1/2/3]: %x/%x/%x/%x\n", 502 ptr[0], ptr[1], ptr[2], ptr[3])); 503 rtpg_len = (unsigned int)((0xff & ptr[0]) << 24); 504 rtpg_len |= (unsigned int)((0xff & ptr[1]) << 16); 505 rtpg_len |= (unsigned int)((0xff & ptr[2]) << 8); 506 rtpg_len |= (unsigned int)(0xff & ptr[3]); 507 rtpg_len += 4; 508 if (rtpg_len > len) { 509 VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_tpgs_report_target_groups:" 510 " bufsize: %d greater than allocated buf: %d\n", 511 rtpg_len, len)); 512 VHCI_DEBUG(4, (CE_NOTE, NULL, "Retrying for size %d\n", 513 rtpg_len)); 514 kmem_free((void *)bufp, len); 515 len = (unsigned int)(rtpg_len + 1); 516 goto try_again; 517 } 518 #ifdef DEBUG 519 print_buf(bufp, rtpg_len); 520 #endif 521 end = ptr + rtpg_len; 522 ptr += 4; 523 while (ptr < end) { 524 mpapi_ptr = ptr; 525 l_tgt_port = ((ptr[2] & 0xff) << 8) + (ptr[3] & 0xff); 526 tpgs_state = ptr[0] & 0x0f; 527 tgt_port_cnt = (ptr[7] & 0xff); 528 VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_tpgs_report_tgt_groups:" 529 " tpgs state: %x" 530 " tgt_group: %x count: %x\n", tpgs_state, 531 l_tgt_port, tgt_port_cnt)); 532 ptr += 8; 533 for (i = 0; i < tgt_port_cnt; i++) { 534 lr_tgt_port = 0; 535 lr_tgt_port |= ((ptr[2] & 0Xff) << 8); 536 lr_tgt_port |= (ptr[3] & 0xff); 537 538 if ((lr_tgt_port == rel_tgt_port) && 539 (l_tgt_port == tgt_port)) { 540 VHCI_DEBUG(4, (CE_NOTE, NULL, 541 "!vhci_tpgs_report_tgt_groups:" 542 " found tgt_port: %x rel_tgt_port:%x" 543 " tpgs_state: %x\n", tgt_port, rel_tgt_port, 544 tpgs_state)); 545 /* 546 * once we have the preferred flag 547 * and a non-optimized state flag 548 * we will get preferred flag from the 549 * report target groups 550 */ 551 if (tpgs_state == STD_ACTIVE_OPTIMIZED) { 552 *pstate = STD_ACTIVE_OPTIMIZED; 553 *preferred = PCLASS_PREFERRED; 554 } else if (tpgs_state == 555 STD_ACTIVE_NONOPTIMIZED) { 556 *pstate = STD_ACTIVE_NONOPTIMIZED; 557 *preferred = PCLASS_NONPREFERRED; 558 } else if (tpgs_state == STD_STANDBY) { 559 *pstate = STD_STANDBY; 560 *preferred = PCLASS_NONPREFERRED; 561 } else { 562 *pstate = STD_UNAVAILABLE; 563 *preferred = PCLASS_NONPREFERRED; 564 } 565 vhci_mpapi_update_tpg_data(ap, mpapi_ptr, 566 rel_tgt_port); 567 kmem_free((void *)bufp, len); 568 scsi_destroy_pkt(pkt); 569 return (0); 570 } 571 VHCI_DEBUG(4, (CE_NOTE, NULL, 572 "!vhci_tpgs_report_tgt_groups:" 573 " tgt_port: %x rel_tgt_port:%x\n", tgt_port, 574 rel_tgt_port)); 575 ptr += 4; 576 } 577 } 578 *pstate = SCSI_PATH_INACTIVE; 579 *preferred = PCLASS_NONPREFERRED; 580 VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_tpgs_report_tgt_groups: " 581 "NO rel_TGTPRT MATCH!!! Assigning Default: state: %x " 582 "preferred: %d\n", *pstate, *preferred)); 583 kmem_free((void *)bufp, len); 584 scsi_destroy_pkt(pkt); 585 return (1); 586 } 587