Print this page
    
NEX-18919 Platform component fix for the MetroHA reboot -dn issue
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-17910 vhci_scsi_reset is too noisy
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-1049 System panic in module "scsi_vhci" due to a NULL pointer dereference
OS-62 slow io error detector is needed.
re #13247 rb4316 Large, fixed command timeouts impair command drop recovery
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c
          +++ new/usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
       21 +
  21   22  /*
  22   23   * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - */
  24      -/*
  25      - * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2018 Nexenta Systems, Inc.
  26   25   * Copyright (c) 2016 by Delphix. All rights reserved.
  27   26   */
  28   27  
  29   28  /*
  30   29   * Multiplexed I/O SCSI vHCI implementation
  31   30   */
  32   31  
  33   32  #include <sys/conf.h>
  34   33  #include <sys/file.h>
  35   34  #include <sys/ddi.h>
  36   35  #include <sys/sunddi.h>
  37   36  #include <sys/scsi/scsi.h>
  38   37  #include <sys/scsi/impl/scsi_reset_notify.h>
  39   38  #include <sys/scsi/impl/services.h>
  40   39  #include <sys/sunmdi.h>
  41   40  #include <sys/mdi_impldefs.h>
  42   41  #include <sys/scsi/adapters/scsi_vhci.h>
  43   42  #include <sys/disp.h>
  44   43  #include <sys/byteorder.h>
  45   44  
  46   45  extern uintptr_t scsi_callback_id;
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
  47   46  extern ddi_dma_attr_t scsi_alloc_attr;
  48   47  
  49   48  #ifdef  DEBUG
  50   49  int     vhci_debug = VHCI_DEBUG_DEFAULT_VAL;
  51   50  #endif
  52   51  
  53   52  /* retry for the vhci_do_prout command when a not ready is returned */
  54   53  int vhci_prout_not_ready_retry = 180;
  55   54  
  56   55  /*
       56 + * Timeout in seconds for SCSI commands used by vHCI.
       57 + */
       58 +int vhci_io_time = 30;
       59 +
       60 +/*
  57   61   * These values are defined to support the internal retry of
  58   62   * SCSI packets for better sense code handling.
  59   63   */
  60   64  #define VHCI_CMD_CMPLT  0
  61   65  #define VHCI_CMD_RETRY  1
  62   66  #define VHCI_CMD_ERROR  -1
  63   67  
  64   68  #define PROPFLAGS (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)
  65   69  #define VHCI_SCSI_PERR          0x47
  66   70  #define VHCI_PGR_ILLEGALOP      -2
  67   71  #define VHCI_NUM_UPDATE_TASKQ   8
  68   72  /* changed to 132 to accomodate HDS */
  69   73  
  70   74  /*
  71   75   * Version Macros
  72   76   */
  73   77  #define VHCI_NAME_VERSION       "SCSI VHCI Driver"
  74   78  char            vhci_version_name[] = VHCI_NAME_VERSION;
  75   79  
  76   80  int             vhci_first_time = 0;
  77   81  clock_t         vhci_to_ticks = 0;
  78   82  int             vhci_init_wait_timeout = VHCI_INIT_WAIT_TIMEOUT;
  79   83  kcondvar_t      vhci_cv;
  80   84  kmutex_t        vhci_global_mutex;
  81   85  void            *vhci_softstate = NULL; /* for soft state */
  82   86  
  83   87  /*
  84   88   * Flag to delay the retry of the reserve command
  85   89   */
  86   90  int             vhci_reserve_delay = 100000;
  87   91  static int      vhci_path_quiesce_timeout = 60;
  88   92  static uchar_t  zero_key[MHIOC_RESV_KEY_SIZE];
  89   93  
  90   94  /* uscsi delay for a TRAN_BUSY */
  91   95  static int vhci_uscsi_delay = 100000;
  92   96  static int vhci_uscsi_retry_count = 180;
  93   97  /* uscsi_restart_sense timeout id in case it needs to get canceled */
  94   98  static timeout_id_t vhci_restart_timeid = 0;
  95   99  
  96  100  static int      vhci_bus_config_debug = 0;
  97  101  
  98  102  /*
  99  103   * Bidirectional map of 'target-port' to port id <pid> for support of
 100  104   * iostat(1M) '-Xx' and '-Yx' output.
 101  105   */
 102  106  static kmutex_t         vhci_targetmap_mutex;
 103  107  static uint_t           vhci_targetmap_pid = 1;
 104  108  static mod_hash_t       *vhci_targetmap_bypid;  /* <pid> -> 'target-port' */
 105  109  static mod_hash_t       *vhci_targetmap_byport; /* 'target-port' -> <pid> */
 106  110  
 107  111  /*
 108  112   * functions exported by scsi_vhci struct cb_ops
 109  113   */
 110  114  static int vhci_open(dev_t *, int, int, cred_t *);
 111  115  static int vhci_close(dev_t, int, int, cred_t *);
 112  116  static int vhci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 113  117  
 114  118  /*
 115  119   * functions exported by scsi_vhci struct dev_ops
 116  120   */
 117  121  static int vhci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 118  122  static int vhci_attach(dev_info_t *, ddi_attach_cmd_t);
 119  123  static int vhci_detach(dev_info_t *, ddi_detach_cmd_t);
 120  124  
 121  125  /*
 122  126   * functions exported by scsi_vhci scsi_hba_tran_t transport table
 123  127   */
 124  128  static int vhci_scsi_tgt_init(dev_info_t *, dev_info_t *,
  
    | 
      ↓ open down ↓ | 
    58 lines elided | 
    
      ↑ open up ↑ | 
  
 125  129      scsi_hba_tran_t *, struct scsi_device *);
 126  130  static void vhci_scsi_tgt_free(dev_info_t *, dev_info_t *, scsi_hba_tran_t *,
 127  131      struct scsi_device *);
 128  132  static int vhci_pgr_register_start(scsi_vhci_lun_t *, struct scsi_pkt *);
 129  133  static int vhci_scsi_start(struct scsi_address *, struct scsi_pkt *);
 130  134  static int vhci_scsi_abort(struct scsi_address *, struct scsi_pkt *);
 131  135  static int vhci_scsi_reset(struct scsi_address *, int);
 132  136  static int vhci_scsi_reset_target(struct scsi_address *, int level,
 133  137      uint8_t select_path);
 134  138  static int vhci_scsi_reset_bus(struct scsi_address *);
      139 +static int vhci_scsi_reset_all_paths(struct scsi_address *);
 135  140  static int vhci_scsi_getcap(struct scsi_address *, char *, int);
 136  141  static int vhci_scsi_setcap(struct scsi_address *, char *, int, int);
 137  142  static int vhci_commoncap(struct scsi_address *, char *, int, int, int);
 138  143  static int vhci_pHCI_cap(struct scsi_address *ap, char *cap, int val, int whom,
 139  144      mdi_pathinfo_t *pip);
 140  145  static struct scsi_pkt *vhci_scsi_init_pkt(struct scsi_address *,
 141  146      struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
 142  147  static void vhci_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
 143  148  static void vhci_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
 144  149  static void vhci_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
 145  150  static int vhci_scsi_reset_notify(struct scsi_address *, int, void (*)(caddr_t),
 146  151      caddr_t);
 147  152  static int vhci_scsi_get_bus_addr(struct scsi_device *, char *, int);
 148  153  static int vhci_scsi_get_name(struct scsi_device *, char *, int);
 149  154  static int vhci_scsi_bus_power(dev_info_t *, void *, pm_bus_power_op_t,
 150  155      void *, void *);
 151  156  static int vhci_scsi_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
 152  157      void *, dev_info_t **);
 153  158  static int vhci_scsi_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
 154  159      void *);
 155  160  static struct scsi_failover_ops *vhci_dev_fo(dev_info_t *, struct scsi_device *,
 156  161      void **, char **);
 157  162  
 158  163  /*
 159  164   * functions registered with the mpxio framework via mdi_vhci_ops_t
 160  165   */
 161  166  static int vhci_pathinfo_init(dev_info_t *, mdi_pathinfo_t *, int);
 162  167  static int vhci_pathinfo_uninit(dev_info_t *, mdi_pathinfo_t *, int);
 163  168  static int vhci_pathinfo_state_change(dev_info_t *, mdi_pathinfo_t *,
 164  169                  mdi_pathinfo_state_t, uint32_t, int);
 165  170  static int vhci_pathinfo_online(dev_info_t *, mdi_pathinfo_t *, int);
 166  171  static int vhci_pathinfo_offline(dev_info_t *, mdi_pathinfo_t *, int);
 167  172  static int vhci_failover(dev_info_t *, dev_info_t *, int);
 168  173  static void vhci_client_attached(dev_info_t *);
 169  174  static int vhci_is_dev_supported(dev_info_t *, dev_info_t *, void *);
 170  175  
 171  176  static int vhci_ctl(dev_t, int, intptr_t, int, cred_t *, int *);
 172  177  static int vhci_devctl(dev_t, int, intptr_t, int, cred_t *, int *);
 173  178  static int vhci_ioc_get_phci_path(sv_iocdata_t *, caddr_t, int, caddr_t);
 174  179  static int vhci_ioc_get_client_path(sv_iocdata_t *, caddr_t, int, caddr_t);
 175  180  static int vhci_ioc_get_paddr(sv_iocdata_t *, caddr_t, int, caddr_t);
 176  181  static int vhci_ioc_send_client_path(caddr_t, sv_iocdata_t *, int, caddr_t);
 177  182  static void vhci_ioc_devi_to_path(dev_info_t *, caddr_t);
 178  183  static int vhci_get_phci_path_list(dev_info_t *, sv_path_info_t *, uint_t);
 179  184  static int vhci_get_client_path_list(dev_info_t *, sv_path_info_t *, uint_t);
 180  185  static int vhci_get_iocdata(const void *, sv_iocdata_t *, int, caddr_t);
 181  186  static int vhci_get_iocswitchdata(const void *, sv_switch_to_cntlr_iocdata_t *,
 182  187      int, caddr_t);
 183  188  static int vhci_ioc_alloc_pathinfo(sv_path_info_t **, sv_path_info_t **,
 184  189      uint_t, sv_iocdata_t *, int, caddr_t);
 185  190  static void vhci_ioc_free_pathinfo(sv_path_info_t *, sv_path_info_t *, uint_t);
 186  191  static int vhci_ioc_send_pathinfo(sv_path_info_t *, sv_path_info_t *, uint_t,
 187  192      sv_iocdata_t *, int, caddr_t);
 188  193  static int vhci_handle_ext_fo(struct scsi_pkt *, int);
 189  194  static int vhci_efo_watch_cb(caddr_t, struct scsi_watch_result *);
 190  195  static int vhci_quiesce_lun(struct scsi_vhci_lun *);
 191  196  static int vhci_pgr_validate_and_register(scsi_vhci_priv_t *);
 192  197  static void vhci_dispatch_scsi_start(void *);
 193  198  static void vhci_efo_done(void *);
 194  199  static void vhci_initiate_auto_failback(void *);
 195  200  static void vhci_update_pHCI_pkt(struct vhci_pkt *, struct scsi_pkt *);
 196  201  static int vhci_update_pathinfo(struct scsi_device *, mdi_pathinfo_t *,
 197  202      struct scsi_failover_ops *, scsi_vhci_lun_t *, struct scsi_vhci *);
 198  203  static void vhci_kstat_create_pathinfo(mdi_pathinfo_t *);
 199  204  static int vhci_quiesce_paths(dev_info_t *, dev_info_t *,
 200  205      scsi_vhci_lun_t *, char *, char *);
 201  206  
 202  207  static char *vhci_devnm_to_guid(char *);
 203  208  static int vhci_bind_transport(struct scsi_address *, struct vhci_pkt *,
 204  209      int, int (*func)(caddr_t));
 205  210  static void vhci_intr(struct scsi_pkt *);
 206  211  static int vhci_do_prout(scsi_vhci_priv_t *);
 207  212  static void vhci_run_cmd(void *);
 208  213  static int vhci_do_prin(struct vhci_pkt **);
 209  214  static struct scsi_pkt *vhci_create_retry_pkt(struct vhci_pkt *);
 210  215  static struct vhci_pkt *vhci_sync_retry_pkt(struct vhci_pkt *);
 211  216  static struct scsi_vhci_lun *vhci_lun_lookup(dev_info_t *);
 212  217  static struct scsi_vhci_lun *vhci_lun_lookup_alloc(dev_info_t *, char *, int *);
 213  218  static void vhci_lun_free(struct scsi_vhci_lun *dvlp, struct scsi_device *sd);
 214  219  static int vhci_recovery_reset(scsi_vhci_lun_t *, struct scsi_address *,
 215  220      uint8_t, uint8_t);
 216  221  void vhci_update_pathstates(void *);
 217  222  
 218  223  #ifdef DEBUG
 219  224  static void vhci_print_prin_keys(vhci_prin_readkeys_t *, int);
 220  225  static void vhci_print_cdb(dev_info_t *dip, uint_t level,
 221  226      char *title, uchar_t *cdb);
 222  227  static void vhci_clean_print(dev_info_t *dev, uint_t level,
 223  228      char *title, uchar_t *data, int len);
 224  229  #endif
 225  230  static void vhci_print_prout_keys(scsi_vhci_lun_t *, char *);
 226  231  static void vhci_uscsi_iodone(struct scsi_pkt *pkt);
 227  232  static void vhci_invalidate_mpapi_lu(struct scsi_vhci *, scsi_vhci_lun_t *);
 228  233  
 229  234  /*
 230  235   * MP-API related functions
 231  236   */
 232  237  extern int vhci_mpapi_init(struct scsi_vhci *);
 233  238  extern void vhci_mpapi_add_dev_prod(struct scsi_vhci *, char *);
 234  239  extern int vhci_mpapi_ctl(dev_t, int, intptr_t, int, cred_t *, int *);
 235  240  extern void vhci_update_mpapi_data(struct scsi_vhci *,
 236  241      scsi_vhci_lun_t *, mdi_pathinfo_t *);
 237  242  extern void* vhci_get_mpapi_item(struct scsi_vhci *, mpapi_list_header_t *,
 238  243      uint8_t, void*);
 239  244  extern void vhci_mpapi_set_path_state(dev_info_t *, mdi_pathinfo_t *, int);
 240  245  extern int vhci_mpapi_update_tpg_acc_state_for_lu(struct scsi_vhci *,
 241  246      scsi_vhci_lun_t *);
 242  247  
 243  248  #define VHCI_DMA_MAX_XFER_CAP   INT_MAX
 244  249  
 245  250  #define VHCI_MAX_PGR_RETRIES    3
 246  251  
 247  252  /*
 248  253   * Macros for the device-type mpxio options
 249  254   */
 250  255  #define LOAD_BALANCE_OPTIONS            "load-balance-options"
 251  256  #define LOGICAL_BLOCK_REGION_SIZE       "region-size"
 252  257  #define MPXIO_OPTIONS_LIST              "device-type-mpxio-options-list"
 253  258  #define DEVICE_TYPE_STR                 "device-type"
 254  259  #define isdigit(ch)                     ((ch) >= '0' && (ch) <= '9')
 255  260  
 256  261  static struct cb_ops vhci_cb_ops = {
 257  262          vhci_open,                      /* open */
 258  263          vhci_close,                     /* close */
 259  264          nodev,                          /* strategy */
 260  265          nodev,                          /* print */
 261  266          nodev,                          /* dump */
 262  267          nodev,                          /* read */
 263  268          nodev,                          /* write */
 264  269          vhci_ioctl,                     /* ioctl */
 265  270          nodev,                          /* devmap */
 266  271          nodev,                          /* mmap */
 267  272          nodev,                          /* segmap */
 268  273          nochpoll,                       /* chpoll */
 269  274          ddi_prop_op,                    /* cb_prop_op */
 270  275          0,                              /* streamtab */
 271  276          D_NEW | D_MP,                   /* cb_flag */
 272  277          CB_REV,                         /* rev */
 273  278          nodev,                          /* aread */
 274  279          nodev                           /* awrite */
 275  280  };
 276  281  
 277  282  static struct dev_ops vhci_ops = {
 278  283          DEVO_REV,
 279  284          0,
 280  285          vhci_getinfo,
 281  286          nulldev,                /* identify */
 282  287          nulldev,                /* probe */
 283  288          vhci_attach,            /* attach and detach are mandatory */
 284  289          vhci_detach,
 285  290          nodev,                  /* reset */
 286  291          &vhci_cb_ops,           /* cb_ops */
 287  292          NULL,                   /* bus_ops */
 288  293          NULL,                   /* power */
 289  294          ddi_quiesce_not_needed, /* quiesce */
 290  295  };
 291  296  
 292  297  extern struct mod_ops mod_driverops;
 293  298  
 294  299  static struct modldrv modldrv = {
 295  300          &mod_driverops,
 296  301          vhci_version_name,      /* module name */
 297  302          &vhci_ops
 298  303  };
 299  304  
 300  305  static struct modlinkage modlinkage = {
 301  306          MODREV_1,
 302  307          &modldrv,
 303  308          NULL
 304  309  };
 305  310  
 306  311  static mdi_vhci_ops_t vhci_opinfo = {
 307  312          MDI_VHCI_OPS_REV,
 308  313          vhci_pathinfo_init,             /* Pathinfo node init callback */
 309  314          vhci_pathinfo_uninit,           /* Pathinfo uninit callback */
 310  315          vhci_pathinfo_state_change,     /* Pathinfo node state change */
 311  316          vhci_failover,                  /* failover callback */
 312  317          vhci_client_attached,           /* client attached callback     */
 313  318          vhci_is_dev_supported           /* is device supported by mdi */
 314  319  };
 315  320  
 316  321  /*
 317  322   * The scsi_failover table defines an ordered set of 'fops' modules supported
 318  323   * by scsi_vhci.  Currently, initialize this table from the 'ddi-forceload'
 319  324   * property specified in scsi_vhci.conf.
 320  325   */
 321  326  static struct scsi_failover {
 322  327          ddi_modhandle_t                 sf_mod;
 323  328          struct scsi_failover_ops        *sf_sfo;
 324  329  } *scsi_failover_table;
 325  330  static uint_t   scsi_nfailover;
 326  331  
 327  332  int
 328  333  _init(void)
 329  334  {
 330  335          int     rval;
 331  336  
 332  337          /*
 333  338           * Allocate soft state and prepare to do ddi_soft_state_zalloc()
 334  339           * before registering with the transport first.
 335  340           */
 336  341          if ((rval = ddi_soft_state_init(&vhci_softstate,
 337  342              sizeof (struct scsi_vhci), 1)) != 0) {
 338  343                  VHCI_DEBUG(1, (CE_NOTE, NULL,
 339  344                      "!_init:soft state init failed\n"));
 340  345                  return (rval);
 341  346          }
 342  347  
 343  348          if ((rval = scsi_hba_init(&modlinkage)) != 0) {
 344  349                  VHCI_DEBUG(1, (CE_NOTE, NULL,
 345  350                      "!_init: scsi hba init failed\n"));
 346  351                  ddi_soft_state_fini(&vhci_softstate);
 347  352                  return (rval);
 348  353          }
 349  354  
 350  355          mutex_init(&vhci_global_mutex, NULL, MUTEX_DRIVER, NULL);
 351  356          cv_init(&vhci_cv, NULL, CV_DRIVER, NULL);
 352  357  
 353  358          mutex_init(&vhci_targetmap_mutex, NULL, MUTEX_DRIVER, NULL);
 354  359          vhci_targetmap_byport = mod_hash_create_strhash(
 355  360              "vhci_targetmap_byport", 256, mod_hash_null_valdtor);
 356  361          vhci_targetmap_bypid = mod_hash_create_idhash(
 357  362              "vhci_targetmap_bypid", 256, mod_hash_null_valdtor);
 358  363  
 359  364          if ((rval = mod_install(&modlinkage)) != 0) {
 360  365                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!_init: mod_install failed\n"));
 361  366                  if (vhci_targetmap_bypid)
 362  367                          mod_hash_destroy_idhash(vhci_targetmap_bypid);
 363  368                  if (vhci_targetmap_byport)
 364  369                          mod_hash_destroy_strhash(vhci_targetmap_byport);
 365  370                  mutex_destroy(&vhci_targetmap_mutex);
 366  371                  cv_destroy(&vhci_cv);
 367  372                  mutex_destroy(&vhci_global_mutex);
 368  373                  scsi_hba_fini(&modlinkage);
 369  374                  ddi_soft_state_fini(&vhci_softstate);
 370  375          }
 371  376          return (rval);
 372  377  }
 373  378  
 374  379  
 375  380  /*
 376  381   * the system is done with us as a driver, so clean up
 377  382   */
 378  383  int
 379  384  _fini(void)
 380  385  {
 381  386          int rval;
 382  387  
 383  388          /*
 384  389           * don't start cleaning up until we know that the module remove
 385  390           * has worked  -- if this works, then we know that each instance
 386  391           * has successfully been DDI_DETACHed
 387  392           */
 388  393          if ((rval = mod_remove(&modlinkage)) != 0) {
 389  394                  VHCI_DEBUG(4, (CE_NOTE, NULL, "!_fini: mod_remove failed\n"));
 390  395                  return (rval);
 391  396          }
 392  397  
 393  398          if (vhci_targetmap_bypid)
 394  399                  mod_hash_destroy_idhash(vhci_targetmap_bypid);
 395  400          if (vhci_targetmap_byport)
 396  401                  mod_hash_destroy_strhash(vhci_targetmap_byport);
 397  402          mutex_destroy(&vhci_targetmap_mutex);
 398  403          cv_destroy(&vhci_cv);
 399  404          mutex_destroy(&vhci_global_mutex);
 400  405          scsi_hba_fini(&modlinkage);
 401  406          ddi_soft_state_fini(&vhci_softstate);
 402  407  
 403  408          return (rval);
 404  409  }
 405  410  
 406  411  int
 407  412  _info(struct modinfo *modinfop)
 408  413  {
 409  414          return (mod_info(&modlinkage, modinfop));
 410  415  }
 411  416  
 412  417  /*
 413  418   * Lookup scsi_failover by "short name" of failover module.
 414  419   */
 415  420  struct scsi_failover_ops *
 416  421  vhci_failover_ops_by_name(char *name)
 417  422  {
 418  423          struct scsi_failover    *sf;
 419  424  
 420  425          for (sf = scsi_failover_table; sf->sf_mod; sf++) {
 421  426                  if (sf->sf_sfo == NULL)
 422  427                          continue;
 423  428                  if (strcmp(sf->sf_sfo->sfo_name, name) == 0)
 424  429                          return (sf->sf_sfo);
 425  430          }
 426  431          return (NULL);
 427  432  }
 428  433  
 429  434  /*
 430  435   * Load all scsi_failover_ops 'fops' modules.
 431  436   */
 432  437  static void
 433  438  vhci_failover_modopen(struct scsi_vhci *vhci)
 434  439  {
 435  440          char                    **module;
 436  441          int                     i;
 437  442          struct scsi_failover    *sf;
 438  443          char                    **dt;
 439  444          int                     e;
 440  445  
 441  446          if (scsi_failover_table)
 442  447                  return;
 443  448  
 444  449          /* Get the list of modules from scsi_vhci.conf */
 445  450          if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY,
 446  451              vhci->vhci_dip, DDI_PROP_DONTPASS, "ddi-forceload",
 447  452              &module, &scsi_nfailover) != DDI_PROP_SUCCESS) {
 448  453                  cmn_err(CE_WARN, "scsi_vhci: "
 449  454                      "scsi_vhci.conf is missing 'ddi-forceload'");
 450  455                  return;
 451  456          }
 452  457          if (scsi_nfailover == 0) {
 453  458                  cmn_err(CE_WARN, "scsi_vhci: "
 454  459                      "scsi_vhci.conf has empty 'ddi-forceload'");
 455  460                  ddi_prop_free(module);
 456  461                  return;
 457  462          }
 458  463  
 459  464          /* allocate failover table based on number of modules */
 460  465          scsi_failover_table = (struct scsi_failover *)
 461  466              kmem_zalloc(sizeof (struct scsi_failover) * (scsi_nfailover + 1),
 462  467              KM_SLEEP);
 463  468  
 464  469          /* loop over modules specified in scsi_vhci.conf and open each module */
 465  470          for (i = 0, sf = scsi_failover_table; i < scsi_nfailover; i++) {
 466  471                  if (module[i] == NULL)
 467  472                          continue;
 468  473  
 469  474                  sf->sf_mod = ddi_modopen(module[i], KRTLD_MODE_FIRST, &e);
 470  475                  if (sf->sf_mod == NULL) {
 471  476                          /*
 472  477                           * A module returns EEXIST if other software is
 473  478                           * supporting the intended function: for example
 474  479                           * the scsi_vhci_f_sum_emc module returns EEXIST
 475  480                           * from _init if EMC powerpath software is installed.
 476  481                           */
 477  482                          if (e != EEXIST)
 478  483                                  cmn_err(CE_WARN, "scsi_vhci: unable to open "
 479  484                                      "module '%s', error %d", module[i], e);
 480  485                          continue;
 481  486                  }
 482  487                  sf->sf_sfo = ddi_modsym(sf->sf_mod,
 483  488                      "scsi_vhci_failover_ops", &e);
 484  489                  if (sf->sf_sfo == NULL) {
 485  490                          cmn_err(CE_WARN, "scsi_vhci: "
 486  491                              "unable to import 'scsi_failover_ops' from '%s', "
 487  492                              "error %d", module[i], e);
 488  493                          (void) ddi_modclose(sf->sf_mod);
 489  494                          sf->sf_mod = NULL;
 490  495                          continue;
 491  496                  }
 492  497  
 493  498                  /* register vid/pid of devices supported with mpapi */
 494  499                  for (dt = sf->sf_sfo->sfo_devices; *dt; dt++)
 495  500                          vhci_mpapi_add_dev_prod(vhci, *dt);
 496  501                  sf++;
 497  502          }
 498  503  
 499  504          /* verify that at least the "well-known" modules were there */
 500  505          if (vhci_failover_ops_by_name(SFO_NAME_SYM) == NULL)
 501  506                  cmn_err(CE_WARN, "scsi_vhci: well-known module \""
 502  507                      SFO_NAME_SYM "\" not defined in scsi_vhci.conf's "
 503  508                      "'ddi-forceload'");
 504  509          if (vhci_failover_ops_by_name(SFO_NAME_TPGS) == NULL)
 505  510                  cmn_err(CE_WARN, "scsi_vhci: well-known module \""
 506  511                      SFO_NAME_TPGS "\" not defined in scsi_vhci.conf's "
 507  512                      "'ddi-forceload'");
 508  513  
 509  514          /* call sfo_init for modules that need it */
 510  515          for (sf = scsi_failover_table; sf->sf_mod; sf++) {
 511  516                  if (sf->sf_sfo && sf->sf_sfo->sfo_init)
 512  517                          sf->sf_sfo->sfo_init();
 513  518          }
 514  519  
 515  520          ddi_prop_free(module);
 516  521  }
 517  522  
 518  523  /*
 519  524   * unload all loaded scsi_failover_ops modules
 520  525   */
 521  526  static void
 522  527  vhci_failover_modclose()
 523  528  {
 524  529          struct scsi_failover    *sf;
 525  530  
 526  531          for (sf = scsi_failover_table; sf->sf_mod; sf++) {
 527  532                  if ((sf->sf_mod == NULL) || (sf->sf_sfo == NULL))
 528  533                          continue;
 529  534                  (void) ddi_modclose(sf->sf_mod);
 530  535                  sf->sf_mod = NULL;
 531  536                  sf->sf_sfo = NULL;
 532  537          }
 533  538  
 534  539          if (scsi_failover_table && scsi_nfailover)
 535  540                  kmem_free(scsi_failover_table,
 536  541                      sizeof (struct scsi_failover) * (scsi_nfailover + 1));
 537  542          scsi_failover_table = NULL;
 538  543          scsi_nfailover = 0;
 539  544  }
 540  545  
 541  546  /* ARGSUSED */
 542  547  static int
 543  548  vhci_open(dev_t *devp, int flag, int otype, cred_t *credp)
 544  549  {
 545  550          struct scsi_vhci        *vhci;
 546  551  
 547  552          if (otype != OTYP_CHR) {
 548  553                  return (EINVAL);
 549  554          }
 550  555  
 551  556          vhci = ddi_get_soft_state(vhci_softstate, MINOR2INST(getminor(*devp)));
 552  557          if (vhci == NULL) {
 553  558                  VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_open: failed ENXIO\n"));
 554  559                  return (ENXIO);
 555  560          }
 556  561  
 557  562          mutex_enter(&vhci->vhci_mutex);
 558  563          if ((flag & FEXCL) && (vhci->vhci_state & VHCI_STATE_OPEN)) {
 559  564                  mutex_exit(&vhci->vhci_mutex);
 560  565                  vhci_log(CE_NOTE, vhci->vhci_dip,
 561  566                      "!vhci%d: Already open\n", getminor(*devp));
 562  567                  return (EBUSY);
 563  568          }
 564  569  
 565  570          vhci->vhci_state |= VHCI_STATE_OPEN;
 566  571          mutex_exit(&vhci->vhci_mutex);
 567  572          return (0);
 568  573  }
 569  574  
 570  575  
 571  576  /* ARGSUSED */
 572  577  static int
 573  578  vhci_close(dev_t dev, int flag, int otype, cred_t *credp)
 574  579  {
 575  580          struct scsi_vhci        *vhci;
 576  581  
 577  582          if (otype != OTYP_CHR) {
 578  583                  return (EINVAL);
 579  584          }
 580  585  
 581  586          vhci = ddi_get_soft_state(vhci_softstate, MINOR2INST(getminor(dev)));
 582  587          if (vhci == NULL) {
 583  588                  VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_close: failed ENXIO\n"));
 584  589                  return (ENXIO);
 585  590          }
 586  591  
 587  592          mutex_enter(&vhci->vhci_mutex);
 588  593          vhci->vhci_state &= ~VHCI_STATE_OPEN;
 589  594          mutex_exit(&vhci->vhci_mutex);
 590  595  
 591  596          return (0);
 592  597  }
 593  598  
 594  599  /* ARGSUSED */
 595  600  static int
 596  601  vhci_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 597  602          cred_t *credp, int *rval)
 598  603  {
 599  604          if (IS_DEVCTL(cmd)) {
 600  605                  return (vhci_devctl(dev, cmd, data, mode, credp, rval));
 601  606          } else if (cmd == MP_CMD) {
 602  607                  return (vhci_mpapi_ctl(dev, cmd, data, mode, credp, rval));
 603  608          } else {
 604  609                  return (vhci_ctl(dev, cmd, data, mode, credp, rval));
 605  610          }
 606  611  }
 607  612  
 608  613  /*
 609  614   * attach the module
 610  615   */
 611  616  static int
 612  617  vhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 613  618  {
 614  619          int                     rval = DDI_FAILURE;
 615  620          int                     scsi_hba_attached = 0;
 616  621          int                     vhci_attached = 0;
 617  622          int                     mutex_initted = 0;
 618  623          int                     instance;
 619  624          struct scsi_vhci        *vhci;
 620  625          scsi_hba_tran_t         *tran;
 621  626          char                    cache_name_buf[64];
 622  627          char                    *data;
 623  628  
 624  629          VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_attach: cmd=0x%x\n", cmd));
 625  630  
 626  631          instance = ddi_get_instance(dip);
 627  632  
 628  633          switch (cmd) {
 629  634          case DDI_ATTACH:
 630  635                  break;
 631  636  
 632  637          case DDI_RESUME:
 633  638          case DDI_PM_RESUME:
 634  639                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_attach: resume not yet"
 635  640                      "implemented\n"));
 636  641                  return (rval);
 637  642  
 638  643          default:
 639  644                  VHCI_DEBUG(1, (CE_NOTE, NULL,
 640  645                      "!vhci_attach: unknown ddi command\n"));
 641  646                  return (rval);
 642  647          }
 643  648  
 644  649          /*
 645  650           * Allocate vhci data structure.
 646  651           */
 647  652          if (ddi_soft_state_zalloc(vhci_softstate, instance) != DDI_SUCCESS) {
 648  653                  VHCI_DEBUG(1, (CE_NOTE, dip, "!vhci_attach:"
 649  654                      "soft state alloc failed\n"));
 650  655                  return (DDI_FAILURE);
 651  656          }
 652  657  
 653  658          if ((vhci = ddi_get_soft_state(vhci_softstate, instance)) == NULL) {
 654  659                  VHCI_DEBUG(1, (CE_NOTE, dip, "!vhci_attach:"
 655  660                      "bad soft state\n"));
 656  661                  ddi_soft_state_free(vhci_softstate, instance);
 657  662                  return (DDI_FAILURE);
 658  663          }
 659  664  
 660  665          /* Allocate packet cache */
 661  666          (void) snprintf(cache_name_buf, sizeof (cache_name_buf),
 662  667              "vhci%d_cache", instance);
 663  668  
 664  669          mutex_init(&vhci->vhci_mutex, NULL, MUTEX_DRIVER, NULL);
 665  670          mutex_initted++;
 666  671  
 667  672          /*
 668  673           * Allocate a transport structure
 669  674           */
 670  675          tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
 671  676          ASSERT(tran != NULL);
 672  677  
 673  678          vhci->vhci_tran         = tran;
 674  679          vhci->vhci_dip          = dip;
 675  680          vhci->vhci_instance     = instance;
 676  681  
 677  682          tran->tran_hba_private  = vhci;
 678  683          tran->tran_tgt_init     = vhci_scsi_tgt_init;
 679  684          tran->tran_tgt_probe    = NULL;
 680  685          tran->tran_tgt_free     = vhci_scsi_tgt_free;
 681  686  
 682  687          tran->tran_start        = vhci_scsi_start;
 683  688          tran->tran_abort        = vhci_scsi_abort;
 684  689          tran->tran_reset        = vhci_scsi_reset;
 685  690          tran->tran_getcap       = vhci_scsi_getcap;
 686  691          tran->tran_setcap       = vhci_scsi_setcap;
 687  692          tran->tran_init_pkt     = vhci_scsi_init_pkt;
 688  693          tran->tran_destroy_pkt  = vhci_scsi_destroy_pkt;
 689  694          tran->tran_dmafree      = vhci_scsi_dmafree;
 690  695          tran->tran_sync_pkt     = vhci_scsi_sync_pkt;
 691  696          tran->tran_reset_notify = vhci_scsi_reset_notify;
 692  697  
 693  698          tran->tran_get_bus_addr = vhci_scsi_get_bus_addr;
 694  699          tran->tran_get_name     = vhci_scsi_get_name;
 695  700          tran->tran_bus_reset    = NULL;
 696  701          tran->tran_quiesce      = NULL;
 697  702          tran->tran_unquiesce    = NULL;
 698  703  
 699  704          /*
 700  705           * register event notification routines with scsa
 701  706           */
 702  707          tran->tran_get_eventcookie = NULL;
 703  708          tran->tran_add_eventcall = NULL;
 704  709          tran->tran_remove_eventcall = NULL;
 705  710          tran->tran_post_event   = NULL;
 706  711  
 707  712          tran->tran_bus_power    = vhci_scsi_bus_power;
 708  713  
 709  714          tran->tran_bus_config   = vhci_scsi_bus_config;
 710  715          tran->tran_bus_unconfig = vhci_scsi_bus_unconfig;
 711  716  
 712  717          /*
 713  718           * Attach this instance with the mpxio framework
 714  719           */
 715  720          if (mdi_vhci_register(MDI_HCI_CLASS_SCSI, dip, &vhci_opinfo, 0)
 716  721              != MDI_SUCCESS) {
 717  722                  VHCI_DEBUG(1, (CE_NOTE, dip, "!vhci_attach:"
 718  723                      "mdi_vhci_register failed\n"));
 719  724                  goto attach_fail;
 720  725          }
 721  726          vhci_attached++;
 722  727  
 723  728          /*
 724  729           * Attach this instance of the hba.
 725  730           *
 726  731           * Regarding dma attributes: Since scsi_vhci is a virtual scsi HBA
 727  732           * driver, it has nothing to do with DMA. However, when calling
 728  733           * scsi_hba_attach_setup() we need to pass something valid in the
 729  734           * dma attributes parameter. So we just use scsi_alloc_attr.
 730  735           * SCSA itself seems to care only for dma_attr_minxfer and
 731  736           * dma_attr_burstsizes fields of dma attributes structure.
 732  737           * It expects those fileds to be non-zero.
 733  738           */
 734  739          if (scsi_hba_attach_setup(dip, &scsi_alloc_attr, tran,
 735  740              SCSI_HBA_ADDR_COMPLEX) != DDI_SUCCESS) {
 736  741                  VHCI_DEBUG(1, (CE_NOTE, dip, "!vhci_attach:"
 737  742                      "hba attach failed\n"));
 738  743                  goto attach_fail;
 739  744          }
 740  745          scsi_hba_attached++;
 741  746  
 742  747          if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
 743  748              INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
 744  749                  VHCI_DEBUG(1, (CE_NOTE, dip, "!vhci_attach:"
 745  750                      " ddi_create_minor_node failed\n"));
 746  751                  goto attach_fail;
 747  752          }
 748  753  
 749  754          /*
 750  755           * Set pm-want-child-notification property for
 751  756           * power management of the phci and client
 752  757           */
 753  758          if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
 754  759              "pm-want-child-notification?", NULL, NULL) != DDI_PROP_SUCCESS) {
 755  760                  cmn_err(CE_WARN,
 756  761                      "%s%d fail to create pm-want-child-notification? prop",
 757  762                      ddi_driver_name(dip), ddi_get_instance(dip));
 758  763                  goto attach_fail;
 759  764          }
 760  765  
 761  766          vhci->vhci_taskq = taskq_create("vhci_taskq", 1, MINCLSYSPRI, 1, 4, 0);
 762  767          vhci->vhci_update_pathstates_taskq =
 763  768              taskq_create("vhci_update_pathstates", VHCI_NUM_UPDATE_TASKQ,
 764  769              MINCLSYSPRI, 1, 4, 0);
 765  770          ASSERT(vhci->vhci_taskq);
 766  771          ASSERT(vhci->vhci_update_pathstates_taskq);
 767  772  
 768  773          /*
 769  774           * Set appropriate configuration flags based on options set in
 770  775           * conf file.
 771  776           */
 772  777          vhci->vhci_conf_flags = 0;
 773  778          if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, PROPFLAGS,
 774  779              "auto-failback", &data) == DDI_SUCCESS) {
 775  780                  if (strcmp(data, "enable") == 0)
 776  781                          vhci->vhci_conf_flags |= VHCI_CONF_FLAGS_AUTO_FAILBACK;
 777  782                  ddi_prop_free(data);
 778  783          }
 779  784  
 780  785          if (!(vhci->vhci_conf_flags & VHCI_CONF_FLAGS_AUTO_FAILBACK))
 781  786                  vhci_log(CE_NOTE, dip, "!Auto-failback capability "
 782  787                      "disabled through scsi_vhci.conf file.");
 783  788  
 784  789          /*
 785  790           * Allocate an mpapi private structure
 786  791           */
 787  792          vhci->mp_priv = kmem_zalloc(sizeof (mpapi_priv_t), KM_SLEEP);
 788  793          if (vhci_mpapi_init(vhci) != 0) {
 789  794                  VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_attach: "
 790  795                      "vhci_mpapi_init() failed"));
 791  796          }
 792  797  
 793  798          vhci_failover_modopen(vhci);            /* load failover modules */
 794  799  
 795  800          ddi_report_dev(dip);
 796  801          return (DDI_SUCCESS);
 797  802  
 798  803  attach_fail:
 799  804          if (vhci_attached)
 800  805                  (void) mdi_vhci_unregister(dip, 0);
 801  806  
 802  807          if (scsi_hba_attached)
 803  808                  (void) scsi_hba_detach(dip);
 804  809  
 805  810          if (vhci->vhci_tran)
 806  811                  scsi_hba_tran_free(vhci->vhci_tran);
 807  812  
 808  813          if (mutex_initted) {
 809  814                  mutex_destroy(&vhci->vhci_mutex);
 810  815          }
 811  816  
 812  817          ddi_soft_state_free(vhci_softstate, instance);
 813  818          return (DDI_FAILURE);
 814  819  }
 815  820  
 816  821  
 817  822  /*ARGSUSED*/
 818  823  static int
 819  824  vhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 820  825  {
 821  826          int                     instance = ddi_get_instance(dip);
 822  827          scsi_hba_tran_t         *tran;
 823  828          struct scsi_vhci        *vhci;
 824  829  
 825  830          VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_detach: cmd=0x%x\n", cmd));
 826  831  
 827  832          if ((tran = ddi_get_driver_private(dip)) == NULL)
 828  833                  return (DDI_FAILURE);
 829  834  
 830  835          vhci = TRAN2HBAPRIVATE(tran);
 831  836          if (!vhci) {
 832  837                  return (DDI_FAILURE);
 833  838          }
 834  839  
 835  840          switch (cmd) {
 836  841          case DDI_DETACH:
 837  842                  break;
 838  843  
 839  844          case DDI_SUSPEND:
 840  845          case DDI_PM_SUSPEND:
 841  846                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_detach: suspend/pm not yet"
 842  847                      "implemented\n"));
 843  848                  return (DDI_FAILURE);
 844  849  
 845  850          default:
 846  851                  VHCI_DEBUG(1, (CE_NOTE, NULL,
 847  852                      "!vhci_detach: unknown ddi command\n"));
 848  853                  return (DDI_FAILURE);
 849  854          }
 850  855  
 851  856          (void) mdi_vhci_unregister(dip, 0);
 852  857          (void) scsi_hba_detach(dip);
 853  858          scsi_hba_tran_free(tran);
 854  859  
 855  860          if (ddi_prop_remove(DDI_DEV_T_NONE, dip,
 856  861              "pm-want-child-notification?") != DDI_PROP_SUCCESS) {
 857  862                  cmn_err(CE_WARN,
 858  863                      "%s%d unable to remove prop pm-want_child_notification?",
 859  864                      ddi_driver_name(dip), ddi_get_instance(dip));
 860  865          }
 861  866          if (vhci_restart_timeid != 0) {
 862  867                  (void) untimeout(vhci_restart_timeid);
 863  868          }
 864  869          vhci_restart_timeid = 0;
 865  870  
 866  871          mutex_destroy(&vhci->vhci_mutex);
 867  872          vhci->vhci_dip = NULL;
 868  873          vhci->vhci_tran = NULL;
 869  874          taskq_destroy(vhci->vhci_taskq);
 870  875          taskq_destroy(vhci->vhci_update_pathstates_taskq);
 871  876          ddi_remove_minor_node(dip, NULL);
 872  877          ddi_soft_state_free(vhci_softstate, instance);
 873  878  
 874  879          vhci_failover_modclose();               /* unload failover modules */
 875  880          return (DDI_SUCCESS);
 876  881  }
 877  882  
 878  883  /*
 879  884   * vhci_getinfo()
 880  885   * Given the device number, return the devinfo pointer or the
 881  886   * instance number.
 882  887   * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach.
 883  888   */
 884  889  
 885  890  /*ARGSUSED*/
 886  891  static int
 887  892  vhci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 888  893  {
 889  894          struct scsi_vhci        *vhcip;
 890  895          int                     instance = MINOR2INST(getminor((dev_t)arg));
 891  896  
 892  897          switch (cmd) {
 893  898          case DDI_INFO_DEVT2DEVINFO:
 894  899                  vhcip = ddi_get_soft_state(vhci_softstate, instance);
 895  900                  if (vhcip != NULL)
 896  901                          *result = vhcip->vhci_dip;
 897  902                  else {
 898  903                          *result = NULL;
 899  904                          return (DDI_FAILURE);
 900  905                  }
 901  906                  break;
 902  907  
 903  908          case DDI_INFO_DEVT2INSTANCE:
 904  909                  *result = (void *)(uintptr_t)instance;
 905  910                  break;
 906  911  
 907  912          default:
 908  913                  return (DDI_FAILURE);
 909  914          }
 910  915  
 911  916          return (DDI_SUCCESS);
 912  917  }
 913  918  
 914  919  /*ARGSUSED*/
 915  920  static int
 916  921  vhci_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 917  922          scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
 918  923  {
 919  924          char                    *guid;
 920  925          scsi_vhci_lun_t         *vlun;
 921  926          struct scsi_vhci        *vhci;
 922  927          clock_t                 from_ticks;
 923  928          mdi_pathinfo_t          *pip;
 924  929          int                     rval;
 925  930  
 926  931          ASSERT(hba_dip != NULL);
 927  932          ASSERT(tgt_dip != NULL);
 928  933  
 929  934          if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip, PROPFLAGS,
 930  935              MDI_CLIENT_GUID_PROP, &guid) != DDI_SUCCESS) {
 931  936                  /*
 932  937                   * This must be the .conf node without GUID property.
 933  938                   * The node under fp already inserts a delay, so we
 934  939                   * just return from here. We rely on this delay to have
 935  940                   * all dips be posted to the ndi hotplug thread's newdev
 936  941                   * list. This is necessary for the deferred attach
 937  942                   * mechanism to work and opens() done soon after boot to
 938  943                   * succeed.
 939  944                   */
 940  945                  VHCI_DEBUG(4, (CE_WARN, hba_dip, "tgt_init: lun guid "
 941  946                      "property failed"));
 942  947                  return (DDI_NOT_WELL_FORMED);
 943  948          }
 944  949  
 945  950          if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
 946  951                  /*
 947  952                   * This must be .conf node with the GUID property. We don't
 948  953                   * merge property by ndi_merge_node() here  because the
 949  954                   * devi_addr_buf of .conf node is "" always according the
 950  955                   * implementation of vhci_scsi_get_name_bus_addr().
 951  956                   */
 952  957                  ddi_set_name_addr(tgt_dip, NULL);
 953  958                  return (DDI_FAILURE);
 954  959          }
 955  960  
 956  961          vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(hba_dip));
 957  962          ASSERT(vhci != NULL);
 958  963  
 959  964          VHCI_DEBUG(4, (CE_NOTE, hba_dip,
 960  965              "!tgt_init: called for %s (instance %d)\n",
 961  966              ddi_driver_name(tgt_dip), ddi_get_instance(tgt_dip)));
 962  967  
 963  968          vlun = vhci_lun_lookup(tgt_dip);
 964  969  
 965  970          mutex_enter(&vhci_global_mutex);
 966  971  
 967  972          from_ticks = ddi_get_lbolt();
 968  973          if (vhci_to_ticks == 0) {
 969  974                  vhci_to_ticks = from_ticks +
 970  975                      drv_usectohz(vhci_init_wait_timeout);
 971  976          }
 972  977  
 973  978  #if DEBUG
 974  979          if (vlun) {
 975  980                  VHCI_DEBUG(1, (CE_WARN, hba_dip, "tgt_init: "
 976  981                      "vhci_scsi_tgt_init: guid %s : found vlun 0x%p "
 977  982                      "from_ticks %lx to_ticks %lx",
 978  983                      guid, (void *)vlun, from_ticks, vhci_to_ticks));
 979  984          } else {
 980  985                  VHCI_DEBUG(1, (CE_WARN, hba_dip, "tgt_init: "
 981  986                      "vhci_scsi_tgt_init: guid %s : vlun not found "
 982  987                      "from_ticks %lx to_ticks %lx", guid, from_ticks,
 983  988                      vhci_to_ticks));
 984  989          }
 985  990  #endif
 986  991  
 987  992          rval = mdi_select_path(tgt_dip, NULL,
 988  993              (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH), NULL, &pip);
 989  994          if (rval == MDI_SUCCESS) {
 990  995                  mdi_rele_path(pip);
 991  996          }
 992  997  
 993  998          /*
 994  999           * Wait for the following conditions :
 995 1000           *      1. no vlun available yet
 996 1001           *      2. no path established
 997 1002           *      3. timer did not expire
 998 1003           */
 999 1004          while ((vlun == NULL) || (mdi_client_get_path_count(tgt_dip) == 0) ||
1000 1005              (rval != MDI_SUCCESS)) {
1001 1006                  if (vlun && vlun->svl_not_supported) {
1002 1007                          VHCI_DEBUG(1, (CE_WARN, hba_dip, "tgt_init: "
1003 1008                              "vlun 0x%p lun guid %s not supported!",
1004 1009                              (void *)vlun, guid));
1005 1010                          mutex_exit(&vhci_global_mutex);
1006 1011                          ddi_prop_free(guid);
1007 1012                          return (DDI_NOT_WELL_FORMED);
1008 1013                  }
1009 1014                  if ((vhci_first_time == 0) && (from_ticks >= vhci_to_ticks)) {
1010 1015                          vhci_first_time = 1;
1011 1016                  }
1012 1017                  if (vhci_first_time == 1) {
1013 1018                          VHCI_DEBUG(1, (CE_WARN, hba_dip, "vhci_scsi_tgt_init: "
1014 1019                              "no wait for %s. from_tick %lx, to_tick %lx",
1015 1020                              guid, from_ticks, vhci_to_ticks));
1016 1021                          mutex_exit(&vhci_global_mutex);
1017 1022                          ddi_prop_free(guid);
1018 1023                          return (DDI_NOT_WELL_FORMED);
1019 1024                  }
1020 1025  
1021 1026                  if (cv_timedwait(&vhci_cv,
1022 1027                      &vhci_global_mutex, vhci_to_ticks) == -1) {
1023 1028                          /* Timed out */
1024 1029  #ifdef DEBUG
1025 1030                          if (vlun == NULL) {
1026 1031                                  VHCI_DEBUG(1, (CE_WARN, hba_dip,
1027 1032                                      "tgt_init: no vlun for %s!", guid));
1028 1033                          } else if (mdi_client_get_path_count(tgt_dip) == 0) {
1029 1034                                  VHCI_DEBUG(1, (CE_WARN, hba_dip,
1030 1035                                      "tgt_init: client path count is "
1031 1036                                      "zero for %s!", guid));
1032 1037                          } else {
1033 1038                                  VHCI_DEBUG(1, (CE_WARN, hba_dip,
1034 1039                                      "tgt_init: client path not "
1035 1040                                      "available yet for %s!", guid));
1036 1041                          }
1037 1042  #endif /* DEBUG */
1038 1043                          mutex_exit(&vhci_global_mutex);
1039 1044                          ddi_prop_free(guid);
1040 1045                          return (DDI_NOT_WELL_FORMED);
1041 1046                  }
1042 1047                  vlun = vhci_lun_lookup(tgt_dip);
1043 1048                  rval = mdi_select_path(tgt_dip, NULL,
1044 1049                      (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH),
1045 1050                      NULL, &pip);
1046 1051                  if (rval == MDI_SUCCESS) {
1047 1052                          mdi_rele_path(pip);
1048 1053                  }
1049 1054                  from_ticks = ddi_get_lbolt();
1050 1055          }
1051 1056          mutex_exit(&vhci_global_mutex);
1052 1057  
1053 1058          ASSERT(vlun != NULL);
1054 1059          ddi_prop_free(guid);
1055 1060  
1056 1061          scsi_device_hba_private_set(sd, vlun);
1057 1062  
1058 1063          return (DDI_SUCCESS);
1059 1064  }
1060 1065  
1061 1066  /*ARGSUSED*/
1062 1067  static void
1063 1068  vhci_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1064 1069          scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
1065 1070  {
1066 1071          struct scsi_vhci_lun *dvlp;
1067 1072          ASSERT(mdi_client_get_path_count(tgt_dip) <= 0);
1068 1073          dvlp = (struct scsi_vhci_lun *)scsi_device_hba_private_get(sd);
1069 1074          ASSERT(dvlp != NULL);
1070 1075  
1071 1076          vhci_lun_free(dvlp, sd);
1072 1077  }
1073 1078  
1074 1079  /*
1075 1080   * a PGR register command has started; copy the info we need
1076 1081   */
1077 1082  int
1078 1083  vhci_pgr_register_start(scsi_vhci_lun_t *vlun, struct scsi_pkt *pkt)
1079 1084  {
1080 1085          struct vhci_pkt         *vpkt = TGTPKT2VHCIPKT(pkt);
1081 1086          void                    *addr;
1082 1087  
1083 1088          if (!vpkt->vpkt_tgt_init_bp)
1084 1089                  return (TRAN_BADPKT);
1085 1090  
1086 1091          addr = bp_mapin_common(vpkt->vpkt_tgt_init_bp,
1087 1092              (vpkt->vpkt_flags & CFLAG_NOWAIT) ? VM_NOSLEEP : VM_SLEEP);
1088 1093          if (addr == NULL)
1089 1094                  return (TRAN_BUSY);
1090 1095  
1091 1096          mutex_enter(&vlun->svl_mutex);
1092 1097  
1093 1098          vhci_print_prout_keys(vlun, "v_pgr_reg_start: before bcopy:");
1094 1099  
1095 1100          bcopy(addr, &vlun->svl_prout, sizeof (vhci_prout_t) -
1096 1101              (2 * MHIOC_RESV_KEY_SIZE*sizeof (char)));
1097 1102          bcopy(pkt->pkt_cdbp, vlun->svl_cdb, sizeof (vlun->svl_cdb));
1098 1103  
1099 1104          vhci_print_prout_keys(vlun, "v_pgr_reg_start: after bcopy:");
1100 1105  
1101 1106          vlun->svl_time = pkt->pkt_time;
1102 1107          vlun->svl_bcount = vpkt->vpkt_tgt_init_bp->b_bcount;
1103 1108          vlun->svl_first_path = vpkt->vpkt_path;
1104 1109          mutex_exit(&vlun->svl_mutex);
1105 1110          return (0);
1106 1111  }
1107 1112  
1108 1113  /*
1109 1114   * Function name : vhci_scsi_start()
1110 1115   *
1111 1116   * Return Values : TRAN_FATAL_ERROR     - vhci has been shutdown
1112 1117   *                                        or other fatal failure
1113 1118   *                                        preventing packet transportation
1114 1119   *                 TRAN_BUSY            - request queue is full
1115 1120   *                 TRAN_ACCEPT          - pkt has been submitted to phci
1116 1121   *                                        (or is held in the waitQ)
1117 1122   * Description   : Implements SCSA's tran_start() entry point for
1118 1123   *                 packet transport
1119 1124   *
1120 1125   */
1121 1126  static int
1122 1127  vhci_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
1123 1128  {
1124 1129          int                     rval = TRAN_ACCEPT;
1125 1130          int                     instance, held;
1126 1131          struct scsi_vhci        *vhci = ADDR2VHCI(ap);
1127 1132          struct scsi_vhci_lun    *vlun = ADDR2VLUN(ap);
1128 1133          struct vhci_pkt         *vpkt = TGTPKT2VHCIPKT(pkt);
1129 1134          int                     flags = 0;
1130 1135          scsi_vhci_priv_t        *svp, *svp_resrv;
1131 1136          dev_info_t              *cdip;
1132 1137          client_lb_t             lbp;
1133 1138          int                     restore_lbp = 0;
1134 1139          /* set if pkt is SCSI-II RESERVE cmd */
1135 1140          int                     pkt_reserve_cmd = 0;
1136 1141          int                     reserve_failed = 0;
1137 1142          int                     resrv_instance = 0;
1138 1143          mdi_pathinfo_t          *pip;
1139 1144          struct scsi_pkt         *rel_pkt;
1140 1145  
1141 1146          ASSERT(vhci != NULL);
1142 1147          ASSERT(vpkt != NULL);
1143 1148          ASSERT(vpkt->vpkt_state != VHCI_PKT_ISSUED);
1144 1149          cdip = ADDR2DIP(ap);
1145 1150  
1146 1151          /*
1147 1152           * Block IOs if LUN is held or QUIESCED for IOs.
1148 1153           */
1149 1154          if ((VHCI_LUN_IS_HELD(vlun)) ||
1150 1155              ((vlun->svl_flags & VLUN_QUIESCED_FLG) == VLUN_QUIESCED_FLG)) {
1151 1156                  return (TRAN_BUSY);
1152 1157          }
1153 1158  
1154 1159          /*
1155 1160           * vhci_lun needs to be quiesced before SCSI-II RESERVE command
1156 1161           * can be issued.  This may require a cv_timedwait, which is
1157 1162           * dangerous to perform in an interrupt context.  So if this
1158 1163           * is a RESERVE command a taskq is dispatched to service it.
1159 1164           * This taskq shall again call vhci_scsi_start, but we shall be
1160 1165           * sure its not in an interrupt context.
1161 1166           */
1162 1167          if ((pkt->pkt_cdbp[0] == SCMD_RESERVE) ||
1163 1168              (pkt->pkt_cdbp[0] == SCMD_RESERVE_G1)) {
1164 1169                  if (!(vpkt->vpkt_state & VHCI_PKT_THRU_TASKQ)) {
1165 1170                          if (taskq_dispatch(vhci->vhci_taskq,
1166 1171                              vhci_dispatch_scsi_start, (void *) vpkt,
1167 1172                              KM_NOSLEEP)) {
1168 1173                                  return (TRAN_ACCEPT);
1169 1174                          } else {
1170 1175                                  return (TRAN_BUSY);
1171 1176                          }
1172 1177                  }
1173 1178  
1174 1179                  /*
1175 1180                   * Here we ensure that simultaneous SCSI-II RESERVE cmds don't
1176 1181                   * get serviced for a lun.
1177 1182                   */
1178 1183                  VHCI_HOLD_LUN(vlun, VH_NOSLEEP, held);
1179 1184                  if (!held) {
1180 1185                          return (TRAN_BUSY);
1181 1186                  } else if ((vlun->svl_flags & VLUN_QUIESCED_FLG) ==
1182 1187                      VLUN_QUIESCED_FLG) {
1183 1188                          VHCI_RELEASE_LUN(vlun);
1184 1189                          return (TRAN_BUSY);
1185 1190                  }
1186 1191  
1187 1192                  /*
1188 1193                   * To ensure that no IOs occur for this LUN for the duration
1189 1194                   * of this pkt set the VLUN_QUIESCED_FLG.
1190 1195                   * In case this routine needs to exit on error make sure that
1191 1196                   * this flag is cleared.
1192 1197                   */
1193 1198                  vlun->svl_flags |= VLUN_QUIESCED_FLG;
1194 1199                  pkt_reserve_cmd = 1;
1195 1200  
1196 1201                  /*
1197 1202                   * if this is a SCSI-II RESERVE command, set load balancing
1198 1203                   * policy to be ALTERNATE PATH to ensure that all subsequent
1199 1204                   * IOs are routed on the same path.  This is because if commands
1200 1205                   * are routed across multiple paths then IOs on paths other than
1201 1206                   * the one on which the RESERVE was executed will get a
1202 1207                   * RESERVATION CONFLICT
1203 1208                   */
1204 1209                  lbp = mdi_get_lb_policy(cdip);
1205 1210                  if (lbp != LOAD_BALANCE_NONE) {
1206 1211                          if (vhci_quiesce_lun(vlun) != 1) {
1207 1212                                  vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1208 1213                                  VHCI_RELEASE_LUN(vlun);
1209 1214                                  return (TRAN_FATAL_ERROR);
1210 1215                          }
1211 1216                          vlun->svl_lb_policy_save = lbp;
1212 1217                          if (mdi_set_lb_policy(cdip, LOAD_BALANCE_NONE) !=
1213 1218                              MDI_SUCCESS) {
1214 1219                                  vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1215 1220                                  VHCI_RELEASE_LUN(vlun);
1216 1221                                  return (TRAN_FATAL_ERROR);
1217 1222                          }
1218 1223                          restore_lbp = 1;
1219 1224                  }
1220 1225  
1221 1226                  VHCI_DEBUG(2, (CE_NOTE, vhci->vhci_dip,
1222 1227                      "!vhci_scsi_start: sending SCSI-2 RESERVE, vlun 0x%p, "
1223 1228                      "svl_resrv_pip 0x%p, svl_flags: %x, lb_policy %x",
1224 1229                      (void *)vlun, (void *)vlun->svl_resrv_pip, vlun->svl_flags,
1225 1230                      mdi_get_lb_policy(cdip)));
1226 1231  
1227 1232                  /*
1228 1233                   * See comments for VLUN_RESERVE_ACTIVE_FLG in scsi_vhci.h
1229 1234                   * To narrow this window where a reserve command may be sent
1230 1235                   * down an inactive path the path states first need to be
1231 1236                   * updated.  Before calling vhci_update_pathstates reset
1232 1237                   * VLUN_RESERVE_ACTIVE_FLG, just in case it was already set
1233 1238                   * for this lun.  This shall prevent an unnecessary reset
1234 1239                   * from being sent out.  Also remember currently reserved path
1235 1240                   * just for a case the new reservation will go to another path.
1236 1241                   */
1237 1242                  if (vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
1238 1243                          resrv_instance = mdi_pi_get_path_instance(
1239 1244                              vlun->svl_resrv_pip);
1240 1245                  }
1241 1246                  vlun->svl_flags &= ~VLUN_RESERVE_ACTIVE_FLG;
1242 1247                  vhci_update_pathstates((void *)vlun);
1243 1248          }
1244 1249  
1245 1250          instance = ddi_get_instance(vhci->vhci_dip);
1246 1251  
1247 1252          /*
1248 1253           * If the command is PRIN with action of zero, then the cmd
1249 1254           * is reading PR keys which requires filtering on completion.
1250 1255           * Data cache sync must be guaranteed.
1251 1256           */
1252 1257          if ((pkt->pkt_cdbp[0] == SCMD_PRIN) && (pkt->pkt_cdbp[1] == 0) &&
1253 1258              (vpkt->vpkt_org_vpkt == NULL)) {
1254 1259                  vpkt->vpkt_tgt_init_pkt_flags |= PKT_CONSISTENT;
1255 1260          }
1256 1261  
1257 1262          /*
1258 1263           * Do not defer bind for PKT_DMA_PARTIAL
1259 1264           */
1260 1265          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
1261 1266  
1262 1267                  /* This is a non pkt_dma_partial case */
1263 1268                  if ((rval = vhci_bind_transport(
1264 1269                      ap, vpkt, vpkt->vpkt_tgt_init_pkt_flags, NULL_FUNC))
1265 1270                      != TRAN_ACCEPT) {
1266 1271                          VHCI_DEBUG(6, (CE_WARN, vhci->vhci_dip,
1267 1272                              "!vhci%d %x: failed to bind transport: "
1268 1273                              "vlun 0x%p pkt_reserved %x restore_lbp %x,"
1269 1274                              "lbp %x", instance, rval, (void *)vlun,
1270 1275                              pkt_reserve_cmd, restore_lbp, lbp));
1271 1276                          if (restore_lbp)
1272 1277                                  (void) mdi_set_lb_policy(cdip, lbp);
1273 1278                          if (pkt_reserve_cmd)
1274 1279                                  vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1275 1280                          return (rval);
1276 1281                  }
1277 1282                  VHCI_DEBUG(8, (CE_NOTE, NULL,
1278 1283                      "vhci_scsi_start: v_b_t called 0x%p\n", (void *)vpkt));
1279 1284          }
1280 1285          ASSERT(vpkt->vpkt_hba_pkt != NULL);
1281 1286          ASSERT(vpkt->vpkt_path != NULL);
1282 1287  
1283 1288          /*
1284 1289           * This is the chance to adjust the pHCI's pkt and other information
1285 1290           * from target driver's pkt.
1286 1291           */
1287 1292          VHCI_DEBUG(8, (CE_NOTE, vhci->vhci_dip, "vhci_scsi_start vpkt %p\n",
1288 1293              (void *)vpkt));
1289 1294          vhci_update_pHCI_pkt(vpkt, pkt);
1290 1295  
1291 1296          if (vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
1292 1297                  if (vpkt->vpkt_path != vlun->svl_resrv_pip) {
1293 1298                          VHCI_DEBUG(1, (CE_WARN, vhci->vhci_dip,
1294 1299                              "!vhci_bind: reserve flag set for vlun 0x%p, but, "
1295 1300                              "pktpath 0x%p resrv path 0x%p differ. lb_policy %x",
1296 1301                              (void *)vlun, (void *)vpkt->vpkt_path,
1297 1302                              (void *)vlun->svl_resrv_pip,
1298 1303                              mdi_get_lb_policy(cdip)));
1299 1304                          reserve_failed = 1;
1300 1305                  }
1301 1306          }
1302 1307  
1303 1308          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
1304 1309          if (svp == NULL || reserve_failed) {
1305 1310                  if (pkt_reserve_cmd) {
1306 1311                          VHCI_DEBUG(6, (CE_WARN, vhci->vhci_dip,
1307 1312                              "!vhci_bind returned null svp vlun 0x%p",
1308 1313                              (void *)vlun));
1309 1314                          vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1310 1315                          if (restore_lbp)
1311 1316                                  (void) mdi_set_lb_policy(cdip, lbp);
1312 1317                  }
1313 1318  pkt_cleanup:
1314 1319                  if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
1315 1320                          scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
1316 1321                          vpkt->vpkt_hba_pkt = NULL;
1317 1322                          if (vpkt->vpkt_path) {
1318 1323                                  mdi_rele_path(vpkt->vpkt_path);
1319 1324                                  vpkt->vpkt_path = NULL;
1320 1325                          }
1321 1326                  }
1322 1327                  if ((pkt->pkt_cdbp[0] == SCMD_PROUT) &&
1323 1328                      (((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
1324 1329                      ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
1325 1330                          sema_v(&vlun->svl_pgr_sema);
1326 1331                  }
1327 1332                  return (TRAN_BUSY);
1328 1333          }
1329 1334  
1330 1335          if ((resrv_instance != 0) && (resrv_instance !=
1331 1336              mdi_pi_get_path_instance(vpkt->vpkt_path))) {
1332 1337                  /*
1333 1338                   * This is an attempt to reserve vpkt->vpkt_path.  But the
1334 1339                   * previously reserved path referred by resrv_instance might
1335 1340                   * still be reserved.  Hence we will send a release command
1336 1341                   * there in order to avoid a reservation conflict.
1337 1342                   */
1338 1343                  VHCI_DEBUG(1, (CE_NOTE, vhci->vhci_dip, "!vhci_scsi_start: "
1339 1344                      "conflicting reservation on another path, vlun 0x%p, "
1340 1345                      "reserved instance %d, new instance: %d, pip: 0x%p",
1341 1346                      (void *)vlun, resrv_instance,
1342 1347                      mdi_pi_get_path_instance(vpkt->vpkt_path),
1343 1348                      (void *)vpkt->vpkt_path));
1344 1349  
1345 1350                  /*
1346 1351                   * In rare cases, the path referred by resrv_instance could
1347 1352                   * disappear in the meantime. Calling mdi_select_path() below
1348 1353                   * is an attempt to find out if the path still exists. It also
1349 1354                   * ensures that the path will be held when the release is sent.
1350 1355                   */
1351 1356                  rval = mdi_select_path(cdip, NULL, MDI_SELECT_PATH_INSTANCE,
1352 1357                      (void *)(intptr_t)resrv_instance, &pip);
1353 1358  
1354 1359                  if ((rval == MDI_SUCCESS) && (pip != NULL)) {
1355 1360                          svp_resrv = (scsi_vhci_priv_t *)
1356 1361                              mdi_pi_get_vhci_private(pip);
1357 1362                          rel_pkt = scsi_init_pkt(&svp_resrv->svp_psd->sd_address,
1358 1363                              NULL, NULL, CDB_GROUP0,
1359 1364                              sizeof (struct scsi_arq_status), 0, 0, SLEEP_FUNC,
1360 1365                              NULL);
1361 1366  
1362 1367                          if (rel_pkt == NULL) {
1363 1368                                  char    *p_path;
1364 1369  
1365 1370                                  /*
1366 1371                                   * This is very unlikely.
1367 1372                                   * scsi_init_pkt(SLEEP_FUNC) does not fail
1368 1373                                   * because of resources. But in theory it could
1369 1374                                   * fail for some other reason. There is not an
1370 1375                                   * easy way how to recover though. Log a warning
1371 1376                                   * and return.
1372 1377                                   */
1373 1378                                  p_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1374 1379                                  vhci_log(CE_WARN, vhci->vhci_dip, "!Sending "
1375 1380                                      "RELEASE(6) to %s failed, a potential "
1376 1381                                      "reservation conflict ahead.",
1377 1382                                      ddi_pathname(mdi_pi_get_phci(pip), p_path));
1378 1383                                  kmem_free(p_path, MAXPATHLEN);
  
    | 
      ↓ open down ↓ | 
    1234 lines elided | 
    
      ↑ open up ↑ | 
  
1379 1384  
1380 1385                                  if (restore_lbp)
1381 1386                                          (void) mdi_set_lb_policy(cdip, lbp);
1382 1387  
1383 1388                                  /* no need to check pkt_reserve_cmd here */
1384 1389                                  vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1385 1390                                  return (TRAN_FATAL_ERROR);
1386 1391                          }
1387 1392  
1388 1393                          rel_pkt->pkt_cdbp[0] = SCMD_RELEASE;
1389      -                        rel_pkt->pkt_time = 60;
     1394 +                        rel_pkt->pkt_time = vhci_io_time;
1390 1395  
1391 1396                          /*
1392 1397                           * Ignore the return value.  If it will fail
1393 1398                           * then most likely it is no longer reserved
1394 1399                           * anyway.
1395 1400                           */
1396 1401                          (void) vhci_do_scsi_cmd(rel_pkt);
1397 1402                          VHCI_DEBUG(1, (CE_NOTE, NULL,
1398 1403                              "!vhci_scsi_start: path 0x%p, issued SCSI-2"
1399 1404                              " RELEASE\n", (void *)pip));
1400 1405                          scsi_destroy_pkt(rel_pkt);
1401 1406                          mdi_rele_path(pip);
1402 1407                  }
1403 1408          }
1404 1409  
1405 1410          VHCI_INCR_PATH_CMDCOUNT(svp);
1406 1411  
1407 1412          /*
1408 1413           * Ensure that no other IOs raced ahead, while a RESERVE cmd was
1409 1414           * QUIESCING the same lun.
1410 1415           */
1411 1416          if ((!pkt_reserve_cmd) &&
1412 1417              ((vlun->svl_flags & VLUN_QUIESCED_FLG) == VLUN_QUIESCED_FLG)) {
1413 1418                  VHCI_DECR_PATH_CMDCOUNT(svp);
1414 1419                  goto pkt_cleanup;
1415 1420          }
1416 1421  
1417 1422          if ((pkt->pkt_cdbp[0] == SCMD_PRIN) ||
1418 1423              (pkt->pkt_cdbp[0] == SCMD_PROUT)) {
1419 1424                  /*
1420 1425                   * currently this thread only handles running PGR
1421 1426                   * commands, so don't bother creating it unless
1422 1427                   * something interesting is going to happen (like
1423 1428                   * either a PGR out, or a PGR in with enough space
1424 1429                   * to hold the keys that are getting returned)
1425 1430                   */
1426 1431                  mutex_enter(&vlun->svl_mutex);
1427 1432                  if (((vlun->svl_flags & VLUN_TASK_D_ALIVE_FLG) == 0) &&
1428 1433                      (pkt->pkt_cdbp[0] == SCMD_PROUT)) {
1429 1434                          vlun->svl_taskq = taskq_create("vlun_pgr_task_daemon",
1430 1435                              1, MINCLSYSPRI, 1, 4, 0);
1431 1436                          vlun->svl_flags |= VLUN_TASK_D_ALIVE_FLG;
1432 1437                  }
1433 1438                  mutex_exit(&vlun->svl_mutex);
1434 1439                  if ((pkt->pkt_cdbp[0] == SCMD_PROUT) &&
1435 1440                      (((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
1436 1441                      ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
1437 1442                          if (rval = vhci_pgr_register_start(vlun, pkt)) {
1438 1443                                  /* an error */
1439 1444                                  sema_v(&vlun->svl_pgr_sema);
1440 1445                                  return (rval);
1441 1446                          }
1442 1447                  }
1443 1448          }
1444 1449  
1445 1450          /*
1446 1451           * SCSI-II RESERVE cmd is not expected in polled mode.
1447 1452           * If this changes it needs to be handled for the polled scenario.
1448 1453           */
1449 1454          flags = vpkt->vpkt_hba_pkt->pkt_flags;
1450 1455  
1451 1456          /*
1452 1457           * Set the path_instance *before* sending the scsi_pkt down the path
1453 1458           * to mpxio's pHCI so that additional path abstractions at a pHCI
1454 1459           * level (like maybe iSCSI at some point in the future) can update
1455 1460           * the path_instance.
1456 1461           */
1457 1462          if (scsi_pkt_allocated_correctly(vpkt->vpkt_hba_pkt))
1458 1463                  vpkt->vpkt_hba_pkt->pkt_path_instance =
1459 1464                      mdi_pi_get_path_instance(vpkt->vpkt_path);
1460 1465  
1461 1466          rval = scsi_transport(vpkt->vpkt_hba_pkt);
1462 1467          if (rval == TRAN_ACCEPT) {
1463 1468                  if (flags & FLAG_NOINTR) {
1464 1469                          struct scsi_pkt *tpkt = vpkt->vpkt_tgt_pkt;
1465 1470                          struct scsi_pkt *pkt = vpkt->vpkt_hba_pkt;
1466 1471  
1467 1472                          ASSERT(tpkt != NULL);
1468 1473                          *(tpkt->pkt_scbp) = *(pkt->pkt_scbp);
1469 1474                          tpkt->pkt_resid = pkt->pkt_resid;
1470 1475                          tpkt->pkt_state = pkt->pkt_state;
1471 1476                          tpkt->pkt_statistics = pkt->pkt_statistics;
1472 1477                          tpkt->pkt_reason = pkt->pkt_reason;
1473 1478  
1474 1479                          if ((*(pkt->pkt_scbp) == STATUS_CHECK) &&
1475 1480                              (pkt->pkt_state & STATE_ARQ_DONE)) {
1476 1481                                  bcopy(pkt->pkt_scbp, tpkt->pkt_scbp,
1477 1482                                      vpkt->vpkt_tgt_init_scblen);
1478 1483                          }
1479 1484  
1480 1485                          VHCI_DECR_PATH_CMDCOUNT(svp);
1481 1486                          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
1482 1487                                  scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
1483 1488                                  vpkt->vpkt_hba_pkt = NULL;
1484 1489                                  if (vpkt->vpkt_path) {
1485 1490                                          mdi_rele_path(vpkt->vpkt_path);
1486 1491                                          vpkt->vpkt_path = NULL;
1487 1492                                  }
1488 1493                          }
1489 1494                          /*
1490 1495                           * This path will not automatically retry pkts
1491 1496                           * internally, therefore, vpkt_org_vpkt should
1492 1497                           * never be set.
1493 1498                           */
1494 1499                          ASSERT(vpkt->vpkt_org_vpkt == NULL);
1495 1500                          scsi_hba_pkt_comp(tpkt);
1496 1501                  }
1497 1502                  return (rval);
1498 1503          } else if ((pkt->pkt_cdbp[0] == SCMD_PROUT) &&
1499 1504              (((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
1500 1505              ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
1501 1506                  /* the command exited with bad status */
1502 1507                  sema_v(&vlun->svl_pgr_sema);
1503 1508          } else if (vpkt->vpkt_tgt_pkt->pkt_cdbp[0] == SCMD_PRIN) {
1504 1509                  /* the command exited with bad status */
1505 1510                  sema_v(&vlun->svl_pgr_sema);
1506 1511          } else if (pkt_reserve_cmd) {
1507 1512                  VHCI_DEBUG(6, (CE_WARN, vhci->vhci_dip,
1508 1513                      "!vhci_scsi_start: reserve failed vlun 0x%p",
1509 1514                      (void *)vlun));
1510 1515                  vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1511 1516                  if (restore_lbp)
1512 1517                          (void) mdi_set_lb_policy(cdip, lbp);
1513 1518          }
1514 1519  
1515 1520          ASSERT(vpkt->vpkt_hba_pkt != NULL);
1516 1521          VHCI_DECR_PATH_CMDCOUNT(svp);
1517 1522  
1518 1523          /* Do not destroy phci packet information for PKT_DMA_PARTIAL */
1519 1524          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
1520 1525                  scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
1521 1526                  vpkt->vpkt_hba_pkt = NULL;
1522 1527                  if (vpkt->vpkt_path) {
1523 1528                          MDI_PI_ERRSTAT(vpkt->vpkt_path, MDI_PI_TRANSERR);
1524 1529                          mdi_rele_path(vpkt->vpkt_path);
1525 1530                          vpkt->vpkt_path = NULL;
1526 1531                  }
1527 1532          }
  
    | 
      ↓ open down ↓ | 
    128 lines elided | 
    
      ↑ open up ↑ | 
  
1528 1533          return (TRAN_BUSY);
1529 1534  }
1530 1535  
1531 1536  /*
1532 1537   * Function name : vhci_scsi_reset()
1533 1538   *
1534 1539   * Return Values : 0 - reset failed
1535 1540   *                 1 - reset succeeded
1536 1541   */
1537 1542  
1538      -/* ARGSUSED */
1539 1543  static int
1540 1544  vhci_scsi_reset(struct scsi_address *ap, int level)
1541 1545  {
1542      -        int rval = 0;
1543      -
1544      -        cmn_err(CE_WARN, "!vhci_scsi_reset 0x%x", level);
1545 1546          if ((level == RESET_TARGET) || (level == RESET_LUN)) {
1546 1547                  return (vhci_scsi_reset_target(ap, level, TRUE));
1547 1548          } else if (level == RESET_ALL) {
1548 1549                  return (vhci_scsi_reset_bus(ap));
     1550 +        } else {
     1551 +                return (0);
1549 1552          }
1550      -
1551      -        return (rval);
1552 1553  }
1553 1554  
1554 1555  /*
1555 1556   * vhci_recovery_reset:
1556 1557   *      Issues reset to the device
1557 1558   * Input:
1558 1559   *      vlun - vhci lun pointer of the device
1559 1560   *      ap - address of the device
1560 1561   *      select_path:
1561 1562   *              If select_path is FALSE, then the address specified in ap is
1562 1563   *              the path on which reset will be issued.
1563 1564   *              If select_path is TRUE, then path is obtained by calling
1564 1565   *              mdi_select_path.
1565 1566   *
1566 1567   *      recovery_depth:
1567 1568   *              Caller can specify the level of reset.
1568 1569   *              VHCI_DEPTH_LUN -
1569 1570   *                      Issues LUN RESET if device supports lun reset.
1570 1571   *              VHCI_DEPTH_TARGET -
1571 1572   *                      If Lun Reset fails or the device does not support
1572 1573   *                      Lun Reset, issues TARGET RESET
1573 1574   *              VHCI_DEPTH_ALL -
1574 1575   *                      If Lun Reset fails or the device does not support
1575 1576   *                      Lun Reset, issues TARGET RESET.
1576 1577   *                      If TARGET RESET does not succeed, issues Bus Reset.
1577 1578   */
1578 1579  
1579 1580  static int
1580 1581  vhci_recovery_reset(scsi_vhci_lun_t *vlun, struct scsi_address *ap,
1581 1582          uint8_t select_path, uint8_t recovery_depth)
1582 1583  {
1583 1584          int     ret = 0;
1584 1585  
1585 1586          ASSERT(ap != NULL);
1586 1587  
1587 1588          if (vlun && vlun->svl_support_lun_reset == 1) {
1588 1589                  ret = vhci_scsi_reset_target(ap, RESET_LUN,
1589 1590                      select_path);
1590 1591          }
1591 1592  
1592 1593          recovery_depth--;
1593 1594  
1594 1595          if ((ret == 0) && recovery_depth) {
1595 1596                  ret = vhci_scsi_reset_target(ap, RESET_TARGET,
1596 1597                      select_path);
1597 1598                  recovery_depth--;
1598 1599          }
1599 1600  
1600 1601          if ((ret == 0) && recovery_depth) {
1601 1602                  (void) scsi_reset(ap, RESET_ALL);
1602 1603          }
1603 1604  
1604 1605          return (ret);
1605 1606  }
1606 1607  
  
    | 
      ↓ open down ↓ | 
    45 lines elided | 
    
      ↑ open up ↑ | 
  
1607 1608  /*
1608 1609   * Note: The scsi_address passed to this routine could be the scsi_address
1609 1610   * for the virtual device or the physical device. No assumptions should be
1610 1611   * made in this routine about the contents of the ap structure.
1611 1612   * Further, note that the child dip would be the dip of the ssd node regardless
1612 1613   * of the scsi_address passed in.
1613 1614   */
1614 1615  static int
1615 1616  vhci_scsi_reset_target(struct scsi_address *ap, int level, uint8_t select_path)
1616 1617  {
1617      -        dev_info_t              *vdip, *cdip;
     1618 +        dev_info_t              *vdip, *cdip = NULL;
1618 1619          mdi_pathinfo_t          *pip = NULL;
1619 1620          mdi_pathinfo_t          *npip = NULL;
1620 1621          int                     rval = -1;
1621 1622          scsi_vhci_priv_t        *svp = NULL;
1622 1623          struct scsi_address     *pap = NULL;
1623 1624          scsi_hba_tran_t         *hba = NULL;
1624 1625          int                     sps;
1625 1626          struct scsi_vhci        *vhci = NULL;
1626 1627  
1627 1628          if (select_path != TRUE) {
1628 1629                  ASSERT(ap != NULL);
1629 1630                  if (level == RESET_LUN) {
1630 1631                          hba = ap->a_hba_tran;
1631 1632                          ASSERT(hba != NULL);
1632 1633                          return (hba->tran_reset(ap, RESET_LUN));
1633 1634                  }
1634 1635                  return (scsi_reset(ap, level));
1635 1636          }
1636 1637  
1637      -        cdip = ADDR2DIP(ap);
     1638 +        /*
     1639 +         * SCSI address should be interpreted according to the pHBA flags.
     1640 +         */
     1641 +        if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX)
     1642 +                cdip = ADDR2DIP(ap);
     1643 +        else if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
     1644 +                cdip = ap->a_hba_tran->tran_sd->sd_dev;
     1645 +
1638 1646          ASSERT(cdip != NULL);
1639 1647          vdip = ddi_get_parent(cdip);
1640 1648          ASSERT(vdip != NULL);
1641 1649          vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1642 1650          ASSERT(vhci != NULL);
1643 1651  
1644 1652          rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
1645 1653          if ((rval != MDI_SUCCESS) || (pip == NULL)) {
1646 1654                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1647 1655                      "Unable to get a path, dip 0x%p", (void *)cdip));
1648 1656                  return (0);
1649 1657          }
1650 1658  again:
1651 1659          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
1652 1660          if (svp == NULL) {
1653 1661                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1654 1662                      "priv is NULL, pip 0x%p", (void *)pip));
1655 1663                  mdi_rele_path(pip);
1656 1664                  return (0);
1657 1665          }
1658 1666  
1659 1667          if (svp->svp_psd == NULL) {
1660 1668                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1661 1669                      "psd is NULL, pip 0x%p, svp 0x%p",
1662 1670                      (void *)pip, (void *)svp));
1663 1671                  mdi_rele_path(pip);
1664 1672                  return (0);
1665 1673          }
1666 1674  
1667 1675          pap = &svp->svp_psd->sd_address;
1668 1676          hba = pap->a_hba_tran;
1669 1677  
1670 1678          ASSERT(pap != NULL);
1671 1679          ASSERT(hba != NULL);
1672 1680  
1673 1681          if (hba->tran_reset != NULL) {
1674 1682                  if (hba->tran_reset(pap, level) == 0) {
1675 1683                          vhci_log(CE_WARN, vdip, "!%s%d: "
1676 1684                              "path %s, reset %d failed",
1677 1685                              ddi_driver_name(cdip), ddi_get_instance(cdip),
1678 1686                              mdi_pi_spathname(pip), level);
1679 1687  
1680 1688                          /*
1681 1689                           * Select next path and issue the reset, repeat
1682 1690                           * until all paths are exhausted
1683 1691                           */
1684 1692                          sps = mdi_select_path(cdip, NULL,
1685 1693                              MDI_SELECT_ONLINE_PATH, pip, &npip);
1686 1694                          if ((sps != MDI_SUCCESS) || (npip == NULL)) {
1687 1695                                  mdi_rele_path(pip);
1688 1696                                  return (0);
1689 1697                          }
1690 1698                          mdi_rele_path(pip);
1691 1699                          pip = npip;
1692 1700                          goto again;
1693 1701                  }
1694 1702                  mdi_rele_path(pip);
1695 1703                  mutex_enter(&vhci->vhci_mutex);
1696 1704                  scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
1697 1705                      &vhci->vhci_reset_notify_listf);
  
    | 
      ↓ open down ↓ | 
    50 lines elided | 
    
      ↑ open up ↑ | 
  
1698 1706                  mutex_exit(&vhci->vhci_mutex);
1699 1707                  VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
1700 1708                      "reset %d sent down pip:%p for cdip:%p\n", level,
1701 1709                      (void *)pip, (void *)cdip));
1702 1710                  return (1);
1703 1711          }
1704 1712          mdi_rele_path(pip);
1705 1713          return (0);
1706 1714  }
1707 1715  
1708      -
1709 1716  /* ARGSUSED */
1710 1717  static int
1711 1718  vhci_scsi_reset_bus(struct scsi_address *ap)
1712 1719  {
1713 1720          return (1);
1714 1721  }
1715 1722  
     1723 +/*
     1724 + * This is a special version of LUN reset routine
     1725 + * which sends a reset down all available paths.
     1726 + */
     1727 +static int
     1728 +vhci_scsi_reset_all_paths(struct scsi_address *ap)
     1729 +{
     1730 +        dev_info_t              *vdip, *cdip = NULL;
     1731 +        mdi_pathinfo_t          *pip = NULL;
     1732 +        mdi_pathinfo_t          *npip = NULL;
     1733 +        int                     rval = -1;
     1734 +        scsi_vhci_priv_t        *svp = NULL;
     1735 +        struct scsi_address     *pap = NULL;
     1736 +        scsi_hba_tran_t         *hba = NULL;
     1737 +        int                     sps = MDI_SUCCESS;
     1738 +        int                     reset_result = 0;
     1739 +        struct scsi_vhci        *vhci = NULL;
1716 1740  
     1741 +        /*
     1742 +         * SCSI address should be interpreted according to the pHBA flags.
     1743 +         */
     1744 +        if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX)
     1745 +                cdip = ADDR2DIP(ap);
     1746 +        else if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
     1747 +                cdip = ap->a_hba_tran->tran_sd->sd_dev;
     1748 +
     1749 +        if (cdip == NULL || (vdip = ddi_get_parent(cdip)) == NULL ||
     1750 +            (vhci = ddi_get_soft_state(vhci_softstate,
     1751 +                ddi_get_instance(vdip))) == NULL) {
     1752 +                VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
     1753 +                    "Child info pointer NULL, cdip 0x%p",
     1754 +                    __func__, (void *)cdip));
     1755 +                return (0);
     1756 +        }
     1757 +
     1758 +        rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
     1759 +        if ((rval != MDI_SUCCESS) || (pip == NULL)) {
     1760 +                VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
     1761 +                    "Unable to get a path, dip 0x%p",
     1762 +                    __func__, (void *)cdip));
     1763 +                return (0);
     1764 +        }
     1765 +again:
     1766 +        svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
     1767 +
     1768 +        if (svp == NULL || svp->svp_psd == NULL) {
     1769 +                VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
     1770 +                    "private data is NULL, pip 0x%p",
     1771 +                    __func__, (void *)pip));
     1772 +                mdi_rele_path(pip);
     1773 +                return (0);
     1774 +        }
     1775 +
     1776 +        pap = &svp->svp_psd->sd_address;
     1777 +        hba = pap->a_hba_tran;
     1778 +
     1779 +        if (pap != NULL && hba != NULL && hba->tran_reset != NULL) {
     1780 +                /*
     1781 +                 * The following sends reset down all available paths
     1782 +                 */
     1783 +                if (sps == MDI_SUCCESS) {
     1784 +                        reset_result = hba->tran_reset(pap, RESET_LUN);
     1785 +
     1786 +                        VHCI_DEBUG(2, (CE_WARN, vdip, "!%s%d: "
     1787 +                            "path %s, reset LUN %s",
     1788 +                            ddi_driver_name(cdip), ddi_get_instance(cdip),
     1789 +                            mdi_pi_spathname(pip),
     1790 +                            (reset_result ? "Success" : "Failed")));
     1791 +
     1792 +                        /*
     1793 +                         * Select next path and issue the reset, repeat
     1794 +                         * until all paths are exhausted regardless of success
     1795 +                         * or failure of the previous reset.
     1796 +                         */
     1797 +                        sps = mdi_select_path(cdip, NULL,
     1798 +                            MDI_SELECT_ONLINE_PATH, pip, &npip);
     1799 +                        if ((sps != MDI_SUCCESS) || (npip == NULL)) {
     1800 +                                mdi_rele_path(pip);
     1801 +                                return (0);
     1802 +                        }
     1803 +                        mdi_rele_path(pip);
     1804 +                        pip = npip;
     1805 +                        goto again;
     1806 +                }
     1807 +                mdi_rele_path(pip);
     1808 +                mutex_enter(&vhci->vhci_mutex);
     1809 +                scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
     1810 +                    &vhci->vhci_reset_notify_listf);
     1811 +                mutex_exit(&vhci->vhci_mutex);
     1812 +                VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
     1813 +                    "reset %d sent down pip:%p for cdip:%p\n", RESET_LUN,
     1814 +                    (void *)pip, (void *)cdip));
     1815 +                return (1);
     1816 +        }
     1817 +        mdi_rele_path(pip);
     1818 +        return (0);
     1819 +}
     1820 +
1717 1821  /*
1718 1822   * called by vhci_getcap and vhci_setcap to get and set (respectively)
1719 1823   * SCSI capabilities
1720 1824   */
1721 1825  /* ARGSUSED */
1722 1826  static int
1723 1827  vhci_commoncap(struct scsi_address *ap, char *cap,
1724 1828      int val, int tgtonly, int doset)
1725 1829  {
1726 1830          struct scsi_vhci                *vhci = ADDR2VHCI(ap);
1727 1831          struct scsi_vhci_lun            *vlun = ADDR2VLUN(ap);
1728 1832          int                     cidx;
1729 1833          int                     rval = 0;
1730 1834  
1731 1835          if (cap == (char *)0) {
1732 1836                  VHCI_DEBUG(3, (CE_WARN, vhci->vhci_dip,
1733 1837                      "!vhci_commoncap: invalid arg"));
1734 1838                  return (rval);
1735 1839          }
1736 1840  
1737 1841          if (vlun == NULL) {
1738 1842                  VHCI_DEBUG(3, (CE_WARN, vhci->vhci_dip,
1739 1843                      "!vhci_commoncap: vlun is null"));
1740 1844                  return (rval);
1741 1845          }
1742 1846  
1743 1847          if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
1744 1848                  return (UNDEFINED);
1745 1849          }
1746 1850  
1747 1851          /*
1748 1852           * Process setcap request.
1749 1853           */
1750 1854          if (doset) {
1751 1855                  /*
1752 1856                   * At present, we can only set binary (0/1) values
1753 1857                   */
1754 1858                  switch (cidx) {
1755 1859                  case SCSI_CAP_ARQ:
1756 1860                          if (val == 0) {
1757 1861                                  rval = 0;
1758 1862                          } else {
1759 1863                                  rval = 1;
1760 1864                          }
1761 1865                          break;
1762 1866  
1763 1867                  case SCSI_CAP_LUN_RESET:
1764 1868                          if (tgtonly == 0) {
1765 1869                                  VHCI_DEBUG(1, (CE_WARN, vhci->vhci_dip,
1766 1870                                      "scsi_vhci_setcap: "
1767 1871                                      "Returning error since whom = 0"));
1768 1872                                  rval = -1;
1769 1873                                  break;
1770 1874                          }
1771 1875                          /*
1772 1876                           * Set the capability accordingly.
1773 1877                           */
1774 1878                          mutex_enter(&vlun->svl_mutex);
1775 1879                          vlun->svl_support_lun_reset = val;
1776 1880                          rval = val;
1777 1881                          mutex_exit(&vlun->svl_mutex);
1778 1882                          break;
1779 1883  
1780 1884                  case SCSI_CAP_SECTOR_SIZE:
1781 1885                          mutex_enter(&vlun->svl_mutex);
1782 1886                          vlun->svl_sector_size = val;
1783 1887                          vlun->svl_setcap_done = 1;
1784 1888                          mutex_exit(&vlun->svl_mutex);
1785 1889                          (void) vhci_pHCI_cap(ap, cap, val, tgtonly, NULL);
1786 1890  
1787 1891                          /* Always return success */
1788 1892                          rval = 1;
1789 1893                          break;
1790 1894  
1791 1895                  default:
1792 1896                          VHCI_DEBUG(6, (CE_WARN, vhci->vhci_dip,
1793 1897                              "!vhci_setcap: unsupported %d", cidx));
1794 1898                          rval = UNDEFINED;
1795 1899                          break;
1796 1900                  }
1797 1901  
1798 1902                  VHCI_DEBUG(6, (CE_NOTE, vhci->vhci_dip,
1799 1903                      "!set cap: cap=%s, val/tgtonly/doset/rval = "
1800 1904                      "0x%x/0x%x/0x%x/%d\n",
1801 1905                      cap, val, tgtonly, doset, rval));
1802 1906  
1803 1907          } else {
1804 1908                  /*
1805 1909                   * Process getcap request.
1806 1910                   */
1807 1911                  switch (cidx) {
1808 1912                  case SCSI_CAP_DMA_MAX:
1809 1913                          /*
1810 1914                           * For X86 this capability is caught in scsi_ifgetcap().
1811 1915                           * XXX Should this be getting the value from the pHCI?
1812 1916                           */
1813 1917                          rval = (int)VHCI_DMA_MAX_XFER_CAP;
1814 1918                          break;
1815 1919  
1816 1920                  case SCSI_CAP_INITIATOR_ID:
1817 1921                          rval = 0x00;
1818 1922                          break;
1819 1923  
1820 1924                  case SCSI_CAP_ARQ:
1821 1925                  case SCSI_CAP_RESET_NOTIFICATION:
1822 1926                  case SCSI_CAP_TAGGED_QING:
1823 1927                          rval = 1;
1824 1928                          break;
1825 1929  
1826 1930                  case SCSI_CAP_SCSI_VERSION:
1827 1931                          rval = 3;
1828 1932                          break;
1829 1933  
1830 1934                  case SCSI_CAP_INTERCONNECT_TYPE:
1831 1935                          rval = INTERCONNECT_FABRIC;
1832 1936                          break;
1833 1937  
1834 1938                  case SCSI_CAP_LUN_RESET:
1835 1939                          /*
1836 1940                           * scsi_vhci will always return success for LUN reset.
1837 1941                           * When request for doing LUN reset comes
1838 1942                           * through scsi_reset entry point, at that time attempt
1839 1943                           * will be made to do reset through all the possible
1840 1944                           * paths.
1841 1945                           */
1842 1946                          mutex_enter(&vlun->svl_mutex);
1843 1947                          rval = vlun->svl_support_lun_reset;
1844 1948                          mutex_exit(&vlun->svl_mutex);
1845 1949                          VHCI_DEBUG(4, (CE_WARN, vhci->vhci_dip,
1846 1950                              "scsi_vhci_getcap:"
1847 1951                              "Getting the Lun reset capability %d", rval));
1848 1952                          break;
1849 1953  
1850 1954                  case SCSI_CAP_SECTOR_SIZE:
1851 1955                          mutex_enter(&vlun->svl_mutex);
1852 1956                          rval = vlun->svl_sector_size;
1853 1957                          mutex_exit(&vlun->svl_mutex);
1854 1958                          break;
1855 1959  
1856 1960                  case SCSI_CAP_CDB_LEN:
1857 1961                          rval = VHCI_SCSI_CDB_SIZE;
1858 1962                          break;
1859 1963  
1860 1964                  case SCSI_CAP_DMA_MAX_ARCH:
1861 1965                          /*
1862 1966                           * For X86 this capability is caught in scsi_ifgetcap().
1863 1967                           * XXX Should this be getting the value from the pHCI?
1864 1968                           */
1865 1969                          rval = 0;
1866 1970                          break;
1867 1971  
1868 1972                  default:
1869 1973                          VHCI_DEBUG(6, (CE_WARN, vhci->vhci_dip,
1870 1974                              "!vhci_getcap: unsupported %d", cidx));
1871 1975                          rval = UNDEFINED;
1872 1976                          break;
1873 1977                  }
1874 1978  
1875 1979                  VHCI_DEBUG(6, (CE_NOTE, vhci->vhci_dip,
1876 1980                      "!get cap: cap=%s, val/tgtonly/doset/rval = "
1877 1981                      "0x%x/0x%x/0x%x/%d\n",
1878 1982                      cap, val, tgtonly, doset, rval));
1879 1983          }
1880 1984          return (rval);
1881 1985  }
1882 1986  
1883 1987  
1884 1988  /*
1885 1989   * Function name : vhci_scsi_getcap()
1886 1990   *
1887 1991   */
1888 1992  static int
1889 1993  vhci_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
1890 1994  {
1891 1995          return (vhci_commoncap(ap, cap, 0, whom, 0));
1892 1996  }
1893 1997  
1894 1998  static int
1895 1999  vhci_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1896 2000  {
1897 2001          return (vhci_commoncap(ap, cap, value, whom, 1));
1898 2002  }
1899 2003  
1900 2004  /*
1901 2005   * Function name : vhci_scsi_abort()
1902 2006   */
1903 2007  /* ARGSUSED */
1904 2008  static int
1905 2009  vhci_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1906 2010  {
1907 2011          return (0);
1908 2012  }
1909 2013  
1910 2014  /*
1911 2015   * Function name : vhci_scsi_init_pkt
1912 2016   *
1913 2017   * Return Values : pointer to scsi_pkt, or NULL
1914 2018   */
1915 2019  /* ARGSUSED */
1916 2020  static struct scsi_pkt *
1917 2021  vhci_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
1918 2022          struct buf *bp, int cmdlen, int statuslen, int tgtlen,
1919 2023          int flags, int (*callback)(caddr_t), caddr_t arg)
1920 2024  {
1921 2025          struct scsi_vhci        *vhci = ADDR2VHCI(ap);
1922 2026          struct vhci_pkt         *vpkt;
1923 2027          int                     rval;
1924 2028          int                     newpkt = 0;
1925 2029          struct scsi_pkt         *pktp;
1926 2030  
1927 2031  
1928 2032          if (pkt == NULL) {
1929 2033                  if (cmdlen > VHCI_SCSI_CDB_SIZE) {
1930 2034                          if ((cmdlen != VHCI_SCSI_OSD_CDB_SIZE) ||
1931 2035                              ((flags & VHCI_SCSI_OSD_PKT_FLAGS) !=
1932 2036                              VHCI_SCSI_OSD_PKT_FLAGS)) {
1933 2037                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
1934 2038                                      "!init pkt: cdb size not supported\n"));
1935 2039                                  return (NULL);
1936 2040                          }
1937 2041                  }
1938 2042  
1939 2043                  pktp = scsi_hba_pkt_alloc(vhci->vhci_dip,
1940 2044                      ap, cmdlen, statuslen, tgtlen, sizeof (*vpkt), callback,
1941 2045                      arg);
1942 2046  
1943 2047                  if (pktp == NULL) {
1944 2048                          return (NULL);
1945 2049                  }
1946 2050  
1947 2051                  /* Get the vhci's private structure */
1948 2052                  vpkt = (struct vhci_pkt *)(pktp->pkt_ha_private);
1949 2053                  ASSERT(vpkt);
1950 2054  
1951 2055                  /* Save the target driver's packet */
1952 2056                  vpkt->vpkt_tgt_pkt = pktp;
1953 2057  
1954 2058                  /*
1955 2059                   * Save pkt_tgt_init_pkt fields if deferred binding
1956 2060                   * is needed or for other purposes.
1957 2061                   */
1958 2062                  vpkt->vpkt_tgt_init_pkt_flags = flags;
1959 2063                  vpkt->vpkt_flags = (callback == NULL_FUNC) ? CFLAG_NOWAIT : 0;
1960 2064                  vpkt->vpkt_state = VHCI_PKT_IDLE;
1961 2065                  vpkt->vpkt_tgt_init_cdblen = cmdlen;
1962 2066                  vpkt->vpkt_tgt_init_scblen = statuslen;
1963 2067                  newpkt = 1;
1964 2068          } else { /* pkt not NULL */
1965 2069                  vpkt = pkt->pkt_ha_private;
1966 2070          }
1967 2071  
1968 2072          VHCI_DEBUG(8, (CE_NOTE, NULL, "vhci_scsi_init_pkt "
1969 2073              "vpkt %p flags %x\n", (void *)vpkt, flags));
1970 2074  
1971 2075          /* Clear any stale error flags */
1972 2076          if (bp) {
1973 2077                  bioerror(bp, 0);
1974 2078          }
1975 2079  
1976 2080          vpkt->vpkt_tgt_init_bp = bp;
1977 2081  
1978 2082          if (flags & PKT_DMA_PARTIAL) {
1979 2083  
1980 2084                  /*
1981 2085                   * Immediate binding is needed.
1982 2086                   * Target driver may not set this flag in next invocation.
1983 2087                   * vhci has to remember this flag was set during first
1984 2088                   * invocation of vhci_scsi_init_pkt.
1985 2089                   */
1986 2090                  vpkt->vpkt_flags |= CFLAG_DMA_PARTIAL;
1987 2091          }
1988 2092  
1989 2093          if (vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) {
1990 2094  
1991 2095                  /*
1992 2096                   * Re-initialize some of the target driver packet state
1993 2097                   * information.
1994 2098                   */
1995 2099                  vpkt->vpkt_tgt_pkt->pkt_state = 0;
1996 2100                  vpkt->vpkt_tgt_pkt->pkt_statistics = 0;
1997 2101                  vpkt->vpkt_tgt_pkt->pkt_reason = 0;
1998 2102  
1999 2103                  /*
2000 2104                   * Binding a vpkt->vpkt_path for this IO at init_time.
2001 2105                   * If an IO error happens later, target driver will clear
2002 2106                   * this vpkt->vpkt_path binding before re-init IO again.
2003 2107                   */
2004 2108                  VHCI_DEBUG(8, (CE_NOTE, NULL,
2005 2109                      "vhci_scsi_init_pkt: calling v_b_t %p, newpkt %d\n",
2006 2110                      (void *)vpkt, newpkt));
2007 2111                  if (pkt && vpkt->vpkt_hba_pkt) {
2008 2112                          VHCI_DEBUG(4, (CE_NOTE, NULL,
2009 2113                              "v_s_i_p calling update_pHCI_pkt resid %ld\n",
2010 2114                              pkt->pkt_resid));
2011 2115                          vhci_update_pHCI_pkt(vpkt, pkt);
2012 2116                  }
2013 2117                  if (callback == SLEEP_FUNC) {
2014 2118                          rval = vhci_bind_transport(
2015 2119                              ap, vpkt, flags, callback);
2016 2120                  } else {
2017 2121                          rval = vhci_bind_transport(
2018 2122                              ap, vpkt, flags, NULL_FUNC);
2019 2123                  }
2020 2124                  VHCI_DEBUG(8, (CE_NOTE, NULL,
2021 2125                      "vhci_scsi_init_pkt: v_b_t called 0x%p rval 0x%x\n",
2022 2126                      (void *)vpkt, rval));
2023 2127                  if (bp) {
2024 2128                          if (rval == TRAN_FATAL_ERROR) {
2025 2129                                  /*
2026 2130                                   * No paths available. Could not bind
2027 2131                                   * any pHCI. Setting EFAULT as a way
2028 2132                                   * to indicate no DMA is mapped.
2029 2133                                   */
2030 2134                                  bioerror(bp, EFAULT);
2031 2135                          } else {
2032 2136                                  /*
2033 2137                                   * Do not indicate any pHCI errors to
2034 2138                                   * target driver otherwise.
2035 2139                                   */
2036 2140                                  bioerror(bp, 0);
2037 2141                          }
2038 2142                  }
2039 2143                  if (rval != TRAN_ACCEPT) {
2040 2144                          VHCI_DEBUG(8, (CE_NOTE, NULL,
2041 2145                              "vhci_scsi_init_pkt: "
2042 2146                              "v_b_t failed 0x%p newpkt %x\n",
2043 2147                              (void *)vpkt, newpkt));
2044 2148                          if (newpkt) {
2045 2149                                  scsi_hba_pkt_free(ap,
2046 2150                                      vpkt->vpkt_tgt_pkt);
2047 2151                          }
2048 2152                          return (NULL);
2049 2153                  }
2050 2154                  ASSERT(vpkt->vpkt_hba_pkt != NULL);
2051 2155                  ASSERT(vpkt->vpkt_path != NULL);
2052 2156  
2053 2157                  /* Update the resid for the target driver */
2054 2158                  vpkt->vpkt_tgt_pkt->pkt_resid =
2055 2159                      vpkt->vpkt_hba_pkt->pkt_resid;
2056 2160          }
2057 2161  
2058 2162          return (vpkt->vpkt_tgt_pkt);
2059 2163  }
2060 2164  
2061 2165  /*
2062 2166   * Function name : vhci_scsi_destroy_pkt
2063 2167   *
2064 2168   * Return Values : none
2065 2169   */
2066 2170  static void
2067 2171  vhci_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
2068 2172  {
2069 2173          struct vhci_pkt         *vpkt = (struct vhci_pkt *)pkt->pkt_ha_private;
2070 2174  
2071 2175          VHCI_DEBUG(8, (CE_NOTE, NULL,
2072 2176              "vhci_scsi_destroy_pkt: vpkt 0x%p\n", (void *)vpkt));
2073 2177  
2074 2178          vpkt->vpkt_tgt_init_pkt_flags = 0;
2075 2179          if (vpkt->vpkt_hba_pkt) {
2076 2180                  scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
2077 2181                  vpkt->vpkt_hba_pkt = NULL;
2078 2182          }
2079 2183          if (vpkt->vpkt_path) {
2080 2184                  mdi_rele_path(vpkt->vpkt_path);
2081 2185                  vpkt->vpkt_path = NULL;
2082 2186          }
2083 2187  
2084 2188          ASSERT(vpkt->vpkt_state != VHCI_PKT_ISSUED);
2085 2189          scsi_hba_pkt_free(ap, vpkt->vpkt_tgt_pkt);
2086 2190  }
2087 2191  
2088 2192  /*
2089 2193   * Function name : vhci_scsi_dmafree()
2090 2194   *
2091 2195   * Return Values : none
2092 2196   */
2093 2197  /*ARGSUSED*/
2094 2198  static void
2095 2199  vhci_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
2096 2200  {
2097 2201          struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_ha_private;
2098 2202  
2099 2203          VHCI_DEBUG(6, (CE_NOTE, NULL,
2100 2204              "vhci_scsi_dmafree: vpkt 0x%p\n", (void *)vpkt));
2101 2205  
2102 2206          ASSERT(vpkt != NULL);
2103 2207          if (vpkt->vpkt_hba_pkt) {
2104 2208                  scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
2105 2209                  vpkt->vpkt_hba_pkt = NULL;
2106 2210          }
2107 2211          if (vpkt->vpkt_path) {
2108 2212                  mdi_rele_path(vpkt->vpkt_path);
2109 2213                  vpkt->vpkt_path = NULL;
2110 2214          }
2111 2215  }
2112 2216  
2113 2217  /*
2114 2218   * Function name : vhci_scsi_sync_pkt()
2115 2219   *
2116 2220   * Return Values : none
2117 2221   */
2118 2222  /*ARGSUSED*/
2119 2223  static void
2120 2224  vhci_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
2121 2225  {
2122 2226          struct vhci_pkt *vpkt = (struct vhci_pkt *)pkt->pkt_ha_private;
2123 2227  
2124 2228          ASSERT(vpkt != NULL);
2125 2229          if (vpkt->vpkt_hba_pkt) {
2126 2230                  scsi_sync_pkt(vpkt->vpkt_hba_pkt);
2127 2231          }
2128 2232  }
2129 2233  
2130 2234  /*
2131 2235   * routine for reset notification setup, to register or cancel.
2132 2236   */
2133 2237  static int
2134 2238  vhci_scsi_reset_notify(struct scsi_address *ap, int flag,
2135 2239      void (*callback)(caddr_t), caddr_t arg)
2136 2240  {
2137 2241          struct scsi_vhci *vhci = ADDR2VHCI(ap);
2138 2242          return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
2139 2243              &vhci->vhci_mutex, &vhci->vhci_reset_notify_listf));
2140 2244  }
2141 2245  
2142 2246  static int
2143 2247  vhci_scsi_get_name_bus_addr(struct scsi_device *sd,
2144 2248      char *name, int len, int bus_addr)
2145 2249  {
2146 2250          dev_info_t              *cdip;
2147 2251          char                    *guid;
2148 2252          scsi_vhci_lun_t         *vlun;
2149 2253  
2150 2254          ASSERT(sd != NULL);
2151 2255          ASSERT(name != NULL);
2152 2256  
2153 2257          *name = 0;
2154 2258          cdip = sd->sd_dev;
2155 2259  
2156 2260          ASSERT(cdip != NULL);
2157 2261  
2158 2262          if (mdi_component_is_client(cdip, NULL) != MDI_SUCCESS)
2159 2263                  return (1);
2160 2264  
2161 2265          if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip, PROPFLAGS,
2162 2266              MDI_CLIENT_GUID_PROP, &guid) != DDI_SUCCESS)
2163 2267                  return (1);
2164 2268  
2165 2269          /*
2166 2270           * Message is "sd# at scsi_vhci0: unit-address <guid>: <bus_addr>".
2167 2271           *      <guid>          bus_addr argument == 0
2168 2272           *      <bus_addr>      bus_addr argument != 0
2169 2273           * Since the <guid> is already provided with unit-address, we just
2170 2274           * provide failover module in <bus_addr> to keep output shorter.
2171 2275           */
2172 2276          vlun = ADDR2VLUN(&sd->sd_address);
2173 2277          if (bus_addr == 0) {
2174 2278                  /* report the guid:  */
2175 2279                  (void) snprintf(name, len, "g%s", guid);
2176 2280          } else if (vlun && vlun->svl_fops_name) {
2177 2281                  /* report the name of the failover module */
2178 2282                  (void) snprintf(name, len, "%s", vlun->svl_fops_name);
2179 2283          }
2180 2284  
2181 2285          ddi_prop_free(guid);
2182 2286          return (1);
2183 2287  }
2184 2288  
2185 2289  static int
2186 2290  vhci_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
2187 2291  {
2188 2292          return (vhci_scsi_get_name_bus_addr(sd, name, len, 1));
2189 2293  }
2190 2294  
2191 2295  static int
2192 2296  vhci_scsi_get_name(struct scsi_device *sd, char *name, int len)
2193 2297  {
2194 2298          return (vhci_scsi_get_name_bus_addr(sd, name, len, 0));
2195 2299  }
2196 2300  
2197 2301  /*
2198 2302   * Return a pointer to the guid part of the devnm.
2199 2303   * devnm format is "nodename@busaddr", busaddr format is "gGUID".
2200 2304   */
2201 2305  static char *
2202 2306  vhci_devnm_to_guid(char *devnm)
2203 2307  {
2204 2308          char *cp = devnm;
2205 2309  
2206 2310          if (devnm == NULL)
2207 2311                  return (NULL);
2208 2312  
2209 2313          while (*cp != '\0' && *cp != '@')
2210 2314                  cp++;
2211 2315          if (*cp == '@' && *(cp + 1) == 'g')
2212 2316                  return (cp + 2);
2213 2317          return (NULL);
2214 2318  }
2215 2319  
2216 2320  static int
2217 2321  vhci_bind_transport(struct scsi_address *ap, struct vhci_pkt *vpkt, int flags,
2218 2322      int (*func)(caddr_t))
2219 2323  {
2220 2324          struct scsi_vhci        *vhci = ADDR2VHCI(ap);
2221 2325          dev_info_t              *cdip = ADDR2DIP(ap);
2222 2326          mdi_pathinfo_t          *pip = NULL;
2223 2327          mdi_pathinfo_t          *npip = NULL;
2224 2328          scsi_vhci_priv_t        *svp = NULL;
2225 2329          struct scsi_device      *psd = NULL;
2226 2330          struct scsi_address     *address = NULL;
2227 2331          struct scsi_pkt         *pkt = NULL;
2228 2332          int                     rval = -1;
2229 2333          int                     pgr_sema_held = 0;
2230 2334          int                     held;
2231 2335          int                     mps_flag = MDI_SELECT_ONLINE_PATH;
2232 2336          struct scsi_vhci_lun    *vlun;
2233 2337          int                     path_instance = 0;
2234 2338  
2235 2339          vlun = ADDR2VLUN(ap);
2236 2340          ASSERT(vlun != 0);
2237 2341  
2238 2342          if ((vpkt->vpkt_tgt_pkt->pkt_cdbp[0] == SCMD_PROUT) &&
2239 2343              (((vpkt->vpkt_tgt_pkt->pkt_cdbp[1] & 0x1f) ==
2240 2344              VHCI_PROUT_REGISTER) ||
2241 2345              ((vpkt->vpkt_tgt_pkt->pkt_cdbp[1] & 0x1f) ==
2242 2346              VHCI_PROUT_R_AND_IGNORE))) {
2243 2347                  if (!sema_tryp(&vlun->svl_pgr_sema))
2244 2348                          return (TRAN_BUSY);
2245 2349                  pgr_sema_held = 1;
2246 2350                  if (vlun->svl_first_path != NULL) {
2247 2351                          rval = mdi_select_path(cdip, NULL,
2248 2352                              MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH,
2249 2353                              NULL, &pip);
2250 2354                          if ((rval != MDI_SUCCESS) || (pip == NULL)) {
2251 2355                                  VHCI_DEBUG(4, (CE_NOTE, NULL,
2252 2356                                      "vhci_bind_transport: path select fail\n"));
2253 2357                          } else {
2254 2358                                  npip = pip;
2255 2359                                  do {
2256 2360                                          if (npip == vlun->svl_first_path) {
2257 2361                                                  VHCI_DEBUG(4, (CE_NOTE, NULL,
2258 2362                                                      "vhci_bind_transport: "
2259 2363                                                      "valid first path 0x%p\n",
2260 2364                                                      (void *)
2261 2365                                                      vlun->svl_first_path));
2262 2366                                                  pip = vlun->svl_first_path;
2263 2367                                                  goto bind_path;
2264 2368                                          }
2265 2369                                          pip = npip;
2266 2370                                          rval = mdi_select_path(cdip, NULL,
2267 2371                                              MDI_SELECT_ONLINE_PATH |
2268 2372                                              MDI_SELECT_STANDBY_PATH,
2269 2373                                              pip, &npip);
2270 2374                                          mdi_rele_path(pip);
2271 2375                                  } while ((rval == MDI_SUCCESS) &&
2272 2376                                      (npip != NULL));
2273 2377                          }
2274 2378                  }
2275 2379  
2276 2380                  if (vlun->svl_first_path) {
2277 2381                          VHCI_DEBUG(4, (CE_NOTE, NULL,
2278 2382                              "vhci_bind_transport: invalid first path 0x%p\n",
2279 2383                              (void *)vlun->svl_first_path));
2280 2384                          vlun->svl_first_path = NULL;
2281 2385                  }
2282 2386          } else if (vpkt->vpkt_tgt_pkt->pkt_cdbp[0] == SCMD_PRIN) {
2283 2387                  if ((vpkt->vpkt_state & VHCI_PKT_THRU_TASKQ) == 0) {
2284 2388                          if (!sema_tryp(&vlun->svl_pgr_sema))
2285 2389                                  return (TRAN_BUSY);
2286 2390                  }
2287 2391                  pgr_sema_held = 1;
2288 2392          }
2289 2393  
2290 2394          /*
2291 2395           * If the path is already bound for PKT_PARTIAL_DMA case,
2292 2396           * try to use the same path.
2293 2397           */
2294 2398          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) && vpkt->vpkt_path) {
2295 2399                  VHCI_DEBUG(4, (CE_NOTE, NULL,
2296 2400                      "vhci_bind_transport: PKT_PARTIAL_DMA "
2297 2401                      "vpkt 0x%p, path 0x%p\n",
2298 2402                      (void *)vpkt, (void *)vpkt->vpkt_path));
2299 2403                  pip = vpkt->vpkt_path;
2300 2404                  goto bind_path;
2301 2405          }
2302 2406  
2303 2407          /*
2304 2408           * Get path_instance. Non-zero with FLAG_PKT_PATH_INSTANCE set
2305 2409           * indicates that mdi_select_path should be called to select a
2306 2410           * specific instance.
2307 2411           *
2308 2412           * NB: Condition pkt_path_instance reference on proper allocation.
2309 2413           */
2310 2414          if ((vpkt->vpkt_tgt_pkt->pkt_flags & FLAG_PKT_PATH_INSTANCE) &&
2311 2415              scsi_pkt_allocated_correctly(vpkt->vpkt_tgt_pkt)) {
2312 2416                  path_instance = vpkt->vpkt_tgt_pkt->pkt_path_instance;
2313 2417          }
2314 2418  
2315 2419          /*
2316 2420           * If reservation is active bind the transport directly to the pip
2317 2421           * with the reservation.
2318 2422           */
2319 2423          if (vpkt->vpkt_hba_pkt == NULL) {
2320 2424                  if (vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
2321 2425                          if (MDI_PI_IS_ONLINE(vlun->svl_resrv_pip)) {
2322 2426                                  pip = vlun->svl_resrv_pip;
2323 2427                                  mdi_hold_path(pip);
2324 2428                                  vlun->svl_waiting_for_activepath = 0;
2325 2429                                  rval = MDI_SUCCESS;
2326 2430                                  goto bind_path;
2327 2431                          } else {
2328 2432                                  if (pgr_sema_held) {
2329 2433                                          sema_v(&vlun->svl_pgr_sema);
2330 2434                                  }
2331 2435                                  return (TRAN_BUSY);
2332 2436                          }
2333 2437                  }
2334 2438  try_again:
2335 2439                  rval = mdi_select_path(cdip, vpkt->vpkt_tgt_init_bp,
2336 2440                      path_instance ? MDI_SELECT_PATH_INSTANCE : 0,
2337 2441                      (void *)(intptr_t)path_instance, &pip);
2338 2442                  if (rval == MDI_BUSY) {
2339 2443                          if (pgr_sema_held) {
2340 2444                                  sema_v(&vlun->svl_pgr_sema);
2341 2445                          }
2342 2446                          return (TRAN_BUSY);
2343 2447                  } else if (rval == MDI_DEVI_ONLINING) {
2344 2448                          /*
2345 2449                           * if we are here then we are in the midst of
2346 2450                           * an attach/probe of the client device.
2347 2451                           * We attempt to bind to ONLINE path if available,
2348 2452                           * else it is OK to bind to a STANDBY path (instead
2349 2453                           * of triggering a failover) because IO associated
2350 2454                           * with attach/probe (eg. INQUIRY, block 0 read)
2351 2455                           * are completed by targets even on passive paths
2352 2456                           * If no ONLINE paths available, it is important
2353 2457                           * to set svl_waiting_for_activepath for two
2354 2458                           * reasons: (1) avoid sense analysis in the
2355 2459                           * "external failure detection" codepath in
2356 2460                           * vhci_intr().  Failure to do so will result in
2357 2461                           * infinite loop (unless an ONLINE path becomes
2358 2462                           * available at some point) (2) avoid
2359 2463                           * unnecessary failover (see "---Waiting For Active
2360 2464                           * Path---" comment below).
2361 2465                           */
2362 2466                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!%p in onlining "
2363 2467                              "state\n", (void *)cdip));
2364 2468                          pip = NULL;
2365 2469                          rval = mdi_select_path(cdip, vpkt->vpkt_tgt_init_bp,
2366 2470                              mps_flag, NULL, &pip);
2367 2471                          if ((rval != MDI_SUCCESS) || (pip == NULL)) {
2368 2472                                  if (vlun->svl_waiting_for_activepath == 0) {
2369 2473                                          vlun->svl_waiting_for_activepath = 1;
2370 2474                                          vlun->svl_wfa_time = gethrtime();
2371 2475                                  }
2372 2476                                  mps_flag |= MDI_SELECT_STANDBY_PATH;
2373 2477                                  rval = mdi_select_path(cdip,
2374 2478                                      vpkt->vpkt_tgt_init_bp,
2375 2479                                      mps_flag, NULL, &pip);
2376 2480                                  if ((rval != MDI_SUCCESS) || (pip == NULL)) {
2377 2481                                          if (pgr_sema_held) {
2378 2482                                                  sema_v(&vlun->svl_pgr_sema);
2379 2483                                          }
2380 2484                                          return (TRAN_FATAL_ERROR);
2381 2485                                  }
2382 2486                                  goto bind_path;
2383 2487                          }
2384 2488                  } else if ((rval == MDI_FAILURE) ||
2385 2489                      ((rval == MDI_NOPATH) && (path_instance))) {
2386 2490                          if (pgr_sema_held) {
2387 2491                                  sema_v(&vlun->svl_pgr_sema);
2388 2492                          }
2389 2493                          return (TRAN_FATAL_ERROR);
2390 2494                  }
2391 2495  
2392 2496                  if ((pip == NULL) || (rval == MDI_NOPATH)) {
2393 2497                          while (vlun->svl_waiting_for_activepath) {
2394 2498                                  /*
2395 2499                                   * ---Waiting For Active Path---
2396 2500                                   * This device was discovered across a
2397 2501                                   * passive path; lets wait for a little
2398 2502                                   * bit, hopefully an active path will
2399 2503                                   * show up obviating the need for a
2400 2504                                   * failover
2401 2505                                   */
2402 2506                                  if ((gethrtime() - vlun->svl_wfa_time) >=
2403 2507                                      (60 * NANOSEC)) {
2404 2508                                          vlun->svl_waiting_for_activepath = 0;
2405 2509                                  } else {
2406 2510                                          drv_usecwait(1000);
2407 2511                                          if (vlun->svl_waiting_for_activepath
2408 2512                                              == 0) {
2409 2513                                                  /*
2410 2514                                                   * an active path has come
2411 2515                                                   * online!
2412 2516                                                   */
2413 2517                                                  goto try_again;
2414 2518                                          }
2415 2519                                  }
2416 2520                          }
2417 2521                          VHCI_HOLD_LUN(vlun, VH_NOSLEEP, held);
2418 2522                          if (!held) {
2419 2523                                  VHCI_DEBUG(4, (CE_NOTE, NULL,
2420 2524                                      "!Lun not held\n"));
2421 2525                                  if (pgr_sema_held) {
2422 2526                                          sema_v(&vlun->svl_pgr_sema);
2423 2527                                  }
2424 2528                                  return (TRAN_BUSY);
2425 2529                          }
2426 2530                          /*
2427 2531                           * now that the LUN is stable, one last check
2428 2532                           * to make sure no other changes sneaked in
2429 2533                           * (like a path coming online or a
2430 2534                           * failover initiated by another thread)
2431 2535                           */
2432 2536                          pip = NULL;
2433 2537                          rval = mdi_select_path(cdip, vpkt->vpkt_tgt_init_bp,
2434 2538                              0, NULL, &pip);
2435 2539                          if (pip != NULL) {
2436 2540                                  VHCI_RELEASE_LUN(vlun);
2437 2541                                  vlun->svl_waiting_for_activepath = 0;
2438 2542                                  goto bind_path;
2439 2543                          }
2440 2544  
2441 2545                          /*
2442 2546                           * Check if there is an ONLINE path OR a STANDBY path
2443 2547                           * available. If none is available, do not attempt
2444 2548                           * to do a failover, just return a fatal error at this
2445 2549                           * point.
2446 2550                           */
2447 2551                          npip = NULL;
2448 2552                          rval = mdi_select_path(cdip, NULL,
2449 2553                              (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH),
2450 2554                              NULL, &npip);
2451 2555                          if ((npip == NULL) || (rval != MDI_SUCCESS)) {
2452 2556                                  /*
2453 2557                                   * No paths available, jus return FATAL error.
2454 2558                                   */
2455 2559                                  VHCI_RELEASE_LUN(vlun);
2456 2560                                  if (pgr_sema_held) {
2457 2561                                          sema_v(&vlun->svl_pgr_sema);
2458 2562                                  }
2459 2563                                  return (TRAN_FATAL_ERROR);
2460 2564                          }
2461 2565                          mdi_rele_path(npip);
2462 2566                          if (!(vpkt->vpkt_state & VHCI_PKT_IN_FAILOVER)) {
2463 2567                                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!invoking "
2464 2568                                      "mdi_failover\n"));
2465 2569                                  rval = mdi_failover(vhci->vhci_dip, cdip,
2466 2570                                      MDI_FAILOVER_ASYNC);
2467 2571                          } else {
2468 2572                                  rval = vlun->svl_failover_status;
2469 2573                          }
2470 2574                          if (rval == MDI_FAILURE) {
2471 2575                                  VHCI_RELEASE_LUN(vlun);
2472 2576                                  if (pgr_sema_held) {
2473 2577                                          sema_v(&vlun->svl_pgr_sema);
2474 2578                                  }
2475 2579                                  return (TRAN_FATAL_ERROR);
2476 2580                          } else if (rval == MDI_BUSY) {
2477 2581                                  VHCI_RELEASE_LUN(vlun);
2478 2582                                  if (pgr_sema_held) {
2479 2583                                          sema_v(&vlun->svl_pgr_sema);
2480 2584                                  }
2481 2585                                  return (TRAN_BUSY);
2482 2586                          } else {
2483 2587                                  if (pgr_sema_held) {
2484 2588                                          sema_v(&vlun->svl_pgr_sema);
2485 2589                                  }
2486 2590                                  vpkt->vpkt_state |= VHCI_PKT_IN_FAILOVER;
2487 2591                                  return (TRAN_BUSY);
2488 2592                          }
2489 2593                  }
2490 2594                  vlun->svl_waiting_for_activepath = 0;
2491 2595  bind_path:
2492 2596                  vpkt->vpkt_path = pip;
2493 2597                  svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
2494 2598                  ASSERT(svp != NULL);
2495 2599  
2496 2600                  psd = svp->svp_psd;
2497 2601                  ASSERT(psd != NULL);
2498 2602                  address = &psd->sd_address;
2499 2603          } else {
2500 2604                  pkt = vpkt->vpkt_hba_pkt;
2501 2605                  address = &pkt->pkt_address;
2502 2606          }
2503 2607  
2504 2608          /* Verify match of specified path_instance and selected path_instance */
2505 2609          ASSERT((path_instance == 0) ||
2506 2610              (path_instance == mdi_pi_get_path_instance(vpkt->vpkt_path)));
2507 2611  
2508 2612          /*
2509 2613           * For PKT_PARTIAL_DMA case, call pHCI's scsi_init_pkt whenever
2510 2614           * target driver calls vhci_scsi_init_pkt.
2511 2615           */
2512 2616          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) &&
2513 2617              vpkt->vpkt_path && vpkt->vpkt_hba_pkt) {
2514 2618                  VHCI_DEBUG(4, (CE_NOTE, NULL,
2515 2619                      "vhci_bind_transport: PKT_PARTIAL_DMA "
2516 2620                      "vpkt 0x%p, path 0x%p hba_pkt 0x%p\n",
2517 2621                      (void *)vpkt, (void *)vpkt->vpkt_path, (void *)pkt));
2518 2622                  pkt = vpkt->vpkt_hba_pkt;
2519 2623                  address = &pkt->pkt_address;
2520 2624          }
2521 2625  
2522 2626          if (pkt == NULL || (vpkt->vpkt_flags & CFLAG_DMA_PARTIAL)) {
2523 2627                  pkt = scsi_init_pkt(address, pkt,
2524 2628                      vpkt->vpkt_tgt_init_bp, vpkt->vpkt_tgt_init_cdblen,
2525 2629                      vpkt->vpkt_tgt_init_scblen, 0, flags, func, NULL);
2526 2630  
2527 2631                  if (pkt == NULL) {
2528 2632                          VHCI_DEBUG(4, (CE_NOTE, NULL,
2529 2633                              "!bind transport: 0x%p 0x%p 0x%p\n",
2530 2634                              (void *)vhci, (void *)psd, (void *)vpkt));
2531 2635                          if ((vpkt->vpkt_hba_pkt == NULL) && vpkt->vpkt_path) {
2532 2636                                  MDI_PI_ERRSTAT(vpkt->vpkt_path,
2533 2637                                      MDI_PI_TRANSERR);
2534 2638                                  mdi_rele_path(vpkt->vpkt_path);
2535 2639                                  vpkt->vpkt_path = NULL;
2536 2640                          }
2537 2641                          if (pgr_sema_held) {
2538 2642                                  sema_v(&vlun->svl_pgr_sema);
2539 2643                          }
2540 2644                          /*
2541 2645                           * Consider it a fatal error if b_error is
2542 2646                           * set as a result of DMA binding failure
2543 2647                           * vs. a condition of being temporarily out of
2544 2648                           * some resource
2545 2649                           */
2546 2650                          if (vpkt->vpkt_tgt_init_bp == NULL ||
2547 2651                              geterror(vpkt->vpkt_tgt_init_bp))
2548 2652                                  return (TRAN_FATAL_ERROR);
2549 2653                          else
2550 2654                                  return (TRAN_BUSY);
2551 2655                  }
2552 2656          }
2553 2657  
2554 2658          pkt->pkt_private = vpkt;
2555 2659          vpkt->vpkt_hba_pkt = pkt;
2556 2660          return (TRAN_ACCEPT);
2557 2661  }
2558 2662  
2559 2663  
2560 2664  /*PRINTFLIKE3*/
2561 2665  void
2562 2666  vhci_log(int level, dev_info_t *dip, const char *fmt, ...)
2563 2667  {
2564 2668          char            buf[256];
2565 2669          va_list         ap;
2566 2670  
2567 2671          va_start(ap, fmt);
2568 2672          (void) vsprintf(buf, fmt, ap);
2569 2673          va_end(ap);
2570 2674  
2571 2675          scsi_log(dip, "scsi_vhci", level, buf);
2572 2676  }
2573 2677  
2574 2678  /* do a PGR out with the information we've saved away */
2575 2679  static int
2576 2680  vhci_do_prout(scsi_vhci_priv_t *svp)
2577 2681  {
2578 2682  
2579 2683          struct scsi_pkt                 *new_pkt;
2580 2684          struct buf                      *bp;
2581 2685          scsi_vhci_lun_t                 *vlun = svp->svp_svl;
2582 2686          int                             rval, retry, nr_retry, ua_retry;
2583 2687          uint8_t                         *sns, skey;
2584 2688  
2585 2689          bp = getrbuf(KM_SLEEP);
2586 2690          bp->b_flags = B_WRITE;
2587 2691          bp->b_resid = 0;
2588 2692          bp->b_un.b_addr = (caddr_t)&vlun->svl_prout;
2589 2693          bp->b_bcount = vlun->svl_bcount;
2590 2694  
2591 2695          VHCI_INCR_PATH_CMDCOUNT(svp);
2592 2696  
2593 2697          new_pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
2594 2698              CDB_GROUP1, sizeof (struct scsi_arq_status), 0, 0,
2595 2699              SLEEP_FUNC, NULL);
2596 2700          if (new_pkt == NULL) {
2597 2701                  VHCI_DECR_PATH_CMDCOUNT(svp);
2598 2702                  freerbuf(bp);
2599 2703                  cmn_err(CE_WARN, "!vhci_do_prout: scsi_init_pkt failed");
2600 2704                  return (0);
2601 2705          }
2602 2706          mutex_enter(&vlun->svl_mutex);
2603 2707          bp->b_un.b_addr = (caddr_t)&vlun->svl_prout;
2604 2708          bp->b_bcount = vlun->svl_bcount;
2605 2709          bcopy(vlun->svl_cdb, new_pkt->pkt_cdbp,
2606 2710              sizeof (vlun->svl_cdb));
2607 2711          new_pkt->pkt_time = vlun->svl_time;
2608 2712          mutex_exit(&vlun->svl_mutex);
2609 2713          new_pkt->pkt_flags = FLAG_NOINTR;
2610 2714  
2611 2715          ua_retry = nr_retry = retry = 0;
2612 2716  again:
2613 2717          rval = vhci_do_scsi_cmd(new_pkt);
2614 2718          if (rval != 1) {
2615 2719                  if ((new_pkt->pkt_reason == CMD_CMPLT) &&
2616 2720                      (SCBP_C(new_pkt) == STATUS_CHECK) &&
2617 2721                      (new_pkt->pkt_state & STATE_ARQ_DONE)) {
2618 2722                          sns = (uint8_t *)
2619 2723                              &(((struct scsi_arq_status *)(uintptr_t)
2620 2724                              (new_pkt->pkt_scbp))->sts_sensedata);
2621 2725                          skey = scsi_sense_key(sns);
2622 2726                          if ((skey == KEY_UNIT_ATTENTION) ||
2623 2727                              (skey == KEY_NOT_READY)) {
2624 2728                                  int max_retry;
2625 2729                                  struct scsi_failover_ops *fops;
2626 2730                                  fops = vlun->svl_fops;
2627 2731                                  rval = fops->sfo_analyze_sense(svp->svp_psd,
2628 2732                                      sns, vlun->svl_fops_ctpriv);
2629 2733                                  if (rval == SCSI_SENSE_NOT_READY) {
2630 2734                                          max_retry = vhci_prout_not_ready_retry;
2631 2735                                          retry = nr_retry++;
2632 2736                                          delay(1*drv_usectohz(1000000));
2633 2737                                  } else {
2634 2738                                          /* chk for state change and update */
2635 2739                                          if (rval == SCSI_SENSE_STATE_CHANGED) {
2636 2740                                                  int held;
2637 2741                                                  VHCI_HOLD_LUN(vlun,
2638 2742                                                      VH_NOSLEEP, held);
2639 2743                                                  if (!held) {
2640 2744                                                          rval = TRAN_BUSY;
2641 2745                                                  } else {
2642 2746                                                          /* chk for alua first */
2643 2747                                                          vhci_update_pathstates(
2644 2748                                                              (void *)vlun);
2645 2749                                                  }
2646 2750                                          }
2647 2751                                          retry = ua_retry++;
2648 2752                                          max_retry = VHCI_MAX_PGR_RETRIES;
2649 2753                                  }
2650 2754                                  if (retry < max_retry) {
2651 2755                                          VHCI_DEBUG(4, (CE_WARN, NULL,
2652 2756                                              "!vhci_do_prout retry 0x%x "
2653 2757                                              "(0x%x 0x%x 0x%x)",
2654 2758                                              SCBP_C(new_pkt),
2655 2759                                              new_pkt->pkt_cdbp[0],
2656 2760                                              new_pkt->pkt_cdbp[1],
2657 2761                                              new_pkt->pkt_cdbp[2]));
2658 2762                                          goto again;
2659 2763                                  }
2660 2764                                  rval = 0;
2661 2765                                  VHCI_DEBUG(4, (CE_WARN, NULL,
2662 2766                                      "!vhci_do_prout 0x%x "
2663 2767                                      "(0x%x 0x%x 0x%x)",
2664 2768                                      SCBP_C(new_pkt),
2665 2769                                      new_pkt->pkt_cdbp[0],
2666 2770                                      new_pkt->pkt_cdbp[1],
2667 2771                                      new_pkt->pkt_cdbp[2]));
2668 2772                          } else if (skey == KEY_ILLEGAL_REQUEST)
2669 2773                                  rval = VHCI_PGR_ILLEGALOP;
2670 2774                  }
2671 2775          } else {
2672 2776                  rval = 1;
2673 2777          }
2674 2778          scsi_destroy_pkt(new_pkt);
2675 2779          VHCI_DECR_PATH_CMDCOUNT(svp);
2676 2780          freerbuf(bp);
2677 2781          return (rval);
2678 2782  }
2679 2783  
2680 2784  static void
2681 2785  vhci_run_cmd(void *arg)
2682 2786  {
2683 2787          struct scsi_pkt         *pkt = (struct scsi_pkt *)arg;
2684 2788          struct scsi_pkt         *tpkt;
2685 2789          scsi_vhci_priv_t        *svp;
2686 2790          mdi_pathinfo_t          *pip, *npip;
2687 2791          scsi_vhci_lun_t         *vlun;
2688 2792          dev_info_t              *cdip;
2689 2793          scsi_vhci_priv_t        *nsvp;
2690 2794          int                     fail = 0;
2691 2795          int                     rval;
2692 2796          struct vhci_pkt         *vpkt;
2693 2797          uchar_t                 cdb_1;
2694 2798          vhci_prout_t            *prout;
2695 2799  
2696 2800          vpkt = (struct vhci_pkt *)pkt->pkt_private;
2697 2801          tpkt = vpkt->vpkt_tgt_pkt;
2698 2802          pip = vpkt->vpkt_path;
2699 2803          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
2700 2804          if (svp == NULL) {
2701 2805                  tpkt->pkt_reason = CMD_TRAN_ERR;
2702 2806                  tpkt->pkt_statistics = STAT_ABORTED;
2703 2807                  goto done;
2704 2808          }
2705 2809          vlun = svp->svp_svl;
2706 2810          prout = &vlun->svl_prout;
2707 2811          if (SCBP_C(pkt) != STATUS_GOOD)
2708 2812                  fail++;
2709 2813          cdip = vlun->svl_dip;
2710 2814          pip = npip = NULL;
2711 2815          rval = mdi_select_path(cdip, NULL,
2712 2816              MDI_SELECT_ONLINE_PATH|MDI_SELECT_STANDBY_PATH, NULL, &npip);
2713 2817          if ((rval != MDI_SUCCESS) || (npip == NULL)) {
2714 2818                  VHCI_DEBUG(4, (CE_NOTE, NULL,
2715 2819                      "vhci_run_cmd: no path! 0x%p\n", (void *)svp));
2716 2820                  tpkt->pkt_reason = CMD_TRAN_ERR;
2717 2821                  tpkt->pkt_statistics = STAT_ABORTED;
2718 2822                  goto done;
2719 2823          }
2720 2824  
2721 2825          cdb_1 = vlun->svl_cdb[1];
2722 2826          vlun->svl_cdb[1] &= 0xe0;
2723 2827          vlun->svl_cdb[1] |= VHCI_PROUT_R_AND_IGNORE;
2724 2828  
2725 2829          do {
2726 2830                  nsvp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(npip);
2727 2831                  if (nsvp == NULL) {
2728 2832                          VHCI_DEBUG(4, (CE_NOTE, NULL,
2729 2833                              "vhci_run_cmd: no "
2730 2834                              "client priv! 0x%p offlined?\n",
2731 2835                              (void *)npip));
2732 2836                          goto next_path;
2733 2837                  }
2734 2838                  if (vlun->svl_first_path == npip) {
2735 2839                          goto next_path;
2736 2840                  } else {
2737 2841                          if (vhci_do_prout(nsvp) != 1)
2738 2842                                  fail++;
2739 2843                  }
2740 2844  next_path:
2741 2845                  pip = npip;
2742 2846                  rval = mdi_select_path(cdip, NULL,
2743 2847                      MDI_SELECT_ONLINE_PATH|MDI_SELECT_STANDBY_PATH,
2744 2848                      pip, &npip);
2745 2849                  mdi_rele_path(pip);
2746 2850          } while ((rval == MDI_SUCCESS) && (npip != NULL));
2747 2851  
2748 2852          vlun->svl_cdb[1] = cdb_1;
2749 2853  
2750 2854          if (fail) {
2751 2855                  VHCI_DEBUG(4, (CE_WARN, NULL, "%s%d: key registration failed, "
2752 2856                      "couldn't be replicated on all paths",
2753 2857                      ddi_driver_name(cdip), ddi_get_instance(cdip)));
2754 2858                  vhci_print_prout_keys(vlun, "vhci_run_cmd: ");
2755 2859  
2756 2860                  if (SCBP_C(pkt) != STATUS_GOOD) {
2757 2861                          tpkt->pkt_reason = CMD_TRAN_ERR;
2758 2862                          tpkt->pkt_statistics = STAT_ABORTED;
2759 2863                  }
2760 2864          } else {
2761 2865                  vlun->svl_pgr_active = 1;
2762 2866                  vhci_print_prout_keys(vlun, "vhci_run_cmd: before bcopy:");
2763 2867  
2764 2868                  bcopy((const void *)prout->service_key,
2765 2869                      (void *)prout->active_service_key, MHIOC_RESV_KEY_SIZE);
2766 2870                  bcopy((const void *)prout->res_key,
2767 2871                      (void *)prout->active_res_key, MHIOC_RESV_KEY_SIZE);
2768 2872  
2769 2873                  vhci_print_prout_keys(vlun, "vhci_run_cmd: after bcopy:");
2770 2874          }
2771 2875  done:
2772 2876          if (SCBP_C(pkt) == STATUS_GOOD)
2773 2877                  vlun->svl_first_path = NULL;
2774 2878  
2775 2879          if (svp)
2776 2880                  VHCI_DECR_PATH_CMDCOUNT(svp);
2777 2881  
2778 2882          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
2779 2883                  scsi_destroy_pkt(pkt);
2780 2884                  vpkt->vpkt_hba_pkt = NULL;
2781 2885                  if (vpkt->vpkt_path) {
2782 2886                          mdi_rele_path(vpkt->vpkt_path);
2783 2887                          vpkt->vpkt_path = NULL;
2784 2888                  }
2785 2889          }
2786 2890  
2787 2891          sema_v(&vlun->svl_pgr_sema);
2788 2892          /*
2789 2893           * The PROUT commands are not included in the automatic retry
2790 2894           * mechanism, therefore, vpkt_org_vpkt should never be set here.
2791 2895           */
2792 2896          ASSERT(vpkt->vpkt_org_vpkt == NULL);
2793 2897          scsi_hba_pkt_comp(tpkt);
2794 2898  }
2795 2899  
2796 2900  /*
2797 2901   * Get the keys registered with this target.  Since we will have
2798 2902   * registered the same key with multiple initiators, strip out
2799 2903   * any duplicate keys.
2800 2904   *
2801 2905   * The pointers which will be used to filter the registered keys from
2802 2906   * the device will be stored in filter_prin and filter_pkt.  If the
2803 2907   * allocation length of the buffer was sufficient for the number of
2804 2908   * parameter data bytes available to be returned by the device then the
2805 2909   * key filtering will use the keylist returned from the original
2806 2910   * request.  If the allocation length of the buffer was not sufficient,
2807 2911   * then the filtering will use the keylist returned from the request
2808 2912   * that is resent below.
2809 2913   *
2810 2914   * If the device returns an additional length field that is greater than
2811 2915   * the allocation length of the buffer, then allocate a new buffer which
2812 2916   * can accommodate the number of parameter data bytes available to be
2813 2917   * returned.  Resend the scsi PRIN command, filter out the duplicate
2814 2918   * keys and return as many of the unique keys found that was originally
2815 2919   * requested and set the additional length field equal to the data bytes
2816 2920   * of unique reservation keys available to be returned.
2817 2921   *
2818 2922   * If the device returns an additional length field that is less than or
2819 2923   * equal to the allocation length of the buffer, then all the available
2820 2924   * keys registered were returned by the device.  Filter out the
2821 2925   * duplicate keys and return all of the unique keys found and set the
2822 2926   * additional length field equal to the data bytes of the reservation
2823 2927   * keys to be returned.
2824 2928   */
2825 2929  
2826 2930  #define VHCI_PRIN_HEADER_SZ (sizeof (prin->length) + sizeof (prin->generation))
2827 2931  
2828 2932  static int
2829 2933  vhci_do_prin(struct vhci_pkt **intr_vpkt)
2830 2934  {
2831 2935          scsi_vhci_priv_t *svp;
2832 2936          struct vhci_pkt *vpkt = *intr_vpkt;
2833 2937          vhci_prin_readkeys_t *prin;
2834 2938          scsi_vhci_lun_t *vlun;
2835 2939          struct scsi_vhci *vhci = ADDR2VHCI(&vpkt->vpkt_tgt_pkt->pkt_address);
2836 2940  
2837 2941          struct buf              *new_bp = NULL;
2838 2942          struct scsi_pkt         *new_pkt = NULL;
2839 2943          struct vhci_pkt         *new_vpkt = NULL;
2840 2944          uint32_t                needed_length;
2841 2945          int                     rval = VHCI_CMD_CMPLT;
2842 2946          uint32_t                prin_length = 0;
2843 2947          uint32_t                svl_prin_length = 0;
2844 2948  
2845 2949          ASSERT(vpkt->vpkt_path);
2846 2950          svp = mdi_pi_get_vhci_private(vpkt->vpkt_path);
2847 2951          ASSERT(svp);
2848 2952          vlun = svp->svp_svl;
2849 2953          ASSERT(vlun);
2850 2954  
2851 2955          /*
2852 2956           * If the caller only asked for an amount of data that would not
2853 2957           * be enough to include any key data it is likely that they will
2854 2958           * send the next command with a buffer size based on the information
2855 2959           * from this header. Doing recovery on this would be a duplication
2856 2960           * of efforts.
2857 2961           */
2858 2962          if (vpkt->vpkt_tgt_init_bp->b_bcount <= VHCI_PRIN_HEADER_SZ) {
2859 2963                  rval = VHCI_CMD_CMPLT;
2860 2964                  goto exit;
2861 2965          }
2862 2966  
2863 2967          if (vpkt->vpkt_org_vpkt == NULL) {
2864 2968                  /*
2865 2969                   * Can fail as sleep is not allowed.
2866 2970                   */
2867 2971                  prin = (vhci_prin_readkeys_t *)
2868 2972                      bp_mapin_common(vpkt->vpkt_tgt_init_bp, VM_NOSLEEP);
2869 2973          } else {
2870 2974                  /*
2871 2975                   * The retry buf doesn't need to be mapped in.
2872 2976                   */
2873 2977                  prin = (vhci_prin_readkeys_t *)
2874 2978                      vpkt->vpkt_tgt_init_bp->b_un.b_daddr;
2875 2979          }
2876 2980  
2877 2981          if (prin == NULL) {
2878 2982                  VHCI_DEBUG(5, (CE_WARN, NULL,
2879 2983                      "vhci_do_prin: bp_mapin_common failed."));
2880 2984                  rval = VHCI_CMD_ERROR;
2881 2985                  goto fail;
2882 2986          }
2883 2987  
2884 2988          prin_length = BE_32(prin->length);
2885 2989  
2886 2990          /*
2887 2991           * According to SPC-3r22, sec 4.3.4.6: "If the amount of
2888 2992           * information to be transferred exceeds the maximum value
2889 2993           * that the ALLOCATION LENGTH field is capable of specifying,
2890 2994           * the device server shall...terminate the command with CHECK
2891 2995           * CONDITION status".  The ALLOCATION LENGTH field of the
2892 2996           * PERSISTENT RESERVE IN command is 2 bytes. We should never
2893 2997           * get here with an ADDITIONAL LENGTH greater than 0xFFFF
2894 2998           * so if we do, then it is an error!
2895 2999           */
2896 3000  
2897 3001  
2898 3002          if ((prin_length + VHCI_PRIN_HEADER_SZ) > 0xFFFF) {
2899 3003                  VHCI_DEBUG(5, (CE_NOTE, NULL,
2900 3004                      "vhci_do_prin: Device returned invalid "
2901 3005                      "length 0x%x\n", prin_length));
2902 3006                  rval = VHCI_CMD_ERROR;
2903 3007                  goto fail;
2904 3008          }
2905 3009          needed_length = prin_length + VHCI_PRIN_HEADER_SZ;
2906 3010  
2907 3011          /*
2908 3012           * If prin->length is greater than the byte count allocated in the
2909 3013           * original buffer, then resend the request with enough buffer
2910 3014           * allocated to get all of the available registered keys.
2911 3015           */
2912 3016          if ((vpkt->vpkt_tgt_init_bp->b_bcount < needed_length) &&
2913 3017              (vpkt->vpkt_org_vpkt == NULL)) {
2914 3018  
2915 3019                  new_pkt = vhci_create_retry_pkt(vpkt);
2916 3020                  if (new_pkt == NULL) {
2917 3021                          rval = VHCI_CMD_ERROR;
2918 3022                          goto fail;
2919 3023                  }
2920 3024                  new_vpkt = TGTPKT2VHCIPKT(new_pkt);
2921 3025  
2922 3026                  /*
2923 3027                   * This is the buf with buffer pointer
2924 3028                   * where the prin readkeys will be
2925 3029                   * returned from the device
2926 3030                   */
2927 3031                  new_bp = scsi_alloc_consistent_buf(&svp->svp_psd->sd_address,
2928 3032                      NULL, needed_length, B_READ, NULL_FUNC, NULL);
2929 3033                  if ((new_bp == NULL) || (new_bp->b_un.b_addr == NULL)) {
2930 3034                          if (new_bp) {
2931 3035                                  scsi_free_consistent_buf(new_bp);
2932 3036                          }
2933 3037                          vhci_scsi_destroy_pkt(&new_pkt->pkt_address, new_pkt);
2934 3038                          rval = VHCI_CMD_ERROR;
2935 3039                          goto fail;
2936 3040                  }
2937 3041                  new_bp->b_bcount = needed_length;
2938 3042                  new_pkt->pkt_cdbp[7] = (uchar_t)(needed_length >> 8);
2939 3043                  new_pkt->pkt_cdbp[8] = (uchar_t)needed_length;
2940 3044  
2941 3045                  rval = VHCI_CMD_RETRY;
2942 3046  
2943 3047                  new_vpkt->vpkt_tgt_init_bp = new_bp;
2944 3048          }
2945 3049  
2946 3050          if (rval == VHCI_CMD_RETRY) {
2947 3051  
2948 3052                  /*
2949 3053                   * There were more keys then the original request asked for.
2950 3054                   */
2951 3055                  mdi_pathinfo_t *path_holder = vpkt->vpkt_path;
2952 3056  
2953 3057                  /*
2954 3058                   * Release the old path because it does not matter which path
2955 3059                   * this command is sent down.  This allows the normal bind
2956 3060                   * transport mechanism to be used.
2957 3061                   */
2958 3062                  if (vpkt->vpkt_path != NULL) {
2959 3063                          mdi_rele_path(vpkt->vpkt_path);
2960 3064                          vpkt->vpkt_path = NULL;
2961 3065                  }
2962 3066  
2963 3067                  /*
2964 3068                   * Dispatch the retry command
2965 3069                   */
2966 3070                  if (taskq_dispatch(vhci->vhci_taskq, vhci_dispatch_scsi_start,
2967 3071                      (void *) new_vpkt, KM_NOSLEEP) == NULL) {
2968 3072                          if (path_holder) {
2969 3073                                  vpkt->vpkt_path = path_holder;
2970 3074                                  mdi_hold_path(path_holder);
2971 3075                          }
2972 3076                          scsi_free_consistent_buf(new_bp);
2973 3077                          vhci_scsi_destroy_pkt(&new_pkt->pkt_address, new_pkt);
2974 3078                          rval = VHCI_CMD_ERROR;
2975 3079                          goto fail;
2976 3080                  }
2977 3081  
2978 3082                  /*
2979 3083                   * If we return VHCI_CMD_RETRY, that means the caller
2980 3084                   * is going to bail and wait for the reissued command
2981 3085                   * to complete.  In that case, we need to decrement
2982 3086                   * the path command count right now.  In any other
2983 3087                   * case, it'll be decremented by the caller.
2984 3088                   */
2985 3089                  VHCI_DECR_PATH_CMDCOUNT(svp);
2986 3090                  goto exit;
2987 3091  
2988 3092          }
2989 3093  
2990 3094          if (rval == VHCI_CMD_CMPLT) {
2991 3095                  /*
2992 3096                   * The original request got all of the keys or the recovery
2993 3097                   * packet returns.
2994 3098                   */
2995 3099                  int new;
2996 3100                  int old;
2997 3101                  int num_keys = prin_length / MHIOC_RESV_KEY_SIZE;
2998 3102  
2999 3103                  VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_do_prin: %d keys read\n",
3000 3104                      num_keys));
3001 3105  
3002 3106  #ifdef DEBUG
3003 3107                  VHCI_DEBUG(5, (CE_NOTE, NULL, "vhci_do_prin: from storage\n"));
3004 3108                  if (vhci_debug == 5)
3005 3109                          vhci_print_prin_keys(prin, num_keys);
3006 3110                  VHCI_DEBUG(5, (CE_NOTE, NULL,
3007 3111                      "vhci_do_prin: MPxIO old keys:\n"));
3008 3112                  if (vhci_debug == 5)
3009 3113                          vhci_print_prin_keys(&vlun->svl_prin, num_keys);
3010 3114  #endif
3011 3115  
3012 3116                  /*
3013 3117                   * Filter out all duplicate keys returned from the device
3014 3118                   * We know that we use a different key for every host, so we
3015 3119                   * can simply strip out duplicates. Otherwise we would need to
3016 3120                   * do more bookkeeping to figure out which keys to strip out.
3017 3121                   */
3018 3122  
3019 3123                  new = 0;
3020 3124  
3021 3125                  /*
3022 3126                   * If we got at least 1 key copy it.
3023 3127                   */
3024 3128                  if (num_keys > 0) {
3025 3129                          vlun->svl_prin.keylist[0] = prin->keylist[0];
3026 3130                          new++;
3027 3131                  }
3028 3132  
3029 3133                  /*
3030 3134                   * find next unique key.
3031 3135                   */
3032 3136                  for (old = 1; old < num_keys; old++) {
3033 3137                          int j;
3034 3138                          int match = 0;
3035 3139  
3036 3140                          if (new >= VHCI_NUM_RESV_KEYS)
3037 3141                                  break;
3038 3142                          for (j = 0; j < new; j++) {
3039 3143                                  if (bcmp(&prin->keylist[old],
3040 3144                                      &vlun->svl_prin.keylist[j],
3041 3145                                      sizeof (mhioc_resv_key_t)) == 0) {
3042 3146                                          match = 1;
3043 3147                                          break;
3044 3148                                  }
3045 3149                          }
3046 3150                          if (!match) {
3047 3151                                  vlun->svl_prin.keylist[new] =
3048 3152                                      prin->keylist[old];
3049 3153                                  new++;
3050 3154                          }
3051 3155                  }
3052 3156  
3053 3157                  /* Stored Big Endian */
3054 3158                  vlun->svl_prin.generation = prin->generation;
3055 3159                  svl_prin_length = new * sizeof (mhioc_resv_key_t);
3056 3160                  /* Stored Big Endian */
3057 3161                  vlun->svl_prin.length = BE_32(svl_prin_length);
3058 3162                  svl_prin_length += VHCI_PRIN_HEADER_SZ;
3059 3163  
3060 3164                  /*
3061 3165                   * If we arrived at this point after issuing a retry, make sure
3062 3166                   * that we put everything back the way it originally was so
3063 3167                   * that the target driver can complete the command correctly.
3064 3168                   */
3065 3169                  if (vpkt->vpkt_org_vpkt != NULL) {
3066 3170                          new_bp = vpkt->vpkt_tgt_init_bp;
3067 3171  
3068 3172                          scsi_free_consistent_buf(new_bp);
3069 3173  
3070 3174                          vpkt = vhci_sync_retry_pkt(vpkt);
3071 3175                          *intr_vpkt = vpkt;
3072 3176  
3073 3177                          /*
3074 3178                           * Make sure the original buffer is mapped into kernel
3075 3179                           * space before we try to copy the filtered keys into
3076 3180                           * it.
3077 3181                           */
3078 3182                          prin = (vhci_prin_readkeys_t *)bp_mapin_common(
3079 3183                              vpkt->vpkt_tgt_init_bp, VM_NOSLEEP);
3080 3184                  }
3081 3185  
3082 3186                  /*
3083 3187                   * Now copy the desired number of prin keys into the original
3084 3188                   * target buffer.
3085 3189                   */
3086 3190                  if (svl_prin_length <= vpkt->vpkt_tgt_init_bp->b_bcount) {
3087 3191                          /*
3088 3192                           * It is safe to return all of the available unique
3089 3193                           * keys
3090 3194                           */
3091 3195                          bcopy(&vlun->svl_prin, prin, svl_prin_length);
3092 3196                  } else {
3093 3197                          /*
3094 3198                           * Not all of the available keys were requested by the
3095 3199                           * original command.
3096 3200                           */
3097 3201                          bcopy(&vlun->svl_prin, prin,
3098 3202                              vpkt->vpkt_tgt_init_bp->b_bcount);
3099 3203                  }
3100 3204  #ifdef DEBUG
3101 3205                  VHCI_DEBUG(5, (CE_NOTE, NULL,
3102 3206                      "vhci_do_prin: To Application:\n"));
3103 3207                  if (vhci_debug == 5)
3104 3208                          vhci_print_prin_keys(prin, new);
3105 3209                  VHCI_DEBUG(5, (CE_NOTE, NULL,
3106 3210                      "vhci_do_prin: MPxIO new keys:\n"));
3107 3211                  if (vhci_debug == 5)
3108 3212                          vhci_print_prin_keys(&vlun->svl_prin, new);
3109 3213  #endif
3110 3214          }
3111 3215  fail:
3112 3216          if (rval == VHCI_CMD_ERROR) {
3113 3217                  /*
3114 3218                   * If we arrived at this point after issuing a
3115 3219                   * retry, make sure that we put everything back
3116 3220                   * the way it originally was so that ssd can
3117 3221                   * complete the command correctly.
3118 3222                   */
3119 3223  
3120 3224                  if (vpkt->vpkt_org_vpkt != NULL) {
3121 3225                          new_bp = vpkt->vpkt_tgt_init_bp;
3122 3226                          if (new_bp != NULL) {
3123 3227                                  scsi_free_consistent_buf(new_bp);
3124 3228                          }
3125 3229  
3126 3230                          new_vpkt = vpkt;
3127 3231                          vpkt = vpkt->vpkt_org_vpkt;
3128 3232  
3129 3233                          vhci_scsi_destroy_pkt(&svp->svp_psd->sd_address,
3130 3234                              new_vpkt->vpkt_tgt_pkt);
3131 3235                  }
3132 3236  
3133 3237                  /*
3134 3238                   * Mark this command completion as having an error so that
3135 3239                   * ssd will retry the command.
3136 3240                   */
3137 3241  
3138 3242                  vpkt->vpkt_tgt_pkt->pkt_reason = CMD_ABORTED;
3139 3243                  vpkt->vpkt_tgt_pkt->pkt_statistics |= STAT_ABORTED;
3140 3244  
3141 3245                  rval = VHCI_CMD_CMPLT;
3142 3246          }
3143 3247  exit:
3144 3248          /*
3145 3249           * Make sure that the semaphore is only released once.
3146 3250           */
3147 3251          if (rval == VHCI_CMD_CMPLT) {
3148 3252                  sema_v(&vlun->svl_pgr_sema);
3149 3253          }
3150 3254  
3151 3255          return (rval);
3152 3256  }
3153 3257  
3154 3258  static void
3155 3259  vhci_intr(struct scsi_pkt *pkt)
3156 3260  {
3157 3261          struct vhci_pkt         *vpkt = (struct vhci_pkt *)pkt->pkt_private;
3158 3262          struct scsi_pkt         *tpkt;
3159 3263          scsi_vhci_priv_t        *svp;
3160 3264          scsi_vhci_lun_t         *vlun;
3161 3265          int                     rval, held;
3162 3266          struct scsi_failover_ops        *fops;
3163 3267          uint8_t                 *sns, skey, asc, ascq;
3164 3268          mdi_pathinfo_t          *lpath;
3165 3269          static char             *timeout_err = "Command Timeout";
3166 3270          static char             *parity_err = "Parity Error";
3167 3271          char                    *err_str = NULL;
3168 3272          dev_info_t              *vdip, *cdip;
3169 3273          char                    *cpath;
3170 3274  
3171 3275          ASSERT(vpkt != NULL);
3172 3276          tpkt = vpkt->vpkt_tgt_pkt;
3173 3277          ASSERT(tpkt != NULL);
3174 3278          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
3175 3279          ASSERT(svp != NULL);
3176 3280          vlun = svp->svp_svl;
3177 3281          ASSERT(vlun != NULL);
3178 3282          lpath = vpkt->vpkt_path;
  
    | 
      ↓ open down ↓ | 
    1452 lines elided | 
    
      ↑ open up ↑ | 
  
3179 3283  
3180 3284          /*
3181 3285           * sync up the target driver's pkt with the pkt that
3182 3286           * we actually used
3183 3287           */
3184 3288          *(tpkt->pkt_scbp) = *(pkt->pkt_scbp);
3185 3289          tpkt->pkt_resid = pkt->pkt_resid;
3186 3290          tpkt->pkt_state = pkt->pkt_state;
3187 3291          tpkt->pkt_statistics = pkt->pkt_statistics;
3188 3292          tpkt->pkt_reason = pkt->pkt_reason;
     3293 +        tpkt->pkt_start = pkt->pkt_start;
     3294 +        tpkt->pkt_stop = pkt->pkt_stop;
3189 3295  
3190 3296          /* Return path_instance information back to the target driver. */
3191 3297          if (scsi_pkt_allocated_correctly(tpkt)) {
3192 3298                  if (scsi_pkt_allocated_correctly(pkt)) {
3193 3299                          /*
3194 3300                           * If both packets were correctly allocated,
3195 3301                           * return path returned by pHCI.
3196 3302                           */
3197 3303                          tpkt->pkt_path_instance = pkt->pkt_path_instance;
3198 3304                  } else {
3199 3305                          /* Otherwise return path of pHCI we used */
3200 3306                          tpkt->pkt_path_instance =
3201 3307                              mdi_pi_get_path_instance(lpath);
3202 3308                  }
3203 3309          }
3204 3310  
3205 3311          if (pkt->pkt_cdbp[0] == SCMD_PROUT &&
3206 3312              ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
3207 3313              ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE)) {
3208 3314                  if ((SCBP_C(pkt) != STATUS_GOOD) ||
3209 3315                      (pkt->pkt_reason != CMD_CMPLT)) {
3210 3316                          sema_v(&vlun->svl_pgr_sema);
3211 3317                  }
3212 3318          } else if (pkt->pkt_cdbp[0] == SCMD_PRIN) {
3213 3319                  if (pkt->pkt_reason != CMD_CMPLT ||
3214 3320                      (SCBP_C(pkt) != STATUS_GOOD)) {
3215 3321                          sema_v(&vlun->svl_pgr_sema);
3216 3322                  }
3217 3323          }
3218 3324  
3219 3325          switch (pkt->pkt_reason) {
3220 3326          case CMD_CMPLT:
3221 3327                  /*
3222 3328                   * cmd completed successfully, check for scsi errors
3223 3329                   */
3224 3330                  switch (*(pkt->pkt_scbp)) {
3225 3331                  case STATUS_CHECK:
3226 3332                          if (pkt->pkt_state & STATE_ARQ_DONE) {
3227 3333                                  sns = (uint8_t *)
3228 3334                                      &(((struct scsi_arq_status *)(uintptr_t)
3229 3335                                      (pkt->pkt_scbp))->sts_sensedata);
3230 3336                                  skey = scsi_sense_key(sns);
3231 3337                                  asc = scsi_sense_asc(sns);
3232 3338                                  ascq = scsi_sense_ascq(sns);
3233 3339                                  fops = vlun->svl_fops;
3234 3340                                  ASSERT(fops != NULL);
3235 3341                                  VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_intr: "
3236 3342                                      "Received sns key %x  esc %x  escq %x\n",
3237 3343                                      skey, asc, ascq));
3238 3344  
3239 3345                                  if (vlun->svl_waiting_for_activepath == 1) {
3240 3346                                          /*
3241 3347                                           * if we are here it means we are
3242 3348                                           * in the midst of a probe/attach
3243 3349                                           * through a passive path; this
3244 3350                                           * case is exempt from sense analysis
3245 3351                                           * for detection of ext. failover
3246 3352                                           * because that would unnecessarily
3247 3353                                           * increase attach time.
3248 3354                                           */
3249 3355                                          bcopy(pkt->pkt_scbp, tpkt->pkt_scbp,
3250 3356                                              vpkt->vpkt_tgt_init_scblen);
3251 3357                                          break;
3252 3358                                  }
3253 3359                                  if (asc == VHCI_SCSI_PERR) {
3254 3360                                          /*
3255 3361                                           * parity error
3256 3362                                           */
3257 3363                                          err_str = parity_err;
3258 3364                                          bcopy(pkt->pkt_scbp, tpkt->pkt_scbp,
3259 3365                                              vpkt->vpkt_tgt_init_scblen);
3260 3366                                          break;
3261 3367                                  }
3262 3368                                  rval = fops->sfo_analyze_sense(svp->svp_psd,
3263 3369                                      sns, vlun->svl_fops_ctpriv);
3264 3370                                  if ((rval == SCSI_SENSE_NOFAILOVER) ||
3265 3371                                      (rval == SCSI_SENSE_UNKNOWN) ||
3266 3372                                      (rval == SCSI_SENSE_NOT_READY)) {
3267 3373                                          bcopy(pkt->pkt_scbp, tpkt->pkt_scbp,
3268 3374                                              vpkt->vpkt_tgt_init_scblen);
3269 3375                                          break;
3270 3376                                  } else if (rval == SCSI_SENSE_STATE_CHANGED) {
3271 3377                                          struct scsi_vhci        *vhci;
3272 3378                                          vhci = ADDR2VHCI(&tpkt->pkt_address);
3273 3379                                          VHCI_HOLD_LUN(vlun, VH_NOSLEEP, held);
3274 3380                                          if (!held) {
3275 3381                                                  /*
3276 3382                                                   * looks like some other thread
3277 3383                                                   * has already detected this
3278 3384                                                   * condition
3279 3385                                                   */
3280 3386                                                  tpkt->pkt_state &=
3281 3387                                                      ~STATE_ARQ_DONE;
3282 3388                                                  *(tpkt->pkt_scbp) =
3283 3389                                                      STATUS_BUSY;
3284 3390                                                  break;
3285 3391                                          }
3286 3392                                          (void) taskq_dispatch(
3287 3393                                              vhci->vhci_update_pathstates_taskq,
3288 3394                                              vhci_update_pathstates,
3289 3395                                              (void *)vlun, KM_SLEEP);
3290 3396                                  } else {
3291 3397                                          /*
3292 3398                                           * externally initiated failover
3293 3399                                           * has occurred or is in progress
3294 3400                                           */
3295 3401                                          VHCI_HOLD_LUN(vlun, VH_NOSLEEP, held);
3296 3402                                          if (!held) {
3297 3403                                                  /*
3298 3404                                                   * looks like some other thread
3299 3405                                                   * has already detected this
3300 3406                                                   * condition
3301 3407                                                   */
3302 3408                                                  tpkt->pkt_state &=
3303 3409                                                      ~STATE_ARQ_DONE;
3304 3410                                                  *(tpkt->pkt_scbp) =
3305 3411                                                      STATUS_BUSY;
3306 3412                                                  break;
3307 3413                                          } else {
3308 3414                                                  rval = vhci_handle_ext_fo
3309 3415                                                      (pkt, rval);
3310 3416                                                  if (rval == BUSY_RETURN) {
3311 3417                                                          tpkt->pkt_state &=
3312 3418                                                              ~STATE_ARQ_DONE;
3313 3419                                                          *(tpkt->pkt_scbp) =
3314 3420                                                              STATUS_BUSY;
3315 3421                                                          break;
3316 3422                                                  }
3317 3423                                                  bcopy(pkt->pkt_scbp,
3318 3424                                                      tpkt->pkt_scbp,
3319 3425                                                      vpkt->vpkt_tgt_init_scblen);
3320 3426                                                  break;
3321 3427                                          }
3322 3428                                  }
3323 3429                          }
3324 3430                          break;
3325 3431  
3326 3432                  /*
3327 3433                   * If this is a good SCSI-II RELEASE cmd completion then restore
3328 3434                   * the load balancing policy and reset VLUN_RESERVE_ACTIVE_FLG.
3329 3435                   * If this is a good SCSI-II RESERVE cmd completion then set
3330 3436                   * VLUN_RESERVE_ACTIVE_FLG.
3331 3437                   */
3332 3438                  case STATUS_GOOD:
3333 3439                          if ((pkt->pkt_cdbp[0] == SCMD_RELEASE) ||
3334 3440                              (pkt->pkt_cdbp[0] == SCMD_RELEASE_G1)) {
3335 3441                                  (void) mdi_set_lb_policy(vlun->svl_dip,
3336 3442                                      vlun->svl_lb_policy_save);
3337 3443                                  vlun->svl_flags &= ~VLUN_RESERVE_ACTIVE_FLG;
3338 3444                                  VHCI_DEBUG(1, (CE_WARN, NULL,
3339 3445                                      "!vhci_intr: vlun 0x%p release path 0x%p",
3340 3446                                      (void *)vlun, (void *)vpkt->vpkt_path));
3341 3447                          }
3342 3448  
3343 3449                          if ((pkt->pkt_cdbp[0] == SCMD_RESERVE) ||
3344 3450                              (pkt->pkt_cdbp[0] == SCMD_RESERVE_G1)) {
3345 3451                                  vlun->svl_flags |= VLUN_RESERVE_ACTIVE_FLG;
3346 3452                                  vlun->svl_resrv_pip = vpkt->vpkt_path;
3347 3453                                  VHCI_DEBUG(1, (CE_WARN, NULL,
3348 3454                                      "!vhci_intr: vlun 0x%p reserved path 0x%p",
3349 3455                                      (void *)vlun, (void *)vpkt->vpkt_path));
3350 3456                          }
3351 3457                          break;
3352 3458  
3353 3459                  case STATUS_RESERVATION_CONFLICT:
3354 3460                          VHCI_DEBUG(1, (CE_WARN, NULL,
3355 3461                              "!vhci_intr: vlun 0x%p "
3356 3462                              "reserve conflict on path 0x%p",
3357 3463                              (void *)vlun, (void *)vpkt->vpkt_path));
3358 3464                          /* FALLTHROUGH */
3359 3465                  default:
3360 3466                          break;
3361 3467                  }
3362 3468  
3363 3469                  /*
3364 3470                   * Update I/O completion statistics for the path
3365 3471                   */
3366 3472                  mdi_pi_kstat_iosupdate(vpkt->vpkt_path, vpkt->vpkt_tgt_init_bp);
3367 3473  
3368 3474                  /*
3369 3475                   * Command completed successfully, release the dma binding and
3370 3476                   * destroy the transport side of the packet.
3371 3477                   */
3372 3478                  if ((pkt->pkt_cdbp[0] == SCMD_PROUT) &&
3373 3479                      (((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
3374 3480                      ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE))) {
3375 3481                          if (SCBP_C(pkt) == STATUS_GOOD) {
3376 3482                                  ASSERT(vlun->svl_taskq);
3377 3483                                  svp->svp_last_pkt_reason = pkt->pkt_reason;
3378 3484                                  (void) taskq_dispatch(vlun->svl_taskq,
3379 3485                                      vhci_run_cmd, pkt, KM_SLEEP);
3380 3486                                  return;
3381 3487                          }
3382 3488                  }
3383 3489                  if ((SCBP_C(pkt) == STATUS_GOOD) &&
3384 3490                      (pkt->pkt_cdbp[0] == SCMD_PRIN) && vpkt->vpkt_tgt_init_bp) {
3385 3491                          /*
3386 3492                           * If the action (value in byte 1 of the cdb) is zero,
3387 3493                           * we're reading keys, and that's the only condition
3388 3494                           * where we need to be concerned with filtering keys
3389 3495                           * and potential retries.  Otherwise, we simply signal
3390 3496                           * the semaphore and move on.
3391 3497                           */
3392 3498                          if (pkt->pkt_cdbp[1] == 0) {
3393 3499                                  /*
3394 3500                                   * If this is the completion of an internal
3395 3501                                   * retry then we need to make sure that the
3396 3502                                   * pkt and tpkt pointers are readjusted so
3397 3503                                   * the calls to scsi_destroy_pkt and pkt_comp
3398 3504                                   * below work * correctly.
3399 3505                                   */
3400 3506                                  if (vpkt->vpkt_org_vpkt != NULL) {
3401 3507                                          pkt = vpkt->vpkt_org_vpkt->vpkt_hba_pkt;
3402 3508                                          tpkt = vpkt->vpkt_org_vpkt->
3403 3509                                              vpkt_tgt_pkt;
3404 3510  
3405 3511                                          /*
3406 3512                                           * If this command was issued through
3407 3513                                           * the taskq then we need to clear
3408 3514                                           * this flag for proper processing in
3409 3515                                           * the case of a retry from the target
3410 3516                                           * driver.
3411 3517                                           */
3412 3518                                          vpkt->vpkt_state &=
3413 3519                                              ~VHCI_PKT_THRU_TASKQ;
3414 3520                                  }
3415 3521  
3416 3522                                  /*
3417 3523                                   * if vhci_do_prin returns VHCI_CMD_CMPLT then
3418 3524                                   * vpkt will contain the address of the
3419 3525                                   * original vpkt
3420 3526                                   */
3421 3527                                  if (vhci_do_prin(&vpkt) == VHCI_CMD_RETRY) {
3422 3528                                          /*
3423 3529                                           * The command has been resent to get
3424 3530                                           * all the keys from the device.  Don't
3425 3531                                           * complete the command with ssd until
3426 3532                                           * the retry completes.
3427 3533                                           */
3428 3534                                          return;
3429 3535                                  }
3430 3536                          } else {
3431 3537                                  sema_v(&vlun->svl_pgr_sema);
3432 3538                          }
3433 3539                  }
3434 3540  
3435 3541                  break;
3436 3542  
3437 3543          case CMD_TIMEOUT:
3438 3544                  if ((pkt->pkt_statistics &
3439 3545                      (STAT_BUS_RESET|STAT_DEV_RESET|STAT_ABORTED)) == 0) {
3440 3546  
3441 3547                          VHCI_DEBUG(1, (CE_NOTE, NULL,
3442 3548                              "!scsi vhci timeout invoked\n"));
3443 3549  
3444 3550                          (void) vhci_recovery_reset(vlun, &pkt->pkt_address,
3445 3551                              FALSE, VHCI_DEPTH_ALL);
3446 3552                  }
3447 3553                  MDI_PI_ERRSTAT(lpath, MDI_PI_TRANSERR);
3448 3554                  tpkt->pkt_statistics |= STAT_ABORTED;
3449 3555                  err_str = timeout_err;
3450 3556                  break;
3451 3557  
3452 3558          case CMD_TRAN_ERR:
3453 3559                  /*
3454 3560                   * This status is returned if the transport has sent the cmd
3455 3561                   * down the link to the target and then some error occurs.
3456 3562                   * In case of SCSI-II RESERVE cmd, we don't know if the
3457 3563                   * reservation been accepted by the target or not, so we need
3458 3564                   * to clear the reservation.
3459 3565                   */
3460 3566                  if ((pkt->pkt_cdbp[0] == SCMD_RESERVE) ||
3461 3567                      (pkt->pkt_cdbp[0] == SCMD_RESERVE_G1)) {
3462 3568                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_intr received"
3463 3569                              " cmd_tran_err for scsi-2 reserve cmd\n"));
3464 3570                          if (!vhci_recovery_reset(vlun, &pkt->pkt_address,
3465 3571                              TRUE, VHCI_DEPTH_TARGET)) {
3466 3572                                  VHCI_DEBUG(1, (CE_WARN, NULL,
3467 3573                                      "!vhci_intr cmd_tran_err reset failed!"));
3468 3574                          }
3469 3575                  }
3470 3576                  break;
3471 3577  
3472 3578          case CMD_DEV_GONE:
3473 3579                  /*
3474 3580                   * If this is the last path then report CMD_DEV_GONE to the
3475 3581                   * target driver, otherwise report BUSY to triggger retry.
3476 3582                   */
3477 3583                  if (vlun->svl_dip &&
3478 3584                      (mdi_client_get_path_count(vlun->svl_dip) <= 1)) {
3479 3585                          struct scsi_vhci        *vhci;
3480 3586                          vhci = ADDR2VHCI(&tpkt->pkt_address);
3481 3587                          VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_intr received "
3482 3588                              "cmd_dev_gone on last path\n"));
3483 3589                          (void) vhci_invalidate_mpapi_lu(vhci, vlun);
3484 3590                          break;
3485 3591                  }
3486 3592  
3487 3593                  /* Report CMD_CMPLT-with-BUSY to cause retry. */
3488 3594                  VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_intr received "
3489 3595                      "cmd_dev_gone\n"));
3490 3596                  tpkt->pkt_reason = CMD_CMPLT;
3491 3597                  tpkt->pkt_state = STATE_GOT_BUS |
3492 3598                      STATE_GOT_TARGET | STATE_SENT_CMD |
3493 3599                      STATE_GOT_STATUS;
3494 3600                  *(tpkt->pkt_scbp) = STATUS_BUSY;
3495 3601                  break;
3496 3602  
3497 3603          default:
3498 3604                  break;
3499 3605          }
3500 3606  
3501 3607          /*
3502 3608           * SCSI-II RESERVE cmd has been serviced by the lower layers clear
3503 3609           * the flag so the lun is not QUIESCED any longer.
3504 3610           * Also clear the VHCI_PKT_THRU_TASKQ flag, to ensure that if this pkt
3505 3611           * is retried, a taskq shall again be dispatched to service it.  Else
3506 3612           * it may lead to a system hang if the retry is within interrupt
3507 3613           * context.
3508 3614           */
3509 3615          if ((pkt->pkt_cdbp[0] == SCMD_RESERVE) ||
3510 3616              (pkt->pkt_cdbp[0] == SCMD_RESERVE_G1)) {
3511 3617                  vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
3512 3618                  vpkt->vpkt_state &= ~VHCI_PKT_THRU_TASKQ;
3513 3619          }
3514 3620  
3515 3621          /*
3516 3622           * vpkt_org_vpkt should always be NULL here if the retry command
3517 3623           * has been successfully processed.  If vpkt_org_vpkt != NULL at
3518 3624           * this point, it is an error so restore the original vpkt and
3519 3625           * return an error to the target driver so it can retry the
3520 3626           * command as appropriate.
3521 3627           */
3522 3628          if (vpkt->vpkt_org_vpkt != NULL) {
3523 3629                  struct vhci_pkt *new_vpkt = vpkt;
3524 3630                  vpkt = vpkt->vpkt_org_vpkt;
3525 3631  
3526 3632                  vhci_scsi_destroy_pkt(&svp->svp_psd->sd_address,
3527 3633                      new_vpkt->vpkt_tgt_pkt);
3528 3634  
3529 3635                  /*
3530 3636                   * Mark this command completion as having an error so that
3531 3637                   * ssd will retry the command.
3532 3638                   */
3533 3639                  vpkt->vpkt_tgt_pkt->pkt_reason = CMD_ABORTED;
3534 3640                  vpkt->vpkt_tgt_pkt->pkt_statistics |= STAT_ABORTED;
3535 3641  
3536 3642                  pkt = vpkt->vpkt_hba_pkt;
3537 3643                  tpkt = vpkt->vpkt_tgt_pkt;
3538 3644          }
3539 3645  
3540 3646          if ((err_str != NULL) && (pkt->pkt_reason !=
3541 3647              svp->svp_last_pkt_reason)) {
3542 3648                  cdip = vlun->svl_dip;
3543 3649                  vdip = ddi_get_parent(cdip);
3544 3650                  cpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
3545 3651                  vhci_log(CE_WARN, vdip, "!%s (%s%d): %s on path %s",
3546 3652                      ddi_pathname(cdip, cpath), ddi_driver_name(cdip),
3547 3653                      ddi_get_instance(cdip), err_str,
3548 3654                      mdi_pi_spathname(vpkt->vpkt_path));
3549 3655                  kmem_free(cpath, MAXPATHLEN);
3550 3656          }
3551 3657          svp->svp_last_pkt_reason = pkt->pkt_reason;
3552 3658          VHCI_DECR_PATH_CMDCOUNT(svp);
3553 3659  
3554 3660          /*
3555 3661           * For PARTIAL_DMA, vhci should not free the path.
3556 3662           * Target driver will call into vhci_scsi_dmafree or
3557 3663           * destroy pkt to release this path.
3558 3664           */
3559 3665          if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
3560 3666                  scsi_destroy_pkt(pkt);
3561 3667                  vpkt->vpkt_hba_pkt = NULL;
3562 3668                  if (vpkt->vpkt_path) {
3563 3669                          mdi_rele_path(vpkt->vpkt_path);
3564 3670                          vpkt->vpkt_path = NULL;
3565 3671                  }
3566 3672          }
3567 3673  
3568 3674          scsi_hba_pkt_comp(tpkt);
3569 3675  }
3570 3676  
3571 3677  /*
3572 3678   * two possibilities: (1) failover has completed
3573 3679   * or (2) is in progress; update our path states for
3574 3680   * the former case; for the latter case,
3575 3681   * initiate a scsi_watch request to
3576 3682   * determine when failover completes - vlun is HELD
3577 3683   * until failover completes; BUSY is returned to upper
3578 3684   * layer in both the cases
3579 3685   */
3580 3686  static int
3581 3687  vhci_handle_ext_fo(struct scsi_pkt *pkt, int fostat)
3582 3688  {
3583 3689          struct vhci_pkt         *vpkt = (struct vhci_pkt *)pkt->pkt_private;
3584 3690          struct scsi_pkt         *tpkt;
3585 3691          scsi_vhci_priv_t        *svp;
3586 3692          scsi_vhci_lun_t         *vlun;
3587 3693          struct scsi_vhci        *vhci;
3588 3694          scsi_vhci_swarg_t       *swarg;
3589 3695          char                    *path;
3590 3696  
3591 3697          ASSERT(vpkt != NULL);
3592 3698          tpkt = vpkt->vpkt_tgt_pkt;
3593 3699          ASSERT(tpkt != NULL);
3594 3700          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
3595 3701          ASSERT(svp != NULL);
3596 3702          vlun = svp->svp_svl;
3597 3703          ASSERT(vlun != NULL);
3598 3704          ASSERT(VHCI_LUN_IS_HELD(vlun));
3599 3705  
3600 3706          vhci = ADDR2VHCI(&tpkt->pkt_address);
3601 3707  
3602 3708          if (fostat == SCSI_SENSE_INACTIVE) {
3603 3709                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!Failover "
3604 3710                      "detected for %s; updating path states...\n",
3605 3711                      vlun->svl_lun_wwn));
3606 3712                  /*
3607 3713                   * set the vlun flag to indicate to the task that the target
3608 3714                   * port group needs updating
3609 3715                   */
3610 3716                  vlun->svl_flags |= VLUN_UPDATE_TPG;
3611 3717                  (void) taskq_dispatch(vhci->vhci_update_pathstates_taskq,
3612 3718                      vhci_update_pathstates, (void *)vlun, KM_SLEEP);
3613 3719          } else {
3614 3720                  path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
3615 3721                  vhci_log(CE_NOTE, ddi_get_parent(vlun->svl_dip),
3616 3722                      "!%s (%s%d): Waiting for externally initiated failover "
3617 3723                      "to complete", ddi_pathname(vlun->svl_dip, path),
3618 3724                      ddi_driver_name(vlun->svl_dip),
3619 3725                      ddi_get_instance(vlun->svl_dip));
3620 3726                  kmem_free(path, MAXPATHLEN);
3621 3727                  swarg = kmem_alloc(sizeof (*swarg), KM_NOSLEEP);
3622 3728                  if (swarg == NULL) {
3623 3729                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_handle_ext_fo: "
3624 3730                              "request packet allocation for %s failed....\n",
3625 3731                              vlun->svl_lun_wwn));
3626 3732                          VHCI_RELEASE_LUN(vlun);
3627 3733                          return (PKT_RETURN);
3628 3734                  }
3629 3735                  swarg->svs_svp = svp;
3630 3736                  swarg->svs_tos = gethrtime();
3631 3737                  swarg->svs_pi = vpkt->vpkt_path;
3632 3738                  swarg->svs_release_lun = 0;
3633 3739                  swarg->svs_done = 0;
3634 3740                  /*
3635 3741                   * place a hold on the path...we don't want it to
3636 3742                   * vanish while scsi_watch is in progress
3637 3743                   */
3638 3744                  mdi_hold_path(vpkt->vpkt_path);
3639 3745                  svp->svp_sw_token = scsi_watch_request_submit(svp->svp_psd,
3640 3746                      VHCI_FOWATCH_INTERVAL, SENSE_LENGTH, vhci_efo_watch_cb,
3641 3747                      (caddr_t)swarg);
3642 3748          }
3643 3749          return (BUSY_RETURN);
3644 3750  }
3645 3751  
3646 3752  /*
3647 3753   * vhci_efo_watch_cb:
3648 3754   *      Callback from scsi_watch request to check the failover status.
3649 3755   *      Completion is either due to successful failover or timeout.
3650 3756   *      Upon successful completion, vhci_update_path_states is called.
3651 3757   *      For timeout condition, vhci_efo_done is called.
3652 3758   *      Always returns 0 to scsi_watch to keep retrying till vhci_efo_done
3653 3759   *      terminates this request properly in a separate thread.
3654 3760   */
3655 3761  
3656 3762  static int
3657 3763  vhci_efo_watch_cb(caddr_t arg, struct scsi_watch_result *resultp)
3658 3764  {
3659 3765          struct scsi_status              *statusp = resultp->statusp;
3660 3766          uint8_t                         *sensep = (uint8_t *)resultp->sensep;
3661 3767          struct scsi_pkt                 *pkt = resultp->pkt;
3662 3768          scsi_vhci_swarg_t               *swarg;
3663 3769          scsi_vhci_priv_t                *svp;
3664 3770          scsi_vhci_lun_t                 *vlun;
3665 3771          struct scsi_vhci                *vhci;
3666 3772          dev_info_t                      *vdip;
3667 3773          int                             rval, updt_paths;
3668 3774  
3669 3775          swarg = (scsi_vhci_swarg_t *)(uintptr_t)arg;
3670 3776          svp = swarg->svs_svp;
3671 3777          if (swarg->svs_done) {
3672 3778                  /*
3673 3779                   * Already completed failover or timedout.
3674 3780                   * Waiting for vhci_efo_done to terminate this scsi_watch.
3675 3781                   */
3676 3782                  return (0);
3677 3783          }
3678 3784  
3679 3785          ASSERT(svp != NULL);
3680 3786          vlun = svp->svp_svl;
3681 3787          ASSERT(vlun != NULL);
3682 3788          ASSERT(VHCI_LUN_IS_HELD(vlun));
3683 3789          vlun->svl_efo_update_path = 0;
3684 3790          vdip = ddi_get_parent(vlun->svl_dip);
3685 3791          vhci = ddi_get_soft_state(vhci_softstate,
3686 3792              ddi_get_instance(vdip));
3687 3793  
3688 3794          updt_paths = 0;
3689 3795  
3690 3796          if (pkt->pkt_reason != CMD_CMPLT) {
3691 3797                  if ((gethrtime() - swarg->svs_tos) >= VHCI_EXTFO_TIMEOUT) {
3692 3798                          swarg->svs_release_lun = 1;
3693 3799                          goto done;
3694 3800                  }
3695 3801                  return (0);
3696 3802          }
3697 3803          if (*((unsigned char *)statusp) == STATUS_CHECK) {
3698 3804                  rval = vlun->svl_fops->sfo_analyze_sense(svp->svp_psd, sensep,
3699 3805                      vlun->svl_fops_ctpriv);
3700 3806                  switch (rval) {
3701 3807                          /*
3702 3808                           * Only update path states in case path is definitely
3703 3809                           * inactive, or no failover occurred.  For all other
3704 3810                           * check conditions continue pinging.  A unexpected
3705 3811                           * check condition shouldn't cause pinging to complete
3706 3812                           * prematurely.
3707 3813                           */
3708 3814                          case SCSI_SENSE_INACTIVE:
3709 3815                          case SCSI_SENSE_NOFAILOVER:
3710 3816                                  updt_paths = 1;
3711 3817                                  break;
3712 3818                          default:
3713 3819                                  if ((gethrtime() - swarg->svs_tos)
3714 3820                                      >= VHCI_EXTFO_TIMEOUT) {
3715 3821                                          swarg->svs_release_lun = 1;
3716 3822                                          goto done;
3717 3823                                  }
3718 3824                                  return (0);
3719 3825                  }
3720 3826          } else if (*((unsigned char *)statusp) ==
3721 3827              STATUS_RESERVATION_CONFLICT) {
3722 3828                  updt_paths = 1;
3723 3829          } else if ((*((unsigned char *)statusp)) &
3724 3830              (STATUS_BUSY | STATUS_QFULL)) {
3725 3831                  return (0);
3726 3832          }
3727 3833          if ((*((unsigned char *)statusp) == STATUS_GOOD) ||
3728 3834              (updt_paths == 1)) {
3729 3835                  /*
3730 3836                   * we got here because we had detected an
3731 3837                   * externally initiated failover; things
3732 3838                   * have settled down now, so let's
3733 3839                   * start up a task to update the
3734 3840                   * path states and target port group
3735 3841                   */
3736 3842                  vlun->svl_efo_update_path = 1;
3737 3843                  swarg->svs_done = 1;
3738 3844                  vlun->svl_swarg = swarg;
3739 3845                  vlun->svl_flags |= VLUN_UPDATE_TPG;
3740 3846                  (void) taskq_dispatch(vhci->vhci_update_pathstates_taskq,
3741 3847                      vhci_update_pathstates, (void *)vlun,
3742 3848                      KM_SLEEP);
3743 3849                  return (0);
3744 3850          }
3745 3851          if ((gethrtime() - swarg->svs_tos) >= VHCI_EXTFO_TIMEOUT) {
3746 3852                  swarg->svs_release_lun = 1;
3747 3853                  goto done;
3748 3854          }
3749 3855          return (0);
3750 3856  done:
3751 3857          swarg->svs_done = 1;
3752 3858          (void) taskq_dispatch(vhci->vhci_taskq,
3753 3859              vhci_efo_done, (void *)swarg, KM_SLEEP);
3754 3860          return (0);
3755 3861  }
3756 3862  
3757 3863  /*
3758 3864   * vhci_efo_done:
3759 3865   *      cleanly terminates scsi_watch and free up resources.
3760 3866   *      Called as taskq function in vhci_efo_watch_cb for EFO timeout condition
3761 3867   *      or by vhci_update_path_states invoked during external initiated
3762 3868   *      failover completion.
3763 3869   */
3764 3870  static void
3765 3871  vhci_efo_done(void *arg)
3766 3872  {
3767 3873          scsi_vhci_lun_t                 *vlun;
3768 3874          scsi_vhci_swarg_t               *swarg = (scsi_vhci_swarg_t *)arg;
3769 3875          scsi_vhci_priv_t                *svp = swarg->svs_svp;
3770 3876          ASSERT(svp);
3771 3877  
3772 3878          vlun = svp->svp_svl;
3773 3879          ASSERT(vlun);
3774 3880  
3775 3881          /* Wait for clean termination of scsi_watch */
3776 3882          (void) scsi_watch_request_terminate(svp->svp_sw_token,
3777 3883              SCSI_WATCH_TERMINATE_ALL_WAIT);
3778 3884          svp->svp_sw_token = NULL;
3779 3885  
3780 3886          /* release path and freeup resources to indicate failover completion */
3781 3887          mdi_rele_path(swarg->svs_pi);
3782 3888          if (swarg->svs_release_lun) {
3783 3889                  VHCI_RELEASE_LUN(vlun);
3784 3890          }
3785 3891          kmem_free((void *)swarg, sizeof (*swarg));
3786 3892  }
3787 3893  
3788 3894  /*
3789 3895   * Update the path states
3790 3896   * vlun should be HELD when this is invoked.
3791 3897   * Calls vhci_efo_done to cleanup resources allocated for EFO.
3792 3898   */
3793 3899  void
3794 3900  vhci_update_pathstates(void *arg)
3795 3901  {
3796 3902          mdi_pathinfo_t                  *pip, *npip;
3797 3903          dev_info_t                      *dip;
3798 3904          struct scsi_failover_ops        *fo;
3799 3905          struct scsi_vhci_priv           *svp;
3800 3906          struct scsi_device              *psd;
3801 3907          struct scsi_path_opinfo         opinfo;
3802 3908          char                            *pclass, *tptr;
3803 3909          struct scsi_vhci_lun            *vlun = (struct scsi_vhci_lun *)arg;
3804 3910          int                             sps; /* mdi_select_path() status */
3805 3911          char                            *cpath;
3806 3912          struct scsi_vhci                *vhci;
3807 3913          struct scsi_pkt                 *pkt;
3808 3914          struct buf                      *bp;
3809 3915          struct scsi_vhci_priv           *svp_conflict = NULL;
3810 3916  
3811 3917          ASSERT(VHCI_LUN_IS_HELD(vlun));
3812 3918          dip  = vlun->svl_dip;
3813 3919          pip = npip = NULL;
3814 3920  
3815 3921          vhci = ddi_get_soft_state(vhci_softstate,
3816 3922              ddi_get_instance(ddi_get_parent(dip)));
3817 3923  
3818 3924          sps = mdi_select_path(dip, NULL, (MDI_SELECT_ONLINE_PATH |
3819 3925              MDI_SELECT_STANDBY_PATH | MDI_SELECT_NO_PREFERRED), NULL, &npip);
3820 3926          if ((npip == NULL) || (sps != MDI_SUCCESS)) {
3821 3927                  goto done;
3822 3928          }
3823 3929  
3824 3930          fo = vlun->svl_fops;
3825 3931          do {
3826 3932                  pip = npip;
3827 3933                  svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
3828 3934                  psd = svp->svp_psd;
3829 3935                  if (fo->sfo_path_get_opinfo(psd, &opinfo,
3830 3936                      vlun->svl_fops_ctpriv) != 0) {
3831 3937                          sps = mdi_select_path(dip, NULL,
3832 3938                              (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH |
3833 3939                              MDI_SELECT_NO_PREFERRED), pip, &npip);
3834 3940                          mdi_rele_path(pip);
3835 3941                          continue;
3836 3942                  }
3837 3943  
3838 3944                  if (mdi_prop_lookup_string(pip, "path-class", &pclass) !=
3839 3945                      MDI_SUCCESS) {
3840 3946                          VHCI_DEBUG(1, (CE_NOTE, NULL,
3841 3947                              "!vhci_update_pathstates: prop lookup failed for "
3842 3948                              "path 0x%p\n", (void *)pip));
3843 3949                          sps = mdi_select_path(dip, NULL,
3844 3950                              (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH |
3845 3951                              MDI_SELECT_NO_PREFERRED), pip, &npip);
3846 3952                          mdi_rele_path(pip);
3847 3953                          continue;
3848 3954                  }
3849 3955  
3850 3956                  /*
3851 3957                   * Need to update the "path-class" property
3852 3958                   * value in the device tree if different
3853 3959                   * from the existing value.
3854 3960                   */
3855 3961                  if (strcmp(pclass, opinfo.opinfo_path_attr) != 0) {
3856 3962                          (void) mdi_prop_update_string(pip, "path-class",
3857 3963                              opinfo.opinfo_path_attr);
3858 3964                  }
3859 3965  
3860 3966                  /*
3861 3967                   * Only change the state if needed. i.e. Don't call
3862 3968                   * mdi_pi_set_state to ONLINE a path if its already
3863 3969                   * ONLINE. Same for STANDBY paths.
3864 3970                   */
3865 3971  
3866 3972                  if ((opinfo.opinfo_path_state == SCSI_PATH_ACTIVE ||
3867 3973                      opinfo.opinfo_path_state == SCSI_PATH_ACTIVE_NONOPT)) {
3868 3974                          if (!(MDI_PI_IS_ONLINE(pip))) {
3869 3975                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
3870 3976                                      "!vhci_update_pathstates: marking path"
3871 3977                                      " 0x%p as ONLINE\n", (void *)pip));
3872 3978                                  cpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
3873 3979                                  vhci_log(CE_NOTE, ddi_get_parent(dip), "!%s "
3874 3980                                      "(%s%d): path %s "
3875 3981                                      "is now ONLINE because of "
3876 3982                                      "an externally initiated failover",
3877 3983                                      ddi_pathname(dip, cpath),
3878 3984                                      ddi_driver_name(dip),
3879 3985                                      ddi_get_instance(dip),
3880 3986                                      mdi_pi_spathname(pip));
3881 3987                                  kmem_free(cpath, MAXPATHLEN);
3882 3988                                  mdi_pi_set_state(pip,
3883 3989                                      MDI_PATHINFO_STATE_ONLINE);
3884 3990                                  mdi_pi_set_preferred(pip,
3885 3991                                      opinfo.opinfo_preferred);
3886 3992                                  tptr = kmem_alloc(strlen
3887 3993                                      (opinfo.opinfo_path_attr)+1, KM_SLEEP);
3888 3994                                  (void) strlcpy(tptr, opinfo.opinfo_path_attr,
3889 3995                                      (strlen(opinfo.opinfo_path_attr)+1));
3890 3996                                  mutex_enter(&vlun->svl_mutex);
3891 3997                                  if (vlun->svl_active_pclass != NULL) {
3892 3998                                          kmem_free(vlun->svl_active_pclass,
3893 3999                                              strlen(vlun->svl_active_pclass)+1);
3894 4000                                  }
3895 4001                                  vlun->svl_active_pclass = tptr;
3896 4002                                  if (vlun->svl_waiting_for_activepath) {
3897 4003                                          vlun->svl_waiting_for_activepath = 0;
3898 4004                                  }
3899 4005                                  mutex_exit(&vlun->svl_mutex);
3900 4006                          } else if (MDI_PI_IS_ONLINE(pip)) {
3901 4007                                  if (strcmp(pclass, opinfo.opinfo_path_attr)
3902 4008                                      != 0) {
3903 4009                                          mdi_pi_set_preferred(pip,
3904 4010                                              opinfo.opinfo_preferred);
3905 4011                                          mutex_enter(&vlun->svl_mutex);
3906 4012                                          if (vlun->svl_active_pclass == NULL ||
3907 4013                                              strcmp(opinfo.opinfo_path_attr,
3908 4014                                              vlun->svl_active_pclass) != 0) {
3909 4015                                                  mutex_exit(&vlun->svl_mutex);
3910 4016                                                  tptr = kmem_alloc(strlen
3911 4017                                                      (opinfo.opinfo_path_attr)+1,
3912 4018                                                      KM_SLEEP);
3913 4019                                                  (void) strlcpy(tptr,
3914 4020                                                      opinfo.opinfo_path_attr,
3915 4021                                                      (strlen
3916 4022                                                      (opinfo.opinfo_path_attr)
3917 4023                                                      +1));
3918 4024                                                  mutex_enter(&vlun->svl_mutex);
3919 4025                                          } else {
3920 4026                                                  /*
3921 4027                                                   * No need to update
3922 4028                                                   * svl_active_pclass
3923 4029                                                   */
3924 4030                                                  tptr = NULL;
3925 4031                                                  mutex_exit(&vlun->svl_mutex);
3926 4032                                          }
3927 4033                                          if (tptr) {
3928 4034                                                  if (vlun->svl_active_pclass
3929 4035                                                      != NULL) {
3930 4036                                                          kmem_free(vlun->
3931 4037                                                              svl_active_pclass,
3932 4038                                                              strlen(vlun->
3933 4039                                                              svl_active_pclass)
3934 4040                                                              +1);
3935 4041                                                  }
3936 4042                                                  vlun->svl_active_pclass = tptr;
3937 4043                                                  mutex_exit(&vlun->svl_mutex);
3938 4044                                          }
3939 4045                                  }
3940 4046                          }
3941 4047  
3942 4048                          /* Check for Reservation Conflict */
3943 4049                          bp = scsi_alloc_consistent_buf(
3944 4050                              &svp->svp_psd->sd_address, (struct buf *)NULL,
3945 4051                              DEV_BSIZE, B_READ, NULL, NULL);
3946 4052                          if (!bp) {
3947 4053                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
3948 4054                                      "!vhci_update_pathstates: No resources "
3949 4055                                      "(buf)\n"));
  
    | 
      ↓ open down ↓ | 
    751 lines elided | 
    
      ↑ open up ↑ | 
  
3950 4056                                  mdi_rele_path(pip);
3951 4057                                  goto done;
3952 4058                          }
3953 4059                          pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
3954 4060                              CDB_GROUP1, sizeof (struct scsi_arq_status), 0,
3955 4061                              PKT_CONSISTENT, NULL, NULL);
3956 4062                          if (pkt) {
3957 4063                                  (void) scsi_setup_cdb((union scsi_cdb *)
3958 4064                                      (uintptr_t)pkt->pkt_cdbp, SCMD_READ, 1, 1,
3959 4065                                      0);
3960      -                                pkt->pkt_time = 3*30;
     4066 +                                pkt->pkt_time = 2 * vhci_io_time;
3961 4067                                  pkt->pkt_flags = FLAG_NOINTR;
3962 4068                                  pkt->pkt_path_instance =
3963 4069                                      mdi_pi_get_path_instance(pip);
3964 4070  
3965 4071                                  if ((scsi_transport(pkt) == TRAN_ACCEPT) &&
3966 4072                                      (pkt->pkt_reason == CMD_CMPLT) &&
3967 4073                                      (SCBP_C(pkt) ==
3968 4074                                      STATUS_RESERVATION_CONFLICT)) {
3969 4075                                          VHCI_DEBUG(1, (CE_NOTE, NULL,
3970 4076                                              "!vhci_update_pathstates: reserv. "
3971 4077                                              "conflict to be resolved on 0x%p\n",
3972 4078                                              (void *)pip));
3973 4079                                          svp_conflict = svp;
3974 4080                                  }
3975 4081                                  scsi_destroy_pkt(pkt);
3976 4082                          }
3977 4083                          scsi_free_consistent_buf(bp);
3978 4084                  } else if ((opinfo.opinfo_path_state == SCSI_PATH_INACTIVE) &&
3979 4085                      !(MDI_PI_IS_STANDBY(pip))) {
3980 4086                          VHCI_DEBUG(1, (CE_NOTE, NULL,
3981 4087                              "!vhci_update_pathstates: marking path"
3982 4088                              " 0x%p as STANDBY\n", (void *)pip));
3983 4089                          cpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
3984 4090                          vhci_log(CE_NOTE, ddi_get_parent(dip), "!%s "
3985 4091                              "(%s%d): path %s "
3986 4092                              "is now STANDBY because of "
3987 4093                              "an externally initiated failover",
3988 4094                              ddi_pathname(dip, cpath),
3989 4095                              ddi_driver_name(dip),
3990 4096                              ddi_get_instance(dip),
3991 4097                              mdi_pi_spathname(pip));
3992 4098                          kmem_free(cpath, MAXPATHLEN);
3993 4099                          mdi_pi_set_state(pip,
3994 4100                              MDI_PATHINFO_STATE_STANDBY);
3995 4101                          mdi_pi_set_preferred(pip,
3996 4102                              opinfo.opinfo_preferred);
3997 4103                          mutex_enter(&vlun->svl_mutex);
3998 4104                          if (vlun->svl_active_pclass != NULL) {
3999 4105                                  if (strcmp(vlun->svl_active_pclass,
4000 4106                                      opinfo.opinfo_path_attr) == 0) {
4001 4107                                          kmem_free(vlun->
4002 4108                                              svl_active_pclass,
4003 4109                                              strlen(vlun->
4004 4110                                              svl_active_pclass)+1);
4005 4111                                          vlun->svl_active_pclass = NULL;
4006 4112                                  }
4007 4113                          }
4008 4114                          mutex_exit(&vlun->svl_mutex);
4009 4115                  }
4010 4116                  (void) mdi_prop_free(pclass);
4011 4117                  sps = mdi_select_path(dip, NULL,
4012 4118                      (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH |
4013 4119                      MDI_SELECT_NO_PREFERRED), pip, &npip);
4014 4120                  mdi_rele_path(pip);
4015 4121  
4016 4122          } while ((npip != NULL) && (sps == MDI_SUCCESS));
4017 4123  
4018 4124          /*
4019 4125           * Check to see if this vlun has an active SCSI-II RESERVE.  If so
4020 4126           * clear the reservation by sending a reset, so the host doesn't
4021 4127           * receive a reservation conflict.  The reset has to be sent via a
4022 4128           * working path.  Let's use a path referred to by svp_conflict as it
4023 4129           * should be working.
4024 4130           * Reset VLUN_RESERVE_ACTIVE_FLG for this vlun.  Also notify ssd
4025 4131           * of the reset, explicitly.
4026 4132           */
4027 4133          if (vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
4028 4134                  if (svp_conflict && (vlun->svl_xlf_capable == 0)) {
4029 4135                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_update_pathstates:"
4030 4136                              " sending recovery reset on 0x%p, path_state: %x",
4031 4137                              svp_conflict->svp_psd->sd_private,
4032 4138                              mdi_pi_get_state((mdi_pathinfo_t *)
4033 4139                              svp_conflict->svp_psd->sd_private)));
4034 4140  
4035 4141                          (void) vhci_recovery_reset(vlun,
4036 4142                              &svp_conflict->svp_psd->sd_address, FALSE,
4037 4143                              VHCI_DEPTH_TARGET);
4038 4144                  }
4039 4145                  vlun->svl_flags &= ~VLUN_RESERVE_ACTIVE_FLG;
4040 4146                  mutex_enter(&vhci->vhci_mutex);
4041 4147                  scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
4042 4148                      &vhci->vhci_reset_notify_listf);
4043 4149                  mutex_exit(&vhci->vhci_mutex);
4044 4150          }
4045 4151          if (vlun->svl_flags & VLUN_UPDATE_TPG) {
4046 4152                  /*
4047 4153                   * Update the AccessState of related MP-API TPGs
4048 4154                   */
4049 4155                  (void) vhci_mpapi_update_tpg_acc_state_for_lu(vhci, vlun);
4050 4156                  vlun->svl_flags &= ~VLUN_UPDATE_TPG;
4051 4157          }
4052 4158  done:
4053 4159          if (vlun->svl_efo_update_path) {
4054 4160                  vlun->svl_efo_update_path = 0;
4055 4161                  vhci_efo_done(vlun->svl_swarg);
4056 4162                  vlun->svl_swarg = 0;
4057 4163          }
4058 4164          VHCI_RELEASE_LUN(vlun);
4059 4165  }
4060 4166  
4061 4167  /* ARGSUSED */
4062 4168  static int
4063 4169  vhci_pathinfo_init(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
4064 4170  {
4065 4171          scsi_hba_tran_t         *hba = NULL;
4066 4172          struct scsi_device      *psd = NULL;
4067 4173          scsi_vhci_lun_t         *vlun = NULL;
4068 4174          dev_info_t              *pdip = NULL;
4069 4175          dev_info_t              *tgt_dip;
4070 4176          struct scsi_vhci        *vhci;
4071 4177          char                    *guid;
4072 4178          scsi_vhci_priv_t        *svp = NULL;
4073 4179          int                     rval = MDI_FAILURE;
4074 4180          int                     vlun_alloced = 0;
4075 4181  
4076 4182          ASSERT(vdip != NULL);
4077 4183          ASSERT(pip != NULL);
4078 4184  
4079 4185          vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
4080 4186          ASSERT(vhci != NULL);
4081 4187  
4082 4188          pdip = mdi_pi_get_phci(pip);
4083 4189          ASSERT(pdip != NULL);
4084 4190  
4085 4191          hba = ddi_get_driver_private(pdip);
4086 4192          ASSERT(hba != NULL);
4087 4193  
4088 4194          tgt_dip = mdi_pi_get_client(pip);
4089 4195          ASSERT(tgt_dip != NULL);
4090 4196  
4091 4197          if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip, PROPFLAGS,
4092 4198              MDI_CLIENT_GUID_PROP, &guid) != DDI_SUCCESS) {
4093 4199                  VHCI_DEBUG(1, (CE_WARN, NULL,
4094 4200                      "vhci_pathinfo_init: lun guid property failed"));
4095 4201                  goto failure;
4096 4202          }
4097 4203  
4098 4204          vlun = vhci_lun_lookup_alloc(tgt_dip, guid, &vlun_alloced);
4099 4205          ddi_prop_free(guid);
4100 4206  
4101 4207          vlun->svl_dip = tgt_dip;
4102 4208  
4103 4209          svp = kmem_zalloc(sizeof (*svp), KM_SLEEP);
4104 4210          svp->svp_svl = vlun;
4105 4211  
4106 4212          /*
4107 4213           * Initialize svl_lb_policy_save only for newly allocated vlun. Writing
4108 4214           * to svl_lb_policy_save later could accidentally overwrite saved lb
4109 4215           * policy.
4110 4216           */
4111 4217          if (vlun_alloced) {
4112 4218                  vlun->svl_lb_policy_save = mdi_get_lb_policy(tgt_dip);
4113 4219          }
4114 4220  
4115 4221          mutex_init(&svp->svp_mutex, NULL, MUTEX_DRIVER, NULL);
4116 4222          cv_init(&svp->svp_cv, NULL, CV_DRIVER, NULL);
4117 4223  
4118 4224          psd = kmem_zalloc(sizeof (*psd), KM_SLEEP);
4119 4225          mutex_init(&psd->sd_mutex, NULL, MUTEX_DRIVER, NULL);
4120 4226  
4121 4227          if (hba->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX) {
4122 4228                  /*
4123 4229                   * For a SCSI_HBA_ADDR_COMPLEX transport we store a pointer to
4124 4230                   * scsi_device in the scsi_address structure.  This allows an
4125 4231                   * an HBA driver to find its scsi_device(9S) and
4126 4232                   * per-scsi_device(9S) HBA private data given a
4127 4233                   * scsi_address(9S) by using scsi_address_device(9F) and
4128 4234                   * scsi_device_hba_private_get(9F)).
4129 4235                   */
4130 4236                  psd->sd_address.a.a_sd = psd;
4131 4237          } else if (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
4132 4238                  /*
4133 4239                   * Clone transport structure if requested, so
4134 4240                   * Self enumerating HBAs always need to use cloning
4135 4241                   */
4136 4242                  scsi_hba_tran_t *clone =
4137 4243                      kmem_alloc(sizeof (scsi_hba_tran_t), KM_SLEEP);
4138 4244                  bcopy(hba, clone, sizeof (scsi_hba_tran_t));
4139 4245                  hba = clone;
4140 4246                  hba->tran_sd = psd;
4141 4247          } else {
4142 4248                  /*
4143 4249                   * SPI pHCI unit-address. If we ever need to support this
4144 4250                   * we could set a.spi.a_target/a.spi.a_lun based on pathinfo
4145 4251                   * node unit-address properties.  For now we fail...
4146 4252                   */
4147 4253                  goto failure;
4148 4254          }
4149 4255  
4150 4256          psd->sd_dev = tgt_dip;
4151 4257          psd->sd_address.a_hba_tran = hba;
4152 4258  
4153 4259          /*
4154 4260           * Mark scsi_device as being associated with a pathinfo node. For
4155 4261           * a scsi_device structure associated with a devinfo node,
4156 4262           * scsi_ctlops_initchild sets this field to NULL.
4157 4263           */
4158 4264          psd->sd_pathinfo = pip;
4159 4265  
4160 4266          /*
4161 4267           * LEGACY: sd_private: set for older mpxio-capable pHCI drivers with
4162 4268           * too much scsi_vhci/mdi/ndi knowledge. Remove this code when all
4163 4269           * mpxio-capable pHCI drivers use SCSA enumeration services (or at
4164 4270           * least have been changed to use sd_pathinfo instead).
4165 4271           */
4166 4272          psd->sd_private = (caddr_t)pip;
4167 4273  
4168 4274          /* See scsi_hba.c for info on sd_tran_safe kludge */
4169 4275          psd->sd_tran_safe = hba;
4170 4276  
4171 4277          svp->svp_psd = psd;
4172 4278          mdi_pi_set_vhci_private(pip, (caddr_t)svp);
4173 4279  
4174 4280          /*
4175 4281           * call hba's target init entry point if it exists
4176 4282           */
4177 4283          if (hba->tran_tgt_init != NULL) {
4178 4284                  psd->sd_tran_tgt_free_done = 0;
4179 4285                  if ((rval = (*hba->tran_tgt_init)(pdip, tgt_dip,
4180 4286                      hba, psd)) != DDI_SUCCESS) {
4181 4287                          VHCI_DEBUG(1, (CE_WARN, pdip,
4182 4288                              "!vhci_pathinfo_init: tran_tgt_init failed for "
4183 4289                              "path=0x%p rval=%x", (void *)pip, rval));
4184 4290                          goto failure;
4185 4291                  }
4186 4292          }
4187 4293  
4188 4294          svp->svp_new_path = 1;
4189 4295  
4190 4296          VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_pathinfo_init: path:%p\n",
4191 4297              (void *)pip));
4192 4298          return (MDI_SUCCESS);
4193 4299  
4194 4300  failure:
4195 4301          if (psd) {
4196 4302                  mutex_destroy(&psd->sd_mutex);
4197 4303                  kmem_free(psd, sizeof (*psd));
4198 4304          }
4199 4305          if (svp) {
4200 4306                  mdi_pi_set_vhci_private(pip, NULL);
4201 4307                  mutex_destroy(&svp->svp_mutex);
4202 4308                  cv_destroy(&svp->svp_cv);
4203 4309                  kmem_free(svp, sizeof (*svp));
4204 4310          }
4205 4311          if (hba && (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE))
4206 4312                  kmem_free(hba, sizeof (scsi_hba_tran_t));
4207 4313  
4208 4314          if (vlun_alloced)
4209 4315                  vhci_lun_free(vlun, NULL);
4210 4316  
4211 4317          return (rval);
4212 4318  }
4213 4319  
4214 4320  /* ARGSUSED */
4215 4321  static int
4216 4322  vhci_pathinfo_uninit(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
4217 4323  {
4218 4324          scsi_hba_tran_t         *hba = NULL;
4219 4325          struct scsi_device      *psd = NULL;
4220 4326          dev_info_t              *pdip = NULL;
4221 4327          dev_info_t              *cdip = NULL;
4222 4328          scsi_vhci_priv_t        *svp = NULL;
4223 4329  
4224 4330          ASSERT(vdip != NULL);
4225 4331          ASSERT(pip != NULL);
4226 4332  
4227 4333          pdip = mdi_pi_get_phci(pip);
4228 4334          ASSERT(pdip != NULL);
4229 4335  
4230 4336          cdip = mdi_pi_get_client(pip);
4231 4337          ASSERT(cdip != NULL);
4232 4338  
4233 4339          hba = ddi_get_driver_private(pdip);
4234 4340          ASSERT(hba != NULL);
4235 4341  
4236 4342          vhci_mpapi_set_path_state(vdip, pip, MP_DRVR_PATH_STATE_UNINIT);
4237 4343          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
4238 4344          if (svp == NULL) {
4239 4345                  /* path already freed. Nothing to do. */
4240 4346                  return (MDI_SUCCESS);
4241 4347          }
4242 4348  
4243 4349          psd = svp->svp_psd;
4244 4350          ASSERT(psd != NULL);
4245 4351  
4246 4352          if (hba->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX) {
4247 4353                  /* Verify plumbing */
4248 4354                  ASSERT(psd->sd_address.a_hba_tran == hba);
4249 4355                  ASSERT(psd->sd_address.a.a_sd == psd);
4250 4356          } else if (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
4251 4357                  /* Switch to cloned scsi_hba_tran(9S) structure */
4252 4358                  hba = psd->sd_address.a_hba_tran;
4253 4359                  ASSERT(hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE);
4254 4360                  ASSERT(hba->tran_sd == psd);
4255 4361          }
4256 4362  
4257 4363          if ((hba->tran_tgt_free != NULL) && !psd->sd_tran_tgt_free_done) {
4258 4364                  (*hba->tran_tgt_free) (pdip, cdip, hba, psd);
4259 4365                  psd->sd_tran_tgt_free_done = 1;
4260 4366          }
4261 4367          mutex_destroy(&psd->sd_mutex);
4262 4368          if (hba->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
4263 4369                  kmem_free(hba, sizeof (*hba));
4264 4370          }
4265 4371  
4266 4372          mdi_pi_set_vhci_private(pip, NULL);
4267 4373  
4268 4374          /*
4269 4375           * Free the pathinfo related scsi_device inquiry data. Note that this
4270 4376           * matches what happens for scsi_hba.c devinfo case at uninitchild time.
4271 4377           */
4272 4378          if (psd->sd_inq)
4273 4379                  kmem_free((caddr_t)psd->sd_inq, sizeof (struct scsi_inquiry));
4274 4380          kmem_free((caddr_t)psd, sizeof (*psd));
4275 4381  
4276 4382          mutex_destroy(&svp->svp_mutex);
4277 4383          cv_destroy(&svp->svp_cv);
4278 4384          kmem_free((caddr_t)svp, sizeof (*svp));
4279 4385  
4280 4386          VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_pathinfo_uninit: path=0x%p\n",
4281 4387              (void *)pip));
4282 4388          return (MDI_SUCCESS);
4283 4389  }
4284 4390  
4285 4391  /* ARGSUSED */
4286 4392  static int
4287 4393  vhci_pathinfo_state_change(dev_info_t *vdip, mdi_pathinfo_t *pip,
4288 4394      mdi_pathinfo_state_t state, uint32_t ext_state, int flags)
4289 4395  {
4290 4396          int                     rval = MDI_SUCCESS;
4291 4397          scsi_vhci_priv_t        *svp;
4292 4398          scsi_vhci_lun_t         *vlun;
4293 4399          int                     held;
4294 4400          int                     op = (flags & 0xf00) >> 8;
4295 4401          struct scsi_vhci        *vhci;
4296 4402  
4297 4403          vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
4298 4404  
4299 4405          if (flags & MDI_EXT_STATE_CHANGE) {
4300 4406                  /*
4301 4407                   * We do not want to issue any commands down the path in case
4302 4408                   * sync flag is set. Lower layers might not be ready to accept
4303 4409                   * any I/O commands.
4304 4410                   */
4305 4411                  if (op == DRIVER_DISABLE)
4306 4412                          return (MDI_SUCCESS);
4307 4413  
4308 4414                  svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
4309 4415                  if (svp == NULL) {
4310 4416                          return (MDI_FAILURE);
4311 4417                  }
4312 4418                  vlun = svp->svp_svl;
4313 4419  
4314 4420                  if (flags & MDI_BEFORE_STATE_CHANGE) {
4315 4421                          /*
4316 4422                           * Hold the LUN.
4317 4423                           */
4318 4424                          VHCI_HOLD_LUN(vlun, VH_SLEEP, held);
4319 4425                          if (flags & MDI_DISABLE_OP)  {
4320 4426                                  /*
4321 4427                                   * Issue scsi reset if it happens to be
4322 4428                                   * reserved path.
4323 4429                                   */
4324 4430                                  if (vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
4325 4431                                          /*
4326 4432                                           * if reservation pending on
4327 4433                                           * this path, dont' mark the
4328 4434                                           * path busy
4329 4435                                           */
4330 4436                                          if (op == DRIVER_DISABLE_TRANSIENT) {
4331 4437                                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
4332 4438                                                      "!vhci_pathinfo"
4333 4439                                                      "_state_change (pip:%p): "
4334 4440                                                      " reservation: fail busy\n",
4335 4441                                                      (void *)pip));
4336 4442                                                  return (MDI_FAILURE);
4337 4443                                          }
4338 4444                                          if (pip == vlun->svl_resrv_pip) {
4339 4445                                                  if (vhci_recovery_reset(
4340 4446                                                      svp->svp_svl,
4341 4447                                                      &svp->svp_psd->sd_address,
4342 4448                                                      TRUE,
4343 4449                                                      VHCI_DEPTH_TARGET) == 0) {
4344 4450                                                          VHCI_DEBUG(1,
4345 4451                                                              (CE_NOTE, NULL,
4346 4452                                                              "!vhci_pathinfo"
4347 4453                                                              "_state_change "
4348 4454                                                              " (pip:%p): "
4349 4455                                                              "reset failed, "
4350 4456                                                              "give up!\n",
4351 4457                                                              (void *)pip));
4352 4458                                                  }
4353 4459                                                  vlun->svl_flags &=
4354 4460                                                      ~VLUN_RESERVE_ACTIVE_FLG;
4355 4461                                          }
4356 4462                                  }
4357 4463                          } else if (flags & MDI_ENABLE_OP)  {
4358 4464                                  if (((vhci->vhci_conf_flags &
4359 4465                                      VHCI_CONF_FLAGS_AUTO_FAILBACK) ==
4360 4466                                      VHCI_CONF_FLAGS_AUTO_FAILBACK) &&
4361 4467                                      MDI_PI_IS_USER_DISABLE(pip) &&
4362 4468                                      MDI_PI_IS_STANDBY(pip)) {
4363 4469                                          struct scsi_failover_ops        *fo;
4364 4470                                          char *best_pclass, *pclass = NULL;
4365 4471                                          int  best_class, rv;
4366 4472                                          /*
4367 4473                                           * Failback if enabling a standby path
4368 4474                                           * and it is the primary class or
4369 4475                                           * preferred class
4370 4476                                           */
4371 4477                                          best_class = mdi_pi_get_preferred(pip);
4372 4478                                          if (best_class == 0) {
4373 4479                                                  /*
4374 4480                                                   * if not preferred - compare
4375 4481                                                   * path-class with class
4376 4482                                                   */
4377 4483                                                  fo = vlun->svl_fops;
4378 4484                                                  (void) fo->sfo_pathclass_next(
4379 4485                                                      NULL, &best_pclass,
4380 4486                                                      vlun->svl_fops_ctpriv);
4381 4487                                                  pclass = NULL;
4382 4488                                                  rv = mdi_prop_lookup_string(pip,
4383 4489                                                      "path-class", &pclass);
4384 4490                                                  if (rv != MDI_SUCCESS ||
4385 4491                                                      pclass == NULL) {
4386 4492                                                          vhci_log(CE_NOTE, vdip,
4387 4493                                                              "!path-class "
4388 4494                                                              " lookup "
4389 4495                                                              "failed. rv: %d"
4390 4496                                                              "class: %p", rv,
4391 4497                                                              (void *)pclass);
4392 4498                                                  } else if (strncmp(pclass,
4393 4499                                                      best_pclass,
4394 4500                                                      strlen(best_pclass)) == 0) {
4395 4501                                                          best_class = 1;
4396 4502                                                  }
4397 4503                                                  if (rv == MDI_SUCCESS &&
4398 4504                                                      pclass != NULL) {
4399 4505                                                          rv = mdi_prop_free(
4400 4506                                                              pclass);
4401 4507                                                          if (rv !=
4402 4508                                                              DDI_PROP_SUCCESS) {
4403 4509                                                                  vhci_log(
4404 4510                                                                      CE_NOTE,
4405 4511                                                                      vdip,
4406 4512                                                                      "!path-"
4407 4513                                                                      "class"
4408 4514                                                                      " free"
4409 4515                                                                      " failed"
4410 4516                                                                      " rv: %d"
4411 4517                                                                      " class: "
4412 4518                                                                      "%p",
4413 4519                                                                      rv,
4414 4520                                                                      (void *)
4415 4521                                                                      pclass);
4416 4522                                                          }
4417 4523                                                  }
4418 4524                                          }
4419 4525                                          if (best_class == 1) {
4420 4526                                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
4421 4527                                                      "preferred path: %p "
4422 4528                                                      "USER_DISABLE->USER_ENABLE "
4423 4529                                                      "transition for lun %s\n",
4424 4530                                                      (void *)pip,
4425 4531                                                      vlun->svl_lun_wwn));
4426 4532                                                  (void) taskq_dispatch(
4427 4533                                                      vhci->vhci_taskq,
4428 4534                                                      vhci_initiate_auto_failback,
4429 4535                                                      (void *) vlun, KM_SLEEP);
4430 4536                                          }
4431 4537                                  }
4432 4538                                  /*
4433 4539                                   * if PGR is active, revalidate key and
4434 4540                                   * register on this path also, if key is
4435 4541                                   * still valid
4436 4542                                   */
4437 4543                                  sema_p(&vlun->svl_pgr_sema);
4438 4544                                  if (vlun->svl_pgr_active)
4439 4545                                          (void)
4440 4546                                              vhci_pgr_validate_and_register(svp);
4441 4547                                  sema_v(&vlun->svl_pgr_sema);
4442 4548                                  /*
4443 4549                                   * Inform target driver about any
4444 4550                                   * reservations to be reinstated if target
4445 4551                                   * has dropped reservation during the busy
4446 4552                                   * period.
4447 4553                                   */
4448 4554                                  mutex_enter(&vhci->vhci_mutex);
4449 4555                                  scsi_hba_reset_notify_callback(
4450 4556                                      &vhci->vhci_mutex,
4451 4557                                      &vhci->vhci_reset_notify_listf);
4452 4558                                  mutex_exit(&vhci->vhci_mutex);
4453 4559                          }
4454 4560                  }
4455 4561                  if (flags & MDI_AFTER_STATE_CHANGE) {
4456 4562                          if (flags & MDI_ENABLE_OP)  {
4457 4563                                  mutex_enter(&vhci_global_mutex);
4458 4564                                  cv_broadcast(&vhci_cv);
4459 4565                                  mutex_exit(&vhci_global_mutex);
4460 4566                          }
4461 4567                          if (vlun->svl_setcap_done) {
4462 4568                                  (void) vhci_pHCI_cap(&svp->svp_psd->sd_address,
4463 4569                                      "sector-size", vlun->svl_sector_size,
4464 4570                                      1, pip);
4465 4571                          }
4466 4572  
4467 4573                          /*
4468 4574                           * Release the LUN
4469 4575                           */
4470 4576                          VHCI_RELEASE_LUN(vlun);
4471 4577  
4472 4578                          /*
4473 4579                           * Path transition is complete.
4474 4580                           * Run callback to indicate target driver to
4475 4581                           * retry to prevent IO starvation.
4476 4582                           */
4477 4583                          if (scsi_callback_id != 0) {
4478 4584                                  ddi_run_callback(&scsi_callback_id);
4479 4585                          }
4480 4586                  }
4481 4587          } else {
4482 4588                  switch (state) {
4483 4589                  case MDI_PATHINFO_STATE_ONLINE:
4484 4590                          rval = vhci_pathinfo_online(vdip, pip, flags);
4485 4591                          break;
4486 4592  
4487 4593                  case MDI_PATHINFO_STATE_OFFLINE:
4488 4594                          rval = vhci_pathinfo_offline(vdip, pip, flags);
4489 4595                          break;
4490 4596  
4491 4597                  default:
4492 4598                          break;
4493 4599                  }
4494 4600                  /*
4495 4601                   * Path transition is complete.
4496 4602                   * Run callback to indicate target driver to
4497 4603                   * retry to prevent IO starvation.
4498 4604                   */
4499 4605                  if ((rval == MDI_SUCCESS) && (scsi_callback_id != 0)) {
4500 4606                          ddi_run_callback(&scsi_callback_id);
4501 4607                  }
4502 4608                  return (rval);
4503 4609          }
4504 4610  
4505 4611          return (MDI_SUCCESS);
4506 4612  }
4507 4613  
4508 4614  /*
4509 4615   * Parse the mpxio load balancing options. The datanameptr
4510 4616   * will point to a string containing the load-balance-options value.
4511 4617   * The load-balance-options value will be a property that
4512 4618   * defines the load-balance algorithm and any arguments to that
4513 4619   * algorithm.
4514 4620   * For example:
4515 4621   * device-type-mpxio-options-list=
4516 4622   * "device-type=SUN    SENA", "load-balance-options=logical-block-options"
4517 4623   * "device-type=SUN     SE6920", "round-robin-options";
4518 4624   * logical-block-options="load-balance=logical-block", "region-size=15";
4519 4625   * round-robin-options="load-balance=round-robin";
4520 4626   *
4521 4627   * If the load-balance is not defined the load balance algorithm will
4522 4628   * default to the global setting. There will be default values assigned
4523 4629   * to the arguments (region-size=18) and if an argument is one
4524 4630   * that is not known, it will be ignored.
4525 4631   */
4526 4632  static void
4527 4633  vhci_parse_mpxio_lb_options(dev_info_t *dip, dev_info_t *cdip,
4528 4634          caddr_t datanameptr)
4529 4635  {
4530 4636          char                    *dataptr, *next_entry;
4531 4637          caddr_t                 config_list     = NULL;
4532 4638          int                     config_list_len = 0, list_len = 0;
4533 4639          int                     region_size = -1;
4534 4640          client_lb_t             load_balance;
4535 4641  
4536 4642          if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, datanameptr,
4537 4643              (caddr_t)&config_list, &config_list_len) != DDI_PROP_SUCCESS) {
4538 4644                  return;
4539 4645          }
4540 4646  
4541 4647          list_len = config_list_len;
4542 4648          next_entry = config_list;
4543 4649          while (config_list_len > 0) {
4544 4650                  dataptr = next_entry;
4545 4651  
4546 4652                  if (strncmp(mdi_load_balance, dataptr,
4547 4653                      strlen(mdi_load_balance)) == 0) {
4548 4654                          /* get the load-balance scheme */
4549 4655                          dataptr += strlen(mdi_load_balance) + 1;
4550 4656                          if (strcmp(dataptr, LOAD_BALANCE_PROP_RR) == 0) {
4551 4657                                  (void) mdi_set_lb_policy(cdip, LOAD_BALANCE_RR);
4552 4658                                  load_balance = LOAD_BALANCE_RR;
4553 4659                          } else if (strcmp(dataptr,
4554 4660                              LOAD_BALANCE_PROP_LBA) == 0) {
4555 4661                                  (void) mdi_set_lb_policy(cdip,
4556 4662                                      LOAD_BALANCE_LBA);
4557 4663                                  load_balance = LOAD_BALANCE_LBA;
4558 4664                          } else if (strcmp(dataptr,
4559 4665                              LOAD_BALANCE_PROP_NONE) == 0) {
4560 4666                                  (void) mdi_set_lb_policy(cdip,
4561 4667                                      LOAD_BALANCE_NONE);
4562 4668                                  load_balance = LOAD_BALANCE_NONE;
4563 4669                          }
4564 4670                  } else if (strncmp(dataptr, LOGICAL_BLOCK_REGION_SIZE,
4565 4671                      strlen(LOGICAL_BLOCK_REGION_SIZE)) == 0) {
4566 4672                          int     i = 0;
4567 4673                          char    *ptr;
4568 4674                          char    *tmp;
4569 4675  
4570 4676                          tmp = dataptr + (strlen(LOGICAL_BLOCK_REGION_SIZE) + 1);
4571 4677                          /* check for numeric value */
4572 4678                          for (ptr = tmp; i < strlen(tmp); i++, ptr++) {
4573 4679                                  if (!isdigit(*ptr)) {
4574 4680                                          cmn_err(CE_WARN,
4575 4681                                              "Illegal region size: %s."
4576 4682                                              " Setting to default value: %d",
4577 4683                                              tmp,
4578 4684                                              LOAD_BALANCE_DEFAULT_REGION_SIZE);
4579 4685                                          region_size =
4580 4686                                              LOAD_BALANCE_DEFAULT_REGION_SIZE;
4581 4687                                          break;
4582 4688                                  }
4583 4689                          }
4584 4690                          if (i >= strlen(tmp)) {
4585 4691                                  region_size = stoi(&tmp);
4586 4692                          }
4587 4693                          (void) mdi_set_lb_region_size(cdip, region_size);
4588 4694                  }
4589 4695                  config_list_len -= (strlen(next_entry) + 1);
4590 4696                  next_entry += strlen(next_entry) + 1;
4591 4697          }
4592 4698  #ifdef DEBUG
4593 4699          if ((region_size >= 0) && (load_balance != LOAD_BALANCE_LBA)) {
4594 4700                  VHCI_DEBUG(1, (CE_NOTE, dip,
4595 4701                      "!vhci_parse_mpxio_lb_options: region-size: %d"
4596 4702                      "only valid for load-balance=logical-block\n",
4597 4703                      region_size));
4598 4704          }
4599 4705  #endif
4600 4706          if ((region_size == -1) && (load_balance == LOAD_BALANCE_LBA)) {
4601 4707                  VHCI_DEBUG(1, (CE_NOTE, dip,
4602 4708                      "!vhci_parse_mpxio_lb_options: No region-size"
4603 4709                      " defined load-balance=logical-block."
4604 4710                      " Default to: %d\n", LOAD_BALANCE_DEFAULT_REGION_SIZE));
4605 4711                  (void) mdi_set_lb_region_size(cdip,
4606 4712                      LOAD_BALANCE_DEFAULT_REGION_SIZE);
4607 4713          }
4608 4714          if (list_len > 0) {
4609 4715                  kmem_free(config_list, list_len);
4610 4716          }
4611 4717  }
4612 4718  
4613 4719  /*
4614 4720   * Parse the device-type-mpxio-options-list looking for the key of
4615 4721   * "load-balance-options". If found, parse the load balancing options.
4616 4722   * Check the comment of the vhci_get_device_type_mpxio_options()
4617 4723   * for the device-type-mpxio-options-list.
4618 4724   */
4619 4725  static void
4620 4726  vhci_parse_mpxio_options(dev_info_t *dip, dev_info_t *cdip,
4621 4727                  caddr_t datanameptr, int list_len)
4622 4728  {
4623 4729          char            *dataptr;
4624 4730          int             len;
4625 4731  
4626 4732          /*
4627 4733           * get the data list
4628 4734           */
4629 4735          dataptr = datanameptr;
4630 4736          len = 0;
4631 4737          while (len < list_len &&
4632 4738              strncmp(dataptr, DEVICE_TYPE_STR, strlen(DEVICE_TYPE_STR))
4633 4739              != 0) {
4634 4740                  if (strncmp(dataptr, LOAD_BALANCE_OPTIONS,
4635 4741                      strlen(LOAD_BALANCE_OPTIONS)) == 0) {
4636 4742                          len += strlen(LOAD_BALANCE_OPTIONS) + 1;
4637 4743                          dataptr += strlen(LOAD_BALANCE_OPTIONS) + 1;
4638 4744                          vhci_parse_mpxio_lb_options(dip, cdip, dataptr);
4639 4745                  }
4640 4746                  len += strlen(dataptr) + 1;
4641 4747                  dataptr += strlen(dataptr) + 1;
4642 4748          }
4643 4749  }
4644 4750  
4645 4751  /*
4646 4752   * Check the inquriy string returned from the device with the device-type
4647 4753   * Check for the existence of the device-type-mpxio-options-list and
4648 4754   * if found parse the list checking for a match with the device-type
4649 4755   * value and the inquiry string returned from the device. If a match
4650 4756   * is found, parse the mpxio options list. The format of the
4651 4757   * device-type-mpxio-options-list is:
4652 4758   * device-type-mpxio-options-list=
4653 4759   * "device-type=SUN    SENA", "load-balance-options=logical-block-options"
4654 4760   * "device-type=SUN     SE6920", "round-robin-options";
4655 4761   * logical-block-options="load-balance=logical-block", "region-size=15";
4656 4762   * round-robin-options="load-balance=round-robin";
4657 4763   */
4658 4764  void
4659 4765  vhci_get_device_type_mpxio_options(dev_info_t *dip, dev_info_t *cdip,
4660 4766          struct scsi_device *devp)
4661 4767  {
4662 4768  
4663 4769          caddr_t                 config_list     = NULL;
4664 4770          caddr_t                 vidptr, datanameptr;
4665 4771          int                     vidlen, dupletlen = 0;
4666 4772          int                     config_list_len = 0, len;
4667 4773          struct scsi_inquiry     *inq = devp->sd_inq;
4668 4774  
4669 4775          /*
4670 4776           * look up the device-type-mpxio-options-list and walk thru
4671 4777           * the list compare the vendor ids of the earlier inquiry command and
4672 4778           * with those vids in the list if there is a match, lookup
4673 4779           * the mpxio-options value
4674 4780           */
4675 4781          if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
4676 4782              MPXIO_OPTIONS_LIST,
4677 4783              (caddr_t)&config_list, &config_list_len) == DDI_PROP_SUCCESS) {
4678 4784  
4679 4785                  /*
4680 4786                   * Compare vids in each duplet - if it matches,
4681 4787                   * parse the mpxio options list.
4682 4788                   */
4683 4789                  for (len = config_list_len, vidptr = config_list; len > 0;
4684 4790                      len -= dupletlen) {
4685 4791  
4686 4792                          dupletlen = 0;
4687 4793  
4688 4794                          if (strlen(vidptr) != 0 &&
4689 4795                              strncmp(vidptr, DEVICE_TYPE_STR,
4690 4796                              strlen(DEVICE_TYPE_STR)) == 0) {
4691 4797                                  /* point to next duplet */
4692 4798                                  datanameptr = vidptr + strlen(vidptr) + 1;
4693 4799                                  /* add len of this duplet */
4694 4800                                  dupletlen += strlen(vidptr) + 1;
4695 4801                                  /* get to device type */
4696 4802                                  vidptr += strlen(DEVICE_TYPE_STR) + 1;
4697 4803                                  vidlen = strlen(vidptr);
4698 4804                                  if ((vidlen != 0) &&
4699 4805                                      bcmp(inq->inq_vid, vidptr, vidlen) == 0) {
4700 4806                                          vhci_parse_mpxio_options(dip, cdip,
4701 4807                                              datanameptr, len - dupletlen);
4702 4808                                          break;
4703 4809                                  }
4704 4810                                  /* get to next duplet */
4705 4811                                  vidptr += strlen(vidptr) + 1;
4706 4812                          }
4707 4813                          /* get to the next device-type */
4708 4814                          while (len - dupletlen > 0 &&
4709 4815                              strlen(vidptr) != 0 &&
4710 4816                              strncmp(vidptr, DEVICE_TYPE_STR,
4711 4817                              strlen(DEVICE_TYPE_STR)) != 0) {
4712 4818                                  dupletlen += strlen(vidptr) + 1;
4713 4819                                  vidptr += strlen(vidptr) + 1;
4714 4820                          }
4715 4821                  }
4716 4822                  if (config_list_len > 0) {
4717 4823                          kmem_free(config_list, config_list_len);
4718 4824                  }
4719 4825          }
4720 4826  }
4721 4827  
4722 4828  static int
4723 4829  vhci_update_pathinfo(struct scsi_device *psd,  mdi_pathinfo_t *pip,
4724 4830          struct scsi_failover_ops *fo,
4725 4831          scsi_vhci_lun_t         *vlun,
4726 4832          struct scsi_vhci        *vhci)
4727 4833  {
4728 4834          struct scsi_path_opinfo         opinfo;
4729 4835          char                            *pclass, *best_pclass;
4730 4836          char                            *resrv_pclass = NULL;
4731 4837          int                             force_rereserve = 0;
4732 4838          int                             update_pathinfo_done = 0;
4733 4839  
4734 4840          if (fo->sfo_path_get_opinfo(psd, &opinfo, vlun->svl_fops_ctpriv) != 0) {
4735 4841                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_update_pathinfo: "
4736 4842                      "Failed to get operation info for path:%p\n", (void *)pip));
4737 4843                  return (MDI_FAILURE);
4738 4844          }
4739 4845          /* set the xlf capable flag in the vlun for future use */
4740 4846          vlun->svl_xlf_capable = opinfo.opinfo_xlf_capable;
4741 4847          (void) mdi_prop_update_string(pip, "path-class",
4742 4848              opinfo.opinfo_path_attr);
4743 4849  
4744 4850          pclass = opinfo.opinfo_path_attr;
4745 4851          if (opinfo.opinfo_path_state == SCSI_PATH_ACTIVE) {
4746 4852                  mutex_enter(&vlun->svl_mutex);
4747 4853                  if (vlun->svl_active_pclass != NULL) {
4748 4854                          if (strcmp(vlun->svl_active_pclass, pclass) != 0) {
4749 4855                                  mutex_exit(&vlun->svl_mutex);
4750 4856                                  /*
4751 4857                                   * Externally initiated failover has happened;
4752 4858                                   * force the path state to be STANDBY/ONLINE,
4753 4859                                   * next IO will trigger failover and thus
4754 4860                                   * sync-up the pathstates.  Reason we don't
4755 4861                                   * sync-up immediately by invoking
4756 4862                                   * vhci_update_pathstates() is because it
4757 4863                                   * needs a VHCI_HOLD_LUN() and we don't
4758 4864                                   * want to block here.
4759 4865                                   *
4760 4866                                   * Further, if the device is an ALUA device,
4761 4867                                   * then failure to exactly match 'pclass' and
4762 4868                                   * 'svl_active_pclass'(as is the case here)
4763 4869                                   * indicates that the currently active path
4764 4870                                   * is a 'non-optimized' path - which means
4765 4871                                   * that 'svl_active_pclass' needs to be
4766 4872                                   * replaced with opinfo.opinfo_path_state
4767 4873                                   * value.
4768 4874                                   */
4769 4875  
4770 4876                                  if (SCSI_FAILOVER_IS_TPGS(vlun->svl_fops)) {
4771 4877                                          char    *tptr;
4772 4878  
4773 4879                                          /*
4774 4880                                           * The device is ALUA compliant. The
4775 4881                                           * state need to be changed to online
4776 4882                                           * rather than standby state which is
4777 4883                                           * done typically for a asymmetric
4778 4884                                           * device that is non ALUA compliant.
4779 4885                                           */
4780 4886                                          mdi_pi_set_state(pip,
4781 4887                                              MDI_PATHINFO_STATE_ONLINE);
4782 4888                                          tptr = kmem_alloc(strlen
4783 4889                                              (opinfo.opinfo_path_attr)+1,
4784 4890                                              KM_SLEEP);
4785 4891                                          (void) strlcpy(tptr,
4786 4892                                              opinfo.opinfo_path_attr,
4787 4893                                              (strlen(opinfo.opinfo_path_attr)
4788 4894                                              +1));
4789 4895                                          mutex_enter(&vlun->svl_mutex);
4790 4896                                          kmem_free(vlun->svl_active_pclass,
4791 4897                                              strlen(vlun->svl_active_pclass)+1);
4792 4898                                          vlun->svl_active_pclass = tptr;
4793 4899                                          mutex_exit(&vlun->svl_mutex);
4794 4900                                  } else {
4795 4901                                          /*
4796 4902                                           * Non ALUA device case.
4797 4903                                           */
4798 4904                                          mdi_pi_set_state(pip,
4799 4905                                              MDI_PATHINFO_STATE_STANDBY);
4800 4906                                  }
4801 4907                                  vlun->svl_fo_support = opinfo.opinfo_mode;
4802 4908                                  mdi_pi_set_preferred(pip,
4803 4909                                      opinfo.opinfo_preferred);
4804 4910                                  update_pathinfo_done = 1;
4805 4911                          }
4806 4912  
4807 4913                          /*
4808 4914                           * Find out a class of currently reserved path if there
4809 4915                           * is any.
4810 4916                           */
4811 4917                          if ((vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) &&
4812 4918                              mdi_prop_lookup_string(vlun->svl_resrv_pip,
4813 4919                              "path-class", &resrv_pclass) != MDI_SUCCESS) {
4814 4920                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
4815 4921                                      "!vhci_update_pathinfo: prop lookup "
4816 4922                                      "failed for path 0x%p\n",
4817 4923                                      (void *)vlun->svl_resrv_pip));
4818 4924                                  /*
4819 4925                                   * Something is wrong with the reserved path.
4820 4926                                   * We can't do much with that right here. Just
4821 4927                                   * force re-reservation to another path.
4822 4928                                   */
4823 4929                                  force_rereserve = 1;
4824 4930                          }
4825 4931  
4826 4932                          (void) fo->sfo_pathclass_next(NULL, &best_pclass,
4827 4933                              vlun->svl_fops_ctpriv);
4828 4934                          if ((force_rereserve == 1) || ((resrv_pclass != NULL) &&
4829 4935                              (strcmp(pclass, best_pclass) == 0) &&
4830 4936                              (strcmp(resrv_pclass, best_pclass) != 0))) {
4831 4937                                  /*
4832 4938                                   * Inform target driver that a reservation
4833 4939                                   * should be reinstated because the reserved
4834 4940                                   * path is not the most preferred one.
4835 4941                                   */
4836 4942                                  mutex_enter(&vhci->vhci_mutex);
4837 4943                                  scsi_hba_reset_notify_callback(
4838 4944                                      &vhci->vhci_mutex,
4839 4945                                      &vhci->vhci_reset_notify_listf);
4840 4946                                  mutex_exit(&vhci->vhci_mutex);
4841 4947                          }
4842 4948  
4843 4949                          if (update_pathinfo_done == 1) {
4844 4950                                  return (MDI_SUCCESS);
4845 4951                          }
4846 4952                  } else {
4847 4953                          char    *tptr;
4848 4954  
4849 4955                          /*
4850 4956                           * lets release the mutex before we try to
4851 4957                           * allocate since the potential to sleep is
4852 4958                           * possible.
4853 4959                           */
4854 4960                          mutex_exit(&vlun->svl_mutex);
4855 4961                          tptr = kmem_alloc(strlen(pclass)+1, KM_SLEEP);
4856 4962                          (void) strlcpy(tptr, pclass, (strlen(pclass)+1));
4857 4963                          mutex_enter(&vlun->svl_mutex);
4858 4964                          vlun->svl_active_pclass = tptr;
4859 4965                  }
4860 4966                  mutex_exit(&vlun->svl_mutex);
4861 4967                  mdi_pi_set_state(pip, MDI_PATHINFO_STATE_ONLINE);
4862 4968                  vlun->svl_waiting_for_activepath = 0;
4863 4969          } else if (opinfo.opinfo_path_state == SCSI_PATH_ACTIVE_NONOPT) {
4864 4970                  mutex_enter(&vlun->svl_mutex);
4865 4971                  if (vlun->svl_active_pclass == NULL) {
4866 4972                          char    *tptr;
4867 4973  
4868 4974                          mutex_exit(&vlun->svl_mutex);
4869 4975                          tptr = kmem_alloc(strlen(pclass)+1, KM_SLEEP);
4870 4976                          (void) strlcpy(tptr, pclass, (strlen(pclass)+1));
4871 4977                          mutex_enter(&vlun->svl_mutex);
4872 4978                          vlun->svl_active_pclass = tptr;
4873 4979                  }
4874 4980                  mutex_exit(&vlun->svl_mutex);
4875 4981                  mdi_pi_set_state(pip, MDI_PATHINFO_STATE_ONLINE);
4876 4982                  vlun->svl_waiting_for_activepath = 0;
4877 4983          } else if (opinfo.opinfo_path_state == SCSI_PATH_INACTIVE) {
4878 4984                  mutex_enter(&vlun->svl_mutex);
4879 4985                  if (vlun->svl_active_pclass != NULL) {
4880 4986                          if (strcmp(vlun->svl_active_pclass, pclass) == 0) {
4881 4987                                  mutex_exit(&vlun->svl_mutex);
4882 4988                                  /*
4883 4989                                   * externally initiated failover has happened;
4884 4990                                   * force state to ONLINE (see comment above)
4885 4991                                   */
4886 4992                                  mdi_pi_set_state(pip,
4887 4993                                      MDI_PATHINFO_STATE_ONLINE);
4888 4994                                  vlun->svl_fo_support = opinfo.opinfo_mode;
4889 4995                                  mdi_pi_set_preferred(pip,
4890 4996                                      opinfo.opinfo_preferred);
4891 4997                                  return (MDI_SUCCESS);
4892 4998                          }
4893 4999                  }
4894 5000                  mutex_exit(&vlun->svl_mutex);
4895 5001                  mdi_pi_set_state(pip, MDI_PATHINFO_STATE_STANDBY);
4896 5002  
4897 5003                  /*
4898 5004                   * Initiate auto-failback, if enabled, for path if path-state
4899 5005                   * is transitioning from OFFLINE->STANDBY and pathclass is the
4900 5006                   * preferred pathclass for this storage.
4901 5007                   * NOTE: In case where opinfo_path_state is SCSI_PATH_ACTIVE
4902 5008                   * (above), where the pi state is set to STANDBY, we don't
4903 5009                   * initiate auto-failback as the next IO shall take care of.
4904 5010                   * this. See comment above.
4905 5011                   */
4906 5012                  (void) fo->sfo_pathclass_next(NULL, &best_pclass,
4907 5013                      vlun->svl_fops_ctpriv);
4908 5014                  if (((vhci->vhci_conf_flags & VHCI_CONF_FLAGS_AUTO_FAILBACK) ==
4909 5015                      VHCI_CONF_FLAGS_AUTO_FAILBACK) &&
4910 5016                      (strcmp(pclass, best_pclass) == 0) &&
4911 5017                      ((MDI_PI_OLD_STATE(pip) == MDI_PATHINFO_STATE_OFFLINE)||
4912 5018                      (MDI_PI_OLD_STATE(pip) == MDI_PATHINFO_STATE_INIT))) {
4913 5019                          VHCI_DEBUG(1, (CE_NOTE, NULL, "%s pathclass path: %p"
4914 5020                              " OFFLINE->STANDBY transition for lun %s\n",
4915 5021                              best_pclass, (void *)pip, vlun->svl_lun_wwn));
4916 5022                          (void) taskq_dispatch(vhci->vhci_taskq,
4917 5023                              vhci_initiate_auto_failback, (void *) vlun,
4918 5024                              KM_SLEEP);
4919 5025                  }
4920 5026          }
4921 5027          vlun->svl_fo_support = opinfo.opinfo_mode;
4922 5028          mdi_pi_set_preferred(pip, opinfo.opinfo_preferred);
4923 5029  
4924 5030          VHCI_DEBUG(8, (CE_NOTE, NULL, "vhci_update_pathinfo: opinfo_rev = %x,"
4925 5031              " opinfo_path_state = %x opinfo_preferred = %x, opinfo_mode = %x\n",
4926 5032              opinfo.opinfo_rev, opinfo.opinfo_path_state,
4927 5033              opinfo.opinfo_preferred, opinfo.opinfo_mode));
4928 5034  
4929 5035          return (MDI_SUCCESS);
4930 5036  }
4931 5037  
4932 5038  /*
4933 5039   * Form the kstat name and and call mdi_pi_kstat_create()
4934 5040   */
4935 5041  void
4936 5042  vhci_kstat_create_pathinfo(mdi_pathinfo_t *pip)
4937 5043  {
4938 5044          dev_info_t      *tgt_dip;
4939 5045          dev_info_t      *pdip;
4940 5046          char            *guid;
4941 5047          char            *target_port, *target_port_dup;
4942 5048          char            ks_name[KSTAT_STRLEN];
4943 5049          uint_t          pid;
4944 5050          int             by_id;
4945 5051          mod_hash_val_t  hv;
4946 5052  
4947 5053  
4948 5054          /* return if we have already allocated kstats */
4949 5055          if (mdi_pi_kstat_exists(pip))
4950 5056                  return;
4951 5057  
4952 5058          /*
4953 5059           * We need instance numbers to create a kstat name, return if we don't
4954 5060           * have instance numbers assigned yet.
4955 5061           */
4956 5062          tgt_dip = mdi_pi_get_client(pip);
4957 5063          pdip = mdi_pi_get_phci(pip);
4958 5064          if ((ddi_get_instance(tgt_dip) == -1) || (ddi_get_instance(pdip) == -1))
4959 5065                  return;
4960 5066  
4961 5067          /*
4962 5068           * A path oriented kstat has a ks_name of the form:
4963 5069           *
4964 5070           * <client-driver><instance>.t<pid>.<pHCI-driver><instance>
4965 5071           *
4966 5072           * We maintain a bidirectional 'target-port' to <pid> map,
4967 5073           * called targetmap. All pathinfo nodes with the same
4968 5074           * 'target-port' map to the same <pid>. The iostat(1M) code,
4969 5075           * when parsing a path oriented kstat name, uses the <pid> as
4970 5076           * a SCSI_VHCI_GET_TARGET_LONGNAME ioctl argument in order
4971 5077           * to get the 'target-port'. For KSTAT_FLAG_PERSISTENT kstats,
4972 5078           * this ioctl needs to translate a <pid> to a 'target-port'
4973 5079           * even after all pathinfo nodes associated with the
4974 5080           * 'target-port' have been destroyed. This is needed to support
4975 5081           * consistent first-iteration activity-since-boot iostat(1M)
4976 5082           * output. Because of this requirement, the mapping can't be
4977 5083           * based on pathinfo information in a devinfo snapshot.
4978 5084           */
4979 5085  
4980 5086          /* determine 'target-port' */
4981 5087          if (mdi_prop_lookup_string(pip,
4982 5088              SCSI_ADDR_PROP_TARGET_PORT, &target_port) == MDI_SUCCESS) {
4983 5089                  target_port_dup = i_ddi_strdup(target_port, KM_SLEEP);
4984 5090                  (void) mdi_prop_free(target_port);
4985 5091                  by_id = 1;
4986 5092          } else {
4987 5093                  /*
4988 5094                   * If the pHCI did not set up 'target-port' on this
4989 5095                   * pathinfo node, assume that our client is the only
4990 5096                   * one with paths to the device by using the guid
4991 5097                   * value as the 'target-port'. Since no other client
4992 5098                   * will have the same guid, no other client will use
4993 5099                   * the same <pid>.  NOTE: a client with an instance
4994 5100                   * number always has a guid.
4995 5101                   */
4996 5102                  (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
4997 5103                      PROPFLAGS, MDI_CLIENT_GUID_PROP, &guid);
4998 5104                  target_port_dup = i_ddi_strdup(guid, KM_SLEEP);
4999 5105                  ddi_prop_free(guid);
5000 5106  
5001 5107                  /*
5002 5108                   * For this type of mapping we don't want the
5003 5109                   * <id> -> 'target-port' mapping to be made.  This
5004 5110                   * will cause the SCSI_VHCI_GET_TARGET_LONGNAME ioctl
5005 5111                   * to fail, and the iostat(1M) long '-n' output will
5006 5112                   * still use the <pid>.  We do this because we just
5007 5113                   * made up the 'target-port' using the guid, and we
5008 5114                   * don't want to expose that fact in iostat output.
5009 5115                   */
5010 5116                  by_id = 0;
5011 5117          }
5012 5118  
5013 5119          /* find/establish <pid> given 'target-port' */
5014 5120          mutex_enter(&vhci_targetmap_mutex);
5015 5121          if (mod_hash_find(vhci_targetmap_byport,
5016 5122              (mod_hash_key_t)target_port_dup, &hv) == 0) {
5017 5123                  pid = (int)(intptr_t)hv;        /* mapping exists */
5018 5124          } else {
5019 5125                  pid = vhci_targetmap_pid++;     /* new mapping */
5020 5126  
5021 5127                  (void) mod_hash_insert(vhci_targetmap_byport,
5022 5128                      (mod_hash_key_t)target_port_dup,
5023 5129                      (mod_hash_val_t)(intptr_t)pid);
5024 5130                  if (by_id) {
5025 5131                          (void) mod_hash_insert(vhci_targetmap_bypid,
5026 5132                              (mod_hash_key_t)(uintptr_t)pid,
5027 5133                              (mod_hash_val_t)(uintptr_t)target_port_dup);
5028 5134                  }
5029 5135                  target_port_dup = NULL;         /* owned by hash */
5030 5136          }
5031 5137          mutex_exit(&vhci_targetmap_mutex);
5032 5138  
5033 5139          /* form kstat name */
5034 5140          (void) snprintf(ks_name, KSTAT_STRLEN, "%s%d.t%d.%s%d",
5035 5141              ddi_driver_name(tgt_dip), ddi_get_instance(tgt_dip),
5036 5142              pid, ddi_driver_name(pdip), ddi_get_instance(pdip));
5037 5143  
5038 5144          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_path_online: path:%p "
5039 5145              "kstat %s: pid %x <-> port %s\n", (void *)pip,
5040 5146              ks_name, pid, target_port_dup));
5041 5147          if (target_port_dup)
5042 5148                  kmem_free(target_port_dup, strlen(target_port_dup) + 1);
5043 5149  
5044 5150          /* call mdi to create kstats with the name we built */
5045 5151          (void) mdi_pi_kstat_create(pip, ks_name);
5046 5152  }
5047 5153  
5048 5154  /* ARGSUSED */
5049 5155  static int
5050 5156  vhci_pathinfo_online(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
5051 5157  {
5052 5158          scsi_hba_tran_t                 *hba = NULL;
5053 5159          struct scsi_device              *psd = NULL;
5054 5160          scsi_vhci_lun_t                 *vlun = NULL;
5055 5161          dev_info_t                      *pdip = NULL;
5056 5162          dev_info_t                      *cdip;
5057 5163          dev_info_t                      *tgt_dip;
5058 5164          struct scsi_vhci                *vhci;
5059 5165          char                            *guid;
5060 5166          struct scsi_failover_ops        *sfo;
5061 5167          scsi_vhci_priv_t                *svp = NULL;
5062 5168          struct scsi_address             *ap;
5063 5169          struct scsi_pkt                 *pkt;
5064 5170          int                             rval = MDI_FAILURE;
5065 5171          mpapi_item_list_t               *list_ptr;
5066 5172          mpapi_lu_data_t                 *ld;
5067 5173  
5068 5174          ASSERT(vdip != NULL);
5069 5175          ASSERT(pip != NULL);
5070 5176  
5071 5177          vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
5072 5178          ASSERT(vhci != NULL);
5073 5179  
5074 5180          pdip = mdi_pi_get_phci(pip);
5075 5181          hba = ddi_get_driver_private(pdip);
5076 5182          ASSERT(hba != NULL);
5077 5183  
5078 5184          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
5079 5185          ASSERT(svp != NULL);
5080 5186  
5081 5187          cdip = mdi_pi_get_client(pip);
5082 5188          ASSERT(cdip != NULL);
5083 5189          if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip, PROPFLAGS,
5084 5190              MDI_CLIENT_GUID_PROP, &guid) != DDI_SUCCESS) {
5085 5191                  VHCI_DEBUG(1, (CE_WARN, NULL, "vhci_path_online: lun guid "
5086 5192                      "property failed"));
5087 5193                  goto failure;
5088 5194          }
5089 5195  
5090 5196          vlun = vhci_lun_lookup(cdip);
5091 5197          ASSERT(vlun != NULL);
5092 5198  
5093 5199          ddi_prop_free(guid);
5094 5200  
5095 5201          vlun->svl_dip = mdi_pi_get_client(pip);
5096 5202          ASSERT(vlun->svl_dip != NULL);
5097 5203  
5098 5204          psd = svp->svp_psd;
5099 5205          ASSERT(psd != NULL);
5100 5206  
5101 5207          ap = &psd->sd_address;
5102 5208  
5103 5209          /*
5104 5210           * Get inquiry data into pathinfo related scsi_device structure.
5105 5211           * Free sq_inq when pathinfo related scsi_device structure is destroyed
5106 5212           * by vhci_pathinfo_uninit(). In other words, vhci maintains its own
5107 5213           * copy of scsi_device and scsi_inquiry data on a per-path basis.
5108 5214           */
5109 5215          if (scsi_probe(psd, SLEEP_FUNC) != SCSIPROBE_EXISTS) {
5110 5216                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_pathinfo_online: "
5111 5217                      "scsi_probe failed path:%p rval:%x\n", (void *)pip, rval));
5112 5218                  rval = MDI_FAILURE;
5113 5219                  goto failure;
5114 5220          }
5115 5221  
5116 5222          /*
5117 5223           * See if we have a failover module to support the device.
5118 5224           *
5119 5225           * We re-probe to determine the failover ops for each path. This
5120 5226           * is done in case there are any path-specific side-effects associated
5121 5227           * with the sfo_device_probe implementation.
5122 5228           *
5123 5229           * Give the first successfull sfo_device_probe the opportunity to
5124 5230           * establish 'ctpriv', vlun/client private data. The ctpriv will
5125 5231           * then be passed into the failover module on all other sfo_device_*()
5126 5232           * operations (and must be freed by sfo_device_unprobe implementation).
5127 5233           *
5128 5234           * NOTE: While sfo_device_probe is done once per path,
5129 5235           * sfo_device_unprobe only occurs once - when the vlun is destroyed.
5130 5236           *
5131 5237           * NOTE: We don't currently support per-path fops private data
5132 5238           * mechanism.
5133 5239           */
5134 5240          sfo = vhci_dev_fo(vdip, psd,
5135 5241              &vlun->svl_fops_ctpriv, &vlun->svl_fops_name);
5136 5242  
5137 5243          /* check path configuration result with current vlun state */
5138 5244          if (((sfo && vlun->svl_fops) && (sfo != vlun->svl_fops)) ||
5139 5245              (sfo && vlun->svl_not_supported) ||
5140 5246              ((sfo == NULL) && vlun->svl_fops)) {
5141 5247                  /* Getting different results for different paths. */
5142 5248                  VHCI_DEBUG(1, (CE_NOTE, vhci->vhci_dip,
5143 5249                      "!vhci_pathinfo_online: dev (path 0x%p) contradiction\n",
5144 5250                      (void *)pip));
5145 5251                  cmn_err(CE_WARN, "scsi_vhci: failover contradiction: "
5146 5252                      "'%s'.vs.'%s': path %s\n",
5147 5253                      vlun->svl_fops ? vlun->svl_fops->sfo_name : "NULL",
5148 5254                      sfo ? sfo->sfo_name : "NULL", mdi_pi_pathname(pip));
5149 5255                  vlun->svl_not_supported = 1;
5150 5256                  rval = MDI_NOT_SUPPORTED;
5151 5257                  goto done;
5152 5258          } else if (sfo == NULL) {
5153 5259                  /* No failover module - device not supported under vHCI.  */
5154 5260                  VHCI_DEBUG(1, (CE_NOTE, vhci->vhci_dip,
5155 5261                      "!vhci_pathinfo_online: dev (path 0x%p) not "
5156 5262                      "supported\n", (void *)pip));
5157 5263  
5158 5264                  /* XXX does this contradict vhci_is_dev_supported ? */
5159 5265                  vlun->svl_not_supported = 1;
5160 5266                  rval = MDI_NOT_SUPPORTED;
5161 5267                  goto done;
5162 5268          }
5163 5269  
5164 5270          /* failover supported for device - save failover_ops in vlun */
5165 5271          vlun->svl_fops = sfo;
5166 5272          ASSERT(vlun->svl_fops_name != NULL);
5167 5273  
5168 5274          /*
5169 5275           * Obtain the device-type based mpxio options as specified in
5170 5276           * scsi_vhci.conf file.
5171 5277           *
5172 5278           * NOTE: currently, the end result is a call to
5173 5279           * mdi_set_lb_region_size().
5174 5280           */
5175 5281          tgt_dip = psd->sd_dev;
5176 5282          ASSERT(tgt_dip != NULL);
5177 5283          vhci_get_device_type_mpxio_options(vdip, tgt_dip, psd);
5178 5284  
5179 5285          /*
5180 5286           * if PGR is active, revalidate key and register on this path also,
5181 5287           * if key is still valid
5182 5288           */
5183 5289          sema_p(&vlun->svl_pgr_sema);
5184 5290          if (vlun->svl_pgr_active) {
5185 5291                  rval = vhci_pgr_validate_and_register(svp);
5186 5292                  if (rval != 1) {
5187 5293                          rval = MDI_FAILURE;
5188 5294                          sema_v(&vlun->svl_pgr_sema);
5189 5295                          goto failure;
5190 5296                  }
5191 5297          }
5192 5298          sema_v(&vlun->svl_pgr_sema);
5193 5299  
5194 5300          if (svp->svp_new_path) {
5195 5301                  /*
5196 5302                   * Last chance to perform any cleanup operations on this
5197 5303                   * new path before making this path completely online.
5198 5304                   */
5199 5305                  svp->svp_new_path = 0;
5200 5306  
5201 5307                  /*
5202 5308                   * If scsi_vhci knows the lun is alread RESERVE'd,
5203 5309                   * then skip the issue of RELEASE on new path.
5204 5310                   */
5205 5311                  if ((vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) == 0) {
5206 5312                          /*
5207 5313                           * Issue SCSI-2 RELEASE only for the first time on
5208 5314                           * a new path just in case the host rebooted and
5209 5315                           * a reservation is still pending on this path.
5210 5316                           * IBM Shark storage does not clear RESERVE upon
5211 5317                           * host reboot.
5212 5318                           */
5213 5319                          pkt = scsi_init_pkt(ap, NULL, NULL, CDB_GROUP0,
5214 5320                              sizeof (struct scsi_arq_status), 0, 0,
  
    | 
      ↓ open down ↓ | 
    1244 lines elided | 
    
      ↑ open up ↑ | 
  
5215 5321                              SLEEP_FUNC, NULL);
5216 5322                          if (pkt == NULL) {
5217 5323                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
5218 5324                                      "!vhci_pathinfo_online: "
5219 5325                                      "Release init_pkt failed :%p\n",
5220 5326                                      (void *)pip));
5221 5327                                  rval = MDI_FAILURE;
5222 5328                                  goto failure;
5223 5329                          }
5224 5330                          pkt->pkt_cdbp[0] = SCMD_RELEASE;
5225      -                        pkt->pkt_time = 60;
     5331 +                        pkt->pkt_time = vhci_io_time;
5226 5332  
5227 5333                          VHCI_DEBUG(1, (CE_NOTE, NULL,
5228 5334                              "!vhci_path_online: path:%p "
5229 5335                              "Issued SCSI-2 RELEASE\n", (void *)pip));
5230 5336  
5231 5337                          /* Ignore the return value */
5232 5338                          (void) vhci_do_scsi_cmd(pkt);
5233 5339                          scsi_destroy_pkt(pkt);
5234 5340                  }
5235 5341          }
5236 5342  
5237 5343          rval = vhci_update_pathinfo(psd, pip, sfo, vlun, vhci);
5238 5344          if (rval == MDI_FAILURE) {
5239 5345                  goto failure;
5240 5346          }
5241 5347  
5242 5348          /* Initialize MP-API data */
5243 5349          vhci_update_mpapi_data(vhci, vlun, pip);
5244 5350  
5245 5351          /*
5246 5352           * MP-API also needs the Inquiry data to be maintained in the
5247 5353           * mp_vendor_prop_t structure, so find the lun and update its
5248 5354           * structure with this data.
5249 5355           */
5250 5356          list_ptr = (mpapi_item_list_t *)vhci_get_mpapi_item(vhci, NULL,
5251 5357              MP_OBJECT_TYPE_MULTIPATH_LU, (void *)vlun);
5252 5358          ld = (mpapi_lu_data_t *)list_ptr->item->idata;
5253 5359          if (ld != NULL) {
5254 5360                  bcopy(psd->sd_inq->inq_vid, ld->prop.prodInfo.vendor, 8);
5255 5361                  bcopy(psd->sd_inq->inq_pid, ld->prop.prodInfo.product, 16);
5256 5362                  bcopy(psd->sd_inq->inq_revision, ld->prop.prodInfo.revision, 4);
5257 5363          } else {
5258 5364                  VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_pathinfo_online: "
5259 5365                      "mpapi_lu_data_t is NULL"));
5260 5366          }
5261 5367  
5262 5368          /* create kstats for path */
5263 5369          vhci_kstat_create_pathinfo(pip);
5264 5370  
5265 5371  done:
5266 5372          mutex_enter(&vhci_global_mutex);
5267 5373          cv_broadcast(&vhci_cv);
5268 5374          mutex_exit(&vhci_global_mutex);
5269 5375  
5270 5376          if (vlun->svl_setcap_done) {
5271 5377                  (void) vhci_pHCI_cap(ap, "sector-size",
5272 5378                      vlun->svl_sector_size, 1, pip);
5273 5379          }
5274 5380  
5275 5381          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_path_online: path:%p\n",
5276 5382              (void *)pip));
5277 5383  
5278 5384  failure:
5279 5385          return (rval);
5280 5386  }
5281 5387  
5282 5388  /*
5283 5389   * path offline handler.  Release all bindings that will not be
5284 5390   * released by the normal packet transport/completion code path.
5285 5391   * Since we don't (presently) keep any bindings alive outside of
5286 5392   * the in-transport packets (which will be released on completion)
5287 5393   * there is not much to do here.
5288 5394   */
5289 5395  /* ARGSUSED */
5290 5396  static int
5291 5397  vhci_pathinfo_offline(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags)
5292 5398  {
5293 5399          scsi_hba_tran_t         *hba = NULL;
5294 5400          struct scsi_device      *psd = NULL;
5295 5401          dev_info_t              *pdip = NULL;
5296 5402          dev_info_t              *cdip = NULL;
5297 5403          scsi_vhci_priv_t        *svp = NULL;
5298 5404  
5299 5405          ASSERT(vdip != NULL);
5300 5406          ASSERT(pip != NULL);
5301 5407  
5302 5408          pdip = mdi_pi_get_phci(pip);
5303 5409          ASSERT(pdip != NULL);
5304 5410          if (pdip == NULL) {
5305 5411                  VHCI_DEBUG(1, (CE_WARN, vdip, "Invalid path 0x%p: NULL "
5306 5412                      "phci dip", (void *)pip));
5307 5413                  return (MDI_FAILURE);
5308 5414          }
5309 5415  
5310 5416          cdip = mdi_pi_get_client(pip);
5311 5417          ASSERT(cdip != NULL);
5312 5418          if (cdip == NULL) {
5313 5419                  VHCI_DEBUG(1, (CE_WARN, vdip, "Invalid path 0x%p: NULL "
5314 5420                      "client dip", (void *)pip));
5315 5421                  return (MDI_FAILURE);
5316 5422          }
5317 5423  
5318 5424          hba = ddi_get_driver_private(pdip);
5319 5425          ASSERT(hba != NULL);
5320 5426  
5321 5427          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
5322 5428          if (svp == NULL) {
5323 5429                  /*
5324 5430                   * mdi_pathinfo node in INIT state can have vHCI private
5325 5431                   * information set to null
5326 5432                   */
5327 5433                  VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
5328 5434                      "svp is NULL for pip 0x%p\n", (void *)pip));
5329 5435                  return (MDI_SUCCESS);
5330 5436          }
5331 5437  
5332 5438          psd = svp->svp_psd;
5333 5439          ASSERT(psd != NULL);
5334 5440  
5335 5441          mutex_enter(&svp->svp_mutex);
5336 5442  
5337 5443          VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
5338 5444              "%d cmds pending on path: 0x%p\n", svp->svp_cmds, (void *)pip));
5339 5445          while (svp->svp_cmds != 0) {
5340 5446                  if (cv_reltimedwait(&svp->svp_cv, &svp->svp_mutex,
5341 5447                      drv_usectohz(vhci_path_quiesce_timeout * 1000000),
5342 5448                      TR_CLOCK_TICK) == -1) {
5343 5449                          /*
5344 5450                           * The timeout time reached without the condition
5345 5451                           * being signaled.
5346 5452                           */
5347 5453                          VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
5348 5454                              "Timeout reached on path 0x%p without the cond\n",
5349 5455                              (void *)pip));
5350 5456                          VHCI_DEBUG(1, (CE_NOTE, vdip, "!vhci_pathinfo_offline: "
5351 5457                              "%d cmds still pending on path: 0x%p\n",
5352 5458                              svp->svp_cmds, (void *)pip));
5353 5459                          break;
5354 5460                  }
5355 5461          }
5356 5462          mutex_exit(&svp->svp_mutex);
5357 5463  
5358 5464          /*
5359 5465           * Check to see if this vlun has an active SCSI-II RESERVE. And this
5360 5466           * is the pip for the path that has been reserved.
5361 5467           * If so clear the reservation by sending a reset, so the host will not
5362 5468           * get a reservation conflict.  Reset the flag VLUN_RESERVE_ACTIVE_FLG
5363 5469           * for this lun.  Also a reset notify is sent to the target driver
5364 5470           * just in case the POR check condition is cleared by some other layer
5365 5471           * in the stack.
5366 5472           */
5367 5473          if (svp->svp_svl->svl_flags & VLUN_RESERVE_ACTIVE_FLG) {
5368 5474                  if (pip == svp->svp_svl->svl_resrv_pip) {
5369 5475                          if (vhci_recovery_reset(svp->svp_svl,
5370 5476                              &svp->svp_psd->sd_address, TRUE,
5371 5477                              VHCI_DEPTH_TARGET) == 0) {
5372 5478                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
5373 5479                                      "!vhci_pathinfo_offline (pip:%p):"
5374 5480                                      "reset failed, retrying\n", (void *)pip));
5375 5481                                  delay(1*drv_usectohz(1000000));
5376 5482                                  if (vhci_recovery_reset(svp->svp_svl,
5377 5483                                      &svp->svp_psd->sd_address, TRUE,
5378 5484                                      VHCI_DEPTH_TARGET) == 0) {
5379 5485                                          VHCI_DEBUG(1, (CE_NOTE, NULL,
5380 5486                                              "!vhci_pathinfo_offline "
5381 5487                                              "(pip:%p): reset failed, "
5382 5488                                              "giving up!\n", (void *)pip));
5383 5489                                  }
5384 5490                          }
5385 5491                          svp->svp_svl->svl_flags &= ~VLUN_RESERVE_ACTIVE_FLG;
5386 5492                  }
5387 5493          }
5388 5494  
5389 5495          mdi_pi_set_state(pip, MDI_PATHINFO_STATE_OFFLINE);
5390 5496          vhci_mpapi_set_path_state(vdip, pip, MP_DRVR_PATH_STATE_REMOVED);
5391 5497  
5392 5498          VHCI_DEBUG(1, (CE_NOTE, NULL,
5393 5499              "!vhci_pathinfo_offline: offlined path 0x%p\n", (void *)pip));
5394 5500          return (MDI_SUCCESS);
5395 5501  }
5396 5502  
5397 5503  
5398 5504  /*
5399 5505   * routine for SCSI VHCI IOCTL implementation.
5400 5506   */
5401 5507  /* ARGSUSED */
5402 5508  static int
5403 5509  vhci_ctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, int *rval)
5404 5510  {
5405 5511          struct scsi_vhci                *vhci;
5406 5512          dev_info_t                      *vdip;
5407 5513          mdi_pathinfo_t                  *pip;
5408 5514          int                             instance, held;
5409 5515          int                             retval = 0;
5410 5516          caddr_t                         phci_path = NULL, client_path = NULL;
5411 5517          caddr_t                         paddr = NULL;
5412 5518          sv_iocdata_t                    ioc;
5413 5519          sv_iocdata_t                    *pioc = &ioc;
5414 5520          sv_switch_to_cntlr_iocdata_t    iocsc;
5415 5521          sv_switch_to_cntlr_iocdata_t    *piocsc = &iocsc;
5416 5522          caddr_t                         s;
5417 5523          scsi_vhci_lun_t                 *vlun;
5418 5524          struct scsi_failover_ops        *fo;
5419 5525          char                            *pclass;
5420 5526  
5421 5527          /* Check for validity of vhci structure */
5422 5528          vhci = ddi_get_soft_state(vhci_softstate, MINOR2INST(getminor(dev)));
5423 5529          if (vhci == NULL) {
5424 5530                  return (ENXIO);
5425 5531          }
5426 5532  
5427 5533          mutex_enter(&vhci->vhci_mutex);
5428 5534          if ((vhci->vhci_state & VHCI_STATE_OPEN) == 0) {
5429 5535                  mutex_exit(&vhci->vhci_mutex);
5430 5536                  return (ENXIO);
5431 5537          }
5432 5538          mutex_exit(&vhci->vhci_mutex);
5433 5539  
5434 5540          /* Get the vhci dip */
5435 5541          vdip = vhci->vhci_dip;
5436 5542          ASSERT(vdip != NULL);
5437 5543          instance = ddi_get_instance(vdip);
5438 5544  
5439 5545          /* Allocate memory for getting parameters from userland */
5440 5546          phci_path       = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
5441 5547          client_path     = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
5442 5548          paddr           = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
5443 5549  
5444 5550          /*
5445 5551           * Set a local variable indicating the ioctl name. Used for
5446 5552           * printing debug strings.
5447 5553           */
5448 5554          switch (cmd) {
5449 5555          case SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO:
5450 5556                  s = "GET_CLIENT_MULTIPATH_INFO";
5451 5557                  break;
5452 5558  
5453 5559          case SCSI_VHCI_GET_PHCI_MULTIPATH_INFO:
5454 5560                  s = "GET_PHCI_MULTIPATH_INFO";
5455 5561                  break;
5456 5562  
5457 5563          case SCSI_VHCI_GET_CLIENT_NAME:
5458 5564                  s = "GET_CLIENT_NAME";
5459 5565                  break;
5460 5566  
5461 5567          case SCSI_VHCI_PATH_ONLINE:
5462 5568                  s = "PATH_ONLINE";
5463 5569                  break;
5464 5570  
5465 5571          case SCSI_VHCI_PATH_OFFLINE:
5466 5572                  s = "PATH_OFFLINE";
5467 5573                  break;
5468 5574  
5469 5575          case SCSI_VHCI_PATH_STANDBY:
5470 5576                  s = "PATH_STANDBY";
5471 5577                  break;
5472 5578  
5473 5579          case SCSI_VHCI_PATH_TEST:
5474 5580                  s = "PATH_TEST";
5475 5581                  break;
5476 5582  
5477 5583          case SCSI_VHCI_SWITCH_TO_CNTLR:
5478 5584                  s = "SWITCH_TO_CNTLR";
5479 5585                  break;
5480 5586          case SCSI_VHCI_PATH_DISABLE:
5481 5587                  s = "PATH_DISABLE";
5482 5588                  break;
5483 5589          case SCSI_VHCI_PATH_ENABLE:
5484 5590                  s = "PATH_ENABLE";
5485 5591                  break;
5486 5592  
5487 5593          case SCSI_VHCI_GET_TARGET_LONGNAME:
5488 5594                  s = "GET_TARGET_LONGNAME";
5489 5595                  break;
5490 5596  
5491 5597  #ifdef  DEBUG
5492 5598          case SCSI_VHCI_CONFIGURE_PHCI:
5493 5599                  s = "CONFIGURE_PHCI";
5494 5600                  break;
5495 5601  
5496 5602          case SCSI_VHCI_UNCONFIGURE_PHCI:
5497 5603                  s = "UNCONFIGURE_PHCI";
5498 5604                  break;
5499 5605  #endif
5500 5606  
5501 5607          default:
5502 5608                  s = "Unknown";
5503 5609                  vhci_log(CE_NOTE, vdip,
5504 5610                      "!vhci%d: ioctl %x (unsupported ioctl)", instance, cmd);
5505 5611                  retval = ENOTSUP;
5506 5612                  break;
5507 5613          }
5508 5614          if (retval != 0) {
5509 5615                  goto end;
5510 5616          }
5511 5617  
5512 5618          VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci%d: ioctl <%s>", instance, s));
5513 5619  
5514 5620          /*
5515 5621           * Get IOCTL parameters from userland
5516 5622           */
5517 5623          switch (cmd) {
5518 5624          case SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO:
5519 5625          case SCSI_VHCI_GET_PHCI_MULTIPATH_INFO:
5520 5626          case SCSI_VHCI_GET_CLIENT_NAME:
5521 5627          case SCSI_VHCI_PATH_ONLINE:
5522 5628          case SCSI_VHCI_PATH_OFFLINE:
5523 5629          case SCSI_VHCI_PATH_STANDBY:
5524 5630          case SCSI_VHCI_PATH_TEST:
5525 5631          case SCSI_VHCI_PATH_DISABLE:
5526 5632          case SCSI_VHCI_PATH_ENABLE:
5527 5633          case SCSI_VHCI_GET_TARGET_LONGNAME:
5528 5634  #ifdef  DEBUG
5529 5635          case SCSI_VHCI_CONFIGURE_PHCI:
5530 5636          case SCSI_VHCI_UNCONFIGURE_PHCI:
5531 5637  #endif
5532 5638                  retval = vhci_get_iocdata((const void *)data, pioc, mode, s);
5533 5639                  break;
5534 5640  
5535 5641          case SCSI_VHCI_SWITCH_TO_CNTLR:
5536 5642                  retval = vhci_get_iocswitchdata((const void *)data, piocsc,
5537 5643                      mode, s);
5538 5644                  break;
5539 5645          }
5540 5646          if (retval != 0) {
5541 5647                  goto end;
5542 5648          }
5543 5649  
5544 5650  
5545 5651          /*
5546 5652           * Process the IOCTL
5547 5653           */
5548 5654          switch (cmd) {
5549 5655          case SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO:
5550 5656          {
5551 5657                  uint_t          num_paths;      /* Num paths to client dev */
5552 5658                  sv_path_info_t  *upibuf = NULL; /* To keep userland values */
5553 5659                  sv_path_info_t  *kpibuf = NULL; /* Kernel data for ioctls */
5554 5660                  dev_info_t      *cdip;          /* Client device dip */
5555 5661  
5556 5662                  if (pioc->ret_elem == NULL) {
5557 5663                          retval = EINVAL;
5558 5664                          break;
5559 5665                  }
5560 5666  
5561 5667                  /* Get client device path from user land */
5562 5668                  if (vhci_ioc_get_client_path(pioc, client_path, mode, s)) {
5563 5669                          retval = EFAULT;
5564 5670                          break;
5565 5671                  }
5566 5672  
5567 5673                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5568 5674                      "client <%s>", s, client_path));
5569 5675  
5570 5676                  /* Get number of paths to this client device */
5571 5677                  if ((cdip = mdi_client_path2devinfo(vdip, client_path))
5572 5678                      == NULL) {
5573 5679                          retval = ENXIO;
5574 5680                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5575 5681                              "client dip doesn't exist. invalid path <%s>",
5576 5682                              s, client_path));
5577 5683                          break;
5578 5684                  }
5579 5685                  num_paths = mdi_client_get_path_count(cdip);
5580 5686  
5581 5687                  if (ddi_copyout(&num_paths, pioc->ret_elem,
5582 5688                      sizeof (num_paths), mode)) {
5583 5689                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5584 5690                              "num_paths copyout failed", s));
5585 5691                          retval = EFAULT;
5586 5692                          break;
5587 5693                  }
5588 5694  
5589 5695                  /* If  user just wanted num_paths, then return */
5590 5696                  if (pioc->buf_elem == 0 || pioc->ret_buf == NULL ||
5591 5697                      num_paths == 0) {
5592 5698                          break;
5593 5699                  }
5594 5700  
5595 5701                  /* Set num_paths to value as much as can be sent to userland */
5596 5702                  if (num_paths > pioc->buf_elem) {
5597 5703                          num_paths = pioc->buf_elem;
5598 5704                  }
5599 5705  
5600 5706                  /* Allocate memory and get userland pointers */
5601 5707                  if (vhci_ioc_alloc_pathinfo(&upibuf, &kpibuf, num_paths,
5602 5708                      pioc, mode, s) != 0) {
5603 5709                          retval = EFAULT;
5604 5710                          break;
5605 5711                  }
5606 5712                  ASSERT(upibuf != NULL);
5607 5713                  ASSERT(kpibuf != NULL);
5608 5714  
5609 5715                  /*
5610 5716                   * Get the path information and send it to userland.
5611 5717                   */
5612 5718                  if (vhci_get_client_path_list(cdip, kpibuf, num_paths)
5613 5719                      != MDI_SUCCESS) {
5614 5720                          retval = ENXIO;
5615 5721                          vhci_ioc_free_pathinfo(upibuf, kpibuf, num_paths);
5616 5722                          break;
5617 5723                  }
5618 5724  
5619 5725                  if (vhci_ioc_send_pathinfo(upibuf, kpibuf, num_paths,
5620 5726                      pioc, mode, s)) {
5621 5727                          retval = EFAULT;
5622 5728                          vhci_ioc_free_pathinfo(upibuf, kpibuf, num_paths);
5623 5729                          break;
5624 5730                  }
5625 5731  
5626 5732                  /* Free the memory allocated for path information */
5627 5733                  vhci_ioc_free_pathinfo(upibuf, kpibuf, num_paths);
5628 5734                  break;
5629 5735          }
5630 5736  
5631 5737          case SCSI_VHCI_GET_PHCI_MULTIPATH_INFO:
5632 5738          {
5633 5739                  uint_t          num_paths;      /* Num paths to client dev */
5634 5740                  sv_path_info_t  *upibuf = NULL; /* To keep userland values */
5635 5741                  sv_path_info_t  *kpibuf = NULL; /* Kernel data for ioctls */
5636 5742                  dev_info_t      *pdip;          /* PHCI device dip */
5637 5743  
5638 5744                  if (pioc->ret_elem == NULL) {
5639 5745                          retval = EINVAL;
5640 5746                          break;
5641 5747                  }
5642 5748  
5643 5749                  /* Get PHCI device path from user land */
5644 5750                  if (vhci_ioc_get_phci_path(pioc, phci_path, mode, s)) {
5645 5751                          retval = EFAULT;
5646 5752                          break;
5647 5753                  }
5648 5754  
5649 5755                  VHCI_DEBUG(6, (CE_WARN, vdip,
5650 5756                      "!vhci_ioctl: ioctl <%s> phci <%s>", s, phci_path));
5651 5757  
5652 5758                  /* Get number of devices associated with this PHCI device */
5653 5759                  if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
5654 5760                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5655 5761                              "phci dip doesn't exist. invalid path <%s>",
5656 5762                              s, phci_path));
5657 5763                          retval = ENXIO;
5658 5764                          break;
5659 5765                  }
5660 5766  
5661 5767                  num_paths = mdi_phci_get_path_count(pdip);
5662 5768  
5663 5769                  if (ddi_copyout(&num_paths, pioc->ret_elem,
5664 5770                      sizeof (num_paths), mode)) {
5665 5771                          VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5666 5772                              "num_paths copyout failed", s));
5667 5773                          retval = EFAULT;
5668 5774                          break;
5669 5775                  }
5670 5776  
5671 5777                  /* If  user just wanted num_paths, then return */
5672 5778                  if (pioc->buf_elem == 0 || pioc->ret_buf == NULL ||
5673 5779                      num_paths == 0) {
5674 5780                          break;
5675 5781                  }
5676 5782  
5677 5783                  /* Set num_paths to value as much as can be sent to userland */
5678 5784                  if (num_paths > pioc->buf_elem) {
5679 5785                          num_paths = pioc->buf_elem;
5680 5786                  }
5681 5787  
5682 5788                  /* Allocate memory and get userland pointers */
5683 5789                  if (vhci_ioc_alloc_pathinfo(&upibuf, &kpibuf, num_paths,
5684 5790                      pioc, mode, s) != 0) {
5685 5791                          retval = EFAULT;
5686 5792                          break;
5687 5793                  }
5688 5794                  ASSERT(upibuf != NULL);
5689 5795                  ASSERT(kpibuf != NULL);
5690 5796  
5691 5797                  /*
5692 5798                   * Get the path information and send it to userland.
5693 5799                   */
5694 5800                  if (vhci_get_phci_path_list(pdip, kpibuf, num_paths)
5695 5801                      != MDI_SUCCESS) {
5696 5802                          retval = ENXIO;
5697 5803                          vhci_ioc_free_pathinfo(upibuf, kpibuf, num_paths);
5698 5804                          break;
5699 5805                  }
5700 5806  
5701 5807                  if (vhci_ioc_send_pathinfo(upibuf, kpibuf, num_paths,
5702 5808                      pioc, mode, s)) {
5703 5809                          retval = EFAULT;
5704 5810                          vhci_ioc_free_pathinfo(upibuf, kpibuf, num_paths);
5705 5811                          break;
5706 5812                  }
5707 5813  
5708 5814                  /* Free the memory allocated for path information */
5709 5815                  vhci_ioc_free_pathinfo(upibuf, kpibuf, num_paths);
5710 5816                  break;
5711 5817          }
5712 5818  
5713 5819          case SCSI_VHCI_GET_CLIENT_NAME:
5714 5820          {
5715 5821                  dev_info_t              *cdip, *pdip;
5716 5822  
5717 5823                  /* Get PHCI path and device address from user land */
5718 5824                  if (vhci_ioc_get_phci_path(pioc, phci_path, mode, s) ||
5719 5825                      vhci_ioc_get_paddr(pioc, paddr, mode, s)) {
5720 5826                          retval = EFAULT;
5721 5827                          break;
5722 5828                  }
5723 5829  
5724 5830                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5725 5831                      "phci <%s>, paddr <%s>", s, phci_path, paddr));
5726 5832  
5727 5833                  /* Get the PHCI dip */
5728 5834                  if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
5729 5835                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5730 5836                              "phci dip doesn't exist. invalid path <%s>",
5731 5837                              s, phci_path));
5732 5838                          retval = ENXIO;
5733 5839                          break;
5734 5840                  }
5735 5841  
5736 5842                  if ((pip = mdi_pi_find(pdip, NULL, paddr)) == NULL) {
5737 5843                          VHCI_DEBUG(1, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5738 5844                              "pathinfo doesn't exist. invalid device addr", s));
5739 5845                          retval = ENXIO;
5740 5846                          break;
5741 5847                  }
5742 5848  
5743 5849                  /* Get the client device pathname and send to userland */
5744 5850                  cdip = mdi_pi_get_client(pip);
5745 5851                  vhci_ioc_devi_to_path(cdip, client_path);
5746 5852  
5747 5853                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5748 5854                      "client <%s>", s, client_path));
5749 5855  
5750 5856                  if (vhci_ioc_send_client_path(client_path, pioc, mode, s)) {
5751 5857                          retval = EFAULT;
5752 5858                          break;
5753 5859                  }
5754 5860                  break;
5755 5861          }
5756 5862  
5757 5863          case SCSI_VHCI_PATH_ONLINE:
5758 5864          case SCSI_VHCI_PATH_OFFLINE:
5759 5865          case SCSI_VHCI_PATH_STANDBY:
5760 5866          case SCSI_VHCI_PATH_TEST:
5761 5867          {
5762 5868                  dev_info_t              *pdip;  /* PHCI dip */
5763 5869  
5764 5870                  /* Get PHCI path and device address from user land */
5765 5871                  if (vhci_ioc_get_phci_path(pioc, phci_path, mode, s) ||
5766 5872                      vhci_ioc_get_paddr(pioc, paddr, mode, s)) {
5767 5873                          retval = EFAULT;
5768 5874                          break;
5769 5875                  }
5770 5876  
5771 5877                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5772 5878                      "phci <%s>, paddr <%s>", s, phci_path, paddr));
5773 5879  
5774 5880                  /* Get the PHCI dip */
5775 5881                  if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
5776 5882                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5777 5883                              "phci dip doesn't exist. invalid path <%s>",
5778 5884                              s, phci_path));
5779 5885                          retval = ENXIO;
5780 5886                          break;
5781 5887                  }
5782 5888  
5783 5889                  if ((pip = mdi_pi_find(pdip, NULL, paddr)) == NULL) {
5784 5890                          VHCI_DEBUG(1, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5785 5891                              "pathinfo doesn't exist. invalid device addr", s));
5786 5892                          retval = ENXIO;
5787 5893                          break;
5788 5894                  }
5789 5895  
5790 5896                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5791 5897                      "Calling MDI function to change device state", s));
5792 5898  
5793 5899                  switch (cmd) {
5794 5900                  case SCSI_VHCI_PATH_ONLINE:
5795 5901                          retval = mdi_pi_online(pip, 0);
5796 5902                          break;
5797 5903  
5798 5904                  case SCSI_VHCI_PATH_OFFLINE:
5799 5905                          retval = mdi_pi_offline(pip, 0);
5800 5906                          break;
5801 5907  
5802 5908                  case SCSI_VHCI_PATH_STANDBY:
5803 5909                          retval = mdi_pi_standby(pip, 0);
5804 5910                          break;
5805 5911  
5806 5912                  case SCSI_VHCI_PATH_TEST:
5807 5913                          break;
5808 5914                  }
5809 5915                  break;
5810 5916          }
5811 5917  
5812 5918          case SCSI_VHCI_SWITCH_TO_CNTLR:
5813 5919          {
5814 5920                  dev_info_t *cdip;
5815 5921                  struct scsi_device *devp;
5816 5922  
5817 5923                  /* Get the client device pathname */
5818 5924                  if (ddi_copyin(piocsc->client, client_path,
5819 5925                      MAXPATHLEN, mode)) {
5820 5926                          VHCI_DEBUG(2, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5821 5927                              "client_path copyin failed", s));
5822 5928                          retval = EFAULT;
5823 5929                          break;
5824 5930                  }
5825 5931  
5826 5932                  /* Get the path class to which user wants to switch */
5827 5933                  if (ddi_copyin(piocsc->class, paddr, MAXNAMELEN, mode)) {
5828 5934                          VHCI_DEBUG(2, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
5829 5935                              "controller_class copyin failed", s));
5830 5936                          retval = EFAULT;
5831 5937                          break;
5832 5938                  }
5833 5939  
5834 5940                  /* Perform validity checks */
5835 5941                  if ((cdip = mdi_client_path2devinfo(vdip,
5836 5942                      client_path)) == NULL) {
5837 5943                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5838 5944                              "client dip doesn't exist. invalid path <%s>",
5839 5945                              s, client_path));
5840 5946                          retval = ENXIO;
5841 5947                          break;
5842 5948                  }
5843 5949  
5844 5950                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: Calling MDI func "
5845 5951                      "to switch controller"));
5846 5952                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: client <%s> "
5847 5953                      "class <%s>", client_path, paddr));
5848 5954  
5849 5955                  if (strcmp(paddr, PCLASS_PRIMARY) &&
5850 5956                      strcmp(paddr, PCLASS_SECONDARY)) {
5851 5957                          VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5852 5958                              "invalid path class <%s>", s, paddr));
5853 5959                          retval = ENXIO;
5854 5960                          break;
5855 5961                  }
5856 5962  
5857 5963                  devp = ddi_get_driver_private(cdip);
5858 5964                  if (devp == NULL) {
5859 5965                          VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5860 5966                              "invalid scsi device <%s>", s, client_path));
5861 5967                          retval = ENXIO;
5862 5968                          break;
5863 5969                  }
5864 5970                  vlun = ADDR2VLUN(&devp->sd_address);
5865 5971                  ASSERT(vlun);
5866 5972  
5867 5973                  /*
5868 5974                   * Checking to see if device has only one pclass, PRIMARY.
5869 5975                   * If so this device doesn't support failovers.  Assumed
5870 5976                   * that the devices with one pclass is PRIMARY, as thats the
5871 5977                   * case today.  If this is not true and in future other
5872 5978                   * symmetric devices are supported with other pclass, this
5873 5979                   * IOCTL shall have to be overhauled anyways as now the only
5874 5980                   * arguments it accepts are PRIMARY and SECONDARY.
5875 5981                   */
5876 5982                  fo = vlun->svl_fops;
5877 5983                  if (fo->sfo_pathclass_next(PCLASS_PRIMARY, &pclass,
5878 5984                      vlun->svl_fops_ctpriv)) {
5879 5985                          retval = ENOTSUP;
5880 5986                          break;
5881 5987                  }
5882 5988  
5883 5989                  VHCI_HOLD_LUN(vlun, VH_SLEEP, held);
5884 5990                  mutex_enter(&vlun->svl_mutex);
5885 5991                  if (vlun->svl_active_pclass != NULL) {
5886 5992                          if (strcmp(vlun->svl_active_pclass, paddr) == 0) {
5887 5993                                  mutex_exit(&vlun->svl_mutex);
5888 5994                                  retval = EALREADY;
5889 5995                                  VHCI_RELEASE_LUN(vlun);
5890 5996                                  break;
5891 5997                          }
5892 5998                  }
5893 5999                  mutex_exit(&vlun->svl_mutex);
5894 6000                  /* Call mdi function to cause  a switch over */
5895 6001                  retval = mdi_failover(vdip, cdip, MDI_FAILOVER_SYNC);
5896 6002                  if (retval == MDI_SUCCESS) {
5897 6003                          retval = 0;
5898 6004                  } else if (retval == MDI_BUSY) {
5899 6005                          retval = EBUSY;
5900 6006                  } else {
5901 6007                          retval = EIO;
5902 6008                  }
5903 6009                  VHCI_RELEASE_LUN(vlun);
5904 6010                  break;
5905 6011          }
5906 6012  
5907 6013          case SCSI_VHCI_PATH_ENABLE:
5908 6014          case SCSI_VHCI_PATH_DISABLE:
5909 6015          {
5910 6016                  dev_info_t      *cdip, *pdip;
5911 6017  
5912 6018                  /*
5913 6019                   * Get client device path from user land
5914 6020                   */
5915 6021                  if (vhci_ioc_get_client_path(pioc, client_path, mode, s)) {
5916 6022                          retval = EFAULT;
5917 6023                          break;
5918 6024                  }
5919 6025  
5920 6026                  /*
5921 6027                   * Get Phci device path from user land
5922 6028                   */
5923 6029                  if (vhci_ioc_get_phci_path(pioc, phci_path, mode, s)) {
5924 6030                          retval = EFAULT;
5925 6031                          break;
5926 6032                  }
5927 6033  
5928 6034                  /*
5929 6035                   * Get the devinfo for the Phci.
5930 6036                   */
5931 6037                  if ((pdip = mdi_phci_path2devinfo(vdip, phci_path)) == NULL) {
5932 6038                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5933 6039                              "phci dip doesn't exist. invalid path <%s>",
5934 6040                              s, phci_path));
5935 6041                          retval = ENXIO;
5936 6042                          break;
5937 6043                  }
5938 6044  
5939 6045                  /*
5940 6046                   * If the client path is set to /scsi_vhci then we need
5941 6047                   * to do the operation on all the clients so set cdip to NULL.
5942 6048                   * Else, try to get the client dip.
5943 6049                   */
5944 6050                  if (strcmp(client_path, "/scsi_vhci") == 0) {
5945 6051                          cdip = NULL;
5946 6052                  } else {
5947 6053                          if ((cdip = mdi_client_path2devinfo(vdip,
5948 6054                              client_path)) == NULL) {
5949 6055                                  retval = ENXIO;
5950 6056                                  VHCI_DEBUG(1, (CE_WARN, NULL,
5951 6057                                      "!vhci_ioctl: ioctl <%s> client dip "
5952 6058                                      "doesn't exist. invalid path <%s>",
5953 6059                                      s, client_path));
5954 6060                                  break;
5955 6061                          }
5956 6062                  }
5957 6063  
5958 6064                  if (cmd == SCSI_VHCI_PATH_ENABLE)
5959 6065                          retval = mdi_pi_enable(cdip, pdip, USER_DISABLE);
5960 6066                  else
5961 6067                          retval = mdi_pi_disable(cdip, pdip, USER_DISABLE);
5962 6068  
5963 6069                  break;
5964 6070          }
5965 6071  
5966 6072          case SCSI_VHCI_GET_TARGET_LONGNAME:
5967 6073          {
5968 6074                  uint_t          pid = pioc->buf_elem;
5969 6075                  char            *target_port;
5970 6076                  mod_hash_val_t  hv;
5971 6077  
5972 6078                  /* targetmap lookup of 'target-port' by <pid> */
5973 6079                  if (mod_hash_find(vhci_targetmap_bypid,
5974 6080                      (mod_hash_key_t)(uintptr_t)pid, &hv) != 0) {
5975 6081                          /*
5976 6082                           * NOTE: failure to find the mapping is OK for guid
5977 6083                           * based 'target-port' values.
5978 6084                           */
5979 6085                          VHCI_DEBUG(3, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5980 6086                              "targetport mapping doesn't exist: pid %d",
5981 6087                              s, pid));
5982 6088                          retval = ENXIO;
5983 6089                          break;
5984 6090                  }
5985 6091  
5986 6092                  /* copyout 'target-port' result */
5987 6093                  target_port = (char *)hv;
5988 6094                  if (copyoutstr(target_port, pioc->addr, MAXNAMELEN, NULL)) {
5989 6095                          VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
5990 6096                              "targetport copyout failed: len: %d",
5991 6097                              s, (int)strlen(target_port)));
5992 6098                          retval = EFAULT;
5993 6099                  }
5994 6100                  break;
5995 6101          }
5996 6102  
5997 6103  #ifdef  DEBUG
5998 6104          case SCSI_VHCI_CONFIGURE_PHCI:
5999 6105          {
6000 6106                  dev_info_t              *pdip;
6001 6107  
6002 6108                  /* Get PHCI path and device address from user land */
6003 6109                  if (vhci_ioc_get_phci_path(pioc, phci_path, mode, s)) {
6004 6110                          retval = EFAULT;
6005 6111                          break;
6006 6112                  }
6007 6113  
6008 6114                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
6009 6115                      "phci <%s>", s, phci_path));
6010 6116  
6011 6117                  /* Get the PHCI dip */
6012 6118                  if ((pdip = e_ddi_hold_devi_by_path(phci_path, 0)) == NULL) {
6013 6119                          VHCI_DEBUG(3, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
6014 6120                              "phci dip doesn't exist. invalid path <%s>",
6015 6121                              s, phci_path));
6016 6122                          retval = ENXIO;
6017 6123                          break;
6018 6124                  }
6019 6125  
6020 6126                  if (ndi_devi_config(pdip,
6021 6127                      NDI_DEVFS_CLEAN|NDI_DEVI_PERSIST) != NDI_SUCCESS) {
6022 6128                          retval = EIO;
6023 6129                  }
6024 6130  
6025 6131                  ddi_release_devi(pdip);
6026 6132                  break;
6027 6133          }
6028 6134  
6029 6135          case SCSI_VHCI_UNCONFIGURE_PHCI:
6030 6136          {
6031 6137                  dev_info_t              *pdip;
6032 6138  
6033 6139                  /* Get PHCI path and device address from user land */
6034 6140                  if (vhci_ioc_get_phci_path(pioc, phci_path, mode, s)) {
6035 6141                          retval = EFAULT;
6036 6142                          break;
6037 6143                  }
6038 6144  
6039 6145                  VHCI_DEBUG(6, (CE_WARN, vdip, "!vhci_ioctl: ioctl <%s> "
6040 6146                      "phci <%s>", s, phci_path));
6041 6147  
6042 6148                  /* Get the PHCI dip */
6043 6149                  if ((pdip = e_ddi_hold_devi_by_path(phci_path, 0)) == NULL) {
6044 6150                          VHCI_DEBUG(3, (CE_WARN, NULL, "!vhci_ioctl: ioctl <%s> "
6045 6151                              "phci dip doesn't exist. invalid path <%s>",
6046 6152                              s, phci_path));
6047 6153                          retval = ENXIO;
6048 6154                          break;
6049 6155                  }
6050 6156  
6051 6157                  if (ndi_devi_unconfig(pdip,
6052 6158                      NDI_DEVI_REMOVE|NDI_DEVFS_CLEAN) != NDI_SUCCESS) {
6053 6159                          retval = EBUSY;
6054 6160                  }
6055 6161  
6056 6162                  ddi_release_devi(pdip);
6057 6163                  break;
6058 6164          }
6059 6165  #endif
6060 6166          }
6061 6167  
6062 6168  end:
6063 6169          /* Free the memory allocated above */
6064 6170          if (phci_path != NULL) {
6065 6171                  kmem_free(phci_path, MAXPATHLEN);
6066 6172          }
6067 6173          if (client_path != NULL) {
6068 6174                  kmem_free(client_path, MAXPATHLEN);
6069 6175          }
6070 6176          if (paddr != NULL) {
6071 6177                  kmem_free(paddr, MAXNAMELEN);
6072 6178          }
6073 6179          return (retval);
6074 6180  }
6075 6181  
6076 6182  /*
6077 6183   * devctl IOCTL support for client device DR
6078 6184   */
6079 6185  /* ARGSUSED */
6080 6186  int
6081 6187  vhci_devctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
6082 6188      int *rvalp)
6083 6189  {
6084 6190          dev_info_t *self;
6085 6191          dev_info_t *child;
6086 6192          scsi_hba_tran_t *hba;
6087 6193          struct devctl_iocdata *dcp;
6088 6194          struct scsi_vhci *vhci;
6089 6195          int rv = 0;
6090 6196          int retval = 0;
6091 6197          scsi_vhci_priv_t *svp;
6092 6198          mdi_pathinfo_t  *pip;
6093 6199  
6094 6200          if ((vhci = ddi_get_soft_state(vhci_softstate,
6095 6201              MINOR2INST(getminor(dev)))) == NULL)
6096 6202                  return (ENXIO);
6097 6203  
6098 6204          /*
6099 6205           * check if :devctl minor device has been opened
6100 6206           */
6101 6207          mutex_enter(&vhci->vhci_mutex);
6102 6208          if ((vhci->vhci_state & VHCI_STATE_OPEN) == 0) {
6103 6209                  mutex_exit(&vhci->vhci_mutex);
6104 6210                  return (ENXIO);
6105 6211          }
6106 6212          mutex_exit(&vhci->vhci_mutex);
6107 6213  
6108 6214          self = vhci->vhci_dip;
6109 6215          hba = ddi_get_driver_private(self);
6110 6216          if (hba == NULL)
6111 6217                  return (ENXIO);
6112 6218  
6113 6219          /*
6114 6220           * We can use the generic implementation for these ioctls
6115 6221           */
6116 6222          switch (cmd) {
6117 6223          case DEVCTL_DEVICE_GETSTATE:
6118 6224          case DEVCTL_DEVICE_ONLINE:
6119 6225          case DEVCTL_DEVICE_OFFLINE:
6120 6226          case DEVCTL_DEVICE_REMOVE:
6121 6227          case DEVCTL_BUS_GETSTATE:
6122 6228                  return (ndi_devctl_ioctl(self, cmd, arg, mode, 0));
6123 6229          }
6124 6230  
6125 6231          /*
6126 6232           * read devctl ioctl data
6127 6233           */
6128 6234          if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
6129 6235                  return (EFAULT);
6130 6236  
6131 6237          switch (cmd) {
6132 6238  
6133 6239          case DEVCTL_DEVICE_RESET:
6134 6240                  /*
6135 6241                   * lookup and hold child device
6136 6242                   */
6137 6243                  if ((child = ndi_devi_find(self, ndi_dc_getname(dcp),
6138 6244                      ndi_dc_getaddr(dcp))) == NULL) {
6139 6245                          rv = ENXIO;
6140 6246                          break;
6141 6247                  }
  
    | 
      ↓ open down ↓ | 
    906 lines elided | 
    
      ↑ open up ↑ | 
  
6142 6248                  retval = mdi_select_path(child, NULL,
6143 6249                      (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH),
6144 6250                      NULL, &pip);
6145 6251                  if ((retval != MDI_SUCCESS) || (pip == NULL)) {
6146 6252                          VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl:"
6147 6253                              "Unable to get a path, dip 0x%p", (void *)child));
6148 6254                          rv = ENXIO;
6149 6255                          break;
6150 6256                  }
6151 6257                  svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
6152      -                if (vhci_recovery_reset(svp->svp_svl,
6153      -                    &svp->svp_psd->sd_address, TRUE,
6154      -                    VHCI_DEPTH_TARGET) == 0) {
6155      -                        VHCI_DEBUG(1, (CE_NOTE, NULL,
6156      -                            "!vhci_ioctl(pip:%p): "
6157      -                            "reset failed\n", (void *)pip));
     6258 +
     6259 +                VHCI_DEBUG(2, (CE_NOTE, NULL,
     6260 +                    "!reset %s@%s on all available paths",
     6261 +                    ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)));
     6262 +
     6263 +                if (vhci_scsi_reset_all_paths(&svp->svp_psd->sd_address) != 0) {
     6264 +                        VHCI_DEBUG(2, (CE_WARN, NULL,
     6265 +                            "!vhci_ioctl(pip:%p): reset failed\n",
     6266 +                            (void *)pip));
6158 6267                          rv = ENXIO;
6159 6268                  }
6160 6269                  mdi_rele_path(pip);
6161 6270                  break;
6162 6271  
6163 6272          case DEVCTL_BUS_QUIESCE:
6164 6273          case DEVCTL_BUS_UNQUIESCE:
6165 6274          case DEVCTL_BUS_RESET:
6166 6275          case DEVCTL_BUS_RESETALL:
6167 6276  #ifdef  DEBUG
6168 6277          case DEVCTL_BUS_CONFIGURE:
6169 6278          case DEVCTL_BUS_UNCONFIGURE:
6170 6279  #endif
6171 6280                  rv = ENOTSUP;
6172 6281                  break;
6173 6282  
6174 6283          default:
6175 6284                  rv = ENOTTY;
6176 6285          } /* end of outer switch */
6177 6286  
6178 6287          ndi_dc_freehdl(dcp);
6179 6288          return (rv);
6180 6289  }
6181 6290  
6182 6291  /*
6183 6292   * Routine to get the PHCI pathname from ioctl structures in userland
6184 6293   */
6185 6294  /* ARGSUSED */
6186 6295  static int
6187 6296  vhci_ioc_get_phci_path(sv_iocdata_t *pioc, caddr_t phci_path,
6188 6297          int mode, caddr_t s)
6189 6298  {
6190 6299          int retval = 0;
6191 6300  
6192 6301          if (ddi_copyin(pioc->phci, phci_path, MAXPATHLEN, mode)) {
6193 6302                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioc_get_phci: ioctl <%s> "
6194 6303                      "phci_path copyin failed", s));
6195 6304                  retval = EFAULT;
6196 6305          }
6197 6306          return (retval);
6198 6307  
6199 6308  }
6200 6309  
6201 6310  
6202 6311  /*
6203 6312   * Routine to get the Client device pathname from ioctl structures in userland
6204 6313   */
6205 6314  /* ARGSUSED */
6206 6315  static int
6207 6316  vhci_ioc_get_client_path(sv_iocdata_t *pioc, caddr_t client_path,
6208 6317          int mode, caddr_t s)
6209 6318  {
6210 6319          int retval = 0;
6211 6320  
6212 6321          if (ddi_copyin(pioc->client, client_path, MAXPATHLEN, mode)) {
6213 6322                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioc_get_client: "
6214 6323                      "ioctl <%s> client_path copyin failed", s));
6215 6324                  retval = EFAULT;
6216 6325          }
6217 6326          return (retval);
6218 6327  }
6219 6328  
6220 6329  
6221 6330  /*
6222 6331   * Routine to get physical device address from ioctl structure in userland
6223 6332   */
6224 6333  /* ARGSUSED */
6225 6334  static int
6226 6335  vhci_ioc_get_paddr(sv_iocdata_t *pioc, caddr_t paddr, int mode, caddr_t s)
6227 6336  {
6228 6337          int retval = 0;
6229 6338  
6230 6339          if (ddi_copyin(pioc->addr, paddr, MAXNAMELEN, mode)) {
6231 6340                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioc_get_paddr: "
6232 6341                      "ioctl <%s> device addr copyin failed", s));
6233 6342                  retval = EFAULT;
6234 6343          }
6235 6344          return (retval);
6236 6345  }
6237 6346  
6238 6347  
6239 6348  /*
6240 6349   * Routine to send client device pathname to userland.
6241 6350   */
6242 6351  /* ARGSUSED */
6243 6352  static int
6244 6353  vhci_ioc_send_client_path(caddr_t client_path, sv_iocdata_t *pioc,
6245 6354          int mode, caddr_t s)
6246 6355  {
6247 6356          int retval = 0;
6248 6357  
6249 6358          if (ddi_copyout(client_path, pioc->client, MAXPATHLEN, mode)) {
6250 6359                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioc_send_client: "
6251 6360                      "ioctl <%s> client_path copyout failed", s));
6252 6361                  retval = EFAULT;
6253 6362          }
6254 6363          return (retval);
6255 6364  }
6256 6365  
6257 6366  
6258 6367  /*
6259 6368   * Routine to translated dev_info pointer (dip) to device pathname.
6260 6369   */
6261 6370  static void
6262 6371  vhci_ioc_devi_to_path(dev_info_t *dip, caddr_t path)
6263 6372  {
6264 6373          (void) ddi_pathname(dip, path);
6265 6374  }
6266 6375  
6267 6376  
6268 6377  /*
6269 6378   * vhci_get_phci_path_list:
6270 6379   *              get information about devices associated with a
6271 6380   *              given PHCI device.
6272 6381   *
6273 6382   * Return Values:
6274 6383   *              path information elements
6275 6384   */
6276 6385  int
6277 6386  vhci_get_phci_path_list(dev_info_t *pdip, sv_path_info_t *pibuf,
6278 6387          uint_t num_elems)
6279 6388  {
6280 6389          uint_t                  count, done;
6281 6390          mdi_pathinfo_t          *pip;
6282 6391          sv_path_info_t          *ret_pip;
6283 6392          int                     status;
6284 6393          size_t                  prop_size;
6285 6394          int                     circular;
6286 6395  
6287 6396          /*
6288 6397           * Get the PHCI structure and retrieve the path information
6289 6398           * from the GUID hash table.
6290 6399           */
6291 6400  
6292 6401          ret_pip = pibuf;
6293 6402          count = 0;
6294 6403  
6295 6404          ndi_devi_enter(pdip, &circular);
6296 6405  
6297 6406          done = (count >= num_elems);
6298 6407          pip = mdi_get_next_client_path(pdip, NULL);
6299 6408          while (pip && !done) {
6300 6409                  mdi_pi_lock(pip);
6301 6410                  (void) ddi_pathname(mdi_pi_get_phci(pip),
6302 6411                      ret_pip->device.ret_phci);
6303 6412                  (void) strcpy(ret_pip->ret_addr, mdi_pi_get_addr(pip));
6304 6413                  (void) mdi_pi_get_state2(pip, &ret_pip->ret_state,
6305 6414                      &ret_pip->ret_ext_state);
6306 6415  
6307 6416                  status = mdi_prop_size(pip, &prop_size);
6308 6417                  if (status == MDI_SUCCESS && ret_pip->ret_prop.ret_buf_size) {
6309 6418                          *ret_pip->ret_prop.ret_buf_size = (uint_t)prop_size;
6310 6419                  }
6311 6420  
6312 6421  #ifdef DEBUG
6313 6422                  if (status != MDI_SUCCESS) {
6314 6423                          VHCI_DEBUG(2, (CE_WARN, NULL,
6315 6424                              "!vhci_get_phci_path_list: "
6316 6425                              "phci <%s>, prop size failure 0x%x",
6317 6426                              ret_pip->device.ret_phci, status));
6318 6427                  }
6319 6428  #endif /* DEBUG */
6320 6429  
6321 6430  
6322 6431                  if (status == MDI_SUCCESS && ret_pip->ret_prop.buf &&
6323 6432                      prop_size && ret_pip->ret_prop.buf_size >= prop_size) {
6324 6433                          status = mdi_prop_pack(pip,
6325 6434                              &ret_pip->ret_prop.buf,
6326 6435                              ret_pip->ret_prop.buf_size);
6327 6436  
6328 6437  #ifdef DEBUG
6329 6438                          if (status != MDI_SUCCESS) {
6330 6439                                  VHCI_DEBUG(2, (CE_WARN, NULL,
6331 6440                                      "!vhci_get_phci_path_list: "
6332 6441                                      "phci <%s>, prop pack failure 0x%x",
6333 6442                                      ret_pip->device.ret_phci, status));
6334 6443                          }
6335 6444  #endif /* DEBUG */
6336 6445                  }
6337 6446  
6338 6447                  mdi_pi_unlock(pip);
6339 6448                  pip = mdi_get_next_client_path(pdip, pip);
6340 6449                  ret_pip++;
6341 6450                  count++;
6342 6451                  done = (count >= num_elems);
6343 6452          }
6344 6453  
6345 6454          ndi_devi_exit(pdip, circular);
6346 6455  
6347 6456          return (MDI_SUCCESS);
6348 6457  }
6349 6458  
6350 6459  
6351 6460  /*
6352 6461   * vhci_get_client_path_list:
6353 6462   *              get information about various paths associated with a
6354 6463   *              given client device.
6355 6464   *
6356 6465   * Return Values:
6357 6466   *              path information elements
6358 6467   */
6359 6468  int
6360 6469  vhci_get_client_path_list(dev_info_t *cdip, sv_path_info_t *pibuf,
6361 6470          uint_t num_elems)
6362 6471  {
6363 6472          uint_t                  count, done;
6364 6473          mdi_pathinfo_t          *pip;
6365 6474          sv_path_info_t          *ret_pip;
6366 6475          int                     status;
6367 6476          size_t                  prop_size;
6368 6477          int                     circular;
6369 6478  
6370 6479          ret_pip = pibuf;
6371 6480          count = 0;
6372 6481  
6373 6482          ndi_devi_enter(cdip, &circular);
6374 6483  
6375 6484          done = (count >= num_elems);
6376 6485          pip = mdi_get_next_phci_path(cdip, NULL);
6377 6486          while (pip && !done) {
6378 6487                  mdi_pi_lock(pip);
6379 6488                  (void) ddi_pathname(mdi_pi_get_phci(pip),
6380 6489                      ret_pip->device.ret_phci);
6381 6490                  (void) strcpy(ret_pip->ret_addr, mdi_pi_get_addr(pip));
6382 6491                  (void) mdi_pi_get_state2(pip, &ret_pip->ret_state,
6383 6492                      &ret_pip->ret_ext_state);
6384 6493  
6385 6494                  status = mdi_prop_size(pip, &prop_size);
6386 6495                  if (status == MDI_SUCCESS && ret_pip->ret_prop.ret_buf_size) {
6387 6496                          *ret_pip->ret_prop.ret_buf_size = (uint_t)prop_size;
6388 6497                  }
6389 6498  
6390 6499  #ifdef DEBUG
6391 6500                  if (status != MDI_SUCCESS) {
6392 6501                          VHCI_DEBUG(2, (CE_WARN, NULL,
6393 6502                              "!vhci_get_client_path_list: "
6394 6503                              "phci <%s>, prop size failure 0x%x",
6395 6504                              ret_pip->device.ret_phci, status));
6396 6505                  }
6397 6506  #endif /* DEBUG */
6398 6507  
6399 6508  
6400 6509                  if (status == MDI_SUCCESS && ret_pip->ret_prop.buf &&
6401 6510                      prop_size && ret_pip->ret_prop.buf_size >= prop_size) {
6402 6511                          status = mdi_prop_pack(pip,
6403 6512                              &ret_pip->ret_prop.buf,
6404 6513                              ret_pip->ret_prop.buf_size);
6405 6514  
6406 6515  #ifdef DEBUG
6407 6516                          if (status != MDI_SUCCESS) {
6408 6517                                  VHCI_DEBUG(2, (CE_WARN, NULL,
6409 6518                                      "!vhci_get_client_path_list: "
6410 6519                                      "phci <%s>, prop pack failure 0x%x",
6411 6520                                      ret_pip->device.ret_phci, status));
6412 6521                          }
6413 6522  #endif /* DEBUG */
6414 6523                  }
6415 6524  
6416 6525                  mdi_pi_unlock(pip);
6417 6526                  pip = mdi_get_next_phci_path(cdip, pip);
6418 6527                  ret_pip++;
6419 6528                  count++;
6420 6529                  done = (count >= num_elems);
6421 6530          }
6422 6531  
6423 6532          ndi_devi_exit(cdip, circular);
6424 6533  
6425 6534          return (MDI_SUCCESS);
6426 6535  }
6427 6536  
6428 6537  
6429 6538  /*
6430 6539   * Routine to get ioctl argument structure from userland.
6431 6540   */
6432 6541  /* ARGSUSED */
6433 6542  static int
6434 6543  vhci_get_iocdata(const void *data, sv_iocdata_t *pioc, int mode, caddr_t s)
6435 6544  {
6436 6545          int     retval = 0;
6437 6546  
6438 6547  #ifdef  _MULTI_DATAMODEL
6439 6548          switch (ddi_model_convert_from(mode & FMODELS)) {
6440 6549          case DDI_MODEL_ILP32:
6441 6550          {
6442 6551                  sv_iocdata32_t  ioc32;
6443 6552  
6444 6553                  if (ddi_copyin(data, &ioc32, sizeof (ioc32), mode)) {
6445 6554                          retval = EFAULT;
6446 6555                          break;
6447 6556                  }
6448 6557                  pioc->client    = (caddr_t)(uintptr_t)ioc32.client;
6449 6558                  pioc->phci      = (caddr_t)(uintptr_t)ioc32.phci;
6450 6559                  pioc->addr      = (caddr_t)(uintptr_t)ioc32.addr;
6451 6560                  pioc->buf_elem  = (uint_t)ioc32.buf_elem;
6452 6561                  pioc->ret_buf   = (sv_path_info_t *)(uintptr_t)ioc32.ret_buf;
6453 6562                  pioc->ret_elem  = (uint_t *)(uintptr_t)ioc32.ret_elem;
6454 6563                  break;
6455 6564          }
6456 6565  
6457 6566          case DDI_MODEL_NONE:
6458 6567                  if (ddi_copyin(data, pioc, sizeof (*pioc), mode)) {
6459 6568                          retval = EFAULT;
6460 6569                          break;
6461 6570                  }
6462 6571                  break;
6463 6572          }
6464 6573  #else   /* _MULTI_DATAMODEL */
6465 6574          if (ddi_copyin(data, pioc, sizeof (*pioc), mode)) {
6466 6575                  retval = EFAULT;
6467 6576          }
6468 6577  #endif  /* _MULTI_DATAMODEL */
6469 6578  
6470 6579  #ifdef DEBUG
6471 6580          if (retval) {
6472 6581                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: cmd <%s> "
6473 6582                      "iocdata copyin failed", s));
6474 6583          }
6475 6584  #endif
6476 6585  
6477 6586          return (retval);
6478 6587  }
6479 6588  
6480 6589  
6481 6590  /*
6482 6591   * Routine to get the ioctl argument for ioctl causing controller switchover.
6483 6592   */
6484 6593  /* ARGSUSED */
6485 6594  static int
6486 6595  vhci_get_iocswitchdata(const void *data, sv_switch_to_cntlr_iocdata_t *piocsc,
6487 6596      int mode, caddr_t s)
6488 6597  {
6489 6598          int     retval = 0;
6490 6599  
6491 6600  #ifdef  _MULTI_DATAMODEL
6492 6601          switch (ddi_model_convert_from(mode & FMODELS)) {
6493 6602          case DDI_MODEL_ILP32:
6494 6603          {
6495 6604                  sv_switch_to_cntlr_iocdata32_t  ioc32;
6496 6605  
6497 6606                  if (ddi_copyin(data, &ioc32, sizeof (ioc32), mode)) {
6498 6607                          retval = EFAULT;
6499 6608                          break;
6500 6609                  }
6501 6610                  piocsc->client  = (caddr_t)(uintptr_t)ioc32.client;
6502 6611                  piocsc->class   = (caddr_t)(uintptr_t)ioc32.class;
6503 6612                  break;
6504 6613          }
6505 6614  
6506 6615          case DDI_MODEL_NONE:
6507 6616                  if (ddi_copyin(data, piocsc, sizeof (*piocsc), mode)) {
6508 6617                          retval = EFAULT;
6509 6618                  }
6510 6619                  break;
6511 6620          }
6512 6621  #else   /* _MULTI_DATAMODEL */
6513 6622          if (ddi_copyin(data, piocsc, sizeof (*piocsc), mode)) {
6514 6623                  retval = EFAULT;
6515 6624          }
6516 6625  #endif  /* _MULTI_DATAMODEL */
6517 6626  
6518 6627  #ifdef DEBUG
6519 6628          if (retval) {
6520 6629                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: cmd <%s> "
6521 6630                      "switch_to_cntlr_iocdata copyin failed", s));
6522 6631          }
6523 6632  #endif
6524 6633  
6525 6634          return (retval);
6526 6635  }
6527 6636  
6528 6637  
6529 6638  /*
6530 6639   * Routine to allocate memory for the path information structures.
6531 6640   * It allocates two chunks of memory - one for keeping userland
6532 6641   * pointers/values for path information and path properties, second for
6533 6642   * keeping allocating kernel memory for path properties. These path
6534 6643   * properties are finally copied to userland.
6535 6644   */
6536 6645  /* ARGSUSED */
6537 6646  static int
6538 6647  vhci_ioc_alloc_pathinfo(sv_path_info_t **upibuf, sv_path_info_t **kpibuf,
6539 6648      uint_t num_paths, sv_iocdata_t *pioc, int mode, caddr_t s)
6540 6649  {
6541 6650          sv_path_info_t  *pi;
6542 6651          uint_t          bufsize;
6543 6652          int             retval = 0;
6544 6653          int             index;
6545 6654  
6546 6655          /* Allocate memory */
6547 6656          *upibuf = (sv_path_info_t *)
6548 6657              kmem_zalloc(sizeof (sv_path_info_t) * num_paths, KM_SLEEP);
6549 6658          ASSERT(*upibuf != NULL);
6550 6659          *kpibuf = (sv_path_info_t *)
6551 6660              kmem_zalloc(sizeof (sv_path_info_t) * num_paths, KM_SLEEP);
6552 6661          ASSERT(*kpibuf != NULL);
6553 6662  
6554 6663          /*
6555 6664           * Get the path info structure from the user space.
6556 6665           * We are interested in the following fields:
6557 6666           *      - user size of buffer for per path properties.
6558 6667           *      - user address of buffer for path info properties.
6559 6668           *      - user pointer for returning actual buffer size
6560 6669           * Keep these fields in the 'upibuf' structures.
6561 6670           * Allocate buffer for per path info properties in kernel
6562 6671           * structure ('kpibuf').
6563 6672           * Size of these buffers will be equal to the size of buffers
6564 6673           * in the user space.
6565 6674           */
6566 6675  #ifdef  _MULTI_DATAMODEL
6567 6676          switch (ddi_model_convert_from(mode & FMODELS)) {
6568 6677          case DDI_MODEL_ILP32:
6569 6678          {
6570 6679                  sv_path_info32_t        *src;
6571 6680                  sv_path_info32_t        pi32;
6572 6681  
6573 6682                  src  = (sv_path_info32_t *)pioc->ret_buf;
6574 6683                  pi = (sv_path_info_t *)*upibuf;
6575 6684                  for (index = 0; index < num_paths; index++, src++, pi++) {
6576 6685                          if (ddi_copyin(src, &pi32, sizeof (pi32), mode)) {
6577 6686                                  retval = EFAULT;
6578 6687                                  break;
6579 6688                          }
6580 6689  
6581 6690                          pi->ret_prop.buf_size   =
6582 6691                              (uint_t)pi32.ret_prop.buf_size;
6583 6692                          pi->ret_prop.ret_buf_size =
6584 6693                              (uint_t *)(uintptr_t)pi32.ret_prop.ret_buf_size;
6585 6694                          pi->ret_prop.buf        =
6586 6695                              (caddr_t)(uintptr_t)pi32.ret_prop.buf;
6587 6696                  }
6588 6697                  break;
6589 6698          }
6590 6699  
6591 6700          case DDI_MODEL_NONE:
6592 6701                  if (ddi_copyin(pioc->ret_buf, *upibuf,
6593 6702                      sizeof (sv_path_info_t) * num_paths, mode)) {
6594 6703                          retval = EFAULT;
6595 6704                  }
6596 6705                  break;
6597 6706          }
6598 6707  #else   /* _MULTI_DATAMODEL */
6599 6708          if (ddi_copyin(pioc->ret_buf, *upibuf,
6600 6709              sizeof (sv_path_info_t) * num_paths, mode)) {
6601 6710                  retval = EFAULT;
6602 6711          }
6603 6712  #endif  /* _MULTI_DATAMODEL */
6604 6713  
6605 6714          if (retval != 0) {
6606 6715                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_alloc_path_info: "
6607 6716                      "ioctl <%s> normal: path_info copyin failed", s));
6608 6717                  kmem_free(*upibuf, sizeof (sv_path_info_t) * num_paths);
6609 6718                  kmem_free(*kpibuf, sizeof (sv_path_info_t) * num_paths);
6610 6719                  *upibuf = NULL;
6611 6720                  *kpibuf = NULL;
6612 6721                  return (retval);
6613 6722          }
6614 6723  
6615 6724          /*
6616 6725           * Allocate memory for per path properties.
6617 6726           */
6618 6727          for (index = 0, pi = *kpibuf; index < num_paths; index++, pi++) {
6619 6728                  bufsize = (*upibuf)[index].ret_prop.buf_size;
6620 6729  
6621 6730                  if (bufsize && bufsize <= SV_PROP_MAX_BUF_SIZE) {
6622 6731                          pi->ret_prop.buf_size = bufsize;
6623 6732                          pi->ret_prop.buf = (caddr_t)
6624 6733                              kmem_zalloc(bufsize, KM_SLEEP);
6625 6734                          ASSERT(pi->ret_prop.buf != NULL);
6626 6735                  } else {
6627 6736                          pi->ret_prop.buf_size = 0;
6628 6737                          pi->ret_prop.buf = NULL;
6629 6738                  }
6630 6739  
6631 6740                  if ((*upibuf)[index].ret_prop.ret_buf_size != NULL) {
6632 6741                          pi->ret_prop.ret_buf_size = (uint_t *)kmem_zalloc(
6633 6742                              sizeof (*pi->ret_prop.ret_buf_size), KM_SLEEP);
6634 6743                          ASSERT(pi->ret_prop.ret_buf_size != NULL);
6635 6744                  } else {
6636 6745                          pi->ret_prop.ret_buf_size = NULL;
6637 6746                  }
6638 6747          }
6639 6748  
6640 6749          return (0);
6641 6750  }
6642 6751  
6643 6752  
6644 6753  /*
6645 6754   * Routine to free memory for the path information structures.
6646 6755   * This is the memory which was allocated earlier.
6647 6756   */
6648 6757  /* ARGSUSED */
6649 6758  static void
6650 6759  vhci_ioc_free_pathinfo(sv_path_info_t *upibuf, sv_path_info_t *kpibuf,
6651 6760      uint_t num_paths)
6652 6761  {
6653 6762          sv_path_info_t  *pi;
6654 6763          int             index;
6655 6764  
6656 6765          /* Free memory for per path properties */
6657 6766          for (index = 0, pi = kpibuf; index < num_paths; index++, pi++) {
6658 6767                  if (pi->ret_prop.ret_buf_size != NULL) {
6659 6768                          kmem_free(pi->ret_prop.ret_buf_size,
6660 6769                              sizeof (*pi->ret_prop.ret_buf_size));
6661 6770                  }
6662 6771  
6663 6772                  if (pi->ret_prop.buf != NULL) {
6664 6773                          kmem_free(pi->ret_prop.buf, pi->ret_prop.buf_size);
6665 6774                  }
6666 6775          }
6667 6776  
6668 6777          /* Free memory for path info structures */
6669 6778          kmem_free(upibuf, sizeof (sv_path_info_t) * num_paths);
6670 6779          kmem_free(kpibuf, sizeof (sv_path_info_t) * num_paths);
6671 6780  }
6672 6781  
6673 6782  
6674 6783  /*
6675 6784   * Routine to copy path information and path properties to userland.
6676 6785   */
6677 6786  /* ARGSUSED */
6678 6787  static int
6679 6788  vhci_ioc_send_pathinfo(sv_path_info_t *upibuf, sv_path_info_t *kpibuf,
6680 6789      uint_t num_paths, sv_iocdata_t *pioc, int mode, caddr_t s)
6681 6790  {
6682 6791          int                     retval = 0, index;
6683 6792          sv_path_info_t          *upi_ptr;
6684 6793          sv_path_info32_t        *upi32_ptr;
6685 6794  
6686 6795  #ifdef  _MULTI_DATAMODEL
6687 6796          switch (ddi_model_convert_from(mode & FMODELS)) {
6688 6797          case DDI_MODEL_ILP32:
6689 6798                  goto copy_32bit;
6690 6799  
6691 6800          case DDI_MODEL_NONE:
6692 6801                  goto copy_normal;
6693 6802          }
6694 6803  #else   /* _MULTI_DATAMODEL */
6695 6804  
6696 6805          goto copy_normal;
6697 6806  
6698 6807  #endif  /* _MULTI_DATAMODEL */
6699 6808  
6700 6809  copy_normal:
6701 6810  
6702 6811          /*
6703 6812           * Copy path information and path properties to user land.
6704 6813           * Pointer fields inside the path property structure were
6705 6814           * saved in the 'upibuf' structure earlier.
6706 6815           */
6707 6816          upi_ptr = pioc->ret_buf;
6708 6817          for (index = 0; index < num_paths; index++) {
6709 6818                  if (ddi_copyout(kpibuf[index].device.ret_ct,
6710 6819                      upi_ptr[index].device.ret_ct, MAXPATHLEN, mode)) {
6711 6820                          retval = EFAULT;
6712 6821                          break;
6713 6822                  }
6714 6823  
6715 6824                  if (ddi_copyout(kpibuf[index].ret_addr,
6716 6825                      upi_ptr[index].ret_addr, MAXNAMELEN, mode)) {
6717 6826                          retval = EFAULT;
6718 6827                          break;
6719 6828                  }
6720 6829  
6721 6830                  if (ddi_copyout(&kpibuf[index].ret_state,
6722 6831                      &upi_ptr[index].ret_state, sizeof (kpibuf[index].ret_state),
6723 6832                      mode)) {
6724 6833                          retval = EFAULT;
6725 6834                          break;
6726 6835                  }
6727 6836  
6728 6837                  if (ddi_copyout(&kpibuf[index].ret_ext_state,
6729 6838                      &upi_ptr[index].ret_ext_state,
6730 6839                      sizeof (kpibuf[index].ret_ext_state), mode)) {
6731 6840                          retval = EFAULT;
6732 6841                          break;
6733 6842                  }
6734 6843  
6735 6844                  if ((kpibuf[index].ret_prop.ret_buf_size != NULL) &&
6736 6845                      ddi_copyout(kpibuf[index].ret_prop.ret_buf_size,
6737 6846                      upibuf[index].ret_prop.ret_buf_size,
6738 6847                      sizeof (*upibuf[index].ret_prop.ret_buf_size), mode)) {
6739 6848                          retval = EFAULT;
6740 6849                          break;
6741 6850                  }
6742 6851  
6743 6852                  if ((kpibuf[index].ret_prop.buf != NULL) &&
6744 6853                      ddi_copyout(kpibuf[index].ret_prop.buf,
6745 6854                      upibuf[index].ret_prop.buf,
6746 6855                      upibuf[index].ret_prop.buf_size, mode)) {
6747 6856                          retval = EFAULT;
6748 6857                          break;
6749 6858                  }
6750 6859          }
6751 6860  
6752 6861  #ifdef DEBUG
6753 6862          if (retval) {
6754 6863                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: ioctl <%s> "
6755 6864                      "normal: path_info copyout failed", s));
6756 6865          }
6757 6866  #endif
6758 6867  
6759 6868          return (retval);
6760 6869  
6761 6870  copy_32bit:
6762 6871          /*
6763 6872           * Copy path information and path properties to user land.
6764 6873           * Pointer fields inside the path property structure were
6765 6874           * saved in the 'upibuf' structure earlier.
6766 6875           */
6767 6876          upi32_ptr = (sv_path_info32_t *)pioc->ret_buf;
6768 6877          for (index = 0; index < num_paths; index++) {
6769 6878                  if (ddi_copyout(kpibuf[index].device.ret_ct,
6770 6879                      upi32_ptr[index].device.ret_ct, MAXPATHLEN, mode)) {
6771 6880                          retval = EFAULT;
6772 6881                          break;
6773 6882                  }
6774 6883  
6775 6884                  if (ddi_copyout(kpibuf[index].ret_addr,
6776 6885                      upi32_ptr[index].ret_addr, MAXNAMELEN, mode)) {
6777 6886                          retval = EFAULT;
6778 6887                          break;
6779 6888                  }
6780 6889  
6781 6890                  if (ddi_copyout(&kpibuf[index].ret_state,
6782 6891                      &upi32_ptr[index].ret_state,
6783 6892                      sizeof (kpibuf[index].ret_state), mode)) {
6784 6893                          retval = EFAULT;
6785 6894                          break;
6786 6895                  }
6787 6896  
6788 6897                  if (ddi_copyout(&kpibuf[index].ret_ext_state,
6789 6898                      &upi32_ptr[index].ret_ext_state,
6790 6899                      sizeof (kpibuf[index].ret_ext_state), mode)) {
6791 6900                          retval = EFAULT;
6792 6901                          break;
6793 6902                  }
6794 6903                  if ((kpibuf[index].ret_prop.ret_buf_size != NULL) &&
6795 6904                      ddi_copyout(kpibuf[index].ret_prop.ret_buf_size,
6796 6905                      upibuf[index].ret_prop.ret_buf_size,
6797 6906                      sizeof (*upibuf[index].ret_prop.ret_buf_size), mode)) {
6798 6907                          retval = EFAULT;
6799 6908                          break;
6800 6909                  }
6801 6910  
6802 6911                  if ((kpibuf[index].ret_prop.buf != NULL) &&
6803 6912                      ddi_copyout(kpibuf[index].ret_prop.buf,
6804 6913                      upibuf[index].ret_prop.buf,
6805 6914                      upibuf[index].ret_prop.buf_size, mode)) {
6806 6915                          retval = EFAULT;
6807 6916                          break;
6808 6917                  }
6809 6918          }
6810 6919  
6811 6920  #ifdef DEBUG
6812 6921          if (retval) {
6813 6922                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_get_ioc: ioctl <%s> "
6814 6923                      "normal: path_info copyout failed", s));
6815 6924          }
6816 6925  #endif
6817 6926  
6818 6927          return (retval);
6819 6928  }
6820 6929  
6821 6930  
6822 6931  /*
6823 6932   * vhci_failover()
6824 6933   * This routine expects VHCI_HOLD_LUN before being invoked.  It can be invoked
6825 6934   * as MDI_FAILOVER_ASYNC or MDI_FAILOVER_SYNC.  For Asynchronous failovers
6826 6935   * this routine shall VHCI_RELEASE_LUN on exiting.  For synchronous failovers
6827 6936   * it is the callers responsibility to release lun.
6828 6937   */
6829 6938  
6830 6939  /* ARGSUSED */
6831 6940  static int
6832 6941  vhci_failover(dev_info_t *vdip, dev_info_t *cdip, int flags)
6833 6942  {
6834 6943          char                    *guid;
6835 6944          scsi_vhci_lun_t         *vlun = NULL;
6836 6945          struct scsi_vhci        *vhci;
6837 6946          mdi_pathinfo_t          *pip, *npip;
6838 6947          char                    *s_pclass, *pclass1, *pclass2, *pclass;
6839 6948          char                    active_pclass_copy[255], *active_pclass_ptr;
6840 6949          char                    *ptr1, *ptr2;
6841 6950          mdi_pathinfo_state_t    pi_state;
6842 6951          uint32_t                pi_ext_state;
6843 6952          scsi_vhci_priv_t        *svp;
6844 6953          struct scsi_device      *sd;
6845 6954          struct scsi_failover_ops        *sfo;
6846 6955          int                     sps; /* mdi_select_path() status */
6847 6956          int                     activation_done = 0;
6848 6957          int                     rval, retval = MDI_FAILURE;
6849 6958          int                     reserve_pending, check_condition, UA_condition;
6850 6959          struct scsi_pkt         *pkt;
6851 6960          struct buf              *bp;
6852 6961  
6853 6962          vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
6854 6963          sd = ddi_get_driver_private(cdip);
6855 6964          vlun = ADDR2VLUN(&sd->sd_address);
6856 6965          ASSERT(vlun != 0);
6857 6966          ASSERT(VHCI_LUN_IS_HELD(vlun));
6858 6967          guid = vlun->svl_lun_wwn;
6859 6968          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(1): guid %s\n", guid));
6860 6969          vhci_log(CE_NOTE, vdip, "!Initiating failover for device %s "
6861 6970              "(GUID %s)", ddi_node_name(cdip), guid);
6862 6971  
6863 6972          /*
6864 6973           * Lets maintain a local copy of the vlun->svl_active_pclass
6865 6974           * for the rest of the processing. Accessing the field
6866 6975           * directly in the loop below causes loop logic to break
6867 6976           * especially when the field gets updated by other threads
6868 6977           * update path status etc and causes 'paths are not currently
6869 6978           * available' condition to be declared prematurely.
6870 6979           */
6871 6980          mutex_enter(&vlun->svl_mutex);
6872 6981          if (vlun->svl_active_pclass != NULL) {
6873 6982                  (void) strlcpy(active_pclass_copy, vlun->svl_active_pclass,
6874 6983                      sizeof (active_pclass_copy));
6875 6984                  active_pclass_ptr = &active_pclass_copy[0];
6876 6985                  mutex_exit(&vlun->svl_mutex);
6877 6986                  if (vhci_quiesce_paths(vdip, cdip, vlun, guid,
6878 6987                      active_pclass_ptr) != 0) {
6879 6988                          retval = MDI_FAILURE;
6880 6989                  }
6881 6990          } else {
6882 6991                  /*
6883 6992                   * can happen only when the available path to device
6884 6993                   * discovered is a STANDBY path.
6885 6994                   */
6886 6995                  mutex_exit(&vlun->svl_mutex);
6887 6996                  active_pclass_copy[0] = '\0';
6888 6997                  active_pclass_ptr = NULL;
6889 6998          }
6890 6999  
6891 7000          sfo = vlun->svl_fops;
6892 7001          ASSERT(sfo != NULL);
6893 7002          pclass1 = s_pclass = active_pclass_ptr;
6894 7003          VHCI_DEBUG(1, (CE_NOTE, NULL, "!(%s)failing over from %s\n", guid,
6895 7004              (s_pclass == NULL ? "<none>" : s_pclass)));
6896 7005  
6897 7006  next_pathclass:
6898 7007  
6899 7008          rval = sfo->sfo_pathclass_next(pclass1, &pclass2,
6900 7009              vlun->svl_fops_ctpriv);
6901 7010          if (rval == ENOENT) {
6902 7011                  if (s_pclass == NULL) {
6903 7012                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(4)(%s): "
6904 7013                              "failed, no more pathclasses\n", guid));
6905 7014                          goto done;
6906 7015                  } else {
6907 7016                          (void) sfo->sfo_pathclass_next(NULL, &pclass2,
6908 7017                              vlun->svl_fops_ctpriv);
6909 7018                  }
6910 7019          } else if (rval == EINVAL) {
6911 7020                  vhci_log(CE_NOTE, vdip, "!Failover operation failed for "
6912 7021                      "device %s (GUID %s): Invalid path-class %s",
6913 7022                      ddi_node_name(cdip), guid,
6914 7023                      ((pclass1 == NULL) ? "<none>" : pclass1));
6915 7024                  goto done;
6916 7025          }
6917 7026          if ((s_pclass != NULL) && (strcmp(pclass2, s_pclass) == 0)) {
6918 7027                  /*
6919 7028                   * paths are not currently available
6920 7029                   */
6921 7030                  vhci_log(CE_NOTE, vdip, "!Failover path currently unavailable"
6922 7031                      " for device %s (GUID %s)",
6923 7032                      ddi_node_name(cdip), guid);
6924 7033                  goto done;
6925 7034          }
6926 7035          pip = npip = NULL;
6927 7036          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(5.2)(%s): considering "
6928 7037              "%s as failover destination\n", guid, pclass2));
6929 7038          sps = mdi_select_path(cdip, NULL, MDI_SELECT_STANDBY_PATH, NULL, &npip);
6930 7039          if ((npip == NULL) || (sps != MDI_SUCCESS)) {
6931 7040                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(%s): no "
6932 7041                      "STANDBY paths found (status:%x)!\n", guid, sps));
6933 7042                  pclass1 = pclass2;
6934 7043                  goto next_pathclass;
6935 7044          }
6936 7045          do {
6937 7046                  pclass = NULL;
6938 7047                  if ((mdi_prop_lookup_string(npip, "path-class",
6939 7048                      &pclass) != MDI_SUCCESS) || (strcmp(pclass2,
6940 7049                      pclass) != 0)) {
6941 7050                          VHCI_DEBUG(1, (CE_NOTE, NULL,
6942 7051                              "!vhci_failover(5.5)(%s): skipping path "
6943 7052                              "%p(%s)...\n", guid, (void *)npip, pclass));
6944 7053                          pip = npip;
6945 7054                          sps = mdi_select_path(cdip, NULL,
6946 7055                              MDI_SELECT_STANDBY_PATH, pip, &npip);
6947 7056                          mdi_rele_path(pip);
6948 7057                          (void) mdi_prop_free(pclass);
6949 7058                          continue;
6950 7059                  }
6951 7060                  svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(npip);
6952 7061  
6953 7062                  /*
6954 7063                   * Issue READ at non-zer block on this STANDBY path.
6955 7064                   * Purple returns
6956 7065                   * 1. RESERVATION_CONFLICT if reservation is pending
6957 7066                   * 2. POR check condition if it reset happened.
6958 7067                   * 2. failover Check Conditions if one is already in progress.
6959 7068                   */
6960 7069                  reserve_pending = 0;
6961 7070                  check_condition = 0;
6962 7071                  UA_condition = 0;
6963 7072  
6964 7073                  bp = scsi_alloc_consistent_buf(&svp->svp_psd->sd_address,
6965 7074                      (struct buf *)NULL, DEV_BSIZE, B_READ, NULL, NULL);
6966 7075                  if (!bp) {
6967 7076                          VHCI_DEBUG(1, (CE_NOTE, NULL,
6968 7077                              "vhci_failover !No resources (buf)\n"));
6969 7078                          mdi_rele_path(npip);
6970 7079                          goto done;
  
    | 
      ↓ open down ↓ | 
    803 lines elided | 
    
      ↑ open up ↑ | 
  
6971 7080                  }
6972 7081                  pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
6973 7082                      CDB_GROUP1, sizeof (struct scsi_arq_status), 0,
6974 7083                      PKT_CONSISTENT, NULL, NULL);
6975 7084                  if (pkt) {
6976 7085                          (void) scsi_setup_cdb((union scsi_cdb *)(uintptr_t)
6977 7086                              pkt->pkt_cdbp, SCMD_READ, 1, 1, 0);
6978 7087                          pkt->pkt_flags = FLAG_NOINTR;
6979 7088  check_path_again:
6980 7089                          pkt->pkt_path_instance = mdi_pi_get_path_instance(npip);
6981      -                        pkt->pkt_time = 3*30;
     7090 +                        pkt->pkt_time = 2 * vhci_io_time;
6982 7091  
6983 7092                          if (scsi_transport(pkt) == TRAN_ACCEPT) {
6984 7093                                  switch (pkt->pkt_reason) {
6985 7094                                  case CMD_CMPLT:
6986 7095                                          switch (SCBP_C(pkt)) {
6987 7096                                          case STATUS_GOOD:
6988 7097                                                  /* Already failed over */
6989 7098                                                  activation_done = 1;
6990 7099                                                  break;
6991 7100                                          case STATUS_RESERVATION_CONFLICT:
6992 7101                                                  reserve_pending = 1;
6993 7102                                                  break;
6994 7103                                          case STATUS_CHECK:
6995 7104                                                  check_condition = 1;
6996 7105                                                  break;
6997 7106                                          }
6998 7107                                  }
6999 7108                          }
7000 7109                          if (check_condition &&
7001 7110                              (pkt->pkt_state & STATE_ARQ_DONE)) {
7002 7111                                  uint8_t *sns, skey, asc, ascq;
7003 7112                                  sns = (uint8_t *)
7004 7113                                      &(((struct scsi_arq_status *)(uintptr_t)
7005 7114                                      (pkt->pkt_scbp))->sts_sensedata);
7006 7115                                  skey = scsi_sense_key(sns);
7007 7116                                  asc = scsi_sense_asc(sns);
7008 7117                                  ascq = scsi_sense_ascq(sns);
7009 7118                                  if (skey == KEY_UNIT_ATTENTION &&
7010 7119                                      asc == 0x29) {
7011 7120                                          /* Already failed over */
7012 7121                                          VHCI_DEBUG(1, (CE_NOTE, NULL,
7013 7122                                              "!vhci_failover(7)(%s): "
7014 7123                                              "path 0x%p POR UA condition\n",
7015 7124                                              guid, (void *)npip));
7016 7125                                          if (UA_condition == 0) {
7017 7126                                                  UA_condition = 1;
7018 7127                                                  goto check_path_again;
7019 7128                                          }
7020 7129                                  } else {
7021 7130                                          activation_done = 0;
7022 7131                                          VHCI_DEBUG(1, (CE_NOTE, NULL,
7023 7132                                              "!vhci_failover(%s): path 0x%p "
7024 7133                                              "unhandled chkcond %x %x %x\n",
7025 7134                                              guid, (void *)npip, skey,
7026 7135                                              asc, ascq));
7027 7136                                  }
7028 7137                          }
7029 7138                          scsi_destroy_pkt(pkt);
7030 7139                  }
7031 7140                  scsi_free_consistent_buf(bp);
7032 7141  
7033 7142                  if (activation_done) {
7034 7143                          mdi_rele_path(npip);
7035 7144                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(7)(%s): "
7036 7145                              "path 0x%p already failedover\n", guid,
7037 7146                              (void *)npip));
7038 7147                          break;
7039 7148                  }
7040 7149                  if (reserve_pending && (vlun->svl_xlf_capable == 0)) {
7041 7150                          (void) vhci_recovery_reset(vlun,
7042 7151                              &svp->svp_psd->sd_address,
7043 7152                              FALSE, VHCI_DEPTH_ALL);
7044 7153                  }
7045 7154                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(6)(%s): "
7046 7155                      "activating path 0x%p(psd:%p)\n", guid, (void *)npip,
7047 7156                      (void *)svp->svp_psd));
7048 7157                  if (sfo->sfo_path_activate(svp->svp_psd, pclass2,
7049 7158                      vlun->svl_fops_ctpriv) == 0) {
7050 7159                          activation_done = 1;
7051 7160                          mdi_rele_path(npip);
7052 7161                          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(7)(%s): "
7053 7162                              "path 0x%p successfully activated\n", guid,
7054 7163                              (void *)npip));
7055 7164                          break;
7056 7165                  }
7057 7166                  pip = npip;
7058 7167                  sps = mdi_select_path(cdip, NULL, MDI_SELECT_STANDBY_PATH,
7059 7168                      pip, &npip);
7060 7169                  mdi_rele_path(pip);
7061 7170          } while ((npip != NULL) && (sps == MDI_SUCCESS));
7062 7171          if (activation_done == 0) {
7063 7172                  pclass1 = pclass2;
7064 7173                  goto next_pathclass;
7065 7174          }
7066 7175  
7067 7176          /*
7068 7177           * if we are here, we have succeeded in activating path npip of
7069 7178           * pathclass pclass2; let us validate all paths of pclass2 by
7070 7179           * "ping"-ing each one and mark the good ones ONLINE
7071 7180           * Also, set the state of the paths belonging to the previously
7072 7181           * active pathclass to STANDBY
7073 7182           */
7074 7183          pip = npip = NULL;
7075 7184          sps = mdi_select_path(cdip, NULL, (MDI_SELECT_ONLINE_PATH |
7076 7185              MDI_SELECT_STANDBY_PATH | MDI_SELECT_USER_DISABLE_PATH),
7077 7186              NULL, &npip);
7078 7187          if (npip == NULL || sps != MDI_SUCCESS) {
7079 7188                  VHCI_DEBUG(1, (CE_NOTE, NULL, "!Failover operation failed for "
7080 7189                      "device %s (GUID %s): paths may be busy\n",
7081 7190                      ddi_node_name(cdip), guid));
7082 7191                  goto done;
7083 7192          }
7084 7193          do {
7085 7194                  (void) mdi_pi_get_state2(npip, &pi_state, &pi_ext_state);
7086 7195                  if (mdi_prop_lookup_string(npip, "path-class", &pclass)
7087 7196                      != MDI_SUCCESS) {
7088 7197                          pip = npip;
7089 7198                          sps = mdi_select_path(cdip, NULL,
7090 7199                              (MDI_SELECT_ONLINE_PATH |
7091 7200                              MDI_SELECT_STANDBY_PATH |
7092 7201                              MDI_SELECT_USER_DISABLE_PATH),
7093 7202                              pip, &npip);
7094 7203                          mdi_rele_path(pip);
7095 7204                          continue;
7096 7205                  }
7097 7206                  if (strcmp(pclass, pclass2) == 0) {
7098 7207                          if (pi_state == MDI_PATHINFO_STATE_STANDBY) {
7099 7208                                  svp = (scsi_vhci_priv_t *)
7100 7209                                      mdi_pi_get_vhci_private(npip);
7101 7210                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
7102 7211                                      "!vhci_failover(8)(%s): "
7103 7212                                      "pinging path 0x%p\n",
7104 7213                                      guid, (void *)npip));
7105 7214                                  if (sfo->sfo_path_ping(svp->svp_psd,
7106 7215                                      vlun->svl_fops_ctpriv) == 1) {
7107 7216                                          mdi_pi_set_state(npip,
7108 7217                                              MDI_PATHINFO_STATE_ONLINE);
7109 7218                                          VHCI_DEBUG(1, (CE_NOTE, NULL,
7110 7219                                              "!vhci_failover(9)(%s): "
7111 7220                                              "path 0x%p ping successful, "
7112 7221                                              "marked online\n", guid,
7113 7222                                              (void *)npip));
7114 7223                                          MDI_PI_ERRSTAT(npip, MDI_PI_FAILTO);
7115 7224                                  }
7116 7225                          }
7117 7226                  } else if ((s_pclass != NULL) && (strcmp(pclass, s_pclass)
7118 7227                      == 0)) {
7119 7228                          if (pi_state == MDI_PATHINFO_STATE_ONLINE) {
7120 7229                                  mdi_pi_set_state(npip,
7121 7230                                      MDI_PATHINFO_STATE_STANDBY);
7122 7231                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
7123 7232                                      "!vhci_failover(10)(%s): path 0x%p marked "
7124 7233                                      "STANDBY\n", guid, (void *)npip));
7125 7234                                  MDI_PI_ERRSTAT(npip, MDI_PI_FAILFROM);
7126 7235                          }
7127 7236                  }
7128 7237                  (void) mdi_prop_free(pclass);
7129 7238                  pip = npip;
7130 7239                  sps = mdi_select_path(cdip, NULL, (MDI_SELECT_ONLINE_PATH |
7131 7240                      MDI_SELECT_STANDBY_PATH|MDI_SELECT_USER_DISABLE_PATH),
7132 7241                      pip, &npip);
7133 7242                  mdi_rele_path(pip);
7134 7243          } while ((npip != NULL) && (sps == MDI_SUCCESS));
7135 7244  
7136 7245          /*
7137 7246           * Update the AccessState of related MP-API TPGs
7138 7247           */
7139 7248          (void) vhci_mpapi_update_tpg_acc_state_for_lu(vhci, vlun);
7140 7249  
7141 7250          vhci_log(CE_NOTE, vdip, "!Failover operation completed successfully "
7142 7251              "for device %s (GUID %s): failed over from %s to %s",
7143 7252              ddi_node_name(cdip), guid, ((s_pclass == NULL) ? "<none>" :
7144 7253              s_pclass), pclass2);
7145 7254          ptr1 = kmem_alloc(strlen(pclass2)+1, KM_SLEEP);
7146 7255          (void) strlcpy(ptr1, pclass2, (strlen(pclass2)+1));
7147 7256          mutex_enter(&vlun->svl_mutex);
7148 7257          ptr2 = vlun->svl_active_pclass;
7149 7258          vlun->svl_active_pclass = ptr1;
7150 7259          mutex_exit(&vlun->svl_mutex);
7151 7260          if (ptr2) {
7152 7261                  kmem_free(ptr2, strlen(ptr2)+1);
7153 7262          }
7154 7263          mutex_enter(&vhci->vhci_mutex);
7155 7264          scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
7156 7265              &vhci->vhci_reset_notify_listf);
7157 7266          /* All reservations are cleared upon these resets. */
7158 7267          vlun->svl_flags &= ~VLUN_RESERVE_ACTIVE_FLG;
7159 7268          mutex_exit(&vhci->vhci_mutex);
7160 7269          VHCI_DEBUG(1, (CE_NOTE, NULL, "!vhci_failover(11): DONE! Active "
7161 7270              "pathclass for %s is now %s\n", guid, pclass2));
7162 7271          retval = MDI_SUCCESS;
7163 7272  
7164 7273  done:
7165 7274          vlun->svl_failover_status = retval;
7166 7275          if (flags == MDI_FAILOVER_ASYNC) {
7167 7276                  VHCI_RELEASE_LUN(vlun);
7168 7277                  VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_failover(12): DONE! "
7169 7278                      "releasing lun, as failover was ASYNC\n"));
7170 7279          } else {
7171 7280                  VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_failover(12): DONE! "
7172 7281                      "NOT releasing lun, as failover was SYNC\n"));
7173 7282          }
7174 7283          return (retval);
7175 7284  }
7176 7285  
7177 7286  /*
7178 7287   * vhci_client_attached is called after the successful attach of a
7179 7288   * client devinfo node.
7180 7289   */
7181 7290  static void
7182 7291  vhci_client_attached(dev_info_t *cdip)
7183 7292  {
7184 7293          mdi_pathinfo_t  *pip;
7185 7294          int             circular;
7186 7295  
7187 7296          /*
7188 7297           * At this point the client has attached and it's instance number is
7189 7298           * valid, so we can set up kstats.  We need to do this here because it
7190 7299           * is possible for paths to go online prior to client attach, in which
7191 7300           * case the call to vhci_kstat_create_pathinfo in vhci_pathinfo_online
7192 7301           * was a noop.
7193 7302           */
7194 7303          ndi_devi_enter(cdip, &circular);
7195 7304          for (pip = mdi_get_next_phci_path(cdip, NULL); pip;
7196 7305              pip = mdi_get_next_phci_path(cdip, pip))
7197 7306                  vhci_kstat_create_pathinfo(pip);
7198 7307          ndi_devi_exit(cdip, circular);
7199 7308  }
7200 7309  
7201 7310  /*
7202 7311   * quiesce all of the online paths
7203 7312   */
7204 7313  static int
7205 7314  vhci_quiesce_paths(dev_info_t *vdip, dev_info_t *cdip, scsi_vhci_lun_t *vlun,
7206 7315          char *guid, char *active_pclass_ptr)
7207 7316  {
7208 7317          scsi_vhci_priv_t        *svp;
7209 7318          char                    *s_pclass = NULL;
7210 7319          mdi_pathinfo_t          *npip, *pip;
7211 7320          int                     sps;
7212 7321  
7213 7322          /* quiesce currently active paths */
7214 7323          s_pclass = NULL;
7215 7324          pip = npip = NULL;
7216 7325          sps = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &npip);
7217 7326          if ((npip == NULL) || (sps != MDI_SUCCESS)) {
7218 7327                  return (1);
7219 7328          }
7220 7329          do {
7221 7330                  if (mdi_prop_lookup_string(npip, "path-class",
7222 7331                      &s_pclass) != MDI_SUCCESS) {
7223 7332                          mdi_rele_path(npip);
7224 7333                          vhci_log(CE_NOTE, vdip, "!Failover operation failed "
7225 7334                              "for device %s (GUID %s) due to an internal "
7226 7335                              "error", ddi_node_name(cdip), guid);
7227 7336                          return (1);
7228 7337                  }
7229 7338                  if (strcmp(s_pclass, active_pclass_ptr) == 0) {
7230 7339                          /*
7231 7340                           * quiesce path. Free s_pclass since
7232 7341                           * we don't need it anymore
7233 7342                           */
7234 7343                          VHCI_DEBUG(1, (CE_NOTE, NULL,
7235 7344                              "!vhci_failover(2)(%s): failing over "
7236 7345                              "from %s; quiescing path %p\n",
7237 7346                              guid, s_pclass, (void *)npip));
7238 7347                          (void) mdi_prop_free(s_pclass);
7239 7348                          svp = (scsi_vhci_priv_t *)
7240 7349                              mdi_pi_get_vhci_private(npip);
7241 7350                          if (svp == NULL) {
7242 7351                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
7243 7352                                      "!vhci_failover(2.5)(%s): no "
7244 7353                                      "client priv! %p offlined?\n",
7245 7354                                      guid, (void *)npip));
7246 7355                                  pip = npip;
7247 7356                                  sps = mdi_select_path(cdip, NULL,
7248 7357                                      MDI_SELECT_ONLINE_PATH, pip, &npip);
7249 7358                                  mdi_rele_path(pip);
7250 7359                                  continue;
7251 7360                          }
7252 7361                          if (scsi_abort(&svp->svp_psd->sd_address, NULL)
7253 7362                              == 0) {
7254 7363                                  (void) vhci_recovery_reset(vlun,
7255 7364                                      &svp->svp_psd->sd_address, FALSE,
7256 7365                                      VHCI_DEPTH_TARGET);
7257 7366                          }
7258 7367                          mutex_enter(&svp->svp_mutex);
7259 7368                          if (svp->svp_cmds == 0) {
7260 7369                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
7261 7370                                      "!vhci_failover(3)(%s):"
7262 7371                                      "quiesced path %p\n", guid, (void *)npip));
7263 7372                          } else {
7264 7373                                  while (svp->svp_cmds != 0) {
7265 7374                                          cv_wait(&svp->svp_cv, &svp->svp_mutex);
7266 7375                                          VHCI_DEBUG(1, (CE_NOTE, NULL,
7267 7376                                              "!vhci_failover(3.cv)(%s):"
7268 7377                                              "quiesced path %p\n", guid,
7269 7378                                              (void *)npip));
7270 7379                                  }
7271 7380                          }
7272 7381                          mutex_exit(&svp->svp_mutex);
7273 7382                  } else {
7274 7383                          /*
7275 7384                           * make sure we freeup the memory
7276 7385                           */
7277 7386                          (void) mdi_prop_free(s_pclass);
7278 7387                  }
7279 7388                  pip = npip;
7280 7389                  sps = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH,
7281 7390                      pip, &npip);
7282 7391                  mdi_rele_path(pip);
7283 7392          } while ((npip != NULL) && (sps == MDI_SUCCESS));
7284 7393          return (0);
7285 7394  }
7286 7395  
7287 7396  static struct scsi_vhci_lun *
7288 7397  vhci_lun_lookup(dev_info_t *tgt_dip)
7289 7398  {
7290 7399          return ((struct scsi_vhci_lun *)
7291 7400              mdi_client_get_vhci_private(tgt_dip));
7292 7401  }
7293 7402  
7294 7403  static struct scsi_vhci_lun *
7295 7404  vhci_lun_lookup_alloc(dev_info_t *tgt_dip, char *guid, int *didalloc)
7296 7405  {
7297 7406          struct scsi_vhci_lun *svl;
7298 7407  
7299 7408          if (svl = vhci_lun_lookup(tgt_dip)) {
7300 7409                  return (svl);
7301 7410          }
7302 7411  
7303 7412          svl = kmem_zalloc(sizeof (*svl), KM_SLEEP);
7304 7413          svl->svl_lun_wwn = kmem_zalloc(strlen(guid)+1, KM_SLEEP);
7305 7414          (void) strcpy(svl->svl_lun_wwn,  guid);
7306 7415          mutex_init(&svl->svl_mutex, NULL, MUTEX_DRIVER, NULL);
7307 7416          cv_init(&svl->svl_cv, NULL, CV_DRIVER, NULL);
7308 7417          sema_init(&svl->svl_pgr_sema, 1, NULL, SEMA_DRIVER, NULL);
7309 7418          svl->svl_waiting_for_activepath = 1;
7310 7419          svl->svl_sector_size = 1;
7311 7420          mdi_client_set_vhci_private(tgt_dip, svl);
7312 7421          *didalloc = 1;
7313 7422          VHCI_DEBUG(1, (CE_NOTE, NULL,
7314 7423              "vhci_lun_lookup_alloc: guid %s vlun 0x%p\n",
7315 7424              guid, (void *)svl));
7316 7425          return (svl);
7317 7426  }
7318 7427  
7319 7428  static void
7320 7429  vhci_lun_free(struct scsi_vhci_lun *dvlp, struct scsi_device *sd)
7321 7430  {
7322 7431          char *guid;
7323 7432  
7324 7433          guid = dvlp->svl_lun_wwn;
7325 7434          ASSERT(guid != NULL);
7326 7435          VHCI_DEBUG(4, (CE_NOTE, NULL, "!vhci_lun_free: %s\n", guid));
7327 7436  
7328 7437          mutex_enter(&dvlp->svl_mutex);
7329 7438          if (dvlp->svl_active_pclass != NULL) {
7330 7439                  kmem_free(dvlp->svl_active_pclass,
7331 7440                      strlen(dvlp->svl_active_pclass)+1);
7332 7441          }
7333 7442          dvlp->svl_active_pclass = NULL;
7334 7443          mutex_exit(&dvlp->svl_mutex);
7335 7444  
7336 7445          if (dvlp->svl_lun_wwn != NULL) {
7337 7446                  kmem_free(dvlp->svl_lun_wwn, strlen(dvlp->svl_lun_wwn)+1);
7338 7447          }
7339 7448          dvlp->svl_lun_wwn = NULL;
7340 7449  
7341 7450          if (dvlp->svl_fops_name) {
7342 7451                  kmem_free(dvlp->svl_fops_name, strlen(dvlp->svl_fops_name)+1);
7343 7452          }
7344 7453          dvlp->svl_fops_name = NULL;
7345 7454  
7346 7455          if (dvlp->svl_fops_ctpriv != NULL &&
7347 7456              dvlp->svl_fops != NULL) {
7348 7457                  dvlp->svl_fops->sfo_device_unprobe(sd, dvlp->svl_fops_ctpriv);
7349 7458          }
7350 7459  
7351 7460          if (dvlp->svl_flags & VLUN_TASK_D_ALIVE_FLG)
7352 7461                  taskq_destroy(dvlp->svl_taskq);
7353 7462  
7354 7463          mutex_destroy(&dvlp->svl_mutex);
7355 7464          cv_destroy(&dvlp->svl_cv);
7356 7465          sema_destroy(&dvlp->svl_pgr_sema);
7357 7466          kmem_free(dvlp, sizeof (*dvlp));
7358 7467          /*
7359 7468           * vhci_lun_free may be called before the tgt_dip
7360 7469           * initialization so check if the sd is NULL.
7361 7470           */
7362 7471          if (sd != NULL)
7363 7472                  scsi_device_hba_private_set(sd, NULL);
7364 7473  }
7365 7474  
7366 7475  int
7367 7476  vhci_do_scsi_cmd(struct scsi_pkt *pkt)
7368 7477  {
7369 7478          int     err = 0;
7370 7479          int     retry_cnt = 0;
7371 7480          uint8_t *sns, skey;
7372 7481  
7373 7482  #ifdef DEBUG
7374 7483          if (vhci_debug > 5) {
7375 7484                  vhci_print_cdb(pkt->pkt_address.a_hba_tran->tran_hba_dip,
7376 7485                      CE_WARN, "Vhci command", pkt->pkt_cdbp);
7377 7486          }
7378 7487  #endif
7379 7488  
7380 7489  retry:
7381 7490          err = scsi_poll(pkt);
7382 7491          if (err) {
7383 7492                  if (pkt->pkt_cdbp[0] == SCMD_RELEASE) {
7384 7493                          if (SCBP_C(pkt) == STATUS_RESERVATION_CONFLICT) {
7385 7494                                  VHCI_DEBUG(1, (CE_NOTE, NULL,
7386 7495                                      "!v_s_do_s_c: RELEASE conflict\n"));
7387 7496                                  return (0);
7388 7497                          }
7389 7498                  }
7390 7499                  if (retry_cnt++ < 6) {
7391 7500                          VHCI_DEBUG(1, (CE_WARN, NULL,
7392 7501                              "!v_s_do_s_c:retry packet 0x%p "
7393 7502                              "status 0x%x reason %s",
7394 7503                              (void *)pkt, SCBP_C(pkt),
7395 7504                              scsi_rname(pkt->pkt_reason)));
7396 7505                          if ((pkt->pkt_reason == CMD_CMPLT) &&
7397 7506                              (SCBP_C(pkt) == STATUS_CHECK) &&
7398 7507                              (pkt->pkt_state & STATE_ARQ_DONE)) {
7399 7508                                  sns = (uint8_t *)
7400 7509                                      &(((struct scsi_arq_status *)(uintptr_t)
7401 7510                                      (pkt->pkt_scbp))->sts_sensedata);
7402 7511                                  skey = scsi_sense_key(sns);
7403 7512                                  VHCI_DEBUG(1, (CE_WARN, NULL,
7404 7513                                      "!v_s_do_s_c:retry "
7405 7514                                      "packet 0x%p  sense data %s", (void *)pkt,
7406 7515                                      scsi_sname(skey)));
7407 7516                          }
7408 7517                          goto retry;
7409 7518                  }
7410 7519                  VHCI_DEBUG(1, (CE_WARN, NULL,
7411 7520                      "!v_s_do_s_c: failed transport 0x%p 0x%x",
7412 7521                      (void *)pkt, SCBP_C(pkt)));
7413 7522                  return (0);
7414 7523          }
7415 7524  
7416 7525          switch (pkt->pkt_reason) {
7417 7526                  case CMD_TIMEOUT:
7418 7527                          VHCI_DEBUG(1, (CE_WARN, NULL, "!pkt timed "
7419 7528                              "out (pkt 0x%p)", (void *)pkt));
7420 7529                          return (0);
7421 7530                  case CMD_CMPLT:
7422 7531                          switch (SCBP_C(pkt)) {
7423 7532                                  case STATUS_GOOD:
7424 7533                                          break;
7425 7534                                  case STATUS_CHECK:
7426 7535                                          if (pkt->pkt_state & STATE_ARQ_DONE) {
7427 7536                                                  sns = (uint8_t *)&(((
7428 7537                                                      struct scsi_arq_status *)
7429 7538                                                      (uintptr_t)
7430 7539                                                      (pkt->pkt_scbp))->
7431 7540                                                      sts_sensedata);
7432 7541                                                  skey = scsi_sense_key(sns);
7433 7542                                                  if ((skey ==
7434 7543                                                      KEY_UNIT_ATTENTION) ||
7435 7544                                                      (skey ==
7436 7545                                                      KEY_NOT_READY)) {
7437 7546                                                          /*
7438 7547                                                           * clear unit attn.
7439 7548                                                           */
7440 7549  
7441 7550                                                          VHCI_DEBUG(1,
7442 7551                                                              (CE_WARN, NULL,
7443 7552                                                              "!v_s_do_s_c: "
7444 7553                                                              "retry "
7445 7554                                                              "packet 0x%p sense "
7446 7555                                                              "data %s",
7447 7556                                                              (void *)pkt,
7448 7557                                                              scsi_sname
7449 7558                                                              (skey)));
7450 7559                                                          goto retry;
7451 7560                                                  }
7452 7561                                                  VHCI_DEBUG(4, (CE_WARN, NULL,
7453 7562                                                      "!ARQ while "
7454 7563                                                      "transporting "
7455 7564                                                      "(pkt 0x%p)",
7456 7565                                                      (void *)pkt));
7457 7566                                                  return (0);
7458 7567                                          }
7459 7568                                          return (0);
7460 7569                                  default:
7461 7570                                          VHCI_DEBUG(1, (CE_WARN, NULL,
7462 7571                                              "!Bad status returned "
7463 7572                                              "(pkt 0x%p, status %x)",
7464 7573                                              (void *)pkt, SCBP_C(pkt)));
7465 7574                                          return (0);
7466 7575                          }
7467 7576                          break;
7468 7577                  case CMD_INCOMPLETE:
7469 7578                  case CMD_RESET:
7470 7579                  case CMD_ABORTED:
7471 7580                  case CMD_TRAN_ERR:
7472 7581                          if (retry_cnt++ < 1) {
7473 7582                                  VHCI_DEBUG(1, (CE_WARN, NULL,
7474 7583                                      "!v_s_do_s_c: retry packet 0x%p %s",
7475 7584                                      (void *)pkt, scsi_rname(pkt->pkt_reason)));
7476 7585                                  goto retry;
7477 7586                          }
7478 7587                          /* FALLTHROUGH */
7479 7588                  default:
7480 7589                          VHCI_DEBUG(1, (CE_WARN, NULL, "!pkt did not "
7481 7590                              "complete successfully (pkt 0x%p,"
7482 7591                              "reason %x)", (void *)pkt, pkt->pkt_reason));
7483 7592                          return (0);
7484 7593          }
7485 7594          return (1);
7486 7595  }
7487 7596  
7488 7597  static int
7489 7598  vhci_quiesce_lun(struct scsi_vhci_lun *vlun)
7490 7599  {
7491 7600          mdi_pathinfo_t          *pip, *spip;
7492 7601          dev_info_t              *cdip;
7493 7602          struct scsi_vhci_priv   *svp;
7494 7603          mdi_pathinfo_state_t    pstate;
7495 7604          uint32_t                p_ext_state;
7496 7605          int                     circular;
7497 7606  
7498 7607          cdip = vlun->svl_dip;
7499 7608          pip = spip = NULL;
7500 7609          ndi_devi_enter(cdip, &circular);
7501 7610          pip = mdi_get_next_phci_path(cdip, NULL);
7502 7611          while (pip != NULL) {
7503 7612                  (void) mdi_pi_get_state2(pip, &pstate, &p_ext_state);
7504 7613                  if (pstate != MDI_PATHINFO_STATE_ONLINE) {
7505 7614                          spip = pip;
7506 7615                          pip = mdi_get_next_phci_path(cdip, spip);
7507 7616                          continue;
7508 7617                  }
7509 7618                  mdi_hold_path(pip);
7510 7619                  ndi_devi_exit(cdip, circular);
7511 7620                  svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
7512 7621                  mutex_enter(&svp->svp_mutex);
7513 7622                  while (svp->svp_cmds != 0) {
7514 7623                          if (cv_reltimedwait(&svp->svp_cv, &svp->svp_mutex,
7515 7624                              drv_usectohz(vhci_path_quiesce_timeout * 1000000),
7516 7625                              TR_CLOCK_TICK) == -1) {
7517 7626                                  mutex_exit(&svp->svp_mutex);
7518 7627                                  mdi_rele_path(pip);
7519 7628                                  VHCI_DEBUG(1, (CE_WARN, NULL,
7520 7629                                      "Quiesce of lun is not successful "
7521 7630                                      "vlun: 0x%p.", (void *)vlun));
7522 7631                                  return (0);
7523 7632                          }
7524 7633                  }
7525 7634                  mutex_exit(&svp->svp_mutex);
7526 7635                  ndi_devi_enter(cdip, &circular);
7527 7636                  spip = pip;
7528 7637                  pip = mdi_get_next_phci_path(cdip, spip);
7529 7638                  mdi_rele_path(spip);
7530 7639          }
7531 7640          ndi_devi_exit(cdip, circular);
7532 7641          return (1);
7533 7642  }
7534 7643  
7535 7644  static int
7536 7645  vhci_pgr_validate_and_register(scsi_vhci_priv_t *svp)
7537 7646  {
7538 7647          scsi_vhci_lun_t         *vlun;
7539 7648          vhci_prout_t            *prout;
7540 7649          int                     rval, success;
7541 7650          mdi_pathinfo_t          *pip, *npip;
7542 7651          scsi_vhci_priv_t        *osvp;
7543 7652          dev_info_t              *cdip;
7544 7653          uchar_t                 cdb_1;
7545 7654          uchar_t                 temp_res_key[MHIOC_RESV_KEY_SIZE];
7546 7655  
7547 7656  
7548 7657          /*
7549 7658           * see if there are any other paths available; if none,
7550 7659           * then there is nothing to do.
7551 7660           */
7552 7661          cdip = svp->svp_svl->svl_dip;
7553 7662          rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH |
7554 7663              MDI_SELECT_STANDBY_PATH, NULL, &pip);
7555 7664          if ((rval != MDI_SUCCESS) || (pip == NULL)) {
7556 7665                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7557 7666                      "%s%d: vhci_pgr_validate_and_register: first path\n",
7558 7667                      ddi_driver_name(cdip), ddi_get_instance(cdip)));
7559 7668                  return (1);
7560 7669          }
7561 7670  
7562 7671          vlun = svp->svp_svl;
7563 7672          prout = &vlun->svl_prout;
7564 7673          ASSERT(vlun->svl_pgr_active != 0);
7565 7674  
7566 7675          /*
7567 7676           * When the path was busy/offlined, some other host might have
7568 7677           * cleared this key. Validate key on some other path first.
7569 7678           * If it fails, return failure.
7570 7679           */
7571 7680  
7572 7681          npip = pip;
7573 7682          pip = NULL;
7574 7683          success = 0;
7575 7684  
7576 7685          /* Save the res key */
7577 7686          bcopy(prout->res_key, temp_res_key, MHIOC_RESV_KEY_SIZE);
7578 7687  
7579 7688          /*
7580 7689           * Sometimes CDB from application can be a Register_And_Ignore.
7581 7690           * Instead of validation, this cdb would result in force registration.
7582 7691           * Convert it to normal cdb for validation.
7583 7692           * After that be sure to restore the cdb.
7584 7693           */
7585 7694          cdb_1 = vlun->svl_cdb[1];
7586 7695          vlun->svl_cdb[1] &= 0xe0;
7587 7696  
7588 7697          do {
7589 7698                  osvp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(npip);
7590 7699                  if (osvp == NULL) {
7591 7700                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7592 7701                              "vhci_pgr_validate_and_register: no "
7593 7702                              "client priv! 0x%p offlined?\n",
7594 7703                              (void *)npip));
7595 7704                          goto next_path_1;
7596 7705                  }
7597 7706  
7598 7707                  if (osvp == svp) {
7599 7708                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7600 7709                              "vhci_pgr_validate_and_register: same svp 0x%p"
7601 7710                              " npip 0x%p vlun 0x%p\n",
7602 7711                              (void *)svp, (void *)npip, (void *)vlun));
7603 7712                          goto next_path_1;
7604 7713                  }
7605 7714  
7606 7715                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7607 7716                      "vhci_pgr_validate_and_register: First validate on"
7608 7717                      " osvp 0x%p being done. vlun 0x%p thread 0x%p Before bcopy"
7609 7718                      " cdb1 %x\n", (void *)osvp, (void *)vlun,
7610 7719                      (void *)curthread, vlun->svl_cdb[1]));
7611 7720                  vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy:");
7612 7721  
7613 7722                  bcopy(prout->service_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
7614 7723  
7615 7724                  VHCI_DEBUG(4, (CE_WARN, NULL, "vlun 0x%p After bcopy",
7616 7725                      (void *)vlun));
7617 7726                  vhci_print_prout_keys(vlun, "v_pgr_val_reg: after bcopy: ");
7618 7727  
7619 7728                  rval = vhci_do_prout(osvp);
7620 7729                  if (rval == 1) {
7621 7730                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7622 7731                              "%s%d: vhci_pgr_validate_and_register: key"
7623 7732                              " validated thread 0x%p\n", ddi_driver_name(cdip),
7624 7733                              ddi_get_instance(cdip), (void *)curthread));
7625 7734                          pip = npip;
7626 7735                          success = 1;
7627 7736                          break;
7628 7737                  } else {
7629 7738                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7630 7739                              "vhci_pgr_validate_and_register: First validation"
7631 7740                              " on osvp 0x%p failed %x\n", (void *)osvp, rval));
7632 7741                          vhci_print_prout_keys(vlun, "v_pgr_val_reg: failed:");
7633 7742                  }
7634 7743  
7635 7744                  /*
7636 7745                   * Try other paths
7637 7746                   */
7638 7747  next_path_1:
7639 7748                  pip = npip;
7640 7749                  rval = mdi_select_path(cdip, NULL,
7641 7750                      MDI_SELECT_ONLINE_PATH|MDI_SELECT_STANDBY_PATH,
7642 7751                      pip, &npip);
7643 7752                  mdi_rele_path(pip);
7644 7753          } while ((rval == MDI_SUCCESS) && (npip != NULL));
7645 7754  
7646 7755  
7647 7756          /* Be sure to restore original cdb */
7648 7757          vlun->svl_cdb[1] = cdb_1;
7649 7758  
7650 7759          /* Restore the res_key */
7651 7760          bcopy(temp_res_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
7652 7761  
7653 7762          /*
7654 7763           * If key could not be registered on any path for the first time,
7655 7764           * return success as online should still continue.
7656 7765           */
7657 7766          if (success == 0) {
7658 7767                  return (1);
7659 7768          }
7660 7769  
7661 7770          ASSERT(pip != NULL);
7662 7771  
7663 7772          /*
7664 7773           * Force register on new path
7665 7774           */
7666 7775          cdb_1 = vlun->svl_cdb[1];               /* store the cdb */
7667 7776  
7668 7777          vlun->svl_cdb[1] &= 0xe0;
7669 7778          vlun->svl_cdb[1] |= VHCI_PROUT_R_AND_IGNORE;
7670 7779  
7671 7780          vhci_print_prout_keys(vlun, "v_pgr_val_reg: keys before bcopy: ");
7672 7781  
7673 7782          bcopy(prout->active_service_key, prout->service_key,
7674 7783              MHIOC_RESV_KEY_SIZE);
7675 7784          bcopy(prout->active_res_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
7676 7785  
7677 7786          vhci_print_prout_keys(vlun, "v_pgr_val_reg:keys after bcopy: ");
7678 7787  
7679 7788          rval = vhci_do_prout(svp);
7680 7789          vlun->svl_cdb[1] = cdb_1;               /* restore the cdb */
7681 7790          if (rval != 1) {
7682 7791                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7683 7792                      "vhci_pgr_validate_and_register: register on new"
7684 7793                      " path 0x%p svp 0x%p failed %x\n",
7685 7794                      (void *)pip, (void *)svp, rval));
7686 7795                  vhci_print_prout_keys(vlun, "v_pgr_val_reg: reg failed: ");
7687 7796                  mdi_rele_path(pip);
7688 7797                  return (0);
7689 7798          }
7690 7799  
7691 7800          if (bcmp(prout->service_key, zero_key, MHIOC_RESV_KEY_SIZE) == 0) {
7692 7801                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7693 7802                      "vhci_pgr_validate_and_register: zero service key\n"));
7694 7803                  mdi_rele_path(pip);
7695 7804                  return (rval);
7696 7805          }
7697 7806  
7698 7807          /*
7699 7808           * While the key was force registered, some other host might have
7700 7809           * cleared the key. Re-validate key on another pre-existing path
7701 7810           * before declaring success.
7702 7811           */
7703 7812          npip = pip;
7704 7813          pip = NULL;
7705 7814  
7706 7815          /*
7707 7816           * Sometimes CDB from application can be Register and Ignore.
7708 7817           * Instead of validation, it would result in force registration.
7709 7818           * Convert it to normal cdb for validation.
7710 7819           * After that be sure to restore the cdb.
7711 7820           */
7712 7821          cdb_1 = vlun->svl_cdb[1];
7713 7822          vlun->svl_cdb[1] &= 0xe0;
7714 7823          success = 0;
7715 7824  
7716 7825          do {
7717 7826                  osvp = (scsi_vhci_priv_t *)
7718 7827                      mdi_pi_get_vhci_private(npip);
7719 7828                  if (osvp == NULL) {
7720 7829                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7721 7830                              "vhci_pgr_validate_and_register: no "
7722 7831                              "client priv! 0x%p offlined?\n",
7723 7832                              (void *)npip));
7724 7833                          goto next_path_2;
7725 7834                  }
7726 7835  
7727 7836                  if (osvp == svp) {
7728 7837                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7729 7838                              "vhci_pgr_validate_and_register: same osvp 0x%p"
7730 7839                              " npip 0x%p vlun 0x%p\n",
7731 7840                              (void *)svp, (void *)npip, (void *)vlun));
7732 7841                          goto next_path_2;
7733 7842                  }
7734 7843  
7735 7844                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7736 7845                      "vhci_pgr_validate_and_register: Re-validation on"
7737 7846                      " osvp 0x%p being done. vlun 0x%p Before bcopy cdb1 %x\n",
7738 7847                      (void *)osvp, (void *)vlun, vlun->svl_cdb[1]));
7739 7848                  vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy: ");
7740 7849  
7741 7850                  bcopy(prout->service_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
7742 7851  
7743 7852                  vhci_print_prout_keys(vlun, "v_pgr_val_reg: after bcopy: ");
7744 7853  
7745 7854                  rval = vhci_do_prout(osvp);
7746 7855                  if (rval == 1) {
7747 7856                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7748 7857                              "%s%d: vhci_pgr_validate_and_register: key"
7749 7858                              " validated thread 0x%p\n", ddi_driver_name(cdip),
7750 7859                              ddi_get_instance(cdip), (void *)curthread));
7751 7860                          pip = npip;
7752 7861                          success = 1;
7753 7862                          break;
7754 7863                  } else {
7755 7864                          VHCI_DEBUG(4, (CE_NOTE, NULL,
7756 7865                              "vhci_pgr_validate_and_register: Re-validation on"
7757 7866                              " osvp 0x%p failed %x\n", (void *)osvp, rval));
7758 7867                          vhci_print_prout_keys(vlun,
7759 7868                              "v_pgr_val_reg: reval failed: ");
7760 7869                  }
7761 7870  
7762 7871                  /*
7763 7872                   * Try other paths
7764 7873                   */
7765 7874  next_path_2:
7766 7875                  pip = npip;
7767 7876                  rval = mdi_select_path(cdip, NULL,
7768 7877                      MDI_SELECT_ONLINE_PATH|MDI_SELECT_STANDBY_PATH,
7769 7878                      pip, &npip);
7770 7879                  mdi_rele_path(pip);
7771 7880          } while ((rval == MDI_SUCCESS) && (npip != NULL));
7772 7881  
7773 7882          /* Be sure to restore original cdb */
7774 7883          vlun->svl_cdb[1] = cdb_1;
7775 7884  
7776 7885          if (success == 1) {
7777 7886                  /* Successfully validated registration */
7778 7887                  mdi_rele_path(pip);
7779 7888                  return (1);
7780 7889          }
7781 7890  
7782 7891          VHCI_DEBUG(4, (CE_WARN, NULL, "key validation failed"));
7783 7892  
7784 7893          /*
7785 7894           * key invalid, back out by registering key value of 0
7786 7895           */
7787 7896          VHCI_DEBUG(4, (CE_NOTE, NULL,
7788 7897              "vhci_pgr_validate_and_register: backout on"
7789 7898              " svp 0x%p being done\n", (void *)svp));
7790 7899          vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy: ");
7791 7900  
7792 7901          bcopy(prout->service_key, prout->res_key, MHIOC_RESV_KEY_SIZE);
7793 7902          bzero(prout->service_key, MHIOC_RESV_KEY_SIZE);
7794 7903  
7795 7904          vhci_print_prout_keys(vlun, "v_pgr_val_reg: before bcopy: ");
7796 7905  
7797 7906          /*
7798 7907           * Get a new path
7799 7908           */
7800 7909          rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH |
7801 7910              MDI_SELECT_STANDBY_PATH, NULL, &pip);
7802 7911          if ((rval != MDI_SUCCESS) || (pip == NULL)) {
7803 7912                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7804 7913                      "%s%d: vhci_pgr_validate_and_register: no valid pip\n",
7805 7914                      ddi_driver_name(cdip), ddi_get_instance(cdip)));
7806 7915                  return (0);
7807 7916          }
7808 7917  
7809 7918          if ((rval = vhci_do_prout(svp)) != 1) {
7810 7919                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7811 7920                      "vhci_pgr_validate_and_register: backout on"
7812 7921                      " svp 0x%p failed\n", (void *)svp));
7813 7922                  vhci_print_prout_keys(vlun, "backout failed");
7814 7923  
7815 7924                  VHCI_DEBUG(4, (CE_WARN, NULL,
7816 7925                      "%s%d: vhci_pgr_validate_and_register: key"
7817 7926                      " validation and backout failed", ddi_driver_name(cdip),
7818 7927                      ddi_get_instance(cdip)));
7819 7928                  if (rval == VHCI_PGR_ILLEGALOP) {
7820 7929                          VHCI_DEBUG(4, (CE_WARN, NULL,
7821 7930                              "%s%d: vhci_pgr_validate_and_register: key"
7822 7931                              " already cleared", ddi_driver_name(cdip),
7823 7932                              ddi_get_instance(cdip)));
7824 7933                          rval = 1;
7825 7934                  } else
7826 7935                          rval = 0;
7827 7936          } else {
7828 7937                  VHCI_DEBUG(4, (CE_NOTE, NULL,
7829 7938                      "%s%d: vhci_pgr_validate_and_register: key"
7830 7939                      " validation failed, key backed out\n",
7831 7940                      ddi_driver_name(cdip), ddi_get_instance(cdip)));
7832 7941                  vhci_print_prout_keys(vlun, "v_pgr_val_reg: key backed out: ");
7833 7942          }
7834 7943          mdi_rele_path(pip);
7835 7944  
7836 7945          return (rval);
7837 7946  }
7838 7947  
7839 7948  /*
7840 7949   * taskq routine to dispatch a scsi cmd to vhci_scsi_start.  This ensures
7841 7950   * that vhci_scsi_start is not called in interrupt context.
7842 7951   * As the upper layer gets TRAN_ACCEPT when the command is dispatched, we
7843 7952   * need to complete the command if something goes wrong.
7844 7953   */
7845 7954  static void
7846 7955  vhci_dispatch_scsi_start(void *arg)
7847 7956  {
7848 7957          struct vhci_pkt *vpkt   = (struct vhci_pkt *)arg;
7849 7958          struct scsi_pkt *tpkt   = vpkt->vpkt_tgt_pkt;
7850 7959          int rval                = TRAN_BUSY;
7851 7960  
7852 7961          VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_dispatch_scsi_start: sending"
7853 7962              " scsi-2 reserve for 0x%p\n",
7854 7963              (void *)ADDR2DIP(&(vpkt->vpkt_tgt_pkt->pkt_address))));
7855 7964  
7856 7965          /*
7857 7966           * To prevent the taskq from being called recursively we set the
7858 7967           * the VHCI_PKT_THRU_TASKQ bit in the vhci_pkt_states.
7859 7968           */
7860 7969          vpkt->vpkt_state |= VHCI_PKT_THRU_TASKQ;
7861 7970  
7862 7971          /*
7863 7972           * Wait for the transport to get ready to send packets
7864 7973           * and if it times out, it will return something other than
7865 7974           * TRAN_BUSY. The vhci_reserve_delay may want to
7866 7975           * get tuned for other transports and is therefore a global.
7867 7976           * Using delay since this routine is called by taskq dispatch
7868 7977           * and not called during interrupt context.
7869 7978           */
7870 7979          while ((rval = vhci_scsi_start(&(vpkt->vpkt_tgt_pkt->pkt_address),
7871 7980              vpkt->vpkt_tgt_pkt)) == TRAN_BUSY) {
7872 7981                  delay(drv_usectohz(vhci_reserve_delay));
7873 7982          }
7874 7983  
7875 7984          switch (rval) {
7876 7985          case TRAN_ACCEPT:
7877 7986                  return;
7878 7987  
7879 7988          default:
7880 7989                  /*
7881 7990                   * This pkt shall be retried, and to ensure another taskq
7882 7991                   * is dispatched for it, clear the VHCI_PKT_THRU_TASKQ
7883 7992                   * flag.
7884 7993                   */
7885 7994                  vpkt->vpkt_state &= ~VHCI_PKT_THRU_TASKQ;
7886 7995  
7887 7996                  /* Ensure that the pkt is retried without a reset */
7888 7997                  tpkt->pkt_reason = CMD_ABORTED;
7889 7998                  tpkt->pkt_statistics |= STAT_ABORTED;
7890 7999                  VHCI_DEBUG(1, (CE_WARN, NULL, "!vhci_dispatch_scsi_start: "
7891 8000                      "TRAN_rval %d returned for dip 0x%p", rval,
7892 8001                      (void *)ADDR2DIP(&(vpkt->vpkt_tgt_pkt->pkt_address))));
7893 8002                  break;
7894 8003          }
7895 8004  
7896 8005          /*
7897 8006           * vpkt_org_vpkt should always be NULL here if the retry command
7898 8007           * has been successfully dispatched.  If vpkt_org_vpkt != NULL at
7899 8008           * this point, it is an error so restore the original vpkt and
7900 8009           * return an error to the target driver so it can retry the
7901 8010           * command as appropriate.
7902 8011           */
7903 8012          if (vpkt->vpkt_org_vpkt != NULL) {
7904 8013                  struct vhci_pkt         *new_vpkt = vpkt;
7905 8014                  scsi_vhci_priv_t        *svp = (scsi_vhci_priv_t *)
7906 8015                      mdi_pi_get_vhci_private(vpkt->vpkt_path);
7907 8016  
7908 8017                  vpkt = vpkt->vpkt_org_vpkt;
7909 8018  
7910 8019                  vpkt->vpkt_tgt_pkt->pkt_reason = tpkt->pkt_reason;
7911 8020                  vpkt->vpkt_tgt_pkt->pkt_statistics = tpkt->pkt_statistics;
7912 8021  
7913 8022                  vhci_scsi_destroy_pkt(&svp->svp_psd->sd_address,
7914 8023                      new_vpkt->vpkt_tgt_pkt);
7915 8024  
7916 8025                  tpkt = vpkt->vpkt_tgt_pkt;
7917 8026          }
7918 8027  
7919 8028          scsi_hba_pkt_comp(tpkt);
7920 8029  }
7921 8030  
7922 8031  static void
7923 8032  vhci_initiate_auto_failback(void *arg)
7924 8033  {
7925 8034          struct scsi_vhci_lun    *vlun = (struct scsi_vhci_lun *)arg;
7926 8035          dev_info_t              *vdip, *cdip;
7927 8036          int                     held;
7928 8037  
7929 8038          cdip = vlun->svl_dip;
7930 8039          vdip = ddi_get_parent(cdip);
7931 8040  
7932 8041          VHCI_HOLD_LUN(vlun, VH_SLEEP, held);
7933 8042  
7934 8043          /*
7935 8044           * Perform a final check to see if the active path class is indeed
7936 8045           * not the preferred path class.  As in the time the auto failback
7937 8046           * was dispatched, an external failover could have been detected.
7938 8047           * [Some other host could have detected this condition and triggered
7939 8048           *  the auto failback before].
7940 8049           * In such a case if we go ahead with failover we will be negating the
7941 8050           * whole purpose of auto failback.
7942 8051           */
7943 8052          mutex_enter(&vlun->svl_mutex);
7944 8053          if (vlun->svl_active_pclass != NULL) {
7945 8054                  char                            *best_pclass;
7946 8055                  struct scsi_failover_ops        *fo;
7947 8056  
7948 8057                  fo = vlun->svl_fops;
7949 8058  
7950 8059                  (void) fo->sfo_pathclass_next(NULL, &best_pclass,
7951 8060                      vlun->svl_fops_ctpriv);
7952 8061                  if (strcmp(vlun->svl_active_pclass, best_pclass) == 0) {
7953 8062                          mutex_exit(&vlun->svl_mutex);
7954 8063                          VHCI_RELEASE_LUN(vlun);
7955 8064                          VHCI_DEBUG(1, (CE_NOTE, NULL, "Not initiating "
7956 8065                              "auto failback for %s as %s pathclass already "
7957 8066                              "active.\n", vlun->svl_lun_wwn, best_pclass));
7958 8067                          return;
7959 8068                  }
7960 8069          }
7961 8070          mutex_exit(&vlun->svl_mutex);
7962 8071          if (mdi_failover(vdip, vlun->svl_dip, MDI_FAILOVER_SYNC)
7963 8072              == MDI_SUCCESS) {
7964 8073                  vhci_log(CE_NOTE, vdip, "!Auto failback operation "
7965 8074                      "succeeded for device %s (GUID %s)",
7966 8075                      ddi_node_name(cdip), vlun->svl_lun_wwn);
7967 8076          } else {
7968 8077                  vhci_log(CE_NOTE, vdip, "!Auto failback operation "
7969 8078                      "failed for device %s (GUID %s)",
7970 8079                      ddi_node_name(cdip), vlun->svl_lun_wwn);
7971 8080          }
7972 8081          VHCI_RELEASE_LUN(vlun);
7973 8082  }
7974 8083  
7975 8084  #ifdef DEBUG
7976 8085  static void
7977 8086  vhci_print_prin_keys(vhci_prin_readkeys_t *prin, int numkeys)
7978 8087  {
7979 8088          vhci_clean_print(NULL, 5, "Current PGR Keys",
7980 8089              (uchar_t *)prin, numkeys * 8);
7981 8090  }
7982 8091  #endif
7983 8092  
7984 8093  static void
7985 8094  vhci_print_prout_keys(scsi_vhci_lun_t *vlun, char *msg)
7986 8095  {
7987 8096          int                     i;
7988 8097          vhci_prout_t            *prout;
7989 8098          char                    buf1[4*MHIOC_RESV_KEY_SIZE + 1];
7990 8099          char                    buf2[4*MHIOC_RESV_KEY_SIZE + 1];
7991 8100          char                    buf3[4*MHIOC_RESV_KEY_SIZE + 1];
7992 8101          char                    buf4[4*MHIOC_RESV_KEY_SIZE + 1];
7993 8102  
7994 8103          prout = &vlun->svl_prout;
7995 8104  
7996 8105          for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
7997 8106                  (void) sprintf(&buf1[4*i], "[%02x]", prout->res_key[i]);
7998 8107          for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
7999 8108                  (void) sprintf(&buf2[(4*i)], "[%02x]", prout->service_key[i]);
8000 8109          for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
8001 8110                  (void) sprintf(&buf3[4*i], "[%02x]", prout->active_res_key[i]);
8002 8111          for (i = 0; i < MHIOC_RESV_KEY_SIZE; i++)
8003 8112                  (void) sprintf(&buf4[4*i], "[%02x]",
8004 8113                      prout->active_service_key[i]);
8005 8114  
8006 8115          /* Printing all in one go. Otherwise it will jumble up */
8007 8116          VHCI_DEBUG(5, (CE_CONT, NULL, "%s vlun 0x%p, thread 0x%p\n"
8008 8117              "res_key:          : %s\n"
8009 8118              "service_key       : %s\n"
8010 8119              "active_res_key    : %s\n"
8011 8120              "active_service_key: %s\n",
8012 8121              msg, (void *)vlun, (void *)curthread, buf1, buf2, buf3, buf4));
8013 8122  }
8014 8123  
8015 8124  /*
8016 8125   * Called from vhci_scsi_start to update the pHCI pkt with target packet.
8017 8126   */
8018 8127  static void
8019 8128  vhci_update_pHCI_pkt(struct vhci_pkt *vpkt, struct scsi_pkt *pkt)
8020 8129  {
8021 8130  
8022 8131          ASSERT(vpkt->vpkt_hba_pkt);
8023 8132  
8024 8133          vpkt->vpkt_hba_pkt->pkt_flags = pkt->pkt_flags;
8025 8134          vpkt->vpkt_hba_pkt->pkt_flags |= FLAG_NOQUEUE;
8026 8135  
8027 8136          if ((vpkt->vpkt_hba_pkt->pkt_flags & FLAG_NOINTR) ||
8028 8137              MDI_PI_IS_SUSPENDED(vpkt->vpkt_path)) {
8029 8138                  /*
8030 8139                   * Polled Command is requested or HBA is in
8031 8140                   * suspended state
8032 8141                   */
8033 8142                  vpkt->vpkt_hba_pkt->pkt_flags |= FLAG_NOINTR;
8034 8143                  vpkt->vpkt_hba_pkt->pkt_comp = NULL;
8035 8144          } else {
8036 8145                  vpkt->vpkt_hba_pkt->pkt_comp = vhci_intr;
8037 8146          }
8038 8147          vpkt->vpkt_hba_pkt->pkt_time = pkt->pkt_time;
8039 8148          bcopy(pkt->pkt_cdbp, vpkt->vpkt_hba_pkt->pkt_cdbp,
8040 8149              vpkt->vpkt_tgt_init_cdblen);
8041 8150          vpkt->vpkt_hba_pkt->pkt_resid = pkt->pkt_resid;
8042 8151  
8043 8152          /* Re-initialize the following pHCI packet state information */
8044 8153          vpkt->vpkt_hba_pkt->pkt_state = 0;
8045 8154          vpkt->vpkt_hba_pkt->pkt_statistics = 0;
8046 8155          vpkt->vpkt_hba_pkt->pkt_reason = 0;
8047 8156  }
8048 8157  
8049 8158  static int
8050 8159  vhci_scsi_bus_power(dev_info_t *parent, void *impl_arg, pm_bus_power_op_t op,
8051 8160      void *arg, void *result)
8052 8161  {
8053 8162          int ret = DDI_SUCCESS;
8054 8163  
8055 8164          /*
8056 8165           * Generic processing in MPxIO framework
8057 8166           */
8058 8167          ret = mdi_bus_power(parent, impl_arg, op, arg, result);
8059 8168  
8060 8169          switch (ret) {
8061 8170          case MDI_SUCCESS:
8062 8171                  ret = DDI_SUCCESS;
8063 8172                  break;
8064 8173          case MDI_FAILURE:
8065 8174                  ret = DDI_FAILURE;
8066 8175                  break;
8067 8176          default:
8068 8177                  break;
8069 8178          }
8070 8179  
8071 8180          return (ret);
8072 8181  }
8073 8182  
8074 8183  static int
8075 8184  vhci_pHCI_cap(struct scsi_address *ap, char *cap, int val, int whom,
8076 8185      mdi_pathinfo_t *pip)
8077 8186  {
8078 8187          dev_info_t              *cdip;
8079 8188          mdi_pathinfo_t          *npip = NULL;
8080 8189          scsi_vhci_priv_t        *svp = NULL;
8081 8190          struct scsi_address     *pap = NULL;
8082 8191          scsi_hba_tran_t         *hba = NULL;
8083 8192          int                     sps;
8084 8193          int                     mps_flag;
8085 8194          int                     rval = 0;
8086 8195  
8087 8196          mps_flag = (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH);
8088 8197          if (pip) {
8089 8198                  /*
8090 8199                   * If the call is from vhci_pathinfo_state_change,
8091 8200                   * then this path was busy and is becoming ready to accept IO.
8092 8201                   */
8093 8202                  ASSERT(ap != NULL);
8094 8203                  hba = ap->a_hba_tran;
8095 8204                  ASSERT(hba != NULL);
8096 8205                  rval = scsi_ifsetcap(ap, cap, val, whom);
8097 8206  
8098 8207                  VHCI_DEBUG(2, (CE_NOTE, NULL,
8099 8208                      "!vhci_pHCI_cap: only on path %p, ap %p, rval %x\n",
8100 8209                      (void *)pip, (void *)ap, rval));
8101 8210  
8102 8211                  return (rval);
8103 8212          }
8104 8213  
8105 8214          /*
8106 8215           * Set capability on all the pHCIs.
8107 8216           * If any path is busy, then the capability would be set by
8108 8217           * vhci_pathinfo_state_change.
8109 8218           */
8110 8219  
8111 8220          cdip = ADDR2DIP(ap);
8112 8221          ASSERT(cdip != NULL);
8113 8222          sps = mdi_select_path(cdip, NULL, mps_flag, NULL, &pip);
8114 8223          if ((sps != MDI_SUCCESS) || (pip == NULL)) {
8115 8224                  VHCI_DEBUG(2, (CE_WARN, NULL,
8116 8225                      "!vhci_pHCI_cap: Unable to get a path, dip 0x%p",
8117 8226                      (void *)cdip));
8118 8227                  return (0);
8119 8228          }
8120 8229  
8121 8230  again:
8122 8231          svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
8123 8232          if (svp == NULL) {
8124 8233                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_pHCI_cap: "
8125 8234                      "priv is NULL, pip 0x%p", (void *)pip));
8126 8235                  mdi_rele_path(pip);
8127 8236                  return (rval);
8128 8237          }
8129 8238  
8130 8239          if (svp->svp_psd == NULL) {
8131 8240                  VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_pHCI_cap: "
8132 8241                      "psd is NULL, pip 0x%p, svp 0x%p",
8133 8242                      (void *)pip, (void *)svp));
8134 8243                  mdi_rele_path(pip);
8135 8244                  return (rval);
8136 8245          }
8137 8246  
8138 8247          pap = &svp->svp_psd->sd_address;
8139 8248          ASSERT(pap != NULL);
8140 8249          hba = pap->a_hba_tran;
8141 8250          ASSERT(hba != NULL);
8142 8251  
8143 8252          if (hba->tran_setcap != NULL) {
8144 8253                  rval = scsi_ifsetcap(pap, cap, val, whom);
8145 8254  
8146 8255                  VHCI_DEBUG(2, (CE_NOTE, NULL,
8147 8256                      "!vhci_pHCI_cap: path %p, ap %p, rval %x\n",
8148 8257                      (void *)pip, (void *)ap, rval));
8149 8258  
8150 8259                  /*
8151 8260                   * Select next path and issue the setcap, repeat
8152 8261                   * until all paths are exhausted
8153 8262                   */
8154 8263                  sps = mdi_select_path(cdip, NULL, mps_flag, pip, &npip);
8155 8264                  if ((sps != MDI_SUCCESS) || (npip == NULL)) {
8156 8265                          mdi_rele_path(pip);
8157 8266                          return (1);
8158 8267                  }
8159 8268                  mdi_rele_path(pip);
8160 8269                  pip = npip;
8161 8270                  goto again;
8162 8271          }
8163 8272          mdi_rele_path(pip);
8164 8273          return (rval);
8165 8274  }
8166 8275  
8167 8276  static int
8168 8277  vhci_scsi_bus_config(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
8169 8278      void *arg, dev_info_t **child)
8170 8279  {
8171 8280          char *guid;
8172 8281  
8173 8282          if (vhci_bus_config_debug)
8174 8283                  flags |= NDI_DEVI_DEBUG;
8175 8284  
8176 8285          if (op == BUS_CONFIG_ONE || op == BUS_UNCONFIG_ONE)
8177 8286                  guid = vhci_devnm_to_guid((char *)arg);
8178 8287          else
8179 8288                  guid = NULL;
8180 8289  
8181 8290          if (mdi_vhci_bus_config(pdip, flags, op, arg, child, guid)
8182 8291              == MDI_SUCCESS)
8183 8292                  return (NDI_SUCCESS);
8184 8293          else
8185 8294                  return (NDI_FAILURE);
8186 8295  }
8187 8296  
8188 8297  static int
8189 8298  vhci_scsi_bus_unconfig(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
8190 8299      void *arg)
8191 8300  {
8192 8301          if (vhci_bus_config_debug)
8193 8302                  flags |= NDI_DEVI_DEBUG;
8194 8303  
8195 8304          return (ndi_busop_bus_unconfig(pdip, flags, op, arg));
8196 8305  }
8197 8306  
8198 8307  /*
8199 8308   * Take the original vhci_pkt, create a duplicate of the pkt for resending
8200 8309   * as though it originated in ssd.
8201 8310   */
8202 8311  static struct scsi_pkt *
8203 8312  vhci_create_retry_pkt(struct vhci_pkt *vpkt)
8204 8313  {
8205 8314          struct vhci_pkt *new_vpkt = NULL;
8206 8315          struct scsi_pkt *pkt = NULL;
8207 8316  
8208 8317          scsi_vhci_priv_t *svp = (scsi_vhci_priv_t *)
8209 8318              mdi_pi_get_vhci_private(vpkt->vpkt_path);
8210 8319  
8211 8320          /*
8212 8321           * Ensure consistent data at completion time by setting PKT_CONSISTENT
8213 8322           */
8214 8323          pkt = vhci_scsi_init_pkt(&svp->svp_psd->sd_address, pkt,
8215 8324              vpkt->vpkt_tgt_init_bp, vpkt->vpkt_tgt_init_cdblen,
8216 8325              vpkt->vpkt_tgt_init_scblen, 0, PKT_CONSISTENT, NULL_FUNC, NULL);
8217 8326          if (pkt != NULL) {
8218 8327                  new_vpkt = TGTPKT2VHCIPKT(pkt);
8219 8328  
8220 8329                  pkt->pkt_address = vpkt->vpkt_tgt_pkt->pkt_address;
8221 8330                  pkt->pkt_flags = vpkt->vpkt_tgt_pkt->pkt_flags;
8222 8331                  pkt->pkt_time = vpkt->vpkt_tgt_pkt->pkt_time;
8223 8332                  pkt->pkt_comp = vpkt->vpkt_tgt_pkt->pkt_comp;
8224 8333  
8225 8334                  pkt->pkt_resid = 0;
8226 8335                  pkt->pkt_statistics = 0;
8227 8336                  pkt->pkt_reason = 0;
8228 8337  
8229 8338                  bcopy(vpkt->vpkt_tgt_pkt->pkt_cdbp,
8230 8339                      pkt->pkt_cdbp, vpkt->vpkt_tgt_init_cdblen);
8231 8340  
8232 8341                  /*
8233 8342                   * Save a pointer to the original vhci_pkt
8234 8343                   */
8235 8344                  new_vpkt->vpkt_org_vpkt = vpkt;
8236 8345          }
8237 8346  
8238 8347          return (pkt);
8239 8348  }
8240 8349  
8241 8350  /*
8242 8351   * Copy the successful completion information from the hba packet into
8243 8352   * the original target pkt from the upper layer.  Returns the original
8244 8353   * vpkt and destroys the new vpkt from the internal retry.
8245 8354   */
8246 8355  static struct vhci_pkt *
8247 8356  vhci_sync_retry_pkt(struct vhci_pkt *vpkt)
8248 8357  {
8249 8358          struct vhci_pkt         *ret_vpkt = NULL;
8250 8359          struct scsi_pkt         *tpkt = NULL;
8251 8360          struct scsi_pkt         *hba_pkt = NULL;
8252 8361          scsi_vhci_priv_t        *svp = (scsi_vhci_priv_t *)
8253 8362              mdi_pi_get_vhci_private(vpkt->vpkt_path);
8254 8363  
8255 8364          ASSERT(vpkt->vpkt_org_vpkt != NULL);
8256 8365          VHCI_DEBUG(0, (CE_NOTE, NULL, "vhci_sync_retry_pkt: Retry pkt "
8257 8366              "completed successfully!\n"));
8258 8367  
8259 8368          ret_vpkt = vpkt->vpkt_org_vpkt;
8260 8369          tpkt = ret_vpkt->vpkt_tgt_pkt;
8261 8370          hba_pkt = vpkt->vpkt_hba_pkt;
8262 8371  
8263 8372          /*
8264 8373           * Copy the good status into the target driver's packet
8265 8374           */
8266 8375          *(tpkt->pkt_scbp) = *(hba_pkt->pkt_scbp);
8267 8376          tpkt->pkt_resid = hba_pkt->pkt_resid;
8268 8377          tpkt->pkt_state = hba_pkt->pkt_state;
8269 8378          tpkt->pkt_statistics = hba_pkt->pkt_statistics;
8270 8379          tpkt->pkt_reason = hba_pkt->pkt_reason;
8271 8380  
8272 8381          /*
8273 8382           * Destroy the internally created vpkt for the retry
8274 8383           */
8275 8384          vhci_scsi_destroy_pkt(&svp->svp_psd->sd_address,
8276 8385              vpkt->vpkt_tgt_pkt);
8277 8386  
8278 8387          return (ret_vpkt);
8279 8388  }
8280 8389  
8281 8390  /* restart the request sense request */
8282 8391  static void
8283 8392  vhci_uscsi_restart_sense(void *arg)
8284 8393  {
8285 8394          struct buf      *rqbp;
8286 8395          struct buf      *bp;
8287 8396          struct scsi_pkt *rqpkt = (struct scsi_pkt *)arg;
8288 8397          mp_uscsi_cmd_t  *mp_uscmdp;
8289 8398  
8290 8399          VHCI_DEBUG(4, (CE_WARN, NULL,
8291 8400              "vhci_uscsi_restart_sense: enter: rqpkt: %p", (void *)rqpkt));
8292 8401  
8293 8402          if (scsi_transport(rqpkt) != TRAN_ACCEPT) {
8294 8403                  /* if it fails - need to wakeup the original command */
8295 8404                  mp_uscmdp = rqpkt->pkt_private;
8296 8405                  bp = mp_uscmdp->cmdbp;
8297 8406                  rqbp = mp_uscmdp->rqbp;
8298 8407                  ASSERT(mp_uscmdp && bp && rqbp);
8299 8408                  scsi_free_consistent_buf(rqbp);
8300 8409                  scsi_destroy_pkt(rqpkt);
8301 8410                  bp->b_resid = bp->b_bcount;
8302 8411                  bioerror(bp, EIO);
8303 8412                  biodone(bp);
8304 8413          }
8305 8414  }
8306 8415  
8307 8416  /*
8308 8417   * auto-rqsense is not enabled so we have to retrieve the request sense
8309 8418   * manually.
8310 8419   */
8311 8420  static int
8312 8421  vhci_uscsi_send_sense(struct scsi_pkt *pkt, mp_uscsi_cmd_t *mp_uscmdp)
8313 8422  {
8314 8423          struct buf              *rqbp, *cmdbp;
8315 8424          struct scsi_pkt         *rqpkt;
8316 8425          int                     rval = 0;
8317 8426  
8318 8427          cmdbp = mp_uscmdp->cmdbp;
8319 8428          ASSERT(cmdbp != NULL);
8320 8429  
8321 8430          VHCI_DEBUG(4, (CE_WARN, NULL,
8322 8431              "vhci_uscsi_send_sense: enter: bp: %p pkt: %p scmd: %p",
8323 8432              (void *)cmdbp, (void *)pkt, (void *)mp_uscmdp));
8324 8433          /* set up the packet information and cdb */
8325 8434          if ((rqbp = scsi_alloc_consistent_buf(mp_uscmdp->ap, NULL,
8326 8435              SENSE_LENGTH, B_READ, NULL, NULL)) == NULL) {
8327 8436                  return (-1);
8328 8437          }
8329 8438  
8330 8439          if ((rqpkt = scsi_init_pkt(mp_uscmdp->ap, NULL, rqbp,
8331 8440              CDB_GROUP0, 1, 0, PKT_CONSISTENT, NULL, NULL)) == NULL) {
  
    | 
      ↓ open down ↓ | 
    1340 lines elided | 
    
      ↑ open up ↑ | 
  
8332 8441                  scsi_free_consistent_buf(rqbp);
8333 8442                  return (-1);
8334 8443          }
8335 8444  
8336 8445          (void) scsi_setup_cdb((union scsi_cdb *)(intptr_t)rqpkt->pkt_cdbp,
8337 8446              SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
8338 8447  
8339 8448          mp_uscmdp->rqbp = rqbp;
8340 8449          rqbp->b_private = mp_uscmdp;
8341 8450          rqpkt->pkt_flags |= FLAG_SENSING;
8342      -        rqpkt->pkt_time = 60;
     8451 +        rqpkt->pkt_time = vhci_io_time;
8343 8452          rqpkt->pkt_comp = vhci_uscsi_iodone;
8344 8453          rqpkt->pkt_private = mp_uscmdp;
8345 8454  
8346 8455          /*
8347 8456           * NOTE: This code path is related to MPAPI uscsi(7I), so path
8348 8457           * selection is not based on path_instance.
8349 8458           */
8350 8459          if (scsi_pkt_allocated_correctly(rqpkt))
8351 8460                  rqpkt->pkt_path_instance = 0;
8352 8461  
8353 8462          switch (scsi_transport(rqpkt)) {
8354 8463          case TRAN_ACCEPT:
8355 8464                  VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8356 8465                      "transport accepted."));
8357 8466                  break;
8358 8467          case TRAN_BUSY:
8359 8468                  VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8360 8469                      "transport busy, setting timeout."));
8361 8470                  vhci_restart_timeid = timeout(vhci_uscsi_restart_sense, rqpkt,
8362 8471                      (drv_usectohz(5 * 1000000)));
8363 8472                  break;
8364 8473          default:
8365 8474                  VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8366 8475                      "transport failed"));
8367 8476                  scsi_free_consistent_buf(rqbp);
8368 8477                  scsi_destroy_pkt(rqpkt);
8369 8478                  rval = -1;
8370 8479          }
8371 8480  
8372 8481          return (rval);
8373 8482  }
8374 8483  
8375 8484  /*
8376 8485   * done routine for the mpapi uscsi command - this is behaving as though
8377 8486   * FLAG_DIAGNOSE is set meaning there are no retries except for a manual
8378 8487   * request sense.
8379 8488   */
8380 8489  void
8381 8490  vhci_uscsi_iodone(struct scsi_pkt *pkt)
8382 8491  {
8383 8492          struct buf                      *bp;
8384 8493          mp_uscsi_cmd_t                  *mp_uscmdp;
8385 8494          struct uscsi_cmd                *uscmdp;
8386 8495          struct scsi_arq_status          *arqstat;
8387 8496          int                             err;
8388 8497  
8389 8498          mp_uscmdp = (mp_uscsi_cmd_t *)pkt->pkt_private;
8390 8499          uscmdp = mp_uscmdp->uscmdp;
8391 8500          bp = mp_uscmdp->cmdbp;
8392 8501          ASSERT(bp != NULL);
8393 8502          VHCI_DEBUG(4, (CE_WARN, NULL,
8394 8503              "vhci_uscsi_iodone: enter: bp: %p pkt: %p scmd: %p",
8395 8504              (void *)bp, (void *)pkt, (void *)mp_uscmdp));
8396 8505          /* Save the status and the residual into the uscsi_cmd struct */
8397 8506          uscmdp->uscsi_status = ((*(pkt)->pkt_scbp) & STATUS_MASK);
8398 8507          uscmdp->uscsi_resid = bp->b_resid;
8399 8508  
8400 8509          /* return on a very successful command */
8401 8510          if (pkt->pkt_reason == CMD_CMPLT &&
8402 8511              SCBP_C(pkt) == 0 && ((pkt->pkt_flags & FLAG_SENSING) == 0) &&
8403 8512              pkt->pkt_resid == 0) {
8404 8513                  mdi_pi_kstat_iosupdate(mp_uscmdp->pip, bp);
8405 8514                  scsi_destroy_pkt(pkt);
8406 8515                  biodone(bp);
8407 8516                  return;
8408 8517          }
8409 8518          VHCI_DEBUG(4, (CE_NOTE, NULL, "iodone: reason=0x%x "
8410 8519              " pkt_resid=%ld pkt_state: 0x%x b_count: %ld b_resid: %ld",
8411 8520              pkt->pkt_reason, pkt->pkt_resid,
8412 8521              pkt->pkt_state, bp->b_bcount, bp->b_resid));
8413 8522  
8414 8523          err = EIO;
8415 8524  
8416 8525          arqstat = (struct scsi_arq_status *)(intptr_t)(pkt->pkt_scbp);
8417 8526          if (pkt->pkt_reason != CMD_CMPLT) {
8418 8527                  /*
8419 8528                   * The command did not complete.
8420 8529                   */
8421 8530                  VHCI_DEBUG(4, (CE_NOTE, NULL,
8422 8531                      "vhci_uscsi_iodone: command did not complete."
8423 8532                      " reason: %x flag: %x", pkt->pkt_reason, pkt->pkt_flags));
8424 8533                  if (pkt->pkt_flags & FLAG_SENSING) {
8425 8534                          MDI_PI_ERRSTAT(mp_uscmdp->pip, MDI_PI_TRANSERR);
8426 8535                  } else if (pkt->pkt_reason == CMD_TIMEOUT) {
8427 8536                          MDI_PI_ERRSTAT(mp_uscmdp->pip, MDI_PI_HARDERR);
8428 8537                          err = ETIMEDOUT;
8429 8538                  }
8430 8539          } else if (pkt->pkt_state & STATE_ARQ_DONE && mp_uscmdp->arq_enabled) {
8431 8540                  /*
8432 8541                   * The auto-rqsense happened, and the packet has a filled-in
8433 8542                   * scsi_arq_status structure, pointed to by pkt_scbp.
8434 8543                   */
8435 8544                  VHCI_DEBUG(4, (CE_NOTE, NULL,
8436 8545                      "vhci_uscsi_iodone: received auto-requested sense"));
8437 8546                  if (uscmdp->uscsi_flags & USCSI_RQENABLE) {
8438 8547                          /* get the amount of data to copy into rqbuf */
8439 8548                          int rqlen = SENSE_LENGTH - arqstat->sts_rqpkt_resid;
8440 8549                          rqlen = min(((int)uscmdp->uscsi_rqlen), rqlen);
8441 8550                          uscmdp->uscsi_rqresid = uscmdp->uscsi_rqlen - rqlen;
8442 8551                          uscmdp->uscsi_rqstatus =
8443 8552                              *((char *)&arqstat->sts_rqpkt_status);
8444 8553                          if (uscmdp->uscsi_rqbuf && uscmdp->uscsi_rqlen &&
8445 8554                              rqlen != 0) {
8446 8555                                  bcopy(&(arqstat->sts_sensedata),
8447 8556                                      uscmdp->uscsi_rqbuf, rqlen);
8448 8557                          }
8449 8558                          mdi_pi_kstat_iosupdate(mp_uscmdp->pip, bp);
8450 8559                          VHCI_DEBUG(4, (CE_NOTE, NULL,
8451 8560                              "vhci_uscsi_iodone: ARQ "
8452 8561                              "uscsi_rqstatus=0x%x uscsi_rqresid=%d rqlen: %d "
8453 8562                              "xfer: %d rqpkt_resid: %d\n",
8454 8563                              uscmdp->uscsi_rqstatus, uscmdp->uscsi_rqresid,
8455 8564                              uscmdp->uscsi_rqlen, rqlen,
8456 8565                              arqstat->sts_rqpkt_resid));
8457 8566                  }
8458 8567          } else if (pkt->pkt_flags & FLAG_SENSING) {
8459 8568                  struct buf *rqbp;
8460 8569                  struct scsi_status *rqstatus;
8461 8570  
8462 8571                  rqstatus = (struct scsi_status *)pkt->pkt_scbp;
8463 8572                  /* a manual request sense was done - get the information */
8464 8573                  if (uscmdp->uscsi_flags & USCSI_RQENABLE) {
8465 8574                          int rqlen = SENSE_LENGTH - pkt->pkt_resid;
8466 8575  
8467 8576                          rqbp = mp_uscmdp->rqbp;
8468 8577                          /* get the amount of data to copy into rqbuf */
8469 8578                          rqlen = min(((int)uscmdp->uscsi_rqlen), rqlen);
8470 8579                          uscmdp->uscsi_rqresid = uscmdp->uscsi_rqlen - rqlen;
8471 8580                          uscmdp->uscsi_rqstatus = *((char *)rqstatus);
8472 8581                          if (uscmdp->uscsi_rqlen && uscmdp->uscsi_rqbuf) {
8473 8582                                  bcopy(rqbp->b_un.b_addr, uscmdp->uscsi_rqbuf,
8474 8583                                      rqlen);
8475 8584                          }
8476 8585                          MDI_PI_ERRSTAT(mp_uscmdp->pip, MDI_PI_TRANSERR);
8477 8586                          scsi_free_consistent_buf(rqbp);
8478 8587                  }
8479 8588                  VHCI_DEBUG(4, (CE_NOTE, NULL, "vhci_uscsi_iodone: FLAG_SENSING"
8480 8589                      "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
8481 8590                      uscmdp->uscsi_rqstatus, uscmdp->uscsi_rqresid));
8482 8591          } else {
8483 8592                  struct scsi_status *status =
8484 8593                      (struct scsi_status *)pkt->pkt_scbp;
8485 8594                  /*
8486 8595                   * Command completed and we're not getting sense. Check for
8487 8596                   * errors and decide what to do next.
8488 8597                   */
8489 8598                  VHCI_DEBUG(4, (CE_NOTE, NULL,
8490 8599                      "vhci_uscsi_iodone: command appears complete: reason: %x",
8491 8600                      pkt->pkt_reason));
8492 8601                  if (status->sts_chk) {
8493 8602                          /* need to manually get the request sense */
8494 8603                          if (vhci_uscsi_send_sense(pkt, mp_uscmdp) == 0) {
8495 8604                                  scsi_destroy_pkt(pkt);
8496 8605                                  return;
8497 8606                          }
8498 8607                  } else {
8499 8608                          VHCI_DEBUG(4, (CE_NOTE, NULL,
8500 8609                              "vhci_chk_err: appears complete"));
8501 8610                          err = 0;
8502 8611                          mdi_pi_kstat_iosupdate(mp_uscmdp->pip, bp);
8503 8612                          if (pkt->pkt_resid) {
8504 8613                                  bp->b_resid += pkt->pkt_resid;
8505 8614                          }
8506 8615                  }
8507 8616          }
8508 8617  
8509 8618          if (err) {
8510 8619                  if (bp->b_resid == 0)
8511 8620                          bp->b_resid = bp->b_bcount;
8512 8621                  bioerror(bp, err);
8513 8622                  bp->b_flags |= B_ERROR;
8514 8623          }
8515 8624  
8516 8625          scsi_destroy_pkt(pkt);
8517 8626          biodone(bp);
8518 8627  
8519 8628          VHCI_DEBUG(4, (CE_WARN, NULL, "vhci_uscsi_iodone: exit"));
8520 8629  }
8521 8630  
8522 8631  /*
8523 8632   * start routine for the mpapi uscsi command
8524 8633   */
8525 8634  int
8526 8635  vhci_uscsi_iostart(struct buf *bp)
8527 8636  {
8528 8637          struct scsi_pkt         *pkt;
8529 8638          struct uscsi_cmd        *uscmdp;
8530 8639          mp_uscsi_cmd_t          *mp_uscmdp;
8531 8640          int                     stat_size, rval;
8532 8641          int                     retry = 0;
8533 8642  
8534 8643          ASSERT(bp->b_private != NULL);
8535 8644  
8536 8645          mp_uscmdp = (mp_uscsi_cmd_t *)bp->b_private;
8537 8646          uscmdp = mp_uscmdp->uscmdp;
8538 8647          if (uscmdp->uscsi_flags & USCSI_RQENABLE) {
8539 8648                  stat_size = SENSE_LENGTH;
8540 8649          } else {
8541 8650                  stat_size = 1;
8542 8651          }
8543 8652  
8544 8653          pkt = scsi_init_pkt(mp_uscmdp->ap, NULL, bp, uscmdp->uscsi_cdblen,
8545 8654              stat_size, 0, 0, SLEEP_FUNC, NULL);
8546 8655          if (pkt == NULL) {
  
    | 
      ↓ open down ↓ | 
    194 lines elided | 
    
      ↑ open up ↑ | 
  
8547 8656                  VHCI_DEBUG(4, (CE_NOTE, NULL,
8548 8657                      "vhci_uscsi_iostart: rval: EINVAL"));
8549 8658                  bp->b_resid = bp->b_bcount;
8550 8659                  uscmdp->uscsi_resid = bp->b_bcount;
8551 8660                  bioerror(bp, EINVAL);
8552 8661                  biodone(bp);
8553 8662                  return (EINVAL);
8554 8663          }
8555 8664  
8556 8665          pkt->pkt_time = uscmdp->uscsi_timeout;
     8666 +        if (pkt->pkt_time == 0)
     8667 +                pkt->pkt_time = vhci_io_time;
     8668 +
8557 8669          bcopy(uscmdp->uscsi_cdb, pkt->pkt_cdbp, (size_t)uscmdp->uscsi_cdblen);
8558 8670          pkt->pkt_comp = vhci_uscsi_iodone;
8559 8671          pkt->pkt_private = mp_uscmdp;
8560 8672          if (uscmdp->uscsi_flags & USCSI_SILENT)
8561 8673                  pkt->pkt_flags |= FLAG_SILENT;
8562 8674          if (uscmdp->uscsi_flags & USCSI_ISOLATE)
8563 8675                  pkt->pkt_flags |= FLAG_ISOLATE;
8564 8676          if (uscmdp->uscsi_flags & USCSI_DIAGNOSE)
8565 8677                  pkt->pkt_flags |= FLAG_DIAGNOSE;
8566 8678          if (uscmdp->uscsi_flags & USCSI_RENEGOT) {
8567 8679                  pkt->pkt_flags |= FLAG_RENEGOTIATE_WIDE_SYNC;
8568 8680          }
8569 8681          VHCI_DEBUG(4, (CE_WARN, NULL,
8570 8682              "vhci_uscsi_iostart: ap: %p pkt: %p pcdbp: %p uscmdp: %p"
8571 8683              " ucdbp: %p pcdblen: %d bp: %p count: %ld pip: %p"
8572 8684              " stat_size: %d",
8573 8685              (void *)mp_uscmdp->ap, (void *)pkt, (void *)pkt->pkt_cdbp,
8574 8686              (void *)uscmdp, (void *)uscmdp->uscsi_cdb, pkt->pkt_cdblen,
8575 8687              (void *)bp, bp->b_bcount, (void *)mp_uscmdp->pip, stat_size));
8576 8688  
8577 8689          /*
8578 8690           * NOTE: This code path is related to MPAPI uscsi(7I), so path
8579 8691           * selection is not based on path_instance.
8580 8692           */
8581 8693          if (scsi_pkt_allocated_correctly(pkt))
8582 8694                  pkt->pkt_path_instance = 0;
8583 8695  
8584 8696          while (((rval = scsi_transport(pkt)) == TRAN_BUSY) &&
8585 8697              retry < vhci_uscsi_retry_count) {
8586 8698                  delay(drv_usectohz(vhci_uscsi_delay));
8587 8699                  retry++;
8588 8700          }
8589 8701          if (retry >= vhci_uscsi_retry_count) {
8590 8702                  VHCI_DEBUG(4, (CE_NOTE, NULL,
8591 8703                      "vhci_uscsi_iostart: tran_busy - retry: %d", retry));
8592 8704          }
8593 8705          switch (rval) {
8594 8706          case TRAN_ACCEPT:
8595 8707                  rval =  0;
8596 8708                  break;
8597 8709  
8598 8710          default:
8599 8711                  VHCI_DEBUG(4, (CE_NOTE, NULL,
8600 8712                      "vhci_uscsi_iostart: rval: %d count: %ld res: %ld",
8601 8713                      rval, bp->b_bcount, bp->b_resid));
8602 8714                  bp->b_resid = bp->b_bcount;
8603 8715                  uscmdp->uscsi_resid = bp->b_bcount;
8604 8716                  bioerror(bp, EIO);
8605 8717                  scsi_destroy_pkt(pkt);
8606 8718                  biodone(bp);
8607 8719                  rval = EIO;
8608 8720                  MDI_PI_ERRSTAT(mp_uscmdp->pip, MDI_PI_TRANSERR);
8609 8721                  break;
8610 8722          }
8611 8723          VHCI_DEBUG(4, (CE_NOTE, NULL,
8612 8724              "vhci_uscsi_iostart: exit: rval: %d", rval));
8613 8725          return (rval);
8614 8726  }
8615 8727  
8616 8728  /* ARGSUSED */
8617 8729  static struct scsi_failover_ops *
8618 8730  vhci_dev_fo(dev_info_t *vdip, struct scsi_device *psd,
8619 8731      void **ctprivp, char **fo_namep)
8620 8732  {
8621 8733          struct scsi_failover_ops        *sfo;
8622 8734          char                            *sfo_name;
8623 8735          char                            *override;
8624 8736          struct scsi_failover            *sf;
8625 8737  
8626 8738          ASSERT(psd && psd->sd_inq);
8627 8739          if ((psd == NULL) || (psd->sd_inq == NULL)) {
8628 8740                  VHCI_DEBUG(1, (CE_NOTE, NULL,
8629 8741                      "!vhci_dev_fo:return NULL no scsi_device or inquiry"));
8630 8742                  return (NULL);
8631 8743          }
8632 8744  
8633 8745          /*
8634 8746           * Determine if device is supported under scsi_vhci, and select
8635 8747           * failover module.
8636 8748           *
8637 8749           * See if there is a scsi_vhci.conf file override for this devices's
8638 8750           * VID/PID. The following values can be returned:
8639 8751           *
8640 8752           * NULL         If the NULL is returned then there is no scsi_vhci.conf
8641 8753           *              override.  For NULL, we determine the failover_ops for
8642 8754           *              this device by checking the sfo_device_probe entry
8643 8755           *              point for each 'fops' module, in order.
8644 8756           *
8645 8757           *              NOTE: Correct operation may depend on module ordering
8646 8758           *              of 'specific' (failover modules that are completely
8647 8759           *              VID/PID table based) to 'generic' (failover modules
8648 8760           *              that based on T10 standards like TPGS).  Currently,
8649 8761           *              the value of 'ddi-forceload' in scsi_vhci.conf is used
8650 8762           *              to establish the module list and probe order.
8651 8763           *
8652 8764           * "NONE"       If value "NONE" is returned then there is a
8653 8765           *              scsi_vhci.conf VID/PID override to indicate the device
8654 8766           *              should not be supported under scsi_vhci (even if there
8655 8767           *              is an 'fops' module supporting the device).
8656 8768           *
8657 8769           * "<other>"    If another value is returned then that value is the
8658 8770           *              name of the 'fops' module that should be used.
8659 8771           */
8660 8772          sfo = NULL;     /* "NONE" */
8661 8773          override = scsi_get_device_type_string(
8662 8774              "scsi-vhci-failover-override", vdip, psd);
8663 8775          if (override == NULL) {
8664 8776                  /* NULL: default: select based on sfo_device_probe results */
8665 8777                  for (sf = scsi_failover_table; sf->sf_mod; sf++) {
8666 8778                          if ((sf->sf_sfo == NULL) ||
8667 8779                              sf->sf_sfo->sfo_device_probe(psd, psd->sd_inq,
8668 8780                              ctprivp) == SFO_DEVICE_PROBE_PHCI)
8669 8781                                  continue;
8670 8782  
8671 8783                          /* found failover module, supported under scsi_vhci */
8672 8784                          sfo = sf->sf_sfo;
8673 8785                          if (fo_namep && (*fo_namep == NULL)) {
8674 8786                                  sfo_name = i_ddi_strdup(sfo->sfo_name,
8675 8787                                      KM_SLEEP);
8676 8788                                  *fo_namep = sfo_name;
8677 8789                          }
8678 8790                          break;
8679 8791                  }
8680 8792          } else if (strcasecmp(override, "NONE")) {
8681 8793                  /* !"NONE": select based on driver.conf specified name */
8682 8794                  for (sf = scsi_failover_table, sfo = NULL; sf->sf_mod; sf++) {
8683 8795                          if ((sf->sf_sfo == NULL) ||
8684 8796                              (sf->sf_sfo->sfo_name == NULL) ||
8685 8797                              strcmp(override, sf->sf_sfo->sfo_name))
8686 8798                                  continue;
8687 8799  
8688 8800                          /*
8689 8801                           * NOTE: If sfo_device_probe() has side-effects,
8690 8802                           * including setting *ctprivp, these are not going
8691 8803                           * to occur with override config.
8692 8804                           */
8693 8805  
8694 8806                          /* found failover module, supported under scsi_vhci */
8695 8807                          sfo = sf->sf_sfo;
8696 8808                          if (fo_namep && (*fo_namep == NULL)) {
8697 8809                                  sfo_name = kmem_alloc(strlen("conf ") +
8698 8810                                      strlen(sfo->sfo_name) + 1, KM_SLEEP);
8699 8811                                  (void) sprintf(sfo_name, "conf %s",
8700 8812                                      sfo->sfo_name);
8701 8813                                  *fo_namep = sfo_name;
8702 8814                          }
8703 8815                          break;
8704 8816                  }
8705 8817          }
8706 8818          if (override)
8707 8819                  kmem_free(override, strlen(override) + 1);
8708 8820          return (sfo);
8709 8821  }
8710 8822  
8711 8823  /*
8712 8824   * Determine the device described by cinfo should be enumerated under
8713 8825   * the vHCI or the pHCI - if there is a failover ops then device is
8714 8826   * supported under vHCI.  By agreement with SCSA cinfo is a pointer
8715 8827   * to a scsi_device structure associated with a decorated pHCI probe node.
8716 8828   */
8717 8829  /* ARGSUSED */
8718 8830  int
8719 8831  vhci_is_dev_supported(dev_info_t *vdip, dev_info_t *pdip, void *cinfo)
8720 8832  {
8721 8833          struct scsi_device      *psd = (struct scsi_device *)cinfo;
8722 8834  
8723 8835          return (vhci_dev_fo(vdip, psd, NULL, NULL) ? MDI_SUCCESS : MDI_FAILURE);
8724 8836  }
8725 8837  
8726 8838  
8727 8839  #ifdef DEBUG
8728 8840  extern struct scsi_key_strings scsi_cmds[];
8729 8841  
8730 8842  static char *
8731 8843  vhci_print_scsi_cmd(char cmd)
8732 8844  {
8733 8845          char tmp[64];
8734 8846          char *cpnt;
8735 8847  
8736 8848          cpnt = scsi_cmd_name(cmd, scsi_cmds, tmp);
8737 8849          /* tmp goes out of scope on return and caller sees garbage */
8738 8850          if (cpnt == tmp) {
8739 8851                  cpnt = "Unknown Command";
8740 8852          }
8741 8853          return (cpnt);
8742 8854  }
8743 8855  
8744 8856  extern uchar_t  scsi_cdb_size[];
8745 8857  
8746 8858  static void
8747 8859  vhci_print_cdb(dev_info_t *dip, uint_t level, char *title, uchar_t *cdb)
8748 8860  {
8749 8861          int len = scsi_cdb_size[CDB_GROUPID(cdb[0])];
8750 8862          char buf[256];
8751 8863  
8752 8864          if (level == CE_NOTE) {
8753 8865                  vhci_log(level, dip, "path cmd %s\n",
8754 8866                      vhci_print_scsi_cmd(*cdb));
8755 8867                  return;
8756 8868          }
8757 8869  
8758 8870          (void) sprintf(buf, "%s for cmd(%s)", title, vhci_print_scsi_cmd(*cdb));
8759 8871          vhci_clean_print(dip, level, buf, cdb, len);
8760 8872  }
8761 8873  
8762 8874  static void
8763 8875  vhci_clean_print(dev_info_t *dev, uint_t level, char *title, uchar_t *data,
8764 8876      int len)
8765 8877  {
8766 8878          int     i;
8767 8879          int     c;
8768 8880          char    *format;
8769 8881          char    buf[256];
8770 8882          uchar_t byte;
8771 8883  
8772 8884          (void) sprintf(buf, "%s:\n", title);
8773 8885          vhci_log(level, dev, "%s", buf);
8774 8886          level = CE_CONT;
8775 8887          for (i = 0; i < len; ) {
8776 8888                  buf[0] = 0;
8777 8889                  for (c = 0; c < 8 && i < len; c++, i++) {
8778 8890                          byte = (uchar_t)data[i];
8779 8891                          if (byte < 0x10)
8780 8892                                  format = "0x0%x ";
8781 8893                          else
8782 8894                                  format = "0x%x ";
8783 8895                          (void) sprintf(&buf[(int)strlen(buf)], format, byte);
8784 8896                  }
8785 8897                  (void) sprintf(&buf[(int)strlen(buf)], "\n");
8786 8898  
8787 8899                  vhci_log(level, dev, "%s\n", buf);
8788 8900          }
8789 8901  }
8790 8902  #endif
8791 8903  static void
8792 8904  vhci_invalidate_mpapi_lu(struct scsi_vhci *vhci, scsi_vhci_lun_t *vlun)
8793 8905  {
8794 8906          char                    *svl_wwn;
8795 8907          mpapi_item_list_t       *ilist;
8796 8908          mpapi_lu_data_t         *ld;
8797 8909  
8798 8910          if (vlun == NULL) {
8799 8911                  return;
8800 8912          } else {
8801 8913                  svl_wwn = vlun->svl_lun_wwn;
8802 8914          }
8803 8915  
8804 8916          ilist = vhci->mp_priv->obj_hdr_list[MP_OBJECT_TYPE_MULTIPATH_LU]->head;
8805 8917  
8806 8918          while (ilist != NULL) {
8807 8919                  ld = (mpapi_lu_data_t *)(ilist->item->idata);
8808 8920                  if ((ld != NULL) && (strncmp(ld->prop.name, svl_wwn,
8809 8921                      strlen(svl_wwn)) == 0)) {
8810 8922                          ld->valid = 0;
8811 8923                          VHCI_DEBUG(6, (CE_WARN, NULL,
8812 8924                              "vhci_invalidate_mpapi_lu: "
8813 8925                              "Invalidated LU(%s)", svl_wwn));
8814 8926                          return;
8815 8927                  }
8816 8928                  ilist = ilist->next;
8817 8929          }
8818 8930          VHCI_DEBUG(6, (CE_WARN, NULL, "vhci_invalidate_mpapi_lu: "
8819 8931              "Could not find LU(%s) to invalidate.", svl_wwn));
8820 8932  }
  
    | 
      ↓ open down ↓ | 
    254 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX