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) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
aa6577ebdcd1cd4be810e610056636f5df7904f9Josef 'Jeff' Sipek * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Multiplexed I/O SCSI vHCI implementation
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* retry for the vhci_do_prout command when a not ready is returned */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * These values are defined to support the internal retry of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * SCSI packets for better sense code handling.
7bc7346c0c75ced7da727f63c2772fd53809244dcm/* changed to 132 to accomodate HDS */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Version Macros
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Flag to delay the retry of the reserve command
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* uscsi delay for a TRAN_BUSY */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* uscsi_restart_sense timeout id in case it needs to get canceled */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Bidirectional map of 'target-port' to port id <pid> for support of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * iostat(1M) '-Xx' and '-Yx' output.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic mod_hash_t *vhci_targetmap_bypid; /* <pid> -> 'target-port' */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic mod_hash_t *vhci_targetmap_byport; /* 'target-port' -> <pid> */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * functions exported by scsi_vhci struct cb_ops
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * functions exported by scsi_vhci struct dev_ops
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * functions exported by scsi_vhci scsi_hba_tran_t transport table
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_tgt_init(dev_info_t *, dev_info_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_scsi_tgt_free(dev_info_t *, dev_info_t *, scsi_hba_tran_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pgr_register_start(scsi_vhci_lun_t *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_start(struct scsi_address *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_abort(struct scsi_address *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_reset_target(struct scsi_address *, int level,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_getcap(struct scsi_address *, char *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_setcap(struct scsi_address *, char *, int, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_commoncap(struct scsi_address *, char *, int, int, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pHCI_cap(struct scsi_address *ap, char *cap, int val, int whom,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_pkt *vhci_scsi_init_pkt(struct scsi_address *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_reset_notify(struct scsi_address *, int, void (*)(caddr_t),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_get_bus_addr(struct scsi_device *, char *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_get_name(struct scsi_device *, char *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_bus_power(dev_info_t *, void *, pm_bus_power_op_t,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth void *, void *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_scsi_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth void *, dev_info_t **);
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Hornestatic int vhci_scsi_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphsstatic struct scsi_failover_ops *vhci_dev_fo(dev_info_t *, struct scsi_device *,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs void **, char **);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * functions registered with the mpxio framework via mdi_vhci_ops_t
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pathinfo_init(dev_info_t *, mdi_pathinfo_t *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pathinfo_uninit(dev_info_t *, mdi_pathinfo_t *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pathinfo_state_change(dev_info_t *, mdi_pathinfo_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pathinfo_online(dev_info_t *, mdi_pathinfo_t *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pathinfo_offline(dev_info_t *, mdi_pathinfo_t *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_failover(dev_info_t *, dev_info_t *, int);
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphsstatic int vhci_is_dev_supported(dev_info_t *, dev_info_t *, void *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ctl(dev_t, int, intptr_t, int, cred_t *, int *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_devctl(dev_t, int, intptr_t, int, cred_t *, int *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioc_get_phci_path(sv_iocdata_t *, caddr_t, int, caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioc_get_client_path(sv_iocdata_t *, caddr_t, int, caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioc_get_paddr(sv_iocdata_t *, caddr_t, int, caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioc_send_client_path(caddr_t, sv_iocdata_t *, int, caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_ioc_devi_to_path(dev_info_t *, caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_get_phci_path_list(dev_info_t *, sv_path_info_t *, uint_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_get_client_path_list(dev_info_t *, sv_path_info_t *, uint_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_get_iocdata(const void *, sv_iocdata_t *, int, caddr_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_get_iocswitchdata(const void *, sv_switch_to_cntlr_iocdata_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioc_alloc_pathinfo(sv_path_info_t **, sv_path_info_t **,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_ioc_free_pathinfo(sv_path_info_t *, sv_path_info_t *, uint_t);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_ioc_send_pathinfo(sv_path_info_t *, sv_path_info_t *, uint_t,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_efo_watch_cb(caddr_t, struct scsi_watch_result *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_pgr_validate_and_register(scsi_vhci_priv_t *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_dispatch_scsi_start(void *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_efo_done(void *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_initiate_auto_failback(void *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_update_pHCI_pkt(struct vhci_pkt *, struct scsi_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_update_pathinfo(struct scsi_device *, mdi_pathinfo_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct scsi_failover_ops *, scsi_vhci_lun_t *, struct scsi_vhci *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_kstat_create_pathinfo(mdi_pathinfo_t *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_quiesce_paths(dev_info_t *, dev_info_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth scsi_vhci_lun_t *, char *, char *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic char *vhci_devnm_to_guid(char *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_bind_transport(struct scsi_address *, struct vhci_pkt *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_run_cmd(void *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_pkt *vhci_create_retry_pkt(struct vhci_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct vhci_pkt *vhci_sync_retry_pkt(struct vhci_pkt *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_vhci_lun *vhci_lun_lookup(dev_info_t *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_vhci_lun *vhci_lun_lookup_alloc(dev_info_t *, char *, int *);
29c56acb8635e0b7173b9ec6046f477942e3ac95Raghuram Prahladastatic void vhci_lun_free(struct scsi_vhci_lun *dvlp, struct scsi_device *sd);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic int vhci_recovery_reset(scsi_vhci_lun_t *, struct scsi_address *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_print_prin_keys(vhci_prin_readkeys_t *, int);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic void vhci_print_cdb(dev_info_t *dip, uint_t level,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic void vhci_clean_print(dev_info_t *dev, uint_t level,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void vhci_print_prout_keys(scsi_vhci_lun_t *, char *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void vhci_invalidate_mpapi_lu(struct scsi_vhci *, scsi_vhci_lun_t *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * MP-API related functions
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthextern void vhci_mpapi_add_dev_prod(struct scsi_vhci *, char *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthextern int vhci_mpapi_ctl(dev_t, int, intptr_t, int, cred_t *, int *);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthextern void* vhci_get_mpapi_item(struct scsi_vhci *, mpapi_list_header_t *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthextern void vhci_mpapi_set_path_state(dev_info_t *, mdi_pathinfo_t *, int);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthextern int vhci_mpapi_update_tpg_acc_state_for_lu(struct scsi_vhci *,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Macros for the device-type mpxio options
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#define MPXIO_OPTIONS_LIST "device-type-mpxio-options-list"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth 0, /* streamtab */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs vhci_pathinfo_init, /* Pathinfo node init callback */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs vhci_pathinfo_uninit, /* Pathinfo uninit callback */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs vhci_pathinfo_state_change, /* Pathinfo node state change */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs vhci_client_attached, /* client attached callback */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs vhci_is_dev_supported /* is device supported by mdi */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The scsi_failover table defines an ordered set of 'fops' modules supported
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * by scsi_vhci. Currently, initialize this table from the 'ddi-forceload'
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * property specified in scsi_vhci.conf.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * before registering with the transport first.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!_init:soft state init failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!_init: scsi hba init failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth mutex_init(&vhci_global_mutex, NULL, MUTEX_DRIVER, NULL);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth mutex_init(&vhci_targetmap_mutex, NULL, MUTEX_DRIVER, NULL);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!_init: mod_install failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the system is done with us as a driver, so clean up
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * don't start cleaning up until we know that the module remove
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has worked -- if this works, then we know that each instance
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has successfully been DDI_DETACHed
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "!_fini: mod_remove failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Lookup scsi_failover by "short name" of failover module.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Load all scsi_failover_ops 'fops' modules.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the list of modules from scsi_vhci.conf */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "scsi_vhci.conf is missing 'ddi-forceload'");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "scsi_vhci.conf has empty 'ddi-forceload'");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* allocate failover table based on number of modules */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_zalloc(sizeof (struct scsi_failover) * (scsi_nfailover + 1),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* loop over modules specified in scsi_vhci.conf and open each module */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (i = 0, sf = scsi_failover_table; i < scsi_nfailover; i++) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sf->sf_mod = ddi_modopen(module[i], KRTLD_MODE_FIRST, &e);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * A module returns EEXIST if other software is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * supporting the intended function: for example
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the scsi_vhci_f_sum_emc module returns EEXIST
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * from _init if EMC powerpath software is installed.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "scsi_vhci_failover_ops", &e);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "unable to import 'scsi_failover_ops' from '%s', "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* register vid/pid of devices supported with mpapi */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* verify that at least the "well-known" modules were there */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "'ddi-forceload'");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "'ddi-forceload'");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* call sfo_init for modules that need it */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * unload all loaded scsi_failover_ops modules
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_open(dev_t *devp, int flag, int otype, cred_t *credp)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, MINOR2INST(getminor(*devp)));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_open: failed ENXIO\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((flag & FEXCL) && (vhci->vhci_state & VHCI_STATE_OPEN)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_close(dev_t dev, int flag, int otype, cred_t *credp)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, MINOR2INST(getminor(dev)));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_close: failed ENXIO\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (vhci_devctl(dev, cmd, data, mode, credp, rval));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (vhci_mpapi_ctl(dev, cmd, data, mode, credp, rval));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * attach the module
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_attach: cmd=0x%x\n", cmd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_attach: resume not yet"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "implemented\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_attach: unknown ddi command\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Allocate vhci data structure.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_soft_state_zalloc(vhci_softstate, instance) != DDI_SUCCESS) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "soft state alloc failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((vhci = ddi_get_soft_state(vhci_softstate, instance)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "bad soft state\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Allocate packet cache */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) snprintf(cache_name_buf, sizeof (cache_name_buf),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth mutex_init(&vhci->vhci_mutex, NULL, MUTEX_DRIVER, NULL);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Allocate a transport structure
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * register event notification routines with scsa
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs tran->tran_bus_config = vhci_scsi_bus_config;
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne tran->tran_bus_unconfig = vhci_scsi_bus_unconfig;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Attach this instance with the mpxio framework
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (mdi_vhci_register(MDI_HCI_CLASS_SCSI, dip, &vhci_opinfo, 0)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "mdi_vhci_register failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Attach this instance of the hba.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Regarding dma attributes: Since scsi_vhci is a virtual scsi HBA
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * driver, it has nothing to do with DMA. However, when calling
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * scsi_hba_attach_setup() we need to pass something valid in the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * dma attributes parameter. So we just use scsi_alloc_attr.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * SCSA itself seems to care only for dma_attr_minxfer and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * dma_attr_burstsizes fields of dma attributes structure.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * It expects those fileds to be non-zero.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "hba attach failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " ddi_create_minor_node failed\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Set pm-want-child-notification property for
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * power management of the phci and client
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "pm-want-child-notification?", NULL, NULL) != DDI_PROP_SUCCESS) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d fail to create pm-want-child-notification? prop",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci->vhci_taskq = taskq_create("vhci_taskq", 1, MINCLSYSPRI, 1, 4, 0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth taskq_create("vhci_update_pathstates", VHCI_NUM_UPDATE_TASKQ,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Set appropriate configuration flags based on options set in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * conf file.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, PROPFLAGS,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (!(vhci->vhci_conf_flags & VHCI_CONF_FLAGS_AUTO_FAILBACK))
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "disabled through scsi_vhci.conf file.");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Allocate an mpapi private structure
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci->mp_priv = kmem_zalloc(sizeof (mpapi_priv_t), KM_SLEEP);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_mpapi_init() failed"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_failover_modopen(vhci); /* load failover modules */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*ARGSUSED*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_detach: cmd=0x%x\n", cmd));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_detach: suspend/pm not yet"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "implemented\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_detach: unknown ddi command\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d unable to remove prop pm-want_child_notification?",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_getinfo()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Given the device number, return the devinfo pointer or the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * instance number.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*ARGSUSED*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*ARGSUSED*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip, PROPFLAGS,
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * This must be the .conf node without GUID property.
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * The node under fp already inserts a delay, so we
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * just return from here. We rely on this delay to have
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * all dips be posted to the ndi hotplug thread's newdev
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * list. This is necessary for the deferred attach
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * mechanism to work and opens() done soon after boot to
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * succeed.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "property failed"));
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * This must be .conf node with the GUID property. We don't
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * merge property by ndi_merge_node() here because the
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * devi_addr_buf of .conf node is "" always according the
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * implementation of vhci_scsi_get_name_bus_addr().
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(hba_dip));
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw "!tgt_init: called for %s (instance %d)\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_scsi_tgt_init: guid %s : found vlun 0x%p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "from_ticks %lx to_ticks %lx",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_scsi_tgt_init: guid %s : vlun not found "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH), NULL, &pip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Wait for the following conditions :
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 1. no vlun available yet
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 2. no path established
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 3. timer did not expire
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth while ((vlun == NULL) || (mdi_client_get_path_count(tgt_dip) == 0) ||
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vlun 0x%p lun guid %s not supported!",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((vhci_first_time == 0) && (from_ticks >= vhci_to_ticks)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "no wait for %s. from_tick %lx, to_tick %lx",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Timed out */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "tgt_init: client path count is "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "tgt_init: client path not "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* DEBUG */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*ARGSUSED*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
29c56acb8635e0b7173b9ec6046f477942e3ac95Raghuram Prahlada ASSERT(mdi_client_get_path_count(tgt_dip) <= 0);
29c56acb8635e0b7173b9ec6046f477942e3ac95Raghuram Prahlada dvlp = (struct scsi_vhci_lun *)scsi_device_hba_private_get(sd);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * a PGR register command has started; copy the info we need
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pgr_register_start(scsi_vhci_lun_t *vlun, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (vpkt->vpkt_flags & CFLAG_NOWAIT) ? VM_NOSLEEP : VM_SLEEP);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_reg_start: before bcopy:");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bcopy(pkt->pkt_cdbp, vlun->svl_cdb, sizeof (vlun->svl_cdb));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_reg_start: after bcopy:");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_start()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values : TRAN_FATAL_ERROR - vhci has been shutdown
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * or other fatal failure
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * preventing packet transportation
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * TRAN_BUSY - request queue is full
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * TRAN_ACCEPT - pkt has been submitted to phci
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * (or is held in the waitQ)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Description : Implements SCSA's tran_start() entry point for
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * packet transport
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* set if pkt is SCSI-II RESERVE cmd */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Block IOs if LUN is held or QUIESCED for IOs.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ((vlun->svl_flags & VLUN_QUIESCED_FLG) == VLUN_QUIESCED_FLG)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_lun needs to be quiesced before SCSI-II RESERVE command
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * can be issued. This may require a cv_timedwait, which is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * dangerous to perform in an interrupt context. So if this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is a RESERVE command a taskq is dispatched to service it.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This taskq shall again call vhci_scsi_start, but we shall be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * sure its not in an interrupt context.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Here we ensure that simultaneous SCSI-II RESERVE cmds don't
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * get serviced for a lun.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * To ensure that no IOs occur for this LUN for the duration
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * of this pkt set the VLUN_QUIESCED_FLG.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * In case this routine needs to exit on error make sure that
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this flag is cleared.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if this is a SCSI-II RESERVE command, set load balancing
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * policy to be ALTERNATE PATH to ensure that all subsequent
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * IOs are routed on the same path. This is because if commands
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * are routed across multiple paths then IOs on paths other than
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the one on which the RESERVE was executed will get a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * RESERVATION CONFLICT
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "!vhci_scsi_start: sending SCSI-2 RESERVE, vlun 0x%p, "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "svl_resrv_pip 0x%p, svl_flags: %x, lb_policy %x",
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik (void *)vlun, (void *)vlun->svl_resrv_pip, vlun->svl_flags,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * See comments for VLUN_RESERVE_ACTIVE_FLG in scsi_vhci.h
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * To narrow this window where a reserve command may be sent
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * down an inactive path the path states first need to be
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * updated. Before calling vhci_update_pathstates reset
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * VLUN_RESERVE_ACTIVE_FLG, just in case it was already set
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * for this lun. This shall prevent an unnecessary reset
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * from being sent out. Also remember currently reserved path
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * just for a case the new reservation will go to another path.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik if (vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the command is PRIN with action of zero, then the cmd
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is reading PR keys which requires filtering on completion.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Data cache sync must be guaranteed.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs if ((pkt->pkt_cdbp[0] == SCMD_PRIN) && (pkt->pkt_cdbp[1] == 0) &&
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Do not defer bind for PKT_DMA_PARTIAL
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* This is a non pkt_dma_partial case */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci%d %x: failed to bind transport: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vlun 0x%p pkt_reserved %x restore_lbp %x,"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This is the chance to adjust the pHCI's pkt and other information
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * from target driver's pkt.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(8, (CE_NOTE, vhci->vhci_dip, "vhci_scsi_start vpkt %p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)vpkt));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_bind: reserve flag set for vlun 0x%p, but, "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "pktpath 0x%p resrv path 0x%p differ. lb_policy %x",
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_bind returned null svp vlun 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)vlun));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * This is an attempt to reserve vpkt->vpkt_path. But the
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * previously reserved path referred by resrv_instance might
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * still be reserved. Hence we will send a release command
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * there in order to avoid a reservation conflict.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik VHCI_DEBUG(1, (CE_NOTE, vhci->vhci_dip, "!vhci_scsi_start: "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "conflicting reservation on another path, vlun 0x%p, "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "reserved instance %d, new instance: %d, pip: 0x%p",
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * In rare cases, the path referred by resrv_instance could
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * disappear in the meantime. Calling mdi_select_path() below
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * is an attempt to find out if the path still exists. It also
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * ensures that the path will be held when the release is sent.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik rval = mdi_select_path(cdip, NULL, MDI_SELECT_PATH_INSTANCE,
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik rel_pkt = scsi_init_pkt(&svp_resrv->svp_psd->sd_address,
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik sizeof (struct scsi_arq_status), 0, 0, SLEEP_FUNC,
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * This is very unlikely.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * scsi_init_pkt(SLEEP_FUNC) does not fail
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * because of resources. But in theory it could
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * fail for some other reason. There is not an
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * easy way how to recover though. Log a warning
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * and return.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "RELEASE(6) to %s failed, a potential "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "reservation conflict ahead.",
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik /* no need to check pkt_reserve_cmd here */
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * Ignore the return value. If it will fail
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * then most likely it is no longer reserved
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "!vhci_scsi_start: path 0x%p, issued SCSI-2"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Ensure that no other IOs raced ahead, while a RESERVE cmd was
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * QUIESCING the same lun.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ((vlun->svl_flags & VLUN_QUIESCED_FLG) == VLUN_QUIESCED_FLG)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * currently this thread only handles running PGR
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * commands, so don't bother creating it unless
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * something interesting is going to happen (like
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * either a PGR out, or a PGR in with enough space
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to hold the keys that are getting returned)
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* an error */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * SCSI-II RESERVE cmd is not expected in polled mode.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If this changes it needs to be handled for the polled scenario.
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * Set the path_instance *before* sending the scsi_pkt down the path
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * to mpxio's pHCI so that additional path abstractions at a pHCI
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * level (like maybe iSCSI at some point in the future) can update
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * the path_instance.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This path will not automatically retry pkts
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * internally, therefore, vpkt_org_vpkt should
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * never be set.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* the command exited with bad status */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (vpkt->vpkt_tgt_pkt->pkt_cdbp[0] == SCMD_PRIN) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* the command exited with bad status */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (pkt_reserve_cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_scsi_start: reserve failed vlun 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)vlun));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Do not destroy phci packet information for PKT_DMA_PARTIAL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_reset()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values : 0 - reset failed
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 1 - reset succeeded
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_recovery_reset:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Issues reset to the device
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vlun - vhci lun pointer of the device
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * ap - address of the device
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * select_path:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If select_path is FALSE, then the address specified in ap is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the path on which reset will be issued.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If select_path is TRUE, then path is obtained by calling
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * mdi_select_path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * recovery_depth:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Caller can specify the level of reset.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * VHCI_DEPTH_LUN -
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Issues LUN RESET if device supports lun reset.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * VHCI_DEPTH_TARGET -
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If Lun Reset fails or the device does not support
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Lun Reset, issues TARGET RESET
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * VHCI_DEPTH_ALL -
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If Lun Reset fails or the device does not support
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Lun Reset, issues TARGET RESET.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If TARGET RESET does not succeed, issues Bus Reset.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_recovery_reset(scsi_vhci_lun_t *vlun, struct scsi_address *ap,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Note: The scsi_address passed to this routine could be the scsi_address
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * for the virtual device or the physical device. No assumptions should be
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * made in this routine about the contents of the ap structure.
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * Further, note that the child dip would be the dip of the ssd node regardless
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * of the scsi_address passed in.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_reset_target(struct scsi_address *ap, int level, uint8_t select_path)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "psd is NULL, pip 0x%p, svp 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "path %s, reset %d failed",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Select next path and issue the reset, repeat
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * until all paths are exhausted
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * called by vhci_getcap and vhci_setcap to get and set (respectively)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * SCSI capabilities
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (cap == (char *)0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_commoncap: invalid arg"));
49569606959a0fe8afc95ca0054b28a4ac77f765jw "!vhci_commoncap: vlun is null"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Process setcap request.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * At present, we can only set binary (0/1) values
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cidx) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (val == 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (tgtonly == 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "scsi_vhci_setcap: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Returning error since whom = 0"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Set the capability accordingly.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Always return success */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "0x%x/0x%x/0x%x/%d\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Process getcap request.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cidx) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * For X86 this capability is caught in scsi_ifgetcap().
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * XXX Should this be getting the value from the pHCI?
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * scsi_vhci will always return success for LUN reset.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * When request for doing LUN reset comes
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * through scsi_reset entry point, at that time attempt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * will be made to do reset through all the possible
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "scsi_vhci_getcap:"
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * For X86 this capability is caught in scsi_ifgetcap().
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * XXX Should this be getting the value from the pHCI?
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "0x%x/0x%x/0x%x/%d\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_getcap()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_abort()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_init_pkt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values : pointer to scsi_pkt, or NULL
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_pkt *
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
f8404091c19a4530e158b930a3d3e459264ec3ffRamana.Srikanth "!init pkt: cdb size not supported\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ap, cmdlen, statuslen, tgtlen, sizeof (*vpkt), callback,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the vhci's private structure */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Save the target driver's packet */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Save pkt_tgt_init_pkt fields if deferred binding
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is needed or for other purposes.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vpkt->vpkt_flags = (callback == NULL_FUNC) ? CFLAG_NOWAIT : 0;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else { /* pkt not NULL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Clear any stale error flags */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Immediate binding is needed.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Target driver may not set this flag in next invocation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci has to remember this flag was set during first
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * invocation of vhci_scsi_init_pkt.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Re-initialize some of the target driver packet state
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * information.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Binding a vpkt->vpkt_path for this IO at init_time.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If an IO error happens later, target driver will clear
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this vpkt->vpkt_path binding before re-init IO again.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_scsi_init_pkt: calling v_b_t %p, newpkt %d\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "v_s_i_p calling update_pHCI_pkt resid %ld\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_scsi_init_pkt: v_b_t called 0x%p rval 0x%x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * No paths available. Could not bind
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * any pHCI. Setting EFAULT as a way
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to indicate no DMA is mapped.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Do not indicate any pHCI errors to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * target driver otherwise.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_scsi_init_pkt: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "v_b_t failed 0x%p newpkt %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Update the resid for the target driver */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_destroy_pkt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values : none
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_ha_private;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_dmafree()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values : none
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*ARGSUSED*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_ha_private;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Function name : vhci_scsi_sync_pkt()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values : none
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*ARGSUSED*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_ha_private;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * routine for reset notification setup, to register or cancel.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_reset_notify(struct scsi_address *ap, int flag,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip, PROPFLAGS,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Message is "sd# at scsi_vhci0: unit-address <guid>: <bus_addr>".
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * <guid> bus_addr argument == 0
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * <bus_addr> bus_addr argument != 0
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Since the <guid> is already provided with unit-address, we just
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * provide failover module in <bus_addr> to keep output shorter.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (bus_addr == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* report the guid: */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* report the name of the failover module */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_get_name(struct scsi_device *sd, char *name, int len)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return a pointer to the guid part of the devnm.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * devnm format is "nodename@busaddr", busaddr format is "gGUID".
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic char *
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_bind_transport(struct scsi_address *ap, struct vhci_pkt *vpkt, int flags,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_bind_transport: path select fail\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_bind_transport: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "valid first path 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_bind_transport: invalid first path 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (vpkt->vpkt_tgt_pkt->pkt_cdbp[0] == SCMD_PRIN) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the path is already bound for PKT_PARTIAL_DMA case,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * try to use the same path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) && vpkt->vpkt_path) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_bind_transport: PKT_PARTIAL_DMA "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vpkt 0x%p, path 0x%p\n",
1cb30f30670732e4f87cfe7c44221ce20b1615f4gap * Get path_instance. Non-zero with FLAG_PKT_PATH_INSTANCE set
1cb30f30670732e4f87cfe7c44221ce20b1615f4gap * indicates that mdi_select_path should be called to select a
1cb30f30670732e4f87cfe7c44221ce20b1615f4gap * specific instance.
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * NB: Condition pkt_path_instance reference on proper allocation.
b98fa0e92123ad03cb93b098099a9392c4bedc0brralphs if ((vpkt->vpkt_tgt_pkt->pkt_flags & FLAG_PKT_PATH_INSTANCE) &&
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If reservation is active bind the transport directly to the pip
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * with the reservation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if we are here then we are in the midst of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * an attach/probe of the client device.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We attempt to bind to ONLINE path if available,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * else it is OK to bind to a STANDBY path (instead
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * of triggering a failover) because IO associated
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * with attach/probe (eg. INQUIRY, block 0 read)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * are completed by targets even on passive paths
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If no ONLINE paths available, it is important
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to set svl_waiting_for_activepath for two
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * reasons: (1) avoid sense analysis in the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "external failure detection" codepath in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_intr(). Failure to do so will result in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * infinite loop (unless an ONLINE path becomes
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * available at some point) (2) avoid
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * unnecessary failover (see "---Waiting For Active
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Path---" comment below).
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * ---Waiting For Active Path---
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This device was discovered across a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * passive path; lets wait for a little
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * bit, hopefully an active path will
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * show up obviating the need for a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * failover
aa6577ebdcd1cd4be810e610056636f5df7904f9Josef 'Jeff' Sipek if ((gethrtime() - vlun->svl_wfa_time) >=
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * an active path has come
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!Lun not held\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * now that the LUN is stable, one last check
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to make sure no other changes sneaked in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * (like a path coming online or a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * failover initiated by another thread)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Check if there is an ONLINE path OR a STANDBY path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * available. If none is available, do not attempt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to do a failover, just return a fatal error at this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * No paths available, jus return FATAL error.
40764c95159232b912f6f16cb1fb1a41897fb0a7Victor Li "mdi_failover\n"));
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth /* Verify match of specified path_instance and selected path_instance */
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth (path_instance == mdi_pi_get_path_instance(vpkt->vpkt_path)));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For PKT_PARTIAL_DMA case, call pHCI's scsi_init_pkt whenever
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * target driver calls vhci_scsi_init_pkt.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_bind_transport: PKT_PARTIAL_DMA "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vpkt 0x%p, path 0x%p hba_pkt 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (pkt == NULL || (vpkt->vpkt_flags & CFLAG_DMA_PARTIAL)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!bind transport: 0x%p 0x%p 0x%p\n",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Consider it a fatal error if b_error is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * set as a result of DMA binding failure
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * vs. a condition of being temporarily out of
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * some resource
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/*PRINTFLIKE3*/
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_log(int level, dev_info_t *dip, const char *fmt, ...)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* do a PGR out with the information we've saved away */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth new_pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth cmn_err(CE_WARN, "!vhci_do_prout: scsi_init_pkt failed");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* chk for state change and update */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* chk for alua first */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_do_prout retry 0x%x "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "(0x%x 0x%x 0x%x)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_do_prout 0x%x "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "(0x%x 0x%x 0x%x)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth MDI_SELECT_ONLINE_PATH|MDI_SELECT_STANDBY_PATH, NULL, &npip);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs nsvp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_run_cmd: no "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client priv! 0x%p offlined?\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_WARN, NULL, "%s%d: key registration failed, "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "couldn't be replicated on all paths",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "vhci_run_cmd: before bcopy:");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)prout->active_service_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "vhci_run_cmd: after bcopy:");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The PROUT commands are not included in the automatic retry
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * mechanism, therefore, vpkt_org_vpkt should never be set here.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get the keys registered with this target. Since we will have
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * registered the same key with multiple initiators, strip out
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * any duplicate keys.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The pointers which will be used to filter the registered keys from
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the device will be stored in filter_prin and filter_pkt. If the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * allocation length of the buffer was sufficient for the number of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * parameter data bytes available to be returned by the device then the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * key filtering will use the keylist returned from the original
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * request. If the allocation length of the buffer was not sufficient,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * then the filtering will use the keylist returned from the request
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that is resent below.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the device returns an additional length field that is greater than
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the allocation length of the buffer, then allocate a new buffer which
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * can accommodate the number of parameter data bytes available to be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * returned. Resend the scsi PRIN command, filter out the duplicate
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * keys and return as many of the unique keys found that was originally
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * requested and set the additional length field equal to the data bytes
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * of unique reservation keys available to be returned.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the device returns an additional length field that is less than or
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * equal to the allocation length of the buffer, then all the available
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * keys registered were returned by the device. Filter out the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * duplicate keys and return all of the unique keys found and set the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * additional length field equal to the data bytes of the reservation
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * keys to be returned.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs#define VHCI_PRIN_HEADER_SZ (sizeof (prin->length) + sizeof (prin->generation))
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs struct scsi_vhci *vhci = ADDR2VHCI(&vpkt->vpkt_tgt_pkt->pkt_address);
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * If the caller only asked for an amount of data that would not
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * be enough to include any key data it is likely that they will
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * send the next command with a buffer size based on the information
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * from this header. Doing recovery on this would be a duplication
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * of efforts.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs if (vpkt->vpkt_tgt_init_bp->b_bcount <= VHCI_PRIN_HEADER_SZ) {
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * Can fail as sleep is not allowed.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs bp_mapin_common(vpkt->vpkt_tgt_init_bp, VM_NOSLEEP);
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * The retry buf doesn't need to be mapped in.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_do_prin: bp_mapin_common failed."));
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * According to SPC-3r22, sec 4.3.4.6: "If the amount of
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * information to be transferred exceeds the maximum value
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * that the ALLOCATION LENGTH field is capable of specifying,
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * the device server shall...terminate the command with CHECK
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * CONDITION status". The ALLOCATION LENGTH field of the
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * PERSISTENT RESERVE IN command is 2 bytes. We should never
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * get here with an ADDITIONAL LENGTH greater than 0xFFFF
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * so if we do, then it is an error!
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs "vhci_do_prin: Device returned invalid "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If prin->length is greater than the byte count allocated in the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * original buffer, then resend the request with enough buffer
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * allocated to get all of the available registered keys.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs if ((vpkt->vpkt_tgt_init_bp->b_bcount < needed_length) &&
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * This is the buf with buffer pointer
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * where the prin readkeys will be
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * returned from the device
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs new_bp = scsi_alloc_consistent_buf(&svp->svp_psd->sd_address,
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs if ((new_bp == NULL) || (new_bp->b_un.b_addr == NULL)) {
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs vhci_scsi_destroy_pkt(&new_pkt->pkt_address, new_pkt);
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs new_pkt->pkt_cdbp[7] = (uchar_t)(needed_length >> 8);
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * There were more keys then the original request asked for.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Release the old path because it does not matter which path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this command is sent down. This allows the normal bind
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * transport mechanism to be used.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Dispatch the retry command
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (taskq_dispatch(vhci->vhci_taskq, vhci_dispatch_scsi_start,
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs vhci_scsi_destroy_pkt(&new_pkt->pkt_address, new_pkt);
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * If we return VHCI_CMD_RETRY, that means the caller
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * is going to bail and wait for the reissued command
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * to complete. In that case, we need to decrement
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * the path command count right now. In any other
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * case, it'll be decremented by the caller.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * The original request got all of the keys or the recovery
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * packet returns.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_do_prin: %d keys read\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(5, (CE_NOTE, NULL, "vhci_do_prin: from storage\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_do_prin: MPxIO old keys:\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Filter out all duplicate keys returned from the device
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We know that we use a different key for every host, so we
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * can simply strip out duplicates. Otherwise we would need to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * do more bookkeeping to figure out which keys to strip out.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * If we got at least 1 key copy it.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs * find next unique key.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (j = 0; j < new; j++) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sizeof (mhioc_resv_key_t)) == 0) {
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs /* Stored Big Endian */
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs /* Stored Big Endian */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If we arrived at this point after issuing a retry, make sure
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that we put everything back the way it originally was so
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that the target driver can complete the command correctly.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Make sure the original buffer is mapped into kernel
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * space before we try to copy the filtered keys into
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Now copy the desired number of prin keys into the original
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * target buffer.
3f51917eaddab73f3785bc93295b825527ebf5e3rralphs if (svl_prin_length <= vpkt->vpkt_tgt_init_bp->b_bcount) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * It is safe to return all of the available unique
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Not all of the available keys were requested by the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * original command.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_do_prin: To Application:\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_do_prin: MPxIO new keys:\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If we arrived at this point after issuing a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * retry, make sure that we put everything back
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the way it originally was so that ssd can
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * complete the command correctly.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Mark this command completion as having an error so that
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * ssd will retry the command.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Make sure that the semaphore is only released once.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_private;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * sync up the target driver's pkt with the pkt that
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * we actually used
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth /* Return path_instance information back to the target driver. */
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * If both packets were correctly allocated,
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * return path returned by pHCI.
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth /* Otherwise return path of pHCI we used */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * cmd completed successfully, check for scsi errors
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Received sns key %x esc %x escq %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if we are here it means we are
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * in the midst of a probe/attach
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * through a passive path; this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * case is exempt from sense analysis
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * for detection of ext. failover
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * because that would unnecessarily
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * increase attach time.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * parity error
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * looks like some other thread
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has already detected this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * condition
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * externally initiated failover
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has occurred or is in progress
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * looks like some other thread
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has already detected this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * condition
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If this is a good SCSI-II RELEASE cmd completion then restore
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the load balancing policy and reset VLUN_RESERVE_ACTIVE_FLG.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If this is a good SCSI-II RESERVE cmd completion then set
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * VLUN_RESERVE_ACTIVE_FLG.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_intr: vlun 0x%p release path 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_intr: vlun 0x%p reserved path 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_intr: vlun 0x%p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "reserve conflict on path 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* FALLTHROUGH */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Update I/O completion statistics for the path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth mdi_pi_kstat_iosupdate(vpkt->vpkt_path, vpkt->vpkt_tgt_init_bp);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Command completed successfully, release the dma binding and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * destroy the transport side of the packet.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs (pkt->pkt_cdbp[0] == SCMD_PRIN) && vpkt->vpkt_tgt_init_bp) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the action (value in byte 1 of the cdb) is zero,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * we're reading keys, and that's the only condition
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * where we need to be concerned with filtering keys
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * and potential retries. Otherwise, we simply signal
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the semaphore and move on.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If this is the completion of an internal
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * retry then we need to make sure that the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * pkt and tpkt pointers are readjusted so
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the calls to scsi_destroy_pkt and pkt_comp
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * below work * correctly.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If this command was issued through
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the taskq then we need to clear
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this flag for proper processing in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the case of a retry from the target
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if vhci_do_prin returns VHCI_CMD_CMPLT then
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vpkt will contain the address of the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * original vpkt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The command has been resent to get
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * all the keys from the device. Don't
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * complete the command with ssd until
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the retry completes.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!scsi vhci timeout invoked\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This status is returned if the transport has sent the cmd
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * down the link to the target and then some error occurs.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * In case of SCSI-II RESERVE cmd, we don't know if the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * reservation been accepted by the target or not, so we need
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to clear the reservation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " cmd_tran_err for scsi-2 reserve cmd\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_intr cmd_tran_err reset failed!"));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this is the last path then report CMD_DEV_GONE to the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * target driver, otherwise report BUSY to triggger retry.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "cmd_dev_gone on last path\n"));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Report CMD_CMPLT-with-BUSY to cause retry. */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "cmd_dev_gone\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * SCSI-II RESERVE cmd has been serviced by the lower layers clear
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the flag so the lun is not QUIESCED any longer.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Also clear the VHCI_PKT_THRU_TASKQ flag, to ensure that if this pkt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is retried, a taskq shall again be dispatched to service it. Else
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * it may lead to a system hang if the retry is within interrupt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * context.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vpkt_org_vpkt should always be NULL here if the retry command
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has been successfully processed. If vpkt_org_vpkt != NULL at
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this point, it is an error so restore the original vpkt and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * return an error to the target driver so it can retry the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * command as appropriate.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Mark this command completion as having an error so that
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * ssd will retry the command.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For PARTIAL_DMA, vhci should not free the path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Target driver will call into vhci_scsi_dmafree or
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * destroy pkt to release this path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * two possibilities: (1) failover has completed
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * or (2) is in progress; update our path states for
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the former case; for the latter case,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * initiate a scsi_watch request to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * determine when failover completes - vlun is HELD
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * until failover completes; BUSY is returned to upper
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * layer in both the cases
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_private;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "detected for %s; updating path states...\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * set the vlun flag to indicate to the task that the target
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * port group needs updating
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) taskq_dispatch(vhci->vhci_update_pathstates_taskq,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!%s (%s%d): Waiting for externally initiated failover "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "request packet allocation for %s failed....\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * place a hold on the path...we don't want it to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vanish while scsi_watch is in progress
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth svp->svp_sw_token = scsi_watch_request_submit(svp->svp_psd,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_efo_watch_cb:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Callback from scsi_watch request to check the failover status.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Completion is either due to successful failover or timeout.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Upon successful completion, vhci_update_path_states is called.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For timeout condition, vhci_efo_done is called.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Always returns 0 to scsi_watch to keep retrying till vhci_efo_done
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * terminates this request properly in a separate thread.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_efo_watch_cb(caddr_t arg, struct scsi_watch_result *resultp)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Already completed failover or timedout.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Waiting for vhci_efo_done to terminate this scsi_watch.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
aa6577ebdcd1cd4be810e610056636f5df7904f9Josef 'Jeff' Sipek if ((gethrtime() - swarg->svs_tos) >= VHCI_EXTFO_TIMEOUT) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs rval = vlun->svl_fops->sfo_analyze_sense(svp->svp_psd, sensep,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (rval) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Only update path states in case path is definitely
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * inactive, or no failover occurred. For all other
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * check conditions continue pinging. A unexpected
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * check condition shouldn't cause pinging to complete
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * prematurely.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (*((unsigned char *)statusp) ==
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if ((*((unsigned char *)statusp)) &
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * we got here because we had detected an
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * externally initiated failover; things
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * have settled down now, so let's
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * start up a task to update the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * path states and target port group
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) taskq_dispatch(vhci->vhci_update_pathstates_taskq,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
aa6577ebdcd1cd4be810e610056636f5df7904f9Josef 'Jeff' Sipek if ((gethrtime() - swarg->svs_tos) >= VHCI_EXTFO_TIMEOUT) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_efo_done:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * cleanly terminates scsi_watch and free up resources.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Called as taskq function in vhci_efo_watch_cb for EFO timeout condition
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * or by vhci_update_path_states invoked during external initiated
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * failover completion.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Wait for clean termination of scsi_watch */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* release path and freeup resources to indicate failover completion */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Update the path states
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vlun should be HELD when this is invoked.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Calls vhci_efo_done to cleanup resources allocated for EFO.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct scsi_vhci_lun *vlun = (struct scsi_vhci_lun *)arg;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(dip, NULL, (MDI_SELECT_ONLINE_PATH |
b08fdaf74b533ea5a3df0741037e7818f1f0c834Sheshadri Vasudevan MDI_SELECT_STANDBY_PATH | MDI_SELECT_NO_PREFERRED), NULL, &npip);
b08fdaf74b533ea5a3df0741037e7818f1f0c834Sheshadri Vasudevan (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (mdi_prop_lookup_string(pip, "path-class", &pclass) !=
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_update_pathstates: prop lookup failed for "
b08fdaf74b533ea5a3df0741037e7818f1f0c834Sheshadri Vasudevan (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Need to update the "path-class" property
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * value in the device tree if different
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * from the existing value.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Only change the state if needed. i.e. Don't call
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * mdi_pi_set_state to ONLINE a path if its already
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * ONLINE. Same for STANDBY paths.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_update_pathstates: marking path"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "(%s%d): path %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "is now ONLINE because of "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "an externally initiated failover",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * No need to update
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * svl_active_pclass
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik /* Check for Reservation Conflict */
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "!vhci_update_pathstates: No resources "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "(buf)\n"));
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "!vhci_update_pathstates: reserv. "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "conflict to be resolved on 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if ((opinfo.opinfo_path_state == SCSI_PATH_INACTIVE) &&
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_update_pathstates: marking path"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "(%s%d): path %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "is now STANDBY because of "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "an externally initiated failover",
b08fdaf74b533ea5a3df0741037e7818f1f0c834Sheshadri Vasudevan (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Check to see if this vlun has an active SCSI-II RESERVE. If so
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * clear the reservation by sending a reset, so the host doesn't
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * receive a reservation conflict. The reset has to be sent via a
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * working path. Let's use a path referred to by svp_conflict as it
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * should be working.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * Reset VLUN_RESERVE_ACTIVE_FLG for this vlun. Also notify ssd
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * of the reset, explicitly.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik if (svp_conflict && (vlun->svl_xlf_capable == 0)) {
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_update_pathstates:"
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik " sending recovery reset on 0x%p, path_state: %x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Update the AccessState of related MP-API TPGs
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) vhci_mpapi_update_tpg_acc_state_for_lu(vhci, vlun);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pathinfo_init(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip, PROPFLAGS,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pathinfo_init: lun guid property failed"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vlun = vhci_lun_lookup_alloc(tgt_dip, guid, &vlun_alloced);
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * Initialize svl_lb_policy_save only for newly allocated vlun. Writing
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * to svl_lb_policy_save later could accidentally overwrite saved lb
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik vlun->svl_lb_policy_save = mdi_get_lb_policy(tgt_dip);
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne if (hba->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX) {
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * For a SCSI_HBA_ADDR_COMPLEX transport we store a pointer to
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * scsi_device in the scsi_address structure. This allows an
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * an HBA driver to find its scsi_device(9S) and
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * per-scsi_device(9S) HBA private data given a
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * scsi_address(9S) by using scsi_address_device(9F) and
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * scsi_device_hba_private_get(9F)).
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne } else if (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * Clone transport structure if requested, so
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * Self enumerating HBAs always need to use cloning
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * SPI pHCI unit-address. If we ever need to support this
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * we could set a.spi.a_target/a.spi.a_lun based on pathinfo
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * node unit-address properties. For now we fail...
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * Mark scsi_device as being associated with a pathinfo node. For
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * a scsi_device structure associated with a devinfo node,
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * scsi_ctlops_initchild sets this field to NULL.
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * LEGACY: sd_private: set for older mpxio-capable pHCI drivers with
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * too much scsi_vhci/mdi/ndi knowledge. Remove this code when all
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * mpxio-capable pHCI drivers use SCSA enumeration services (or at
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne * least have been changed to use sd_pathinfo instead).
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne /* See scsi_hba.c for info on sd_tran_safe kludge */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * call hba's target init entry point if it exists
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo_init: tran_tgt_init failed for "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_pathinfo_init: path:%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne if (hba && (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE))
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pathinfo_uninit(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh vhci_mpapi_set_path_state(vdip, pip, MP_DRVR_PATH_STATE_UNINIT);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* path already freed. Nothing to do. */
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne if (hba->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX) {
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne /* Verify plumbing */
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne } else if (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne /* Switch to cloned scsi_hba_tran(9S) structure */
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed if ((hba->tran_tgt_free != NULL) && !psd->sd_tran_tgt_free_done) {
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Free the pathinfo related scsi_device inquiry data. Note that this
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * matches what happens for scsi_hba.c devinfo case at uninitchild time.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs kmem_free((caddr_t)psd->sd_inq, sizeof (struct scsi_inquiry));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_pathinfo_uninit: path=0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pathinfo_state_change(dev_info_t *vdip, mdi_pathinfo_t *pip,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth mdi_pathinfo_state_t state, uint32_t ext_state, int flags)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We do not want to issue any commands down the path in case
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * sync flag is set. Lower layers might not be ready to accept
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * any I/O commands.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Hold the LUN.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Issue scsi reset if it happens to be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * reserved path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if reservation pending on
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this path, dont' mark the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * path busy
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "_state_change (pip:%p): "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " reservation: fail busy\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "_state_change "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " (pip:%p): "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "reset failed, "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "give up!\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Failback if enabling a standby path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * and it is the primary class or
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * preferred class
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if not preferred - compare
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * path-class with class
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!path-class "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " lookup "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "failed. rv: %d"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " class: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "preferred path: %p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "USER_DISABLE->USER_ENABLE "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "transition for lun %s\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if PGR is active, revalidate key and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * register on this path also, if key is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * still valid
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Inform target driver about any
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * reservations to be reinstated if target
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has dropped reservation during the busy
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Release the LUN
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Path transition is complete.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Run callback to indicate target driver to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * retry to prevent IO starvation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (state) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Path transition is complete.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Run callback to indicate target driver to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * retry to prevent IO starvation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Parse the mpxio load balancing options. The datanameptr
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * will point to a string containing the load-balance-options value.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The load-balance-options value will be a property that
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * defines the load-balance algorithm and any arguments to that
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * algorithm.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For example:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * device-type-mpxio-options-list=
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "device-type=SUN SENA", "load-balance-options=logical-block-options"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "device-type=SUN SE6920", "round-robin-options";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * logical-block-options="load-balance=logical-block", "region-size=15";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * round-robin-options="load-balance=round-robin";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the load-balance is not defined the load balance algorithm will
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * default to the global setting. There will be default values assigned
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to the arguments (region-size=18) and if an argument is one
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that is not known, it will be ignored.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_parse_mpxio_lb_options(dev_info_t *dip, dev_info_t *cdip,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, datanameptr,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (caddr_t)&config_list, &config_list_len) != DDI_PROP_SUCCESS) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth while (config_list_len > 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get the load-balance scheme */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth int i = 0;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth tmp = dataptr + (strlen(LOGICAL_BLOCK_REGION_SIZE) + 1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* check for numeric value */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Illegal region size: %s."
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " Setting to default value: %d",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((region_size >= 0) && (load_balance != LOAD_BALANCE_LBA)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_parse_mpxio_lb_options: region-size: %d"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "only valid for load-balance=logical-block\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((region_size == -1) && (load_balance == LOAD_BALANCE_LBA)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_parse_mpxio_lb_options: No region-size"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " defined load-balance=logical-block."
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " Default to: %d\n", LOAD_BALANCE_DEFAULT_REGION_SIZE));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Parse the device-type-mpxio-options-list looking for the key of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "load-balance-options". If found, parse the load balancing options.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Check the comment of the vhci_get_device_type_mpxio_options()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * for the device-type-mpxio-options-list.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_parse_mpxio_options(dev_info_t *dip, dev_info_t *cdip,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * get the data list
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth strncmp(dataptr, DEVICE_TYPE_STR, strlen(DEVICE_TYPE_STR))
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Check the inquriy string returned from the device with the device-type
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Check for the existence of the device-type-mpxio-options-list and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if found parse the list checking for a match with the device-type
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * value and the inquiry string returned from the device. If a match
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is found, parse the mpxio options list. The format of the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * device-type-mpxio-options-list is:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * device-type-mpxio-options-list=
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "device-type=SUN SENA", "load-balance-options=logical-block-options"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "device-type=SUN SE6920", "round-robin-options";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * logical-block-options="load-balance=logical-block", "region-size=15";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * round-robin-options="load-balance=round-robin";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_get_device_type_mpxio_options(dev_info_t *dip, dev_info_t *cdip,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * look up the device-type-mpxio-options-list and walk thru
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the list compare the vendor ids of the earlier inquiry command and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * with those vids in the list if there is a match, lookup
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the mpxio-options value
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (caddr_t)&config_list, &config_list_len) == DDI_PROP_SUCCESS) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Compare vids in each duplet - if it matches,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * parse the mpxio options list.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (len = config_list_len, vidptr = config_list; len > 0;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* point to next duplet */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* add len of this duplet */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get to device type */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((vidlen != 0) &&
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get to next duplet */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get to the next device-type */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_update_pathinfo(struct scsi_device *psd, mdi_pathinfo_t *pip,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs if (fo->sfo_path_get_opinfo(psd, &opinfo, vlun->svl_fops_ctpriv) != 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Failed to get operation info for path:%p\n", (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* set the xlf capable flag in the vlun for future use */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Externally initiated failover has happened;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * force the path state to be STANDBY/ONLINE,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * next IO will trigger failover and thus
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * sync-up the pathstates. Reason we don't
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * sync-up immediately by invoking
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_update_pathstates() is because it
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * needs a VHCI_HOLD_LUN() and we don't
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * want to block here.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Further, if the device is an ALUA device,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * then failure to exactly match 'pclass' and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 'svl_active_pclass'(as is the case here)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * indicates that the currently active path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is a 'non-optimized' path - which means
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that 'svl_active_pclass' needs to be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * replaced with opinfo.opinfo_path_state
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The device is ALUA compliant. The
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * state need to be changed to online
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * rather than standby state which is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * done typically for a asymmetric
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * device that is non ALUA compliant.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Non ALUA device case.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * Find out a class of currently reserved path if there
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik if ((vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) &&
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "!vhci_update_pathinfo: prop lookup "
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik "failed for path 0x%p\n",
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * Something is wrong with the reserved path.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * We can't do much with that right here. Just
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * force re-reservation to another path.
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik (void) fo->sfo_pathclass_next(NULL, &best_pclass,
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik if ((force_rereserve == 1) || ((resrv_pclass != NULL) &&
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * Inform target driver that a reservation
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * should be reinstated because the reserved
1c8dbe373c495062a47947238bee6410414fa97dMilos Muzik * path is not the most preferred one.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * lets release the mutex before we try to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * allocate since the potential to sleep is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * possible.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (opinfo.opinfo_path_state == SCSI_PATH_ACTIVE_NONOPT) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (opinfo.opinfo_path_state == SCSI_PATH_INACTIVE) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * externally initiated failover has happened;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * force state to ONLINE (see comment above)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Initiate auto-failback, if enabled, for path if path-state
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is transitioning from OFFLINE->STANDBY and pathclass is the
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * preferred pathclass for this storage.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * NOTE: In case where opinfo_path_state is SCSI_PATH_ACTIVE
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * (above), where the pi state is set to STANDBY, we don't
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * initiate auto-failback as the next IO shall take care of.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this. See comment above.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (((vhci->vhci_conf_flags & VHCI_CONF_FLAGS_AUTO_FAILBACK) ==
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ((MDI_PI_OLD_STATE(pip) == MDI_PATHINFO_STATE_OFFLINE)||
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " OFFLINE->STANDBY transition for lun %s\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(8, (CE_NOTE, NULL, "vhci_update_pathinfo: opinfo_rev = %x,"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " opinfo_path_state = %x opinfo_preferred = %x, opinfo_mode = %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Form the kstat name and and call mdi_pi_kstat_create()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* return if we have already allocated kstats */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We need instance numbers to create a kstat name, return if we don't
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * have instance numbers assigned yet.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((ddi_get_instance(tgt_dip) == -1) || (ddi_get_instance(pdip) == -1))
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * A path oriented kstat has a ks_name of the form:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * <client-driver><instance>.t<pid>.<pHCI-driver><instance>
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We maintain a bidirectional 'target-port' to <pid> map,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * called targetmap. All pathinfo nodes with the same
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 'target-port' map to the same <pid>. The iostat(1M) code,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * when parsing a path oriented kstat name, uses the <pid> as
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * a SCSI_VHCI_GET_TARGET_LONGNAME ioctl argument in order
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to get the 'target-port'. For KSTAT_FLAG_PERSISTENT kstats,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this ioctl needs to translate a <pid> to a 'target-port'
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * even after all pathinfo nodes associated with the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 'target-port' have been destroyed. This is needed to support
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * consistent first-iteration activity-since-boot iostat(1M)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * output. Because of this requirement, the mapping can't be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * based on pathinfo information in a devinfo snapshot.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* determine 'target-port' */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs SCSI_ADDR_PROP_TARGET_PORT, &target_port) == MDI_SUCCESS) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the pHCI did not set up 'target-port' on this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * pathinfo node, assume that our client is the only
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * one with paths to the device by using the guid
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * value as the 'target-port'. Since no other client
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * will have the same guid, no other client will use
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the same <pid>. NOTE: a client with an instance
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * number always has a guid.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * For this type of mapping we don't want the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * <id> -> 'target-port' mapping to be made. This
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * will cause the SCSI_VHCI_GET_TARGET_LONGNAME ioctl
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to fail, and the iostat(1M) long '-n' output will
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * still use the <pid>. We do this because we just
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * made up the 'target-port' using the guid, and we
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * don't want to expose that fact in iostat output.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* find/establish <pid> given 'target-port' */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* form kstat name */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_path_online: path:%p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_free(target_port_dup, strlen(target_port_dup) + 1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* call mdi to create kstats with the name we built */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pathinfo_online(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip, PROPFLAGS,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "vhci_path_online: lun guid "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "property failed"));
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Get inquiry data into pathinfo related scsi_device structure.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Free sq_inq when pathinfo related scsi_device structure is destroyed
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * by vhci_pathinfo_uninit(). In other words, vhci maintains its own
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * copy of scsi_device and scsi_inquiry data on a per-path basis.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs if (scsi_probe(psd, SLEEP_FUNC) != SCSIPROBE_EXISTS) {
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs "scsi_probe failed path:%p rval:%x\n", (void *)pip, rval));
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * See if we have a failover module to support the device.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * We re-probe to determine the failover ops for each path. This
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * is done in case there are any path-specific side-effects associated
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * with the sfo_device_probe implementation.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Give the first successfull sfo_device_probe the opportunity to
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * establish 'ctpriv', vlun/client private data. The ctpriv will
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * then be passed into the failover module on all other sfo_device_*()
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * operations (and must be freed by sfo_device_unprobe implementation).
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * NOTE: While sfo_device_probe is done once per path,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * sfo_device_unprobe only occurs once - when the vlun is destroyed.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * NOTE: We don't currently support per-path fops private data
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs &vlun->svl_fops_ctpriv, &vlun->svl_fops_name);
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* check path configuration result with current vlun state */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs if (((sfo && vlun->svl_fops) && (sfo != vlun->svl_fops)) ||
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* Getting different results for different paths. */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs "!vhci_pathinfo_online: dev (path 0x%p) contradiction\n",
9b4f248c6f408a203f768690ab6456e797b512f3Chris Liu cmn_err(CE_WARN, "scsi_vhci: failover contradiction: "
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs "'%s'.vs.'%s': path %s\n",
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs vlun->svl_fops ? vlun->svl_fops->sfo_name : "NULL",
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs sfo ? sfo->sfo_name : "NULL", mdi_pi_pathname(pip));
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* No failover module - device not supported under vHCI. */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo_online: dev (path 0x%p) not "
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* XXX does this contradict vhci_is_dev_supported ? */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* failover supported for device - save failover_ops in vlun */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Obtain the device-type based mpxio options as specified in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * NOTE: currently, the end result is a call to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * mdi_set_lb_region_size().
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if PGR is active, revalidate key and register on this path also,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if key is still valid
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Last chance to perform any cleanup operations on this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * new path before making this path completely online.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If scsi_vhci knows the lun is alread RESERVE'd,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * then skip the issue of RELEASE on new path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Issue SCSI-2 RELEASE only for the first time on
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * a new path just in case the host rebooted and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * a reservation is still pending on this path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * IBM Shark storage does not clear RESERVE upon
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * host reboot.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sizeof (struct scsi_arq_status), 0, 0,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo_online: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Release init_pkt failed :%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_path_online: path:%p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Ignore the return value */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Initialize MP-API data */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * MP-API also needs the Inquiry data to be maintained in the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * mp_vendor_prop_t structure, so find the lun and update its
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * structure with this data.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth list_ptr = (mpapi_item_list_t *)vhci_get_mpapi_item(vhci, NULL,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bcopy(psd->sd_inq->inq_vid, ld->prop.prodInfo.vendor, 8);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bcopy(psd->sd_inq->inq_pid, ld->prop.prodInfo.product, 16);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bcopy(psd->sd_inq->inq_revision, ld->prop.prodInfo.revision, 4);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "mpapi_lu_data_t is NULL"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* create kstats for path */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_path_online: path:%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * path offline handler. Release all bindings that will not be
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * released by the normal packet transport/completion code path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Since we don't (presently) keep any bindings alive outside of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the in-transport packets (which will be released on completion)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * there is not much to do here.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pathinfo_offline(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, vdip, "Invalid path 0x%p: NULL "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, vdip, "Invalid path 0x%p: NULL "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * mdi_pathinfo node in INIT state can have vHCI private
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * information set to null
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%d cmds pending on path: 0x%p\n", svp->svp_cmds, (void *)pip));
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(&svp->svp_cv, &svp->svp_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(vhci_path_quiesce_timeout * 1000000),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The timeout time reached without the condition
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * being signaled.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Timeout reached on path 0x%p without the cond\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%d cmds still pending on path: 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Check to see if this vlun has an active SCSI-II RESERVE. And this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is the pip for the path that has been reserved.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If so clear the reservation by sending a reset, so the host will not
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * get a reservation conflict. Reset the flag VLUN_RESERVE_ACTIVE_FLG
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * for this lun. Also a reset notify is sent to the target driver
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * just in case the POR check condition is cleared by some other layer
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * in the stack.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (svp->svp_svl->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo_offline (pip:%p):"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo_offline "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "(pip:%p): reset failed, "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_mpapi_set_path_state(vdip, pip, MP_DRVR_PATH_STATE_REMOVED);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pathinfo_offline: offlined path 0x%p\n", (void *)pip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * routine for SCSI VHCI IOCTL implementation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, int *rval)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Check for validity of vhci structure */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, MINOR2INST(getminor(dev)));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the vhci dip */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Allocate memory for getting parameters from userland */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Set a local variable indicating the ioctl name. Used for
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * printing debug strings.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "GET_CLIENT_MULTIPATH_INFO";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "GET_PHCI_MULTIPATH_INFO";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "GET_CLIENT_NAME";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "PATH_ONLINE";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "PATH_OFFLINE";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "PATH_STANDBY";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "PATH_TEST";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "SWITCH_TO_CNTLR";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "PATH_DISABLE";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "PATH_ENABLE";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "GET_TARGET_LONGNAME";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "CONFIGURE_PHCI";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "UNCONFIGURE_PHCI";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth s = "Unknown";
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci%d: ioctl %x (unsupported ioctl)", instance, cmd);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (retval != 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci%d: ioctl <%s>", instance, s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get IOCTL parameters from userland
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth retval = vhci_get_iocdata((const void *)data, pioc, mode, s);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth retval = vhci_get_iocswitchdata((const void *)data, piocsc,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (retval != 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Process the IOCTL
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sv_path_info_t *upibuf = NULL; /* To keep userland values */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sv_path_info_t *kpibuf = NULL; /* Kernel data for ioctls */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get client device path from user land */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (vhci_ioc_get_client_path(pioc, client_path, mode, s)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get number of paths to this client device */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "num_paths copyout failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* If user just wanted num_paths, then return */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Set num_paths to value as much as can be sent to userland */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Allocate memory and get userland pointers */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (vhci_ioc_alloc_pathinfo(&upibuf, &kpibuf, num_paths,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get the path information and send it to userland.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Free the memory allocated for path information */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sv_path_info_t *upibuf = NULL; /* To keep userland values */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sv_path_info_t *kpibuf = NULL; /* Kernel data for ioctls */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get PHCI device path from user land */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get number of devices associated with this PHCI device */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "num_paths copyout failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* If user just wanted num_paths, then return */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Set num_paths to value as much as can be sent to userland */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Allocate memory and get userland pointers */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (vhci_ioc_alloc_pathinfo(&upibuf, &kpibuf, num_paths,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get the path information and send it to userland.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Free the memory allocated for path information */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get PHCI path and device address from user land */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the PHCI dip */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "pathinfo doesn't exist. invalid device addr", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the client device pathname and send to userland */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (vhci_ioc_send_client_path(client_path, pioc, mode, s)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get PHCI path and device address from user land */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the PHCI dip */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "pathinfo doesn't exist. invalid device addr", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Calling MDI function to change device state", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the client device pathname */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client_path copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the path class to which user wants to switch */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_copyin(piocsc->class, paddr, MAXNAMELEN, mode)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "controller_class copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Perform validity checks */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: Calling MDI func "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "to switch controller"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: client <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Checking to see if device has only one pclass, PRIMARY.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If so this device doesn't support failovers. Assumed
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that the devices with one pclass is PRIMARY, as thats the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * case today. If this is not true and in future other
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * symmetric devices are supported with other pclass, this
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * IOCTL shall have to be overhauled anyways as now the only
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * arguments it accepts are PRIMARY and SECONDARY.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Call mdi function to cause a switch over */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get client device path from user land
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (vhci_ioc_get_client_path(pioc, client_path, mode, s)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get Phci device path from user land
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get the devinfo for the Phci.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the client path is set to /scsi_vhci then we need
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * to do the operation on all the clients so set cdip to NULL.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Else, try to get the client dip.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_ioctl: ioctl <%s> client dip "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* targetmap lookup of 'target-port' by <pid> */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * NOTE: failure to find the mapping is OK for guid
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * based 'target-port' values.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(3, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "targetport mapping doesn't exist: pid %d",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* copyout 'target-port' result */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (copyoutstr(target_port, pioc->addr, MAXNAMELEN, NULL)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "targetport copyout failed: len: %d",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get PHCI path and device address from user land */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the PHCI dip */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((pdip = e_ddi_hold_devi_by_path(phci_path, 0)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(3, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get PHCI path and device address from user land */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Get the PHCI dip */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((pdip = e_ddi_hold_devi_by_path(phci_path, 0)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(3, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci dip doesn't exist. invalid path <%s>",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Free the memory allocated above */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * devctl IOCTL support for client device DR
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_devctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * check if :devctl minor device has been opened
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We can use the generic implementation for these ioctls
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * read devctl ioctl data
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (cmd) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * lookup and hold child device
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_ioctl(pip:%p): "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } /* end of outer switch */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to get the PHCI pathname from ioctl structures in userland
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_get_phci_path(sv_iocdata_t *pioc, caddr_t phci_path,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_copyin(pioc->phci, phci_path, MAXPATHLEN, mode)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioc_get_phci: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci_path copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to get the Client device pathname from ioctl structures in userland
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_get_client_path(sv_iocdata_t *pioc, caddr_t client_path,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_copyin(pioc->client, client_path, MAXPATHLEN, mode)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "ioctl <%s> client_path copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to get physical device address from ioctl structure in userland
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_get_paddr(sv_iocdata_t *pioc, caddr_t paddr, int mode, caddr_t s)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "ioctl <%s> device addr copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to send client device pathname to userland.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_send_client_path(caddr_t client_path, sv_iocdata_t *pioc,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (ddi_copyout(client_path, pioc->client, MAXPATHLEN, mode)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "ioctl <%s> client_path copyout failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to translated dev_info pointer (dip) to device pathname.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_get_phci_path_list:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * get information about devices associated with a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * given PHCI device.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * path information elements
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_get_phci_path_list(dev_info_t *pdip, sv_path_info_t *pibuf,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get the PHCI structure and retrieve the path information
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * from the GUID hash table.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (status == MDI_SUCCESS && ret_pip->ret_prop.ret_buf_size) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_get_phci_path_list: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci <%s>, prop size failure 0x%x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* DEBUG */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_get_phci_path_list: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci <%s>, prop pack failure 0x%x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* DEBUG */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_get_client_path_list:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * get information about various paths associated with a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * given client device.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Return Values:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * path information elements
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_get_client_path_list(dev_info_t *cdip, sv_path_info_t *pibuf,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (status == MDI_SUCCESS && ret_pip->ret_prop.ret_buf_size) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_get_client_path_list: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci <%s>, prop size failure 0x%x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* DEBUG */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_get_client_path_list: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "phci <%s>, prop pack failure 0x%x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* DEBUG */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to get ioctl argument structure from userland.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_get_iocdata(const void *data, sv_iocdata_t *pioc, int mode, caddr_t s)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth pioc->ret_buf = (sv_path_info_t *)(uintptr_t)ioc32.ret_buf;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#else /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: cmd <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "iocdata copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to get the ioctl argument for ioctl causing controller switchover.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_get_iocswitchdata(const void *data, sv_switch_to_cntlr_iocdata_t *piocsc,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#else /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: cmd <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "switch_to_cntlr_iocdata copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to allocate memory for the path information structures.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * It allocates two chunks of memory - one for keeping userland
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * pointers/values for path information and path properties, second for
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * keeping allocating kernel memory for path properties. These path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * properties are finally copied to userland.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_alloc_pathinfo(sv_path_info_t **upibuf, sv_path_info_t **kpibuf,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth uint_t num_paths, sv_iocdata_t *pioc, int mode, caddr_t s)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Allocate memory */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_zalloc(sizeof (sv_path_info_t) * num_paths, KM_SLEEP);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_zalloc(sizeof (sv_path_info_t) * num_paths, KM_SLEEP);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get the path info structure from the user space.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * We are interested in the following fields:
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * - user size of buffer for per path properties.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * - user address of buffer for path info properties.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * - user pointer for returning actual buffer size
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Keep these fields in the 'upibuf' structures.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Allocate buffer for per path info properties in kernel
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * structure ('kpibuf').
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Size of these buffers will be equal to the size of buffers
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * in the user space.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (index = 0; index < num_paths; index++, src++, pi++) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#else /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (retval != 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "ioctl <%s> normal: path_info copyin failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_free(*upibuf, sizeof (sv_path_info_t) * num_paths);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_free(*kpibuf, sizeof (sv_path_info_t) * num_paths);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Allocate memory for per path properties.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (index = 0, pi = *kpibuf; index < num_paths; index++, pi++) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to free memory for the path information structures.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This is the memory which was allocated earlier.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_free_pathinfo(sv_path_info_t *upibuf, sv_path_info_t *kpibuf,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Free memory for per path properties */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (index = 0, pi = kpibuf; index < num_paths; index++, pi++) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Free memory for path info structures */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Routine to copy path information and path properties to userland.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_ioc_send_pathinfo(sv_path_info_t *upibuf, sv_path_info_t *kpibuf,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth uint_t num_paths, sv_iocdata_t *pioc, int mode, caddr_t s)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#else /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth#endif /* _MULTI_DATAMODEL */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Copy path information and path properties to user land.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Pointer fields inside the path property structure were
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * saved in the 'upibuf' structure earlier.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth &upi_ptr[index].ret_state, sizeof (kpibuf[index].ret_state),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "normal: path_info copyout failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Copy path information and path properties to user land.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Pointer fields inside the path property structure were
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * saved in the 'upibuf' structure earlier.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: ioctl <%s> "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "normal: path_info copyout failed", s));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_failover()
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This routine expects VHCI_HOLD_LUN before being invoked. It can be invoked
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * as MDI_FAILOVER_ASYNC or MDI_FAILOVER_SYNC. For Asynchronous failovers
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this routine shall VHCI_RELEASE_LUN on exiting. For synchronous failovers
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * it is the callers responsibility to release lun.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* ARGSUSED */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_failover(dev_info_t *vdip, dev_info_t *cdip, int flags)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(1): guid %s\n", guid));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_log(CE_NOTE, vdip, "!Initiating failover for device %s "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Lets maintain a local copy of the vlun->svl_active_pclass
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * for the rest of the processing. Accessing the field
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * directly in the loop below causes loop logic to break
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * especially when the field gets updated by other threads
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * update path status etc and causes 'paths are not currently
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * available' condition to be declared prematurely.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) strlcpy(active_pclass_copy, vlun->svl_active_pclass,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * can happen only when the available path to device
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * discovered is a STANDBY path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!(%s)failing over from %s\n", guid,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_log(CE_NOTE, vdip, "!Failover operation failed for "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "device %s (GUID %s): Invalid path-class %s",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((s_pclass != NULL) && (strcmp(pclass2, s_pclass) == 0)) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * paths are not currently available
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_log(CE_NOTE, vdip, "!Failover path currently unavailable"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " for device %s (GUID %s)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(5.2)(%s): considering "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, MDI_SELECT_STANDBY_PATH, NULL, &npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(5.5)(%s): skipping path "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Issue READ at non-zer block on this STANDBY path.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Purple returns
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 1. RESERVATION_CONFLICT if reservation is pending
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 2. POR check condition if it reset happened.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * 2. failover Check Conditions if one is already in progress.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bp = scsi_alloc_consistent_buf(&svp->svp_psd->sd_address,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_failover !No resources (buf)\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth pkt->pkt_path_instance = mdi_pi_get_path_instance(npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Already failed over */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Already failed over */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(7)(%s): "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "path 0x%p POR UA condition\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(%s): path 0x%p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "unhandled chkcond %x %x %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, MDI_SELECT_STANDBY_PATH,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * if we are here, we have succeeded in activating path npip of
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * pathclass pclass2; let us validate all paths of pclass2 by
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * "ping"-ing each one and mark the good ones ONLINE
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Also, set the state of the paths belonging to the previously
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * active pathclass to STANDBY
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, (MDI_SELECT_ONLINE_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth MDI_SELECT_STANDBY_PATH | MDI_SELECT_USER_DISABLE_PATH),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!Failover operation failed for "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "device %s (GUID %s): paths may be busy\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) mdi_pi_get_state2(npip, &pi_state, &pi_ext_state);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(8)(%s): "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "pinging path 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(9)(%s): "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "path 0x%p ping successful, "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if ((s_pclass != NULL) && (strcmp(pclass, s_pclass)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(10)(%s): path 0x%p marked "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, (MDI_SELECT_ONLINE_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Update the AccessState of related MP-API TPGs
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) vhci_mpapi_update_tpg_acc_state_for_lu(vhci, vlun);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_log(CE_NOTE, vdip, "!Failover operation completed successfully "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "for device %s (GUID %s): failed over from %s to %s",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth ddi_node_name(cdip), guid, ((s_pclass == NULL) ? "<none>" :
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* All reservations are cleared upon these resets. */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(11): DONE! Active "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_failover(12): DONE! "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "releasing lun, as failover was ASYNC\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_failover(12): DONE! "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "NOT releasing lun, as failover was SYNC\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_client_attached is called after the successful attach of a
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * client devinfo node.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * At this point the client has attached and it's instance number is
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * valid, so we can set up kstats. We need to do this here because it
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is possible for paths to go online prior to client attach, in which
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * case the call to vhci_kstat_create_pathinfo in vhci_pathinfo_online
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * was a noop.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * quiesce all of the online paths
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_quiesce_paths(dev_info_t *vdip, dev_info_t *cdip, scsi_vhci_lun_t *vlun,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* quiesce currently active paths */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "for device %s (GUID %s) due to an internal "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * quiesce path. Free s_pclass since
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * we don't need it anymore
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(2)(%s): failing over "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "from %s; quiescing path %p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(2.5)(%s): no "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client priv! %p offlined?\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(3)(%s):"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_failover(3.cv)(%s):"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * make sure we freeup the memory
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_vhci_lun *
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return ((struct scsi_vhci_lun *)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_vhci_lun *
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_lun_lookup_alloc(dev_info_t *tgt_dip, char *guid, int *didalloc)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth svl->svl_lun_wwn = kmem_zalloc(strlen(guid)+1, KM_SLEEP);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sema_init(&svl->svl_pgr_sema, 1, NULL, SEMA_DRIVER, NULL);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_lun_lookup_alloc: guid %s vlun 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
29c56acb8635e0b7173b9ec6046f477942e3ac95Raghuram Prahladavhci_lun_free(struct scsi_vhci_lun *dvlp, struct scsi_device *sd)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_lun_free: %s\n", guid));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_free(dvlp->svl_lun_wwn, strlen(dvlp->svl_lun_wwn)+1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth kmem_free(dvlp->svl_fops_name, strlen(dvlp->svl_fops_name)+1);
7bc7346c0c75ced7da727f63c2772fd53809244dcm dvlp->svl_fops->sfo_device_unprobe(sd, dvlp->svl_fops_ctpriv);
82b6b7e49b0fa37a284dd9bca23cf928518393dcjw * vhci_lun_free may be called before the tgt_dip
82b6b7e49b0fa37a284dd9bca23cf928518393dcjw * initialization so check if the sd is NULL.
82b70b7c6cab4b550539de1b433e5625b1ce671frralphs vhci_print_cdb(pkt->pkt_address.a_hba_tran->tran_hba_dip,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!v_s_do_s_c: RELEASE conflict\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!v_s_do_s_c:retry packet 0x%p "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "status 0x%x reason %s",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!v_s_do_s_c:retry "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!v_s_do_s_c: failed transport 0x%p 0x%x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * clear unit attn.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!v_s_do_s_c: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "packet 0x%p sense "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "data %s",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!ARQ while "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "transporting "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "(pkt 0x%p)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)pkt));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!Bad status returned "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "(pkt 0x%p, status %x)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!v_s_do_s_c: retry packet 0x%p %s",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* FALLTHROUGH */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "complete successfully (pkt 0x%p,"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(&svp->svp_cv, &svp->svp_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(vhci_path_quiesce_timeout * 1000000),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "Quiesce of lun is not successful "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * see if there are any other paths available; if none,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * then there is nothing to do.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: first path\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * When the path was busy/offlined, some other host might have
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * cleared this key. Validate key on some other path first.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If it fails, return failure.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Save the res key */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(prout->res_key, temp_res_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Sometimes CDB from application can be a Register_And_Ignore.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Instead of validation, this cdb would result in force registration.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Convert it to normal cdb for validation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * After that be sure to restore the cdb.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs osvp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: no "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client priv! 0x%p offlined?\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: same svp 0x%p"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " npip 0x%p vlun 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: First validate on"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " osvp 0x%p being done. vlun 0x%p thread 0x%p Before bcopy"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy:");
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(prout->service_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)vlun));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: after bcopy: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: key"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: First validation"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Try other paths
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Be sure to restore original cdb */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Restore the res_key */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(temp_res_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If key could not be registered on any path for the first time,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * return success as online should still continue.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (success == 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Force register on new path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: keys before bcopy: ");
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(prout->active_service_key, prout->service_key,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(prout->active_res_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg:keys after bcopy: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: register on new"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " path 0x%p svp 0x%p failed %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: reg failed: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (bcmp(prout->service_key, zero_key, MHIOC_RESV_KEY_SIZE) == 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: zero service key\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * While the key was force registered, some other host might have
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * cleared the key. Re-validate key on another pre-existing path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * before declaring success.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Sometimes CDB from application can be Register and Ignore.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Instead of validation, it would result in force registration.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Convert it to normal cdb for validation.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * After that be sure to restore the cdb.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: no "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "client priv! 0x%p offlined?\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)npip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: same osvp 0x%p"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " npip 0x%p vlun 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: Re-validation on"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " osvp 0x%p being done. vlun 0x%p Before bcopy cdb1 %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy: ");
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(prout->service_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: after bcopy: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: key"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: Re-validation on"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "v_pgr_val_reg: reval failed: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Try other paths
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Be sure to restore original cdb */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Successfully validated registration */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_WARN, NULL, "key validation failed"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * key invalid, back out by registering key value of 0
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: backout on"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy: ");
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs bcopy(prout->service_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Get a new path
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH |
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: no valid pip\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_pgr_validate_and_register: backout on"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: key"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " validation and backout failed", ddi_driver_name(cdip),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: key"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "%s%d: vhci_pgr_validate_and_register: key"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " validation failed, key backed out\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_print_prout_keys(vlun, "v_pgr_val_reg: key backed out: ");
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * taskq routine to dispatch a scsi cmd to vhci_scsi_start. This ensures
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * that vhci_scsi_start is not called in interrupt context.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * As the upper layer gets TRAN_ACCEPT when the command is dispatched, we
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * need to complete the command if something goes wrong.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_dispatch_scsi_start: sending"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " scsi-2 reserve for 0x%p\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * To prevent the taskq from being called recursively we set the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the VHCI_PKT_THRU_TASKQ bit in the vhci_pkt_states.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Wait for the transport to get ready to send packets
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * and if it times out, it will return something other than
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * TRAN_BUSY. The vhci_reserve_delay may want to
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * get tuned for other transports and is therefore a global.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Using delay since this routine is called by taskq dispatch
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * and not called during interrupt context.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth while ((rval = vhci_scsi_start(&(vpkt->vpkt_tgt_pkt->pkt_address),
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (rval) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * This pkt shall be retried, and to ensure another taskq
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * is dispatched for it, clear the VHCI_PKT_THRU_TASKQ
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Ensure that the pkt is retried without a reset */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_dispatch_scsi_start: "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vpkt_org_vpkt should always be NULL here if the retry command
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * has been successfully dispatched. If vpkt_org_vpkt != NULL at
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * this point, it is an error so restore the original vpkt and
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * return an error to the target driver so it can retry the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * command as appropriate.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vpkt->vpkt_tgt_pkt->pkt_statistics = tpkt->pkt_statistics;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth struct scsi_vhci_lun *vlun = (struct scsi_vhci_lun *)arg;
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Perform a final check to see if the active path class is indeed
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * not the preferred path class. As in the time the auto failback
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * was dispatched, an external failover could have been detected.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * [Some other host could have detected this condition and triggered
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the auto failback before].
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * In such a case if we go ahead with failover we will be negating the
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * whole purpose of auto failback.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (strcmp(vlun->svl_active_pclass, best_pclass) == 0) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "auto failback for %s as %s pathclass already "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (mdi_failover(vdip, vlun->svl_dip, MDI_FAILOVER_SYNC)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "succeeded for device %s (GUID %s)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "failed for device %s (GUID %s)",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_print_prin_keys(vhci_prin_readkeys_t *prin, int numkeys)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) sprintf(&buf1[4*i], "[%02x]", prout->res_key[i]);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) sprintf(&buf2[(4*i)], "[%02x]", prout->service_key[i]);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) sprintf(&buf3[4*i], "[%02x]", prout->active_res_key[i]);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Printing all in one go. Otherwise it will jumble up */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(5, (CE_CONT, NULL, "%s vlun 0x%p, thread 0x%p\n"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "res_key: : %s\n"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "service_key : %s\n"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "active_res_key : %s\n"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "active_service_key: %s\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth msg, (void *)vlun, (void *)curthread, buf1, buf2, buf3, buf4));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Called from vhci_scsi_start to update the pHCI pkt with target packet.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_update_pHCI_pkt(struct vhci_pkt *vpkt, struct scsi_pkt *pkt)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Polled Command is requested or HBA is in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * suspended state
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Re-initialize the following pHCI packet state information */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_bus_power(dev_info_t *parent, void *impl_arg, pm_bus_power_op_t op,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Generic processing in MPxIO framework
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (ret) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_pHCI_cap(struct scsi_address *ap, char *cap, int val, int whom,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth mps_flag = (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If the call is from vhci_pathinfo_state_change,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * then this path was busy and is becoming ready to accept IO.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pHCI_cap: only on path %p, ap %p, rval %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Set capability on all the pHCIs.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * If any path is busy, then the capability would be set by
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vhci_pathinfo_state_change.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, mps_flag, NULL, &pip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pHCI_cap: Unable to get a path, dip 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)cdip));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (0);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "psd is NULL, pip 0x%p, svp 0x%p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "!vhci_pHCI_cap: path %p, ap %p, rval %x\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Select next path and issue the setcap, repeat
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * until all paths are exhausted
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth sps = mdi_select_path(cdip, NULL, mps_flag, pip, &npip);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_scsi_bus_config(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if (mdi_vhci_bus_config(pdip, flags, op, arg, child, guid)
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Hornevhci_scsi_bus_unconfig(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
53a7b6b6763f5865522a76e5e887390a8f4777d7Chris Horne return (ndi_busop_bus_unconfig(pdip, flags, op, arg));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Take the original vhci_pkt, create a duplicate of the pkt for resending
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * as though it originated in ssd.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct scsi_pkt *
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Ensure consistent data at completion time by setting PKT_CONSISTENT
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth pkt = vhci_scsi_init_pkt(&svp->svp_psd->sd_address, pkt,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs vpkt->vpkt_tgt_init_scblen, 0, PKT_CONSISTENT, NULL_FUNC, NULL);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Save a pointer to the original vhci_pkt
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Copy the successful completion information from the hba packet into
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * the original target pkt from the upper layer. Returns the original
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * vpkt and destroys the new vpkt from the internal retry.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic struct vhci_pkt *
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(0, (CE_NOTE, NULL, "vhci_sync_retry_pkt: Retry pkt "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "completed successfully!\n"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Copy the good status into the target driver's packet
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Destroy the internally created vpkt for the retry
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth/* restart the request sense request */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthstatic void
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_restart_sense: enter: rqpkt: %p", (void *)rqpkt));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* if it fails - need to wakeup the original command */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * auto-rqsense is not enabled so we have to retrieve the request sense
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * manually.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcthvhci_uscsi_send_sense(struct scsi_pkt *pkt, mp_uscsi_cmd_t *mp_uscmdp)
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_send_sense: enter: bp: %p pkt: %p scmd: %p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* set up the packet information and cdb */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth if ((rqbp = scsi_alloc_consistent_buf(mp_uscmdp->ap, NULL,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (-1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth CDB_GROUP0, 1, 0, PKT_CONSISTENT, NULL, NULL)) == NULL) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth return (-1);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void) scsi_setup_cdb((union scsi_cdb *)(intptr_t)rqpkt->pkt_cdbp,
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * NOTE: This code path is related to MPAPI uscsi(7I), so path
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * selection is not based on path_instance.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get her done */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "transport accepted."));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "transport busy, setting timeout."));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth vhci_restart_timeid = timeout(vhci_uscsi_restart_sense, rqpkt,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "transport failed"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * done routine for the mpapi uscsi command - this is behaving as though
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * FLAG_DIAGNOSE is set meaning there are no retries except for a manual
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * request sense.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iodone: enter: bp: %p pkt: %p scmd: %p",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* Save the status and the residual into the uscsi_cmd struct */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth uscmdp->uscsi_status = ((*(pkt)->pkt_scbp) & STATUS_MASK);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* return on a very successful command */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth SCBP_C(pkt) == 0 && ((pkt->pkt_flags & FLAG_SENSING) == 0) &&
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " pkt_resid=%ld pkt_state: 0x%x b_count: %ld b_resid: %ld",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth arqstat = (struct scsi_arq_status *)(intptr_t)(pkt->pkt_scbp);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The command did not complete.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iodone: command did not complete."
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " reason: %x flag: %x", pkt->pkt_reason, pkt->pkt_flags));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth } else if (pkt->pkt_state & STATE_ARQ_DONE && mp_uscmdp->arq_enabled) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * The auto-rqsense happened, and the packet has a filled-in
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * scsi_arq_status structure, pointed to by pkt_scbp.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iodone: received auto-requested sense"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get the amount of data to copy into rqbuf */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iodone: ARQ "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "uscsi_rqstatus=0x%x uscsi_rqresid=%d rqlen: %d "
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "xfer: %d rqpkt_resid: %d\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* a manual request sense was done - get the information */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* get the amount of data to copy into rqbuf */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_uscsi_iodone: FLAG_SENSING"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * Command completed and we're not getting sense. Check for
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * errors and decide what to do next.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iodone: command appears complete: reason: %x",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth /* need to manually get the request sense */
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_chk_err: appears complete"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth VHCI_DEBUG(4, (CE_WARN, NULL, "vhci_uscsi_iodone: exit"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth * start routine for the mpapi uscsi command
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth pkt = scsi_init_pkt(mp_uscmdp->ap, NULL, bp, uscmdp->uscsi_cdblen,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iostart: rval: EINVAL"));
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth bcopy(uscmdp->uscsi_cdb, pkt->pkt_cdbp, (size_t)uscmdp->uscsi_cdblen);
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iostart: ap: %p pkt: %p pcdbp: %p uscmdp: %p"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " ucdbp: %p pcdblen: %d bp: %p count: %ld pip: %p"
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth " stat_size: %d",
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)mp_uscmdp->ap, (void *)pkt, (void *)pkt->pkt_cdbp,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)uscmdp, (void *)uscmdp->uscsi_cdb, pkt->pkt_cdblen,
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth (void *)bp, bp->b_bcount, (void *)mp_uscmdp->pip, stat_size));
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * NOTE: This code path is related to MPAPI uscsi(7I), so path
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * selection is not based on path_instance.
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth switch (rval) {
1e1ddd6cc98ab5af8293f7ebd132be62900730fdcth "vhci_uscsi_iostart: rval: %d count: %ld res: %ld",
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs/* ARGSUSED */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphsvhci_dev_fo(dev_info_t *vdip, struct scsi_device *psd,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs if ((psd == NULL) || (psd->sd_inq == NULL)) {
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs "!vhci_dev_fo:return NULL no scsi_device or inquiry"));
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Determine if device is supported under scsi_vhci, and select
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * failover module.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * See if there is a scsi_vhci.conf file override for this devices's
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * VID/PID. The following values can be returned:
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * NULL If the NULL is returned then there is no scsi_vhci.conf
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * override. For NULL, we determine the failover_ops for
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * this device by checking the sfo_device_probe entry
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * point for each 'fops' module, in order.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * NOTE: Correct operation may depend on module ordering
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * of 'specific' (failover modules that are completely
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * VID/PID table based) to 'generic' (failover modules
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * that based on T10 standards like TPGS). Currently,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * the value of 'ddi-forceload' in scsi_vhci.conf is used
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * to establish the module list and probe order.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * "NONE" If value "NONE" is returned then there is a
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * scsi_vhci.conf VID/PID override to indicate the device
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * should not be supported under scsi_vhci (even if there
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * is an 'fops' module supporting the device).
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * "<other>" If another value is returned then that value is the
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * name of the 'fops' module that should be used.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* NULL: default: select based on sfo_device_probe results */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs for (sf = scsi_failover_table; sf->sf_mod; sf++) {
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs sf->sf_sfo->sfo_device_probe(psd, psd->sd_inq,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* found failover module, supported under scsi_vhci */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* !"NONE": select based on driver.conf specified name */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs for (sf = scsi_failover_table, sfo = NULL; sf->sf_mod; sf++) {
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * NOTE: If sfo_device_probe() has side-effects,
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * including setting *ctprivp, these are not going
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * to occur with override config.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs /* found failover module, supported under scsi_vhci */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * Determine the device described by cinfo should be enumerated under
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * the vHCI or the pHCI - if there is a failover ops then device is
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * supported under vHCI. By agreement with SCSA cinfo is a pointer
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs * to a scsi_device structure associated with a decorated pHCI probe node.
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs/* ARGSUSED */
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphsvhci_is_dev_supported(dev_info_t *vdip, dev_info_t *pdip, void *cinfo)
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs struct scsi_device *psd = (struct scsi_device *)cinfo;
55e592a20765db6f52a590785ae2390c3b12fda9Randall Ralphs return (vhci_dev_fo(vdip, psd, NULL, NULL) ? MDI_SUCCESS : MDI_FAILURE);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic char *
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs /* tmp goes out of scope on return and caller sees garbage */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsvhci_print_cdb(dev_info_t *dip, uint_t level, char *title, uchar_t *cdb)
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs (void) sprintf(buf, "%s for cmd(%s)", title, vhci_print_scsi_cmd(*cdb));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsvhci_clean_print(dev_info_t *dev, uint_t level, char *title, uchar_t *data,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs for (i = 0; i < len; ) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs (void) sprintf(&buf[(int)strlen(buf)], format, byte);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvhci_invalidate_mpapi_lu(struct scsi_vhci *vhci, scsi_vhci_lun_t *vlun)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ilist = vhci->mp_priv->obj_hdr_list[MP_OBJECT_TYPE_MULTIPATH_LU]->head;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "vhci_invalidate_mpapi_lu: "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh VHCI_DEBUG(6, (CE_WARN, NULL, "vhci_invalidate_mpapi_lu: "