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 /* 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Implementation of "scsi_vhci_f_tpgs" T10 standard based failover_ops. 28 * 29 * NOTE: for non-sequential devices only. 30 */ 31 32 #include <sys/conf.h> 33 #include <sys/file.h> 34 #include <sys/ddi.h> 35 #include <sys/sunddi.h> 36 #include <sys/scsi/scsi.h> 37 #include <sys/scsi/adapters/scsi_vhci.h> 38 #include <sys/scsi/adapters/scsi_vhci_tpgs.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); 45 46 #define STD_FO_CMD_RETRY_DELAY 1000000 /* 1 seconds */ 47 #define STD_FO_RETRY_DELAY 2000000 /* 2 seconds */ 48 /* 49 * max time for failover to complete is 3 minutes. Compute 50 * number of retries accordingly, to ensure we wait for at least 51 * 3 minutes 52 */ 53 #define STD_FO_MAX_RETRIES (3*60*1000000)/STD_FO_RETRY_DELAY 54 55 56 /* ARGSUSED */ 57 static int 58 std_device_probe(struct scsi_device *sd, struct scsi_inquiry *inq, 59 void **ctpriv) 60 { 61 int mode, state, xlf, preferred = 0; 62 63 VHCI_DEBUG(6, (CE_NOTE, NULL, "std_device_probe: vidpid %s\n", 64 inq->inq_vid)); 65 66 if (inq->inq_tpgs == TPGS_FAILOVER_NONE) { 67 VHCI_DEBUG(4, (CE_WARN, NULL, 68 "!std_device_probe: not a standard tpgs device")); 69 return (SFO_DEVICE_PROBE_PHCI); 70 } 71 72 if (inq->inq_dtype == DTYPE_SEQUENTIAL) { 73 VHCI_DEBUG(4, (CE_NOTE, NULL, 74 "!std_device_probe: Detected a " 75 "Standard Asymmetric device " 76 "not yet supported\n")); 77 return (SFO_DEVICE_PROBE_PHCI); 78 } 79 80 if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) { 81 VHCI_DEBUG(4, (CE_WARN, NULL, "!unable to fetch fo " 82 "mode: sd(%p)", (void *) sd)); 83 return (SFO_DEVICE_PROBE_PHCI); 84 } 85 86 if (inq->inq_tpgs == TPGS_FAILOVER_IMPLICIT) { 87 VHCI_DEBUG(1, (CE_NOTE, NULL, 88 "!std_device_probe: Detected a " 89 "Standard Asymmetric device " 90 "with implicit failover\n")); 91 return (SFO_DEVICE_PROBE_VHCI); 92 } 93 if (inq->inq_tpgs == TPGS_FAILOVER_EXPLICIT) { 94 VHCI_DEBUG(1, (CE_NOTE, NULL, 95 "!std_device_probe: Detected a " 96 "Standard Asymmetric device " 97 "with explicit failover\n")); 98 return (SFO_DEVICE_PROBE_VHCI); 99 } 100 if (inq->inq_tpgs == TPGS_FAILOVER_BOTH) { 101 VHCI_DEBUG(1, (CE_NOTE, NULL, 102 "!std_device_probe: Detected a " 103 "Standard Asymmetric device " 104 "which supports both implicit and explicit failover\n")); 105 return (SFO_DEVICE_PROBE_VHCI); 106 } 107 VHCI_DEBUG(1, (CE_WARN, NULL, 108 "!std_device_probe: " 109 "Unknown tpgs_bits: %x", inq->inq_tpgs)); 110 return (SFO_DEVICE_PROBE_PHCI); 111 } 112 113 /* ARGSUSED */ 114 static void 115 std_device_unprobe(struct scsi_device *sd, void *ctpriv) 116 { 117 /* 118 * For future use 119 */ 120 } 121 122 /* ARGSUSED */ 123 static int 124 std_activate_explicit(struct scsi_device *sd, int xlf_capable) 125 { 126 cmn_err(CE_NOTE, "Explicit Activation is done by " 127 "vhci_tpgs_set_target_groups() call from MPAPI"); 128 return (1); 129 } 130 131 /* 132 * Process the packet reason of CMD_PKT_CMPLT - return 0 if no 133 * retry and 1 if a retry should be done 134 */ 135 static int 136 std_process_cmplt_pkt(struct scsi_device *sd, struct scsi_pkt *pkt, 137 int *retry_cnt, int *retval) 138 { 139 *retval = 1; /* fail */ 140 141 switch (SCBP_C(pkt)) { 142 case STATUS_GOOD: 143 *retval = 0; 144 break; 145 case STATUS_CHECK: 146 if (pkt->pkt_state & STATE_ARQ_DONE) { 147 uint8_t *sns, skey, asc, ascq; 148 sns = (uint8_t *) 149 &(((struct scsi_arq_status *)(uintptr_t) 150 (pkt->pkt_scbp))->sts_sensedata); 151 skey = scsi_sense_key(sns); 152 asc = scsi_sense_asc(sns); 153 ascq = scsi_sense_ascq(sns); 154 if (skey == KEY_UNIT_ATTENTION) { 155 /* 156 * tpgs access state changed 157 */ 158 if (asc == STD_SCSI_ASC_STATE_CHG && 159 ascq == 160 STD_SCSI_ASCQ_STATE_CHG_SUCC) { 161 /* XXX: update path info? */ 162 cmn_err(CE_WARN, 163 "!Device failover" 164 " state change"); 165 } 166 return (1); 167 } else if (skey == KEY_NOT_READY) { 168 if (asc == 169 STD_LOGICAL_UNIT_NOT_ACCESSIBLE && 170 ascq == STD_TGT_PORT_STANDBY) { 171 /* 172 * Don't retry on the path 173 * which is indicated as 174 * standby, return failure. 175 */ 176 return (0); 177 } else if ((*retry_cnt)++ >= 178 STD_FO_MAX_RETRIES) { 179 cmn_err(CE_WARN, 180 "!Device failover failed: " 181 "timed out waiting for " 182 "path to become active"); 183 return (0); 184 } 185 VHCI_DEBUG(6, (CE_NOTE, NULL, 186 "!(sd:%p)lun becoming active...\n", 187 (void *)sd)); 188 drv_usecwait(STD_FO_RETRY_DELAY); 189 return (1); 190 } 191 cmn_err(CE_NOTE, "!Failover failed;" 192 " sense key:%x, ASC: %x, " 193 "ASCQ:%x", skey, asc, ascq); 194 return (0); 195 } 196 VHCI_DEBUG(4, (CE_WARN, NULL, 197 "!(sd:%p):" 198 " status returned CHECK during std" 199 " path activation", (void *)sd)); 200 return (0); 201 case STATUS_QFULL: 202 VHCI_DEBUG(6, (CE_NOTE, NULL, "QFULL " 203 "status returned QFULL during std " 204 "path activation for %p\n", (void *)sd)); 205 drv_usecwait(5000); 206 return (1); 207 case STATUS_BUSY: 208 VHCI_DEBUG(6, (CE_NOTE, NULL, "BUSY " 209 "status returned BUSY during std " 210 "path activation for %p\n", (void *)sd)); 211 drv_usecwait(5000); 212 return (1); 213 default: 214 VHCI_DEBUG(4, (CE_WARN, NULL, 215 "!(sd:%p) Bad status returned during std " 216 "activation (pkt %p, status %x)", 217 (void *)sd, (void *)pkt, SCBP_C(pkt))); 218 return (0); 219 } 220 return (0); 221 } 222 223 /* 224 * For now we are going to use primary/online and secondary/online. 225 * There is no standby path returned by the dsp and we may have 226 * to do something different for other devices that use standby 227 */ 228 /* ARGSUSED */ 229 static int 230 std_path_activate(struct scsi_device *sd, char *pathclass, 231 void *ctpriv) 232 { 233 struct buf *bp; 234 struct scsi_pkt *pkt; 235 struct scsi_address *ap; 236 int err, retry_cnt, retry_cmd_cnt; 237 int mode, state, retval, xlf, preferred; 238 239 ap = &sd->sd_address; 240 241 mode = state = 0; 242 243 if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) { 244 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_path_activate:" 245 " failed vhci_tpgs_get_target_fo_mode\n")); 246 return (1); 247 } 248 if ((state == STD_ACTIVE_OPTIMIZED) || 249 (state == STD_ACTIVE_NONOPTIMIZED)) { 250 VHCI_DEBUG(4, (CE_NOTE, NULL, "!path already active for %p\n", 251 (void *)sd)); 252 return (0); 253 } 254 255 if (mode == SCSI_EXPLICIT_FAILOVER) { 256 VHCI_DEBUG(4, (CE_NOTE, NULL, 257 "!mode is EXPLICIT for %p xlf %x\n", 258 (void *)sd, xlf)); 259 retval = std_activate_explicit(sd, xlf); 260 if (retval != 0) { 261 VHCI_DEBUG(4, (CE_NOTE, NULL, 262 "!(sd:%p)std_path_activate failed(1)\n", 263 (void *)sd)); 264 return (1); 265 } 266 } else { 267 VHCI_DEBUG(4, (CE_NOTE, NULL, "STD mode is IMPLICIT for %p\n", 268 (void *)sd)); 269 } 270 271 bp = scsi_alloc_consistent_buf(ap, (struct buf *)NULL, DEV_BSIZE, 272 B_READ, NULL, NULL); 273 if (!bp) { 274 VHCI_DEBUG(4, (CE_WARN, NULL, 275 "!(sd:%p)std_path_activate failed to alloc buffer", 276 (void *)sd)); 277 return (1); 278 } 279 280 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP1, 281 sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, NULL, NULL); 282 if (!pkt) { 283 VHCI_DEBUG(4, (CE_WARN, NULL, 284 "!(sd:%p)std_path_activate failed to initialize packet", 285 (void *)sd)); 286 scsi_free_consistent_buf(bp); 287 return (1); 288 } 289 290 (void) scsi_setup_cdb((union scsi_cdb *)(uintptr_t)pkt->pkt_cdbp, 291 SCMD_READ, 1, 1, 0); 292 pkt->pkt_time = 3*30; 293 pkt->pkt_flags |= FLAG_NOINTR; 294 295 retry_cnt = 0; 296 retry_cmd_cnt = 0; 297 retry: 298 err = scsi_transport(pkt); 299 if (err != TRAN_ACCEPT) { 300 /* 301 * Retry TRAN_BUSY till STD_FO_MAX_RETRIES is exhausted. 302 * All other errors are fatal and should not be retried. 303 */ 304 if ((err == TRAN_BUSY) && 305 (retry_cnt++ < STD_FO_MAX_RETRIES)) { 306 drv_usecwait(STD_FO_RETRY_DELAY); 307 goto retry; 308 } 309 cmn_err(CE_WARN, "Failover failed, " 310 "couldn't transport packet"); 311 scsi_destroy_pkt(pkt); 312 scsi_free_consistent_buf(bp); 313 return (1); 314 } 315 switch (pkt->pkt_reason) { 316 case CMD_CMPLT: 317 /* 318 * Re-initialize retry_cmd_cnt. Allow transport and 319 * cmd errors to go through a full retry count when 320 * these are encountered. This way TRAN/CMD errors 321 * retry count is not exhausted due to CMD_CMPLTs 322 * delay. This allows the system 323 * to brave a hick-up on the link at any given time, 324 * while waiting for the fo to complete. 325 */ 326 retry_cmd_cnt = 0; 327 if (std_process_cmplt_pkt(sd, pkt, &retry_cnt, 328 &retval) != 0) { 329 goto retry; 330 } 331 break; 332 case CMD_TIMEOUT: 333 cmn_err(CE_WARN, "!Failover failed: timed out "); 334 retval = 1; 335 break; 336 case CMD_INCOMPLETE: 337 case CMD_RESET: 338 case CMD_ABORTED: 339 case CMD_TRAN_ERR: 340 /* 341 * Increased the number of retries when these error 342 * cases are encountered. Also added a 1 sec wait 343 * before retrying. 344 */ 345 if (retry_cmd_cnt++ < STD_FO_MAX_CMD_RETRIES) { 346 drv_usecwait(STD_FO_CMD_RETRY_DELAY); 347 VHCI_DEBUG(4, (CE_WARN, NULL, 348 "!Retrying path activation due to " 349 "pkt reason:%x, retry cnt:%d", 350 pkt->pkt_reason, retry_cmd_cnt)); 351 goto retry; 352 } 353 /* FALLTHROUGH */ 354 default: 355 cmn_err(CE_WARN, "!Path activation did not " 356 "complete successfully," 357 "(pkt reason %x)", pkt->pkt_reason); 358 retval = 1; 359 break; 360 } 361 362 scsi_destroy_pkt(pkt); 363 scsi_free_consistent_buf(bp); 364 return (retval); 365 } 366 367 /* ARGSUSED */ 368 static int std_path_deactivate(struct scsi_device *sd, char *pathclass, 369 void *ctpriv) 370 { 371 return (0); 372 } 373 374 /* ARGSUSED */ 375 static int 376 std_path_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo, 377 void *ctpriv) 378 { 379 int mode, preferred, state, xlf; 380 381 opinfo->opinfo_rev = OPINFO_REV; 382 383 if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) { 384 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_path_getopinfo:" 385 " failed vhci_tpgs_get_target_fo_mode\n")); 386 return (1); 387 } 388 389 if (state == STD_ACTIVE_OPTIMIZED) { 390 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE; 391 } else if (state == STD_ACTIVE_NONOPTIMIZED) { 392 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE_NONOPT; 393 } else if (state == STD_STANDBY) { 394 opinfo->opinfo_path_state = SCSI_PATH_INACTIVE; 395 } else if (state == STD_UNAVAILABLE) { 396 opinfo->opinfo_path_state = SCSI_PATH_INACTIVE; 397 } 398 if (preferred) { 399 (void) strcpy(opinfo->opinfo_path_attr, PCLASS_PRIMARY); 400 } else { 401 (void) strcpy(opinfo->opinfo_path_attr, PCLASS_SECONDARY); 402 } 403 VHCI_DEBUG(4, (CE_NOTE, NULL, "std_path_get_opinfo: " 404 "class: %s state: %s\n", opinfo->opinfo_path_attr, 405 opinfo->opinfo_path_state == SCSI_PATH_ACTIVE ? 406 "ACTIVE" : "INACTIVE")); 407 opinfo->opinfo_xlf_capable = 0; 408 opinfo->opinfo_pswtch_best = 30; 409 opinfo->opinfo_pswtch_worst = 3*30; 410 opinfo->opinfo_preferred = (uint16_t)preferred; 411 opinfo->opinfo_mode = (uint16_t)mode; 412 413 return (0); 414 } 415 416 /* ARGSUSED */ 417 static int std_path_ping(struct scsi_device *sd, void *ctpriv) 418 { 419 /* 420 * For future use 421 */ 422 return (1); 423 } 424 425 /* 426 * Analyze the sense code to determine whether failover process 427 */ 428 /* ARGSUSED */ 429 static int 430 std_analyze_sense(struct scsi_device *sd, uint8_t *sense, 431 void *ctpriv) 432 { 433 int rval = SCSI_SENSE_UNKNOWN; 434 435 uint8_t skey, asc, ascq; 436 437 skey = scsi_sense_key(sense); 438 asc = scsi_sense_asc(sense); 439 ascq = scsi_sense_ascq(sense); 440 441 if ((skey == KEY_UNIT_ATTENTION) && 442 (asc == STD_SCSI_ASC_STATE_CHG) && 443 (ascq == STD_SCSI_ASCQ_STATE_CHG_SUCC)) { 444 rval = SCSI_SENSE_STATE_CHANGED; 445 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_analyze_sense:" 446 " sense_key:%x, add_code: %x, qual_code:%x" 447 " sense:%x\n", skey, asc, ascq, rval)); 448 } else if ((skey == KEY_NOT_READY) && 449 (asc == STD_LOGICAL_UNIT_NOT_ACCESSIBLE) && 450 ((ascq == STD_TGT_PORT_UNAVAILABLE) || 451 (ascq == STD_TGT_PORT_STANDBY))) { 452 rval = SCSI_SENSE_INACTIVE; 453 VHCI_DEBUG(4, (CE_NOTE, NULL, "!std_analyze_sense:" 454 " sense_key:%x, add_code: %x, qual_code:%x" 455 " sense:%x\n", skey, asc, ascq, rval)); 456 } else if ((skey == KEY_ILLEGAL_REQUEST) && 457 (asc == STD_SCSI_ASC_INVAL_PARAM_LIST)) { 458 rval = SCSI_SENSE_NOFAILOVER; 459 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_analyze_sense:" 460 " sense_key:%x, add_code: %x, qual_code:%x" 461 " sense:%x\n", skey, asc, ascq, rval)); 462 } else if ((skey == KEY_ILLEGAL_REQUEST) && 463 (asc == STD_SCSI_ASC_INVAL_CMD_OPCODE)) { 464 rval = SCSI_SENSE_NOFAILOVER; 465 VHCI_DEBUG(1, (CE_NOTE, NULL, "!std_analyze_sense:" 466 " sense_key:%x, add_code: %x, qual_code:%x" 467 " sense:%x\n", skey, asc, ascq, rval)); 468 } else { 469 /* 470 * At this point sense data may be for power-on-reset 471 * UNIT ATTN hardware errors, vendor unqiue sense data etc. 472 * For all these cases, return SCSI_SENSE_UNKNOWN. 473 */ 474 VHCI_DEBUG(1, (CE_NOTE, NULL, "!Analyze sense UNKNOWN:" 475 " sense key:%x, ASC:%x, ASCQ:%x\n", skey, asc, ascq)); 476 } 477 478 return (rval); 479 } 480 481 /* ARGSUSED */ 482 static int 483 std_pathclass_next(char *cur, char **nxt, void *ctpriv) 484 { 485 /* 486 * The first phase does not have a standby path so 487 * there will be no explicit failover - when standard tpgs. 488 * standard defines preferred flag then we should start 489 * using this as the selection mechanism - there can be 490 * preferred primary standby that we should fail to first and then 491 * nonpreferred secondary standby. 492 */ 493 if (cur == NULL) { 494 *nxt = PCLASS_PRIMARY; 495 return (0); 496 } else if (strcmp(cur, PCLASS_PRIMARY) == 0) { 497 *nxt = PCLASS_SECONDARY; 498 return (0); 499 } else if (strcmp(cur, PCLASS_SECONDARY) == 0) { 500 return (ENOENT); 501 } else { 502 return (EINVAL); 503 } 504 } 505