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