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