1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * CDDL HEADER START
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The contents of this file are subject to the terms of the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Common Development and Distribution License (the "License").
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * You may not use this file except in compliance with the License.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * See the License for the specific language governing permissions
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * and limitations under the License.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * When distributing Covered Code, include this CDDL HEADER in each
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If applicable, add the following below this CDDL HEADER, with the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * fields enclosed by brackets "[]" replaced with your own identifying
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * information: Portions Copyright [yyyy] [name of copyright owner]
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * CDDL HEADER END
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Implementation of "scsi_vhci_f_tpgs" T10 standard based failover_ops.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * NOTE: for non-sequential devices only.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* Supported device table entries. */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* Failover module plumbing. */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * max time for failover to complete is 3 minutes. Compute
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * number of retries accordingly, to ensure we wait for at least
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 3 minutes
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#define STD_FO_MAX_RETRIES (3*60*1000000)/STD_FO_RETRY_DELAY
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstd_device_probe(struct scsi_device *sd, struct scsi_inquiry *inq,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_NOTE, NULL, "std_device_probe: vidpid %s\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!std_device_probe: not a standard tpgs device"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!std_device_probe: Detected a "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Standard Asymmetric device "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "not yet supported\n"));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!std_device_probe: Detected a "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Standard Asymmetric device "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "with implicit failover\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!std_device_probe: Detected a "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Standard Asymmetric device "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "with explicit failover\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!std_device_probe: Detected a "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Standard Asymmetric device "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "which supports both implicit and explicit failover\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!std_device_probe: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For future use
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstd_activate_explicit(struct scsi_device *sd, int xlf_capable)
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "vhci_tpgs_set_target_groups() call from MPAPI");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Process the packet reason of CMD_PKT_CMPLT - return 0 if no
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * retry and 1 if a retry should be done
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstd_process_cmplt_pkt(struct scsi_device *sd, struct scsi_pkt *pkt,
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * tpgs access state changed
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li /* XXX: update path info? */
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li "!Device failover"
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li " state change");
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * Don't retry on the path
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * which is indicated as
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * standby, return failure.
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li } else if ((*retry_cnt)++ >=
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li "!Device failover failed: "
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li "timed out waiting for "
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li "path to become active");
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li "!(sd:%p)lun becoming active...\n",
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li " sense key:%x, ASC: %x, "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!(sd:%p):"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " status returned CHECK during std"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "status returned QFULL during std "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "status returned BUSY during std "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!(sd:%p) Bad status returned during std "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "activation (pkt %p, status %x)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For now we are going to use primary/online and secondary/online.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * There is no standby path returned by the dsp and we may have
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to do something different for other devices that use standby
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstd_path_activate(struct scsi_device *sd, char *pathclass,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs " failed vhci_tpgs_get_target_fo_mode\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "!path already active for %p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)sd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!mode is EXPLICIT for %p xlf %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (retval != 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!(sd:%p)std_path_activate failed(1)\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)sd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "STD mode is IMPLICIT for %p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)sd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bp = scsi_alloc_consistent_buf(ap, (struct buf *)NULL, DEV_BSIZE,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!(sd:%p)std_path_activate failed to alloc buffer",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)sd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, NULL, NULL);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!(sd:%p)std_path_activate failed to initialize packet",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)sd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) scsi_setup_cdb((union scsi_cdb *)(uintptr_t)pkt->pkt_cdbp,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Retry TRAN_BUSY till STD_FO_MAX_RETRIES is exhausted.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * All other errors are fatal and should not be retried.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "couldn't transport packet");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * Re-initialize retry_cmd_cnt. Allow transport and
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * cmd errors to go through a full retry count when
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * these are encountered. This way TRAN/CMD errors
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * retry count is not exhausted due to CMD_CMPLTs
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * delay. This allows the system
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * to brave a hick-up on the link at any given time,
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li * while waiting for the fo to complete.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Increased the number of retries when these error
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * cases are encountered. Also added a 1 sec wait
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * before retrying.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!Retrying path activation due to "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "pkt reason:%x, retry cnt:%d",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* FALLTHROUGH */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "complete successfully,"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int std_path_deactivate(struct scsi_device *sd, char *pathclass,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstd_path_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs " failed vhci_tpgs_get_target_fo_mode\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) strcpy(opinfo->opinfo_path_attr, PCLASS_PRIMARY);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) strcpy(opinfo->opinfo_path_attr, PCLASS_SECONDARY);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int std_path_ping(struct scsi_device *sd, void *ctpriv)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For future use
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Analyze the sense code to determine whether failover process
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " sense_key:%x, add_code: %x, qual_code:%x"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " sense_key:%x, add_code: %x, qual_code:%x"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " sense_key:%x, add_code: %x, qual_code:%x"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " sense_key:%x, add_code: %x, qual_code:%x"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * At this point sense data may be for power-on-reset
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * UNIT ATTN hardware errors, vendor unqiue sense data etc.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For all these cases, return SCSI_SENSE_UNKNOWN.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The first phase does not have a standby path so
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * there will be no explicit failover - when standard tpgs.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * standard defines preferred flag then we should start
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * using this as the selection mechanism - there can be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * preferred primary standby that we should fail to first and then
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * nonpreferred secondary standby.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);