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