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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 /* 28 * Implementation of "scsi_vhci_f_tpgs" T10 standard based failover_ops. 29 * 30 * NOTE: for non-sequential devices only. 31 */ 32 33 #include <sys/conf.h> 34 #include <sys/file.h> 35 #include <sys/ddi.h> 36 #include <sys/sunddi.h> 37 #include <sys/scsi/scsi.h> 38 #include <sys/scsi/adapters/scsi_vhci.h> 39 40 /* Supported device table entries. */ 41 char *std_dev_table[] = { NULL }; 42 43 /* Failover module plumbing. */ 44 SCSI_FAILOVER_OP(SFO_NAME_TPGS, std, "%I%"); 45 46 #define STD_SCSI_CMD_LEN 0xff 47 48 #define STD_FO_CMD_RETRY_DELAY 1000000 /* 1 seconds */ 49 #define STD_FO_RETRY_DELAY 2000000 /* 2 seconds */ 50 /* 51 * max time for failover to complete is 3 minutes. Compute 52 * number of retries accordingly, to ensure we wait for at least 53 * 3 minutes 54 */ 55 #define STD_FO_MAX_RETRIES (3*60*1000000)/STD_FO_RETRY_DELAY 56 57 /* 58 * max number of retries for std failover to complete where the ping 59 * command is failing due to transport errors or commands being rejected by 60 * std. 61 * STD_FO_MAX_RETRIES takes into account the case where CMD_CMPLTs but 62 * std takes time to complete the failover. 63 */ 64 #define STD_FO_MAX_CMD_RETRIES 3 65 66 #define STD_ACTIVE_OPTIMIZED 0x0 67 #define STD_ACTIVE_NONOPTIMIZED 0x1 68 #define STD_STANDBY 0x2 69 #define STD_UNAVAILABLE 0x3 70 #define STD_TRANSITIONING 0xf 71 72 #define STD_SCSI_TPG_SERVICE_ACTION 0x0A 73 #define STD_SCSI_ASC_STATE_TRANS 0x04 74 #define STD_SCSI_ASCQ_STATE_TRANS_FAIL 0x0A 75 #define STD_SCSI_ASC_STATE_CHG 0x2A 76 #define STD_SCSI_ASCQ_STATE_CHG_SUCC 0x06 77 #define STD_SCSI_ASCQ_STATE_CHG_FAILED 0x07 78 #define STD_SCSI_ASC_INVAL_PARAM_LIST 0x26 79 #define STD_SCSI_ASC_INVAL_CMD_OPCODE 0x20 80 #define STD_LOGICAL_UNIT_NOT_ACCESSIBLE 0x04 81 #define STD_TGT_PORT_UNAVAILABLE 0x0C 82 83 #define SCMD_REPORT_TARGET_PORT_GROUP 0xA3; 84 #define SCMD_SET_TARGET_PORT_GROUP 0xA4; 85 86 /* Special exported for direct use by MP-API */ 87 int std_set_target_groups(struct scsi_address *, int, int); 88 89 /* 90 * External function definitions 91 */ 92 extern void vhci_mpapi_update_tpg_data(struct scsi_address *, char *); 93 94 static int std_get_fo_mode(struct scsi_device *, 95 int *, int *, int *, int *); 96 static int std_report_target_groups(struct scsi_address *, struct buf *, 97 int, int, int *, int *); 98 99 /* ARGSUSED */ 100 static int 101 std_device_probe(struct scsi_device *sd, struct scsi_inquiry *inq, 102 void **ctpriv) 103 { 104 unsigned int tpgs_bits; 105 unsigned char *inqbuf = (unsigned char *)inq; 106 unsigned char dtype = (inq->inq_dtype & DTYPE_MASK); 107 108 int mode, state, xlf, preferred = 0; 109 110 VHCI_DEBUG(6, (CE_NOTE, NULL, "std_device_probe: vidpid %s\n", 111 inq->inq_vid)); 112 113 tpgs_bits = ((inqbuf[5] & 0x30) >> 4); 114 115 if (tpgs_bits == 0) { 116 VHCI_DEBUG(4, (CE_WARN, NULL, 117 "!std_device_probe: not a standard tpgs device")); 118 return (SFO_DEVICE_PROBE_PHCI); 119 } 120 121 if (dtype == DTYPE_SEQUENTIAL) { 122 VHCI_DEBUG(4, (CE_NOTE, NULL, 123 "!std_device_probe: Detected a " 124 "Standard Asymmetric device " 125 "not yet supported\n")); 126 return (SFO_DEVICE_PROBE_PHCI); 127 } 128 129 if (std_get_fo_mode(sd, &mode, &state, &xlf, &preferred)) { 130 VHCI_DEBUG(4, (CE_WARN, NULL, "!unable to fetch fo " 131 "mode: sd(%p)", (void *) sd)); 132 return (SFO_DEVICE_PROBE_PHCI); 133 } 134 135 if (tpgs_bits == SCSI_IMPLICIT_FAILOVER) { 136 VHCI_DEBUG(1, (CE_NOTE, NULL, 137 "!std_device_probe: Detected a " 138 "Standard Asymmetric device " 139 "with implicit failover\n")); 140 return (SFO_DEVICE_PROBE_VHCI); 141 } 142 if (tpgs_bits == SCSI_EXPLICIT_FAILOVER) { 143 VHCI_DEBUG(1, (CE_NOTE, NULL, 144 "!std_device_probe: Detected a " 145 "Standard Asymmetric device " 146 "with explicit failover\n")); 147 return (SFO_DEVICE_PROBE_VHCI); 148 } 149 if (tpgs_bits == SCSI_BOTH_FAILOVER) { 150 VHCI_DEBUG(1, (CE_NOTE, NULL, 151 "!std_device_probe: Detected a " 152 "Standard Asymmetric device " 153 "which supports both implicit and explicit failover\n")); 154 return (SFO_DEVICE_PROBE_VHCI); 155 } 156 VHCI_DEBUG(1, (CE_WARN, NULL, 157 "!std_device_probe: " 158 "Unknown tpgs_bits: %x", tpgs_bits)); 159 return (SFO_DEVICE_PROBE_PHCI); 160 } 161 162 /* ARGSUSED */ 163 static void 164 std_device_unprobe(struct scsi_device *sd, void *ctpriv) 165 { 166 /* 167 * For future use 168 */ 169 } 170 171 static int 172 std_inquiry(struct scsi_address *ap, struct buf *bp, int *mode) 173 { 174 struct scsi_pkt *pkt; 175 char buf[STD_SCSI_CMD_LEN]; 176 int buf_size = sizeof (buf); 177 unsigned int tpgs_bits; 178 int retval; 179 180 *mode = 0; 181 bp->b_un.b_addr = (caddr_t)&buf; 182 bp->b_flags = B_READ; 183 bp->b_bcount = buf_size; 184 bp->b_resid = 0; 185 186 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 187 sizeof (struct scsi_arq_status), 0, 0, SLEEP_FUNC, NULL); 188 pkt->pkt_cdbp[0] = SCMD_INQUIRY; 189 pkt->pkt_cdbp[4] = (unsigned char)buf_size; 190 pkt->pkt_time = 60; 191 192 retval = vhci_do_scsi_cmd(pkt); 193 scsi_destroy_pkt(pkt); 194 if (retval == 0) { 195 VHCI_DEBUG(1, (CE_WARN, NULL, 196 "!std_inquiry: Failure returned from vhci_do_scsi_cmd")); 197 return (1); 198 } 199 200 tpgs_bits = ((buf[5] & 0x30) >> 4); 201 if (tpgs_bits == 0) { 202 VHCI_DEBUG(1, (CE_WARN, NULL, 203 "!std_inquiry: zero tpgs_bits")); 204 return (1); 205 } 206 retval = 0; 207 if (tpgs_bits == SCSI_IMPLICIT_FAILOVER) { 208 *mode = SCSI_IMPLICIT_FAILOVER; 209 } else if (tpgs_bits == SCSI_EXPLICIT_FAILOVER) { 210 *mode = SCSI_EXPLICIT_FAILOVER; 211 } else if (tpgs_bits == SCSI_BOTH_FAILOVER) { 212 *mode = SCSI_BOTH_FAILOVER; 213 } else { 214 VHCI_DEBUG(1, (CE_WARN, NULL, 215 "!std_inquiry: Illegal mode returned: %x mode: %x", 216 tpgs_bits, *mode)); 217 retval = 1; 218 } 219 220 return (retval); 221 } 222 223 static int 224 std_page83(struct scsi_address *ap, struct buf *bp, 225 int *rel_tgt_port, int *tgt_port, int *lu) 226 { 227 char *ptr, *end; 228 struct scsi_pkt *pkt; 229 char *bufp; 230 unsigned int buf_len, rx_bsize; 231 232 /* 233 * lets start the buf size with 512 bytes. If this 234 * if found to be insufficient, we can allocate 235 * appropriate size in the next iteration. 236 */ 237 buf_len = 512; 238 239 once_again: 240 bufp = kmem_zalloc(buf_len, KM_NOSLEEP); 241 if (bufp == NULL) { 242 VHCI_DEBUG(1, (CE_WARN, NULL, "!std_page83: " 243 "request packet allocation for %d failed....", 244 buf_len)); 245 return (1); 246 } 247 248 249 bp->b_un.b_addr = bufp; 250 bp->b_flags = B_READ; 251 bp->b_bcount = buf_len; 252 bp->b_resid = 0; 253 254 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 255 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 256 if (pkt == NULL) { 257 VHCI_DEBUG(1, (CE_WARN, NULL, 258 "!std_page83: Failure returned from scsi_init_pkt")); 259 kmem_free((void *)bufp, buf_len); 260 return (1); 261 } 262 263 pkt->pkt_cdbp[0] = SCMD_INQUIRY; 264 pkt->pkt_cdbp[1] = 0x1; 265 pkt->pkt_cdbp[2] = 0x83; 266 pkt->pkt_cdbp[3] = (unsigned char)((buf_len >> 8) & 0xff); 267 pkt->pkt_cdbp[4] = (unsigned char)(buf_len & 0xff); 268 pkt->pkt_time = 90; 269 270 if (vhci_do_scsi_cmd(pkt) == 0) { 271 VHCI_DEBUG(1, (CE_NOTE, NULL, 272 "!std_page83: vhci_do_scsi_cmd failed\n")); 273 kmem_free((void *)bufp, buf_len); 274 scsi_destroy_pkt(pkt); 275 return (1); 276 } 277 278 /* 279 * Now lets check if the size that was provided was 280 * sufficient. If not, allocate the appropriate size 281 * and retry the command again. 282 */ 283 rx_bsize = (((bufp[2] & 0xff) << 8) | (bufp[3] & 0xff)); 284 rx_bsize += 4; 285 if (rx_bsize > buf_len) { 286 /* 287 * Need to allocate more buf and retry again 288 */ 289 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_page83: " 290 "bufsize: %d greater than allocated buf: %d\n", 291 rx_bsize, buf_len)); 292 VHCI_DEBUG(1, (CE_NOTE, NULL, "Retrying for size %d\n", 293 rx_bsize)); 294 kmem_free((void *)bufp, buf_len); 295 buf_len = (unsigned int)(rx_bsize); 296 goto once_again; 297 } 298 299 ptr = bufp; 300 ptr += 4; /* identification descriptor 0 */ 301 end = bufp + rx_bsize; 302 while (ptr < end) { 303 VHCI_DEBUG(1, (CE_NOTE, NULL, "std_page83: desc[1/4/5/6/7]:" 304 "%x %x %x %x %x\n", 305 ptr[1], ptr[4], ptr[5], ptr[6], ptr[7])); 306 if ((ptr[1] & 0x0f) == 0x04) { 307 *rel_tgt_port = 0; 308 *rel_tgt_port |= ((ptr[6] & 0xff) << 8); 309 *rel_tgt_port |= (ptr[7] & 0xff); 310 VHCI_DEBUG(1, (CE_NOTE, NULL, 311 "!std_page83: relative target port: %x\n", 312 *rel_tgt_port)); 313 } else if ((ptr[1] & 0x0f) == 0x05) { 314 *tgt_port = 0; 315 *tgt_port = ((ptr[6] & 0xff) << 8); 316 *tgt_port |= (ptr[7] & 0xff); 317 VHCI_DEBUG(1, (CE_NOTE, NULL, 318 "!std_page83: target port: %x\n", *tgt_port)); 319 } else if ((ptr[1] & 0x0f) == 0x06) { 320 *lu = 0; 321 *lu |= ((ptr[6] & 0xff)<< 8); 322 *lu |= (ptr[7] & 0xff); 323 VHCI_DEBUG(1, (CE_NOTE, NULL, 324 "!std_page83: logical unit: %x\n", *lu)); 325 } 326 ptr += ptr[3] + 4; /* next identification descriptor */ 327 } 328 kmem_free((void *)bufp, buf_len); 329 scsi_destroy_pkt(pkt); 330 return (0); 331 } 332 333 #ifdef DEBUG 334 static void 335 print_buf(char *buf, int buf_size) 336 { 337 int i = 0, j; 338 int loop, left; 339 340 loop = buf_size / 8; 341 left = buf_size % 8; 342 343 VHCI_DEBUG(4, (CE_NOTE, NULL, "!buf_size: %x loop: %x left: %x", 344 buf_size, loop, left)); 345 346 for (j = 0; j < loop; j++) { 347 VHCI_DEBUG(4, (CE_NOTE, NULL, 348 "!buf[%d-%d]: %x %x %x %x %x %x %x %x", 349 i, i + 7, buf[i], buf[i+1], buf[i+2], buf[i+3], 350 buf[i+4], buf[i+5], buf[i+6], buf[i+7])); 351 i += 8; 352 } 353 354 if (left) { 355 VHCI_DEBUG(4, (CE_CONT, NULL, 356 "NOTICE: buf[%d-%d]:", i, i + left)); 357 for (j = 0; j < left; j++) { 358 VHCI_DEBUG(4, (CE_CONT, NULL, " %x", buf[i + j])); 359 } 360 VHCI_DEBUG(4, (CE_CONT, NULL, "\n")); 361 } 362 } 363 #endif 364 365 static int 366 std_report_target_groups(struct scsi_address *ap, struct buf *bp, 367 int rel_tgt_port, int tgt_port, int *pstate, int *preferred) 368 { 369 struct scsi_pkt *pkt; 370 char *ptr, *end, *bufp, *mpapi_ptr; 371 unsigned int rtpg_len = 0; 372 unsigned int l_tgt_port = 0, tpgs_state = 0; 373 unsigned int tgt_port_cnt = 0, lr_tgt_port = 0; 374 int i, len; 375 376 /* 377 * Start with buffer size of 512. 378 * If this is found to be insufficient, required size 379 * will be allocated and the command will be retried. 380 */ 381 len = 512; 382 383 try_again: 384 bufp = kmem_zalloc(len, KM_NOSLEEP); 385 if (bufp == NULL) { 386 VHCI_DEBUG(1, (CE_WARN, NULL, "!std_report_target_groups: " 387 "request packet allocation for %d failed....", 388 len)); 389 return (1); 390 } 391 392 bp->b_un.b_addr = bufp; 393 bp->b_flags = B_READ; 394 bp->b_bcount = len; 395 bp->b_resid = 0; 396 397 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP5, 398 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 399 400 if (pkt == NULL) { 401 VHCI_DEBUG(1, (CE_NOTE, NULL, 402 "!std_report_target_groups: scsi_init_pkt error\n")); 403 kmem_free((void *)bufp, len); 404 return (1); 405 } 406 407 pkt->pkt_cdbp[0] = SCMD_REPORT_TARGET_PORT_GROUP; 408 pkt->pkt_cdbp[1] = STD_SCSI_TPG_SERVICE_ACTION; 409 pkt->pkt_cdbp[6] = ((len >> 24) & 0xff); 410 pkt->pkt_cdbp[7] = ((len >> 16) & 0xff); 411 pkt->pkt_cdbp[8] = ((len >> 8) & 0xff); 412 pkt->pkt_cdbp[9] = len & 0xff; 413 pkt->pkt_time = 90; 414 415 VHCI_DEBUG(6, (CE_NOTE, NULL, 416 "!std_report_target_groups: sending target port group:" 417 " cdb[6/7/8/9]: %x/%x/%x/%x\n", pkt->pkt_cdbp[6], 418 pkt->pkt_cdbp[7], pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); 419 if (vhci_do_scsi_cmd(pkt) == 0) { 420 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_report_target_groups:" 421 " vhci_do_scsi_cmd failed\n")); 422 kmem_free((void *)bufp, len); 423 scsi_destroy_pkt(pkt); 424 return (1); 425 } 426 ptr = bufp; 427 VHCI_DEBUG(6, (CE_NOTE, NULL, "!std_report_target_groups:" 428 " returned from target" 429 " port group: buf[0/1/2/3]: %x/%x/%x/%x\n", 430 ptr[0], ptr[1], ptr[2], ptr[3])); 431 rtpg_len = (unsigned int)((0xff & ptr[0]) << 24); 432 rtpg_len |= (unsigned int)((0xff & ptr[1]) << 16); 433 rtpg_len |= (unsigned int)((0xff & ptr[2]) << 8); 434 rtpg_len |= (unsigned int)(0xff & ptr[3]); 435 rtpg_len += 4; 436 if (rtpg_len > len) { 437 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_report_target_groups: " 438 "bufsize: %d greater than allocated buf: %d\n", 439 rtpg_len, len)); 440 VHCI_DEBUG(4, (CE_NOTE, NULL, "Retrying for size %d\n", 441 rtpg_len)); 442 kmem_free((void *)bufp, len); 443 len = (unsigned int)(rtpg_len + 1); 444 goto try_again; 445 } 446 #ifdef DEBUG 447 print_buf(bufp, rtpg_len); 448 #endif 449 end = ptr + rtpg_len; 450 ptr += 4; 451 while (ptr < end) { 452 mpapi_ptr = ptr; 453 l_tgt_port = ((ptr[2] & 0xff) << 8) + (ptr[3] & 0xff); 454 tpgs_state = ptr[0] & 0x0f; 455 tgt_port_cnt = (ptr[7] & 0xff); 456 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_report_tgt_groups:" 457 " tpgs state: %x" 458 " tgt_group: %x count: %x\n", tpgs_state, 459 l_tgt_port, tgt_port_cnt)); 460 ptr += 8; 461 for (i = 0; i < tgt_port_cnt; i++) { 462 lr_tgt_port = 0; 463 lr_tgt_port |= ((ptr[2] & 0Xff) << 8); 464 lr_tgt_port |= (ptr[3] & 0xff); 465 466 if ((lr_tgt_port == rel_tgt_port) && 467 (l_tgt_port == tgt_port)) { 468 VHCI_DEBUG(4, (CE_NOTE, NULL, 469 "!std_report_tgt_groups:" 470 " found tgt_port: %x rel_tgt_port:%x" 471 " tpgs_state: %x\n", tgt_port, rel_tgt_port, 472 tpgs_state)); 473 /* 474 * once we have the preferred flag 475 * and a non-optimized state flag 476 * we will get preferred flag from the 477 * report target groups 478 */ 479 if (tpgs_state == STD_ACTIVE_OPTIMIZED) { 480 *pstate = STD_ACTIVE_OPTIMIZED; 481 *preferred = PCLASS_PREFERRED; 482 } else if (tpgs_state == 483 STD_ACTIVE_NONOPTIMIZED) { 484 *pstate = STD_ACTIVE_NONOPTIMIZED; 485 *preferred = PCLASS_NONPREFERRED; 486 } else if (tpgs_state == STD_STANDBY) { 487 *pstate = STD_STANDBY; 488 *preferred = PCLASS_NONPREFERRED; 489 } else { 490 *pstate = STD_UNAVAILABLE; 491 *preferred = PCLASS_NONPREFERRED; 492 } 493 vhci_mpapi_update_tpg_data(ap, mpapi_ptr); 494 kmem_free((void *)bufp, len); 495 scsi_destroy_pkt(pkt); 496 return (0); 497 } 498 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_report_tgt_groups:" 499 " tgt_port: %x rel_tgt_port:%x\n", tgt_port, 500 rel_tgt_port)); 501 ptr += 4; 502 } 503 } 504 *pstate = SCSI_PATH_INACTIVE; 505 *preferred = PCLASS_NONPREFERRED; 506 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_report_tgt_groups: " 507 "NO rel_TGTPRT MATCH!!! Assigning Default: state: %x " 508 "preferred: %d\n", *pstate, *preferred)); 509 kmem_free((void *)bufp, len); 510 scsi_destroy_pkt(pkt); 511 return (1); 512 } 513 514 /* 515 * get the failover mode, ownership and if it has extended failover 516 * capability. The mode(bits5-4/byte5) is defined as implicit, explicit, or 517 * both. The state is defined as online-optimized(0h), 518 * online-nonoptimized(1h), standby(2h), offline(3h), 519 * and transitioning(fh). Currently, there is online, 520 * standby, and offline(defined in sunmdi.h). 521 * Online-nonoptimized will be a mode of secondary 522 * and an ownership of online. Thought about using a different mode but 523 * it appears the states are really for the states for secondary mode. 524 * We currently have IS_ONLINING, IS_OFFLINING - should we have TRANSITIONING 525 * to mean from online-optimized to online-nonoptimized or does onlining 526 * cover this? 527 */ 528 /* ARGSUSED */ 529 static int 530 std_get_fo_mode(struct scsi_device *sd, int *mode, 531 int *state, int *xlf_capable, int *preferred) 532 { 533 int retval = 0; 534 struct buf *bp; 535 struct scsi_address *ap; 536 int lu = 0, rel_tgt_port = 0, tgt_port = 0x0; 537 538 VHCI_DEBUG(6, (CE_NOTE, NULL, "!std_get_fo_mode: enter\n")); 539 *mode = *state = *xlf_capable = 0; 540 bp = getrbuf(KM_NOSLEEP); 541 if (bp == NULL) { 542 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_get_fo_mode: " 543 " failed getrbuf\n")); 544 return (1); 545 } 546 547 ap = &sd->sd_address; 548 if (std_inquiry(ap, bp, mode)) { 549 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_get_fo_mode: " 550 " failed std_inquiry\n")); 551 retval = 1; 552 } else if (std_page83(ap, bp, &rel_tgt_port, &tgt_port, &lu)) { 553 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_get_fo_mode: " 554 " failed std_page83\n")); 555 retval = 1; 556 } else if (std_report_target_groups(ap, bp, rel_tgt_port, tgt_port, 557 state, preferred)) { 558 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_get_fo_mode: " 559 " failed std_report_target_groups\n")); 560 retval = 1; 561 } 562 563 freerbuf(bp); 564 if (retval == 0) { 565 VHCI_DEBUG(6, (CE_NOTE, NULL, "!std_get_fo_mode: " 566 "SUCCESS\n")); 567 } 568 return (retval); 569 } 570 571 /* ARGSUSED */ 572 static int 573 std_activate_explicit(struct scsi_device *sd, int xlf_capable) 574 { 575 cmn_err(CE_NOTE, "Explicit Activation is done by " 576 "std_set_target_groups() call from MPAPI"); 577 return (1); 578 } 579 580 /* 581 * Process the packet reason of CMD_PKT_CMPLT - return 0 if no 582 * retry and 1 if a retry should be done 583 */ 584 static int 585 std_process_cmplt_pkt(struct scsi_device *sd, struct scsi_pkt *pkt, 586 int *retry_cnt) 587 { 588 struct scsi_extended_sense *sns; 589 590 /* 591 * Re-initialize retry_cmd_cnt. Allow transport and 592 * cmd errors to go through a full retry count when 593 * these are encountered. This way TRAN/CMD errors 594 * retry count is not exhausted due to CMD_CMPLTs 595 * delay. This allows the system 596 * to brave a hick-up on the link at any given time, 597 * while waiting for the fo to complete. 598 */ 599 if (pkt->pkt_state & STATE_ARQ_DONE) { 600 sns = &(((struct scsi_arq_status *)(uintptr_t) 601 (pkt->pkt_scbp))->sts_sensedata); 602 if (sns->es_key == KEY_UNIT_ATTENTION) { 603 /* 604 * tpgs access state changed 605 */ 606 if (sns->es_add_code == STD_SCSI_ASC_STATE_CHG && 607 sns->es_qual_code == STD_SCSI_ASCQ_STATE_CHG_SUCC) { 608 /* XXX: update path info? */ 609 cmn_err(CE_WARN, "!Device failover" 610 " state change"); 611 } 612 return (1); 613 } else if (sns->es_key == KEY_NOT_READY) { 614 if ((*retry_cnt)++ >= 615 STD_FO_MAX_RETRIES) { 616 cmn_err(CE_WARN, "!Device failover" 617 " failed: timed out waiting " 618 "for path to become active"); 619 return (0); 620 } 621 VHCI_DEBUG(6, (CE_NOTE, NULL, 622 "!(sd:%p)lun " 623 "becoming active...\n", (void *)sd)); 624 drv_usecwait(STD_FO_RETRY_DELAY); 625 return (1); 626 } 627 cmn_err(CE_NOTE, "!Failover failed;" 628 " sense key:%x, ASC: %x, " 629 "ASCQ:%x", sns->es_key, 630 sns->es_add_code, sns->es_qual_code); 631 return (0); 632 } 633 switch (SCBP_C(pkt)) { 634 case STATUS_GOOD: 635 break; 636 case STATUS_CHECK: 637 VHCI_DEBUG(4, (CE_WARN, NULL, 638 "!(sd:%p):" 639 " status returned CHECK during std" 640 " path activation", (void *)sd)); 641 return (0); 642 case STATUS_QFULL: 643 VHCI_DEBUG(6, (CE_NOTE, NULL, "QFULL " 644 "status returned QFULL during std " 645 "path activation for %p\n", (void *)sd)); 646 drv_usecwait(5000); 647 return (1); 648 case STATUS_BUSY: 649 VHCI_DEBUG(6, (CE_NOTE, NULL, "BUSY " 650 "status returned BUSY during std " 651 "path activation for %p\n", (void *)sd)); 652 drv_usecwait(5000); 653 return (1); 654 default: 655 VHCI_DEBUG(4, (CE_WARN, NULL, 656 "!(sd:%p) Bad status returned during std " 657 "activation (pkt %p, status %x)", 658 (void *)sd, (void *)pkt, SCBP_C(pkt))); 659 return (0); 660 } 661 return (0); 662 } 663 664 /* 665 * For now we are going to use primary/online and secondary/online. 666 * There is no standby path returned by the dsp and we may have 667 * to do something different for other devices that use standby 668 */ 669 /* ARGSUSED */ 670 static int 671 std_path_activate(struct scsi_device *sd, char *pathclass, 672 void *ctpriv) 673 { 674 struct buf *bp; 675 struct scsi_pkt *pkt; 676 struct scsi_address *ap; 677 int err, retry_cnt, retry_cmd_cnt; 678 int mode, state, retval, xlf, preferred; 679 680 ap = &sd->sd_address; 681 682 mode = state = 0; 683 684 if (std_get_fo_mode(sd, &mode, &state, &xlf, &preferred)) { 685 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_path_activate:" 686 " failed std_get_fo_mode\n")); 687 return (1); 688 } 689 if ((state == STD_ACTIVE_OPTIMIZED) || 690 (state == STD_ACTIVE_NONOPTIMIZED)) { 691 VHCI_DEBUG(4, (CE_NOTE, NULL, "!path already active for %p\n", 692 (void *)sd)); 693 return (0); 694 } 695 696 if (mode != SCSI_IMPLICIT_FAILOVER) { 697 VHCI_DEBUG(4, (CE_NOTE, NULL, 698 "!mode is EXPLICIT for %p xlf %x\n", 699 (void *)sd, xlf)); 700 retval = std_activate_explicit(sd, xlf); 701 if (retval != 0) { 702 VHCI_DEBUG(4, (CE_NOTE, NULL, 703 "!(sd:%p)std_path_activate failed(1)\n", 704 (void *)sd)); 705 return (1); 706 } 707 } else { 708 VHCI_DEBUG(4, (CE_NOTE, NULL, "STD mode is IMPLICIT for %p\n", 709 (void *)sd)); 710 } 711 712 bp = scsi_alloc_consistent_buf(ap, (struct buf *)NULL, DEV_BSIZE, 713 B_READ, NULL, NULL); 714 if (!bp) { 715 VHCI_DEBUG(4, (CE_WARN, NULL, 716 "!(sd:%p)std_path_activate failed to alloc buffer", 717 (void *)sd)); 718 return (1); 719 } 720 721 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP1, 722 sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, NULL, NULL); 723 if (!pkt) { 724 VHCI_DEBUG(4, (CE_WARN, NULL, 725 "!(sd:%p)std_path_activate failed to initialize packet", 726 (void *)sd)); 727 scsi_free_consistent_buf(bp); 728 return (1); 729 } 730 731 (void) scsi_setup_cdb((union scsi_cdb *)(uintptr_t)pkt->pkt_cdbp, 732 SCMD_READ, 1, 1, 0); 733 pkt->pkt_time = 3*30; 734 pkt->pkt_flags |= FLAG_NOINTR; 735 736 retry_cnt = 0; 737 retry_cmd_cnt = 0; 738 retry: 739 err = scsi_transport(pkt); 740 if (err != TRAN_ACCEPT) { 741 /* 742 * Retry TRAN_BUSY till STD_FO_MAX_RETRIES is exhausted. 743 * All other errors are fatal and should not be retried. 744 */ 745 if ((err == TRAN_BUSY) && 746 (retry_cnt++ < STD_FO_MAX_RETRIES)) { 747 drv_usecwait(STD_FO_RETRY_DELAY); 748 goto retry; 749 } 750 cmn_err(CE_WARN, "Failover failed, " 751 "couldn't transport packet"); 752 scsi_destroy_pkt(pkt); 753 scsi_free_consistent_buf(bp); 754 return (1); 755 } 756 switch (pkt->pkt_reason) { 757 case CMD_CMPLT: 758 retry_cmd_cnt = 0; 759 retval = std_process_cmplt_pkt(sd, pkt, &retry_cnt); 760 if (retval != 0) { 761 goto retry; 762 } 763 break; 764 case CMD_TIMEOUT: 765 cmn_err(CE_WARN, "!Failover failed: timed out "); 766 retval = 1; 767 break; 768 case CMD_INCOMPLETE: 769 case CMD_RESET: 770 case CMD_ABORTED: 771 case CMD_TRAN_ERR: 772 /* 773 * Increased the number of retries when these error 774 * cases are encountered. Also added a 1 sec wait 775 * before retrying. 776 */ 777 if (retry_cmd_cnt++ < STD_FO_MAX_CMD_RETRIES) { 778 drv_usecwait(STD_FO_CMD_RETRY_DELAY); 779 VHCI_DEBUG(4, (CE_WARN, NULL, 780 "!Retrying path activation due to " 781 "pkt reason:%x, retry cnt:%d", 782 pkt->pkt_reason, retry_cmd_cnt)); 783 goto retry; 784 } 785 /* FALLTHROUGH */ 786 default: 787 cmn_err(CE_WARN, "!Path activation did not " 788 "complete successfully," 789 "(pkt reason %x)", pkt->pkt_reason); 790 retval = 1; 791 break; 792 } 793 794 795 VHCI_DEBUG(4, (CE_NOTE, NULL, "!Path activation success\n")); 796 scsi_destroy_pkt(pkt); 797 scsi_free_consistent_buf(bp); 798 return (retval); 799 } 800 801 /* ARGSUSED */ 802 static int std_path_deactivate(struct scsi_device *sd, char *pathclass, 803 void *ctpriv) 804 { 805 return (0); 806 } 807 808 /* ARGSUSED */ 809 static int 810 std_path_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo 811 *opinfo, void *ctpriv) 812 { 813 int mode, preferred, state, xlf; 814 815 opinfo->opinfo_rev = OPINFO_REV; 816 817 if (std_get_fo_mode(sd, &mode, &state, &xlf, &preferred)) { 818 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_path_getopinfo:" 819 " failed std_get_fo_mode\n")); 820 return (1); 821 } 822 823 if (state == STD_ACTIVE_OPTIMIZED) { 824 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE; 825 } else if (state == STD_ACTIVE_NONOPTIMIZED) { 826 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE_NONOPT; 827 } else if (state == STD_STANDBY) { 828 opinfo->opinfo_path_state = SCSI_PATH_INACTIVE; 829 } else if (state == STD_UNAVAILABLE) { 830 opinfo->opinfo_path_state = SCSI_PATH_INACTIVE; 831 } 832 if (preferred) { 833 (void) strcpy(opinfo->opinfo_path_attr, PCLASS_PRIMARY); 834 } else { 835 (void) strcpy(opinfo->opinfo_path_attr, PCLASS_SECONDARY); 836 } 837 VHCI_DEBUG(4, (CE_NOTE, NULL, "std_path_get_opinfo: " 838 "class: %s state: %s\n", opinfo->opinfo_path_attr, 839 opinfo->opinfo_path_state == SCSI_PATH_ACTIVE ? 840 "ACTIVE" : "INACTIVE")); 841 opinfo->opinfo_xlf_capable = 0; 842 opinfo->opinfo_pswtch_best = 30; 843 opinfo->opinfo_pswtch_worst = 3*30; 844 opinfo->opinfo_preferred = (uint16_t)preferred; 845 opinfo->opinfo_mode = (uint16_t)mode; 846 847 return (0); 848 } 849 850 /* ARGSUSED */ 851 static int std_path_ping(struct scsi_device *sd, void *ctpriv) 852 { 853 /* 854 * For future use 855 */ 856 return (1); 857 } 858 859 /* 860 * Analyze the sense code to determine whether failover process 861 */ 862 /* ARGSUSED */ 863 static int 864 std_analyze_sense(struct scsi_device *sd, struct scsi_extended_sense 865 *sense, void *ctpriv) 866 { 867 int rval = SCSI_SENSE_UNKNOWN; 868 869 if ((sense->es_key == KEY_UNIT_ATTENTION) && 870 (sense->es_add_code == STD_SCSI_ASC_STATE_CHG) && 871 (sense->es_qual_code == STD_SCSI_ASCQ_STATE_CHG_SUCC)) { 872 rval = SCSI_SENSE_STATE_CHANGED; 873 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_analyze_sense:" 874 " sense_key:%x, add_code: %x, qual_code:%x" 875 " sense:%x\n", sense->es_key, sense->es_add_code, 876 sense->es_qual_code, rval)); 877 } else if ((sense->es_key == KEY_NOT_READY) && 878 (sense->es_add_code == STD_LOGICAL_UNIT_NOT_ACCESSIBLE) && 879 (sense->es_qual_code == STD_TGT_PORT_UNAVAILABLE)) { 880 rval = SCSI_SENSE_INACTIVE; 881 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_analyze_sense:" 882 " sense_key:%x, add_code: %x, qual_code:%x" 883 " sense:%x\n", sense->es_key, sense->es_add_code, 884 sense->es_qual_code, rval)); 885 } else if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 886 (sense->es_add_code == STD_SCSI_ASC_INVAL_PARAM_LIST)) { 887 rval = SCSI_SENSE_NOFAILOVER; 888 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_analyze_sense:" 889 " sense_key:%x, add_code: %x, qual_code:%x" 890 " sense:%x\n", sense->es_key, sense->es_add_code, 891 sense->es_qual_code, rval)); 892 } else if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 893 (sense->es_add_code == STD_SCSI_ASC_INVAL_CMD_OPCODE)) { 894 rval = SCSI_SENSE_NOFAILOVER; 895 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_analyze_sense:" 896 " sense_key:%x, add_code: %x, qual_code:%x" 897 " sense:%x\n", sense->es_key, sense->es_add_code, 898 sense->es_qual_code, rval)); 899 } else { 900 /* 901 * At this point sense data may be for power-on-reset 902 * UNIT ATTN hardware errors, vendor unqiue sense data etc. 903 * For all these cases, return SCSI_SENSE_UNKNOWN. 904 */ 905 VHCI_DEBUG(1, (CE_NOTE, NULL, "!Analyze sense UNKNOWN:" 906 " sense key:%x, ASC:%x, ASCQ:%x\n", sense->es_key, 907 sense->es_add_code, sense->es_qual_code)); 908 } 909 910 return (rval); 911 } 912 913 /* ARGSUSED */ 914 static int 915 std_pathclass_next(char *cur, char **nxt, void *ctpriv) 916 { 917 /* 918 * The first phase does not have a standby path so 919 * there will be no explicit failover - when standard tpgs. 920 * standard defines preferred flag then we should start 921 * using this as the selection mechanism - there can be 922 * preferred primary standby that we should fail to first and then 923 * nonpreferred secondary standby. 924 */ 925 if (cur == NULL) { 926 *nxt = PCLASS_PRIMARY; 927 return (0); 928 } else if (strcmp(cur, PCLASS_PRIMARY) == 0) { 929 *nxt = PCLASS_SECONDARY; 930 return (0); 931 } else if (strcmp(cur, PCLASS_SECONDARY) == 0) { 932 return (ENOENT); 933 } else { 934 return (EINVAL); 935 } 936 } 937 938 int 939 std_set_target_groups(struct scsi_address *ap, int set_state, int tpg_id) 940 { 941 struct scsi_pkt *pkt; 942 struct buf *bp; 943 int len, rval, ss = SCSI_SENSE_UNKNOWN; 944 char *bufp; 945 struct scsi_extended_sense *sns; 946 947 len = 8; 948 949 bp = getrbuf(KM_NOSLEEP); 950 if (bp == NULL) { 951 VHCI_DEBUG(1, (CE_WARN, NULL, "!std_set_target_groups: " 952 " failed getrbuf")); 953 return (1); 954 } 955 956 bufp = kmem_zalloc(len, KM_NOSLEEP); 957 if (bufp == NULL) { 958 VHCI_DEBUG(1, (CE_WARN, NULL, "!std_set_target_groups: " 959 "request packet allocation for %d failed....", len)); 960 freerbuf(bp); 961 return (1); 962 } 963 964 bp->b_un.b_addr = bufp; 965 bp->b_flags = B_READ; 966 bp->b_bcount = len; 967 bp->b_resid = 0; 968 969 bufp[4] = (0x0f & set_state); 970 bufp[6] = (0xff00 & tpg_id) >> 8; 971 bufp[7] = (0x00ff & tpg_id); 972 973 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP5, 974 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL); 975 976 if (pkt == NULL) { 977 VHCI_DEBUG(1, (CE_NOTE, NULL, 978 "!std_set_target_groups: scsi_init_pkt error\n")); 979 freerbuf(bp); 980 kmem_free((void *)bufp, len); 981 return (1); 982 } 983 984 /* 985 * Sends 1 TPG descriptor only. Hence Parameter list length pkt_cdbp[9] 986 * is set to 8 bytes - Refer SPC3 for details. 987 */ 988 pkt->pkt_cdbp[0] = SCMD_SET_TARGET_PORT_GROUP; 989 pkt->pkt_cdbp[1] = STD_SCSI_TPG_SERVICE_ACTION; 990 pkt->pkt_cdbp[9] = 8; 991 pkt->pkt_time = 90; 992 993 VHCI_DEBUG(1, (CE_NOTE, NULL, 994 "!std_set_target_groups: sending set target port group:" 995 " cdb[0/1/6/7/8/9]: %x/%x/%x/%x/%x/%x\n", pkt->pkt_cdbp[0], 996 pkt->pkt_cdbp[1], pkt->pkt_cdbp[6], pkt->pkt_cdbp[7], 997 pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); 998 999 #ifdef DEBUG 1000 print_buf(bufp, len); 1001 #endif 1002 rval = vhci_do_scsi_cmd(pkt); 1003 1004 if (rval == 0) { 1005 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_set_target_groups:" 1006 " vhci_do_scsi_cmd failed\n")); 1007 freerbuf(bp); 1008 kmem_free((void *)bufp, len); 1009 scsi_destroy_pkt(pkt); 1010 return (-1); 1011 } else if ((pkt->pkt_reason == CMD_CMPLT) && 1012 (SCBP_C(pkt) == STATUS_CHECK) && 1013 (pkt->pkt_state & STATE_ARQ_DONE)) { 1014 sns = &(((struct scsi_arq_status *)(uintptr_t) 1015 (pkt->pkt_scbp))->sts_sensedata); 1016 1017 if ((sns->es_key == KEY_UNIT_ATTENTION) && 1018 (sns->es_add_code == STD_SCSI_ASC_STATE_CHG) && 1019 (sns->es_qual_code == STD_SCSI_ASCQ_STATE_CHG_SUCC)) { 1020 ss = SCSI_SENSE_STATE_CHANGED; 1021 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_set_target_groups:" 1022 " sense:%x, add_code: %x, qual_code:%x" 1023 " sense:%x\n", sns->es_key, sns->es_add_code, 1024 sns->es_qual_code, ss)); 1025 } else if ((sns->es_key == KEY_ILLEGAL_REQUEST) && 1026 (sns->es_add_code == STD_SCSI_ASC_INVAL_PARAM_LIST)) { 1027 ss = SCSI_SENSE_NOFAILOVER; 1028 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_set_target_groups:" 1029 " sense:%x, add_code: %x, qual_code:%x" 1030 " sense:%x\n", sns->es_key, sns->es_add_code, 1031 sns->es_qual_code, ss)); 1032 } else if ((sns->es_key == KEY_ILLEGAL_REQUEST) && 1033 (sns->es_add_code == STD_SCSI_ASC_INVAL_CMD_OPCODE)) { 1034 ss = SCSI_SENSE_NOFAILOVER; 1035 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_set_target_groups:" 1036 " sense_key:%x, add_code: %x, qual_code:%x" 1037 " sense:%x\n", sns->es_key, sns->es_add_code, 1038 sns->es_qual_code, rval)); 1039 } else { 1040 /* 1041 * At this point sns data may be for power-on-reset 1042 * UNIT ATTN hardware errors, vendor unqiue sense etc. 1043 * For all these cases, sense is unknown. 1044 */ 1045 ss = SCSI_SENSE_NOFAILOVER; 1046 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_set_target_groups: " 1047 " sense UNKNOWN: sense key:%x, ASC:%x, ASCQ:%x\n", 1048 sns->es_key, sns->es_add_code, sns->es_qual_code)); 1049 } 1050 1051 if (ss == SCSI_SENSE_STATE_CHANGED) { 1052 freerbuf(bp); 1053 kmem_free((void *)bufp, len); 1054 scsi_destroy_pkt(pkt); 1055 return (0); 1056 } 1057 } 1058 1059 freerbuf(bp); 1060 kmem_free((void *)bufp, len); 1061 scsi_destroy_pkt(pkt); 1062 return (1); 1063 } 1064