1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2023 Tintri by DDN, Inc. All rights reserved.
14  * Copyright 2021 RackTop Systems, Inc.
15  */
16 
17 /*
18  * This file contains all routines necessary to interface with SCSA trans.
19  */
20 #include <smartpqi.h>
21 
22 /*
23  * []------------------------------------------------------------------[]
24  * | Forward declarations for SCSA trans routines.			|
25  * []------------------------------------------------------------------[]
26  */
27 static int pqi_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
28     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
29 static void pqi_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
30     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
31 static int pqi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
32 static int pqi_scsi_reset(struct scsi_address *ap, int level);
33 static int pqi_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
34 static int pqi_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
35 static int pqi_scsi_setcap(struct scsi_address *ap, char *cap, int value,
36     int tgtonly);
37 static struct scsi_pkt *pqi_init_pkt(struct scsi_address *ap,
38     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, int tgtlen,
39     int flags,  int (*callback)(), caddr_t arg);
40 static void pqi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
41 static void pqi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
42 static void pqi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
43 static int pqi_reset_notify(struct scsi_address *ap, int flag,
44     void (*callback)(caddr_t), caddr_t arg);
45 static int pqi_quiesce(dev_info_t *dip);
46 static int pqi_unquiesce(dev_info_t *dip);
47 static int pqi_bus_config(dev_info_t *pdip, uint_t flag,
48     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
49 
50 /* ---- Support method declaration ---- */
51 static int config_one(dev_info_t *pdip, pqi_state_t *s,  pqi_device_t *,
52     dev_info_t **childp);
53 static void abort_all(struct scsi_address *ap, pqi_state_t *s);
54 static int cmd_ext_alloc(pqi_cmd_t *cmd, int kf);
55 static void cmd_ext_free(pqi_cmd_t *cmd);
56 static boolean_t is_physical_dev(pqi_device_t *d);
57 static void cmd_timeout_scan(void *);
58 
59 boolean_t
smartpqi_register_hba(pqi_state_t * s)60 smartpqi_register_hba(pqi_state_t *s)
61 {
62 	scsi_hba_tran_t		*tran;
63 	int			flags;
64 	char			iport_str[16];
65 	int			instance = ddi_get_instance(s->s_dip);
66 
67 	tran = scsi_hba_tran_alloc(s->s_dip, SCSI_HBA_CANSLEEP);
68 	if (tran == NULL)
69 		return (B_FALSE);
70 	s->s_tran = tran;
71 
72 	tran->tran_hba_private		= s;
73 	tran->tran_tgt_private		= NULL;
74 
75 	tran->tran_tgt_init		= pqi_scsi_tgt_init;
76 	tran->tran_tgt_free		= pqi_scsi_tgt_free;
77 	tran->tran_tgt_probe		= scsi_hba_probe;
78 
79 	tran->tran_start		= pqi_start;
80 	tran->tran_reset		= pqi_scsi_reset;
81 	tran->tran_abort		= pqi_scsi_abort;
82 	tran->tran_getcap		= pqi_scsi_getcap;
83 	tran->tran_setcap		= pqi_scsi_setcap;
84 	tran->tran_bus_config		= pqi_bus_config;
85 
86 	tran->tran_init_pkt		= pqi_init_pkt;
87 	tran->tran_destroy_pkt		= pqi_destroy_pkt;
88 	tran->tran_dmafree		= pqi_dmafree;
89 	tran->tran_sync_pkt		= pqi_sync_pkt;
90 
91 	tran->tran_reset_notify		= pqi_reset_notify;
92 	tran->tran_quiesce		= pqi_quiesce;
93 	tran->tran_unquiesce		= pqi_unquiesce;
94 	tran->tran_bus_reset		= NULL;
95 
96 	tran->tran_add_eventcall	= NULL;
97 	tran->tran_get_eventcookie	= NULL;
98 	tran->tran_post_event		= NULL;
99 	tran->tran_remove_eventcall	= NULL;
100 	tran->tran_bus_config		= pqi_bus_config;
101 	tran->tran_interconnect_type	= INTERCONNECT_SAS;
102 
103 	/*
104 	 * scsi_vhci needs to have "initiator-port" set, but doesn't
105 	 * seem to care what it's set to. iSCSI uses the InitiatorName
106 	 * whereas mpt_sas uses the WWN port id, but this HBA doesn't
107 	 * have such a value. So, for now the instance number will be used.
108 	 */
109 	(void) snprintf(iport_str, sizeof (iport_str), "0x%x", instance);
110 	if (ddi_prop_update_string(DDI_DEV_T_NONE, s->s_dip,
111 	    SCSI_ADDR_PROP_INITIATOR_PORT, iport_str) != DDI_PROP_SUCCESS) {
112 		cmn_err(CE_WARN, "%s: Failed to create prop (%s) on %d\n",
113 		    __func__, SCSI_ADDR_PROP_INITIATOR_PORT, instance);
114 	}
115 
116 	flags = SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB;
117 	if (scsi_hba_attach_setup(s->s_dip, &s->s_msg_dma_attr, tran,
118 	    flags) != DDI_SUCCESS) {
119 		dev_err(s->s_dip, CE_NOTE, "scsi_hba_attach_setup failed");
120 		scsi_hba_tran_free(s->s_tran);
121 		s->s_tran = NULL;
122 		return (B_FALSE);
123 	}
124 
125 	if (!s->s_disable_mpxio) {
126 		if (mdi_phci_register(MDI_HCI_CLASS_SCSI, s->s_dip, 0) !=
127 		    MDI_SUCCESS) {
128 			cmn_err(CE_WARN, "%s: Failed to register with mpxio",
129 			    __func__);
130 			s->s_disable_mpxio = B_TRUE;
131 		}
132 	}
133 
134 	s->s_cmd_timeout = timeout(cmd_timeout_scan, s,
135 	    CMD_TIMEOUT_SCAN_SECS * drv_usectohz(MICROSEC));
136 
137 	return (B_TRUE);
138 }
139 
140 void
smartpqi_unregister_hba(pqi_state_t * s)141 smartpqi_unregister_hba(pqi_state_t *s)
142 {
143 	if (!s->s_disable_mpxio)
144 		(void) mdi_phci_unregister(s->s_dip, 0);
145 
146 	if (s->s_cmd_timeout != NULL) {
147 		(void) untimeout(s->s_cmd_timeout);
148 		s->s_cmd_timeout = NULL;
149 	}
150 
151 	if (s->s_tran == NULL)
152 		return;
153 	scsi_hba_tran_free(s->s_tran);
154 	s->s_tran = NULL;
155 }
156 
157 static int
pqi_scsi_tgt_init(dev_info_t * hba_dip __unused,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)158 pqi_scsi_tgt_init(dev_info_t *hba_dip __unused, dev_info_t *tgt_dip,
159     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
160 {
161 	pqi_device_t	*d;
162 	pqi_state_t	*s	= hba_tran->tran_hba_private;
163 	mdi_pathinfo_t	*pip;
164 	int		type;
165 	char		*ua;
166 
167 	if ((ua = scsi_device_unit_address(sd)) == NULL) {
168 		return (DDI_FAILURE);
169 	}
170 
171 	if ((d = pqi_find_target_ua(s, ua)) == NULL) {
172 		return (DDI_FAILURE);
173 	}
174 
175 	scsi_device_hba_private_set(sd, d);
176 
177 	type = mdi_get_component_type(tgt_dip);
178 	if (type == MDI_COMPONENT_CLIENT) {
179 		char	wwid_str[64];
180 
181 		if ((pip = (mdi_pathinfo_t *)sd->sd_private) == NULL)
182 			return (DDI_NOT_WELL_FORMED);
183 
184 		(void) snprintf(wwid_str, sizeof (wwid_str), "%" PRIx64,
185 		    d->pd_wwid);
186 		(void) mdi_prop_update_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
187 		    wwid_str);
188 	}
189 
190 	return (DDI_SUCCESS);
191 }
192 
193 static void
pqi_scsi_tgt_free(dev_info_t * hba_dip __unused,dev_info_t * tgt_dip __unused,scsi_hba_tran_t * hba_tran __unused,struct scsi_device * sd __unused)194 pqi_scsi_tgt_free(dev_info_t *hba_dip __unused, dev_info_t *tgt_dip __unused,
195     scsi_hba_tran_t *hba_tran __unused, struct scsi_device *sd __unused)
196 {
197 }
198 
199 /*
200  * Notes:
201  *      - transport the command to the addressed SCSI target/lun device
202  *      - normal operation is to schedule the command to be transported,
203  *        and return TRAN_ACCEPT if this is successful.
204  *      - if NO_INTR, tran_start must poll device for command completion
205  */
206 static int
pqi_start(struct scsi_address * ap,struct scsi_pkt * pkt)207 pqi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
208 {
209 	boolean_t	poll	= ((pkt->pkt_flags & FLAG_NOINTR) != 0);
210 	int		rc;
211 	pqi_cmd_t	*cmd	= PKT2CMD(pkt);
212 	pqi_state_t	*s	= ap->a_hba_tran->tran_hba_private;
213 
214 	ASSERT3P(cmd->pc_pkt, ==, pkt);
215 	ASSERT3P(cmd->pc_softc, ==, s);
216 
217 	if (pqi_is_offline(s) || !cmd->pc_device->pd_online)
218 		return (TRAN_FATAL_ERROR);
219 
220 	/*
221 	 * Reinitialize some fields because the packet may have been
222 	 * resubmitted.
223 	 */
224 	pkt->pkt_reason = CMD_CMPLT;
225 	pkt->pkt_state = 0;
226 	pkt->pkt_statistics = 0;
227 
228 	/* ---- Zero status byte ---- */
229 	*(pkt->pkt_scbp) = 0;
230 
231 	if ((cmd->pc_flags & PQI_FLAG_DMA_VALID) != 0) {
232 		ASSERT(cmd->pc_dma_count);
233 		pkt->pkt_resid = cmd->pc_dma_count;
234 
235 		/* ---- Sync consistent packets first (only write data) ---- */
236 		if (((cmd->pc_flags & PQI_FLAG_IO_IOPB) != 0) ||
237 		    ((cmd->pc_flags & PQI_FLAG_IO_READ) == 0)) {
238 			(void) ddi_dma_sync(cmd->pc_dmahdl, 0, 0,
239 			    DDI_DMA_SYNC_FORDEV);
240 		}
241 	}
242 
243 	mutex_enter(&s->s_mutex);
244 	if (HBA_IS_QUIESCED(s) && !poll) {
245 		mutex_exit(&s->s_mutex);
246 		return (TRAN_BUSY);
247 	}
248 	mutex_exit(&s->s_mutex);
249 
250 	rc = pqi_transport_command(s, cmd);
251 
252 	if (poll) {
253 		boolean_t	qnotify;
254 
255 		if (rc == TRAN_ACCEPT) {
256 			uint32_t	old_state;
257 			int		timeo;
258 
259 			timeo = pkt->pkt_time ? pkt->pkt_time :
260 			    SCSI_POLL_TIMEOUT;
261 			timeo *= MILLISEC / 2;
262 			old_state = pqi_disable_intr(s);
263 			do {
264 				drv_usecwait(MILLISEC / 2);
265 				pqi_process_io_intr(s, &s->s_queue_groups[0]);
266 				if (--timeo == 0) {
267 					pkt->pkt_state |= STAT_TIMEOUT;
268 					pkt->pkt_reason = CMD_TIMEOUT;
269 					break;
270 				}
271 			} while (pkt->pkt_state == 0);
272 			pqi_enable_intr(s, old_state);
273 		}
274 
275 		scsi_hba_pkt_comp(pkt);
276 
277 		mutex_enter(&s->s_mutex);
278 		qnotify = HBA_QUIESCED_PENDING(s);
279 		mutex_exit(&s->s_mutex);
280 
281 		if (qnotify)
282 			pqi_quiesced_notify(s);
283 	}
284 
285 	return (rc);
286 }
287 
288 static int
pqi_scsi_reset(struct scsi_address * ap,int level)289 pqi_scsi_reset(struct scsi_address *ap, int level)
290 {
291 	pqi_device_t	*d;
292 	pqi_state_t	*s;
293 	int		rval = FALSE;
294 
295 	s = ap->a_hba_tran->tran_hba_private;
296 	switch (level) {
297 	case RESET_TARGET:
298 	case RESET_LUN:
299 		if ((d = scsi_device_hba_private_get(ap->a.a_sd)) == NULL)
300 			break;
301 
302 		pqi_lun_reset(s, d);
303 		rval = TRUE;
304 		break;
305 
306 	case RESET_BUS:
307 	case RESET_ALL:
308 		mutex_enter(&s->s_mutex);
309 		for (d = list_head(&s->s_devnodes); d != NULL;
310 		    d = list_next(&s->s_devnodes, d)) {
311 			pqi_lun_reset(s, d);
312 		}
313 		mutex_exit(&s->s_mutex);
314 		rval = TRUE;
315 		break;
316 	}
317 	return (rval);
318 }
319 
320 /*
321  * abort handling:
322  *
323  * Notes:
324  *      - if pkt is not NULL, abort just that command
325  *      - if pkt is NULL, abort all outstanding commands for target
326  */
327 static int
pqi_scsi_abort(struct scsi_address * ap,struct scsi_pkt * pkt)328 pqi_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
329 {
330 	boolean_t	qnotify	= B_FALSE;
331 	pqi_state_t	*s	= ADDR2PQI(ap);
332 
333 	if (pkt != NULL) {
334 		/* ---- Abort single command ---- */
335 		pqi_cmd_t	*cmd = PKT2CMD(pkt);
336 
337 		mutex_enter(&cmd->pc_device->pd_mutex);
338 		(void) pqi_fail_cmd(cmd, CMD_ABORTED, STAT_ABORTED);
339 		mutex_exit(&cmd->pc_device->pd_mutex);
340 	} else {
341 		abort_all(ap, s);
342 	}
343 	qnotify = HBA_QUIESCED_PENDING(s);
344 
345 	if (qnotify)
346 		pqi_quiesced_notify(s);
347 	return (1);
348 }
349 
350 /*
351  * capability handling:
352  * (*tran_getcap).  Get the capability named, and return its value.
353  */
354 static int
pqi_scsi_getcap(struct scsi_address * ap,char * cap,int tgtonly __unused)355 pqi_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly __unused)
356 {
357 	pqi_state_t *s = ap->a_hba_tran->tran_hba_private;
358 
359 	if (cap == NULL)
360 		return (-1);
361 	switch (scsi_hba_lookup_capstr(cap)) {
362 	case SCSI_CAP_LUN_RESET:
363 		return ((s->s_flags & PQI_HBA_LUN_RESET_CAP) != 0);
364 	case SCSI_CAP_ARQ:
365 		return ((s->s_flags & PQI_HBA_AUTO_REQUEST_SENSE) != 0);
366 	case SCSI_CAP_UNTAGGED_QING:
367 		return (1);
368 	default:
369 		return (-1);
370 	}
371 }
372 
373 /*
374  * (*tran_setcap).  Set the capability named to the value given.
375  */
376 static int
pqi_scsi_setcap(struct scsi_address * ap,char * cap,int value,int tgtonly __unused)377 pqi_scsi_setcap(struct scsi_address *ap, char *cap, int value,
378     int tgtonly __unused)
379 {
380 	pqi_state_t	*s	= ADDR2PQI(ap);
381 	int		rval	= FALSE;
382 
383 	if (cap == NULL)
384 		return (-1);
385 
386 	switch (scsi_hba_lookup_capstr(cap)) {
387 	case SCSI_CAP_ARQ:
388 		if (value)
389 			s->s_flags |= PQI_HBA_AUTO_REQUEST_SENSE;
390 		else
391 			s->s_flags &= ~PQI_HBA_AUTO_REQUEST_SENSE;
392 		rval = 1;
393 		break;
394 
395 	case SCSI_CAP_LUN_RESET:
396 		if (value)
397 			s->s_flags |= PQI_HBA_LUN_RESET_CAP;
398 		else
399 			s->s_flags &= ~PQI_HBA_LUN_RESET_CAP;
400 		break;
401 
402 	default:
403 		break;
404 	}
405 
406 	return (rval);
407 }
408 
409 int
pqi_cache_constructor(void * buf,void * un,int flags)410 pqi_cache_constructor(void *buf, void *un, int flags)
411 {
412 	pqi_cmd_t		*c	= (pqi_cmd_t *)buf;
413 	pqi_state_t		*s	= un;
414 	int			(*callback)(caddr_t);
415 
416 	bzero(c, sizeof (*c));
417 	c->pc_softc = s;
418 	callback = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
419 
420 	/* ---- Allocate a DMA handle for data transfers ---- */
421 	if (ddi_dma_alloc_handle(s->s_dip, &s->s_msg_dma_attr, callback,
422 	    NULL, &c->pc_dmahdl) != DDI_SUCCESS) {
423 		dev_err(s->s_dip, CE_WARN, "Failed to alloc dma handle");
424 		return (-1);
425 	}
426 
427 	return (0);
428 }
429 
430 void
pqi_cache_destructor(void * buf,void * un __unused)431 pqi_cache_destructor(void *buf, void *un __unused)
432 {
433 	pqi_cmd_t	*cmd = buf;
434 	if (cmd->pc_dmahdl != NULL) {
435 		(void) ddi_dma_unbind_handle(cmd->pc_dmahdl);
436 		ddi_dma_free_handle(&cmd->pc_dmahdl);
437 		cmd->pc_dmahdl = NULL;
438 	}
439 }
440 
441 /*
442  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
443  *
444  * One of three possibilities:
445  *      - allocate scsi_pkt
446  *      - allocate scsi_pkt and DMA resources
447  *      - allocate DMA resources to an already-allocated pkt
448  */
449 static struct scsi_pkt *
pqi_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)450 pqi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
451     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
452     int (*callback)(), caddr_t arg)
453 {
454 	pqi_cmd_t	*cmd;
455 	pqi_state_t	*s;
456 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
457 	boolean_t	is_new = B_FALSE;
458 	int		rc;
459 	int		i;
460 	pqi_device_t	*devp;
461 
462 	s = ap->a_hba_tran->tran_hba_private;
463 
464 	if (pkt == NULL) {
465 		ddi_dma_handle_t	saved_dmahdl;
466 		pqi_cmd_action_t	saved_action;
467 
468 		if ((devp = scsi_device_hba_private_get(ap->a.a_sd)) == NULL)
469 			return (NULL);
470 		if ((cmd = kmem_cache_alloc(s->s_cmd_cache, kf)) == NULL)
471 			return (NULL);
472 
473 		is_new = B_TRUE;
474 		saved_dmahdl = cmd->pc_dmahdl;
475 		saved_action = cmd->pc_last_action;
476 
477 		(void) memset(cmd, 0, sizeof (*cmd));
478 		mutex_init(&cmd->pc_mutex, NULL, MUTEX_DRIVER, NULL);
479 
480 		cmd->pc_dmahdl = saved_dmahdl;
481 		cmd->pc_last_action = saved_action;
482 
483 		cmd->pc_device = devp;
484 		cmd->pc_pkt = &cmd->pc_cached_pkt;
485 		cmd->pc_softc = s;
486 		cmd->pc_tgtlen = tgtlen;
487 		cmd->pc_statuslen = statuslen;
488 		cmd->pc_cmdlen = cmdlen;
489 		cmd->pc_dma_count = 0;
490 
491 		pkt = cmd->pc_pkt;
492 		pkt->pkt_ha_private = cmd;
493 		pkt->pkt_address = *ap;
494 		pkt->pkt_scbp = (uint8_t *)&cmd->pc_cmd_scb;
495 		pkt->pkt_cdbp = cmd->pc_cdb;
496 		pkt->pkt_private = (opaque_t)cmd->pc_tgt_priv;
497 		if (pkt->pkt_time == 0)
498 			pkt->pkt_time = SCSI_POLL_TIMEOUT;
499 
500 		if (cmdlen > sizeof (cmd->pc_cdb) ||
501 		    statuslen > sizeof (cmd->pc_cmd_scb) ||
502 		    tgtlen > sizeof (cmd->pc_tgt_priv)) {
503 			if (cmd_ext_alloc(cmd, kf) != DDI_SUCCESS) {
504 				dev_err(s->s_dip, CE_WARN,
505 				    "extent allocation failed");
506 				goto out;
507 			}
508 		}
509 	} else {
510 		cmd = PKT2CMD(pkt);
511 		cmd->pc_flags &= PQI_FLAGS_PERSISTENT;
512 	}
513 
514 	/* ---- Handle partial DMA transfer ---- */
515 	if (cmd->pc_nwin > 0) {
516 		if (++cmd->pc_winidx >= cmd->pc_nwin)
517 			return (NULL);
518 		if (ddi_dma_getwin(cmd->pc_dmahdl, cmd->pc_winidx,
519 		    &cmd->pc_dma_offset, &cmd->pc_dma_len, &cmd->pc_dmac,
520 		    &cmd->pc_dmaccount) == DDI_FAILURE)
521 			return (NULL);
522 		goto handle_dma_cookies;
523 	}
524 
525 	/* ---- Setup data buffer ---- */
526 	if (bp != NULL && bp->b_bcount > 0 &&
527 	    (cmd->pc_flags & PQI_FLAG_DMA_VALID) == 0) {
528 		int	dma_flags;
529 
530 		ASSERT(cmd->pc_dmahdl != NULL);
531 
532 		if ((bp->b_flags & B_READ) != 0) {
533 			cmd->pc_flags |= PQI_FLAG_IO_READ;
534 			dma_flags = DDI_DMA_READ;
535 		} else {
536 			cmd->pc_flags &= ~PQI_FLAG_IO_READ;
537 			dma_flags = DDI_DMA_WRITE;
538 		}
539 		if ((flags & PKT_CONSISTENT) != 0) {
540 			cmd->pc_flags |= PQI_FLAG_IO_IOPB;
541 			dma_flags |= DDI_DMA_CONSISTENT;
542 		}
543 		if ((flags & PKT_DMA_PARTIAL) != 0) {
544 			dma_flags |= DDI_DMA_PARTIAL;
545 		}
546 		rc = ddi_dma_buf_bind_handle(cmd->pc_dmahdl, bp,
547 		    dma_flags, callback, arg, &cmd->pc_dmac,
548 		    &cmd->pc_dmaccount);
549 
550 		if (rc == DDI_DMA_PARTIAL_MAP) {
551 			(void) ddi_dma_numwin(cmd->pc_dmahdl, &cmd->pc_nwin);
552 			cmd->pc_winidx = 0;
553 			(void) ddi_dma_getwin(cmd->pc_dmahdl, cmd->pc_winidx,
554 			    &cmd->pc_dma_offset, &cmd->pc_dma_len,
555 			    &cmd->pc_dmac, &cmd->pc_dmaccount);
556 		} else if (rc != 0 && rc != DDI_DMA_MAPPED) {
557 			switch (rc) {
558 			case DDI_DMA_NORESOURCES:
559 				bioerror(bp, 0);
560 				break;
561 			case DDI_DMA_BADATTR:
562 			case DDI_DMA_NOMAPPING:
563 				bioerror(bp, EFAULT);
564 				break;
565 			case DDI_DMA_TOOBIG:
566 			default:
567 				bioerror(bp, EINVAL);
568 				break;
569 			}
570 			goto out;
571 		}
572 
573 handle_dma_cookies:
574 		ASSERT(cmd->pc_dmaccount > 0);
575 		if (cmd->pc_dmaccount >
576 		    (sizeof (cmd->pc_cached_cookies) /
577 		    sizeof (ddi_dma_cookie_t))) {
578 			dev_err(s->s_dip, CE_WARN,
579 			    "invalid cookie count: %d", cmd->pc_dmaccount);
580 			goto out;
581 		}
582 		if (cmd->pc_dmaccount >
583 		    (s->s_sg_chain_buf_length / sizeof (pqi_sg_entry_t))) {
584 			dev_err(s->s_dip, CE_WARN,
585 			    "Cookie(0x%x) verses SG(0x%" PRIx64 ") mismatch",
586 			    cmd->pc_dmaccount,
587 			    s->s_sg_chain_buf_length / sizeof (pqi_sg_entry_t));
588 			goto out;
589 		}
590 
591 		cmd->pc_flags |= PQI_FLAG_DMA_VALID;
592 		cmd->pc_dma_count = cmd->pc_dmac.dmac_size;
593 		cmd->pc_cached_cookies[0] = cmd->pc_dmac;
594 
595 		for (i = 1; i < cmd->pc_dmaccount; i++) {
596 			ddi_dma_nextcookie(cmd->pc_dmahdl, &cmd->pc_dmac);
597 			cmd->pc_cached_cookies[i] = cmd->pc_dmac;
598 			cmd->pc_dma_count += cmd->pc_dmac.dmac_size;
599 		}
600 
601 		pkt->pkt_resid = bp->b_bcount - cmd->pc_dma_count;
602 	}
603 
604 	return (pkt);
605 
606 out:
607 	if (is_new == B_TRUE)
608 		pqi_destroy_pkt(ap, pkt);
609 	return (NULL);
610 }
611 
612 /*
613  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
614  *
615  * Notes:
616  *      - also frees DMA resources if allocated
617  *      - implicit DMA synchonization
618  */
619 static void
pqi_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)620 pqi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
621 {
622 	pqi_cmd_t	*c = PKT2CMD(pkt);
623 	pqi_state_t	*s = ADDR2PQI(ap);
624 
625 	if ((c->pc_flags & PQI_FLAG_DMA_VALID) != 0) {
626 		c->pc_flags &= ~PQI_FLAG_DMA_VALID;
627 		(void) ddi_dma_unbind_handle(c->pc_dmahdl);
628 	}
629 	cmd_ext_free(c);
630 
631 	kmem_cache_free(s->s_cmd_cache, c);
632 }
633 
634 /*
635  * tran_dmafree(9E) - deallocate DMA resources allocated for command
636  */
637 static void
pqi_dmafree(struct scsi_address * ap __unused,struct scsi_pkt * pkt)638 pqi_dmafree(struct scsi_address *ap __unused, struct scsi_pkt *pkt)
639 {
640 	pqi_cmd_t	*cmd = PKT2CMD(pkt);
641 
642 	if (cmd->pc_flags & PQI_FLAG_DMA_VALID) {
643 		cmd->pc_flags &= ~PQI_FLAG_DMA_VALID;
644 		(void) ddi_dma_unbind_handle(cmd->pc_dmahdl);
645 	}
646 }
647 
648 /*
649  * tran_sync_pkt(9E) - explicit DMA synchronization
650  */
651 static void
pqi_sync_pkt(struct scsi_address * ap __unused,struct scsi_pkt * pkt)652 pqi_sync_pkt(struct scsi_address *ap __unused, struct scsi_pkt *pkt)
653 {
654 	pqi_cmd_t	*cmd = PKT2CMD(pkt);
655 
656 	if (cmd->pc_dmahdl != NULL) {
657 		(void) ddi_dma_sync(cmd->pc_dmahdl, 0, 0,
658 		    (cmd->pc_flags & PQI_FLAG_IO_READ) ? DDI_DMA_SYNC_FORCPU :
659 		    DDI_DMA_SYNC_FORDEV);
660 	}
661 }
662 
663 static int
pqi_reset_notify(struct scsi_address * ap,int flag,void (* callback)(caddr_t),caddr_t arg)664 pqi_reset_notify(struct scsi_address *ap, int flag,
665     void (*callback)(caddr_t), caddr_t arg)
666 {
667 	pqi_state_t	*s = ADDR2PQI(ap);
668 
669 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
670 	    &s->s_mutex, &s->s_reset_notify_listf));
671 }
672 
673 /*
674  * Device / Hotplug control
675  */
676 static int
pqi_quiesce(dev_info_t * dip)677 pqi_quiesce(dev_info_t *dip)
678 {
679 	pqi_state_t	*s;
680 	scsi_hba_tran_t	*tran;
681 
682 	if ((tran = ddi_get_driver_private(dip)) == NULL ||
683 	    (s = TRAN2PQI(tran)) == NULL)
684 		return (-1);
685 
686 	mutex_enter(&s->s_mutex);
687 	if (!HBA_IS_QUIESCED(s))
688 		s->s_flags |= PQI_HBA_QUIESCED;
689 
690 	if (s->s_cmd_queue_len != 0) {
691 		/* ---- Outstanding commands present, wait ---- */
692 		s->s_flags |= PQI_HBA_QUIESCED_PENDING;
693 		cv_wait(&s->s_quiescedvar, &s->s_mutex);
694 		ASSERT0(s->s_cmd_queue_len);
695 	}
696 	mutex_exit(&s->s_mutex);
697 
698 	return (0);
699 }
700 
701 static int
pqi_unquiesce(dev_info_t * dip)702 pqi_unquiesce(dev_info_t *dip)
703 {
704 	pqi_state_t	*s;
705 	scsi_hba_tran_t	*tran;
706 
707 	if ((tran = ddi_get_driver_private(dip)) == NULL ||
708 	    (s = TRAN2PQI(tran)) == NULL)
709 		return (-1);
710 
711 	mutex_enter(&s->s_mutex);
712 	if (!HBA_IS_QUIESCED(s)) {
713 		mutex_exit(&s->s_mutex);
714 		return (0);
715 	}
716 	ASSERT0(s->s_cmd_queue_len);
717 	s->s_flags &= ~PQI_HBA_QUIESCED;
718 	mutex_exit(&s->s_mutex);
719 
720 	return (0);
721 }
722 
723 static int
pqi_bus_config(dev_info_t * pdip,uint_t flag,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)724 pqi_bus_config(dev_info_t *pdip, uint_t flag,
725     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
726 {
727 	scsi_hba_tran_t	*tran;
728 	pqi_state_t	*s;
729 	int		ret	= NDI_FAILURE;
730 	pqi_device_t	*d;
731 	char		*ua;
732 
733 	tran = ddi_get_driver_private(pdip);
734 	s = tran->tran_hba_private;
735 	if (pqi_is_offline(s))
736 		return (NDI_FAILURE);
737 
738 	ndi_devi_enter(scsi_vhci_dip);
739 	ndi_devi_enter(pdip);
740 	switch (op) {
741 	case BUS_CONFIG_ONE:
742 		if ((ua = strrchr((char *)arg, '@')) != NULL) {
743 			ua++;
744 			d = pqi_find_target_ua(s, ua);
745 			if (d != NULL)
746 				ret = config_one(pdip, s, d, childp);
747 		} else {
748 			dev_err(s->s_dip, CE_WARN, "Couldn't decode %s",
749 			    (char *)arg);
750 		}
751 		flag |= NDI_MDI_FALLBACK;
752 		break;
753 
754 	case BUS_CONFIG_DRIVER:
755 	case BUS_CONFIG_ALL:
756 		ret = pqi_config_all(pdip, s);
757 		break;
758 	default:
759 		ret = NDI_FAILURE;
760 	}
761 	if (ret == NDI_SUCCESS)
762 		ret = ndi_busop_bus_config(pdip, flag, op, arg, childp, 0);
763 	ndi_devi_exit(pdip);
764 	ndi_devi_exit(scsi_vhci_dip);
765 
766 	return (ret);
767 }
768 
769 pqi_device_t *
pqi_find_target_ua(pqi_state_t * s,char * ua)770 pqi_find_target_ua(pqi_state_t *s, char *ua)
771 {
772 	pqi_device_t *d;
773 
774 	mutex_enter(&s->s_mutex);
775 	for (d = list_head(&s->s_devnodes); d != NULL;
776 	    d = list_next(&s->s_devnodes, d)) {
777 		if (d->pd_online && strcmp(ua, d->pd_unit_address) == 0)
778 			break;
779 	}
780 	mutex_exit(&s->s_mutex);
781 	return (d);
782 }
783 
784 int
pqi_config_all(dev_info_t * pdip,pqi_state_t * s)785 pqi_config_all(dev_info_t *pdip, pqi_state_t *s)
786 {
787 	pqi_device_t *d;
788 
789 	/*
790 	 * Make sure we bring the available devices into play first. These
791 	 * might be brand new devices just hotplugged into the system or
792 	 * they could be devices previously offlined because either they
793 	 * were pulled from an enclosure or a cable to the enclosure was
794 	 * pulled.
795 	 */
796 	/* ---- XXX Grab s_mutex ---- */
797 	for (d = list_head(&s->s_devnodes); d != NULL;
798 	    d = list_next(&s->s_devnodes, d)) {
799 		if (d->pd_online)
800 			(void) config_one(pdip, s, d, NULL);
801 	}
802 
803 	/*
804 	 * Now deal with devices that we had previously known about, but are
805 	 * no longer available.
806 	 */
807 	for (d = list_head(&s->s_devnodes); d != NULL;
808 	    d = list_next(&s->s_devnodes, d)) {
809 		if (!d->pd_online)
810 			(void) config_one(pdip, s, d, NULL);
811 	}
812 
813 	return (NDI_SUCCESS);
814 }
815 
816 void
pqi_quiesced_notify(pqi_state_t * s)817 pqi_quiesced_notify(pqi_state_t *s)
818 {
819 	mutex_enter(&s->s_mutex);
820 	if (s->s_cmd_queue_len == 0 &&
821 	    (s->s_flags & PQI_HBA_QUIESCED_PENDING) != 0) {
822 		s->s_flags &= ~PQI_HBA_QUIESCED_PENDING;
823 		cv_broadcast(&s->s_quiescedvar);
824 	}
825 	mutex_exit(&s->s_mutex);
826 }
827 
828 /*
829  * []------------------------------------------------------------------[]
830  * | Support routines used only by the trans_xxx routines		|
831  * []------------------------------------------------------------------[]
832  */
833 #ifdef DEBUG
834 int	pqi_force_timeout;
835 #endif	/* DEBUG */
836 
837 static void
cmd_timeout_drive(pqi_device_t * d)838 cmd_timeout_drive(pqi_device_t *d)
839 {
840 	uint32_t	timed_out_cnt = 0;
841 	pqi_cmd_t	*c, *next_c;
842 	hrtime_t	now = gethrtime();
843 
844 	mutex_enter(&d->pd_mutex);
845 
846 rescan:
847 	c = list_head(&d->pd_cmd_list);
848 	while (c != NULL) {
849 		next_c = list_next(&d->pd_cmd_list, c);
850 #ifdef DEBUG
851 		if (c->pc_expiration < now || pqi_force_timeout != 0) {
852 			pqi_force_timeout = 0;
853 #else
854 		if (c->pc_expiration < now) {
855 #endif	/* DEBUG */
856 			struct scsi_pkt	*pkt = CMD2PKT(c);
857 
858 			if (pkt != NULL) {
859 				pkt->pkt_reason = CMD_TIMEOUT;
860 				pkt->pkt_statistics = STAT_TIMEOUT;
861 			}
862 			ASSERT(c->pc_io_rqst != NULL);
863 			/*
864 			 * If the i/o has not been serviced yet,
865 			 * mark the i/o as timed out and clear it out
866 			 */
867 			if (pqi_timeout_io(c->pc_io_rqst)) {
868 				(void) pqi_cmd_action_nolock(c,
869 				    PQI_CMD_TIMEOUT);
870 				timed_out_cnt++;
871 				/*
872 				 * We dropped pd_mutex so the cmd
873 				 * list could have changed, restart the
874 				 * scan of the cmds.  This will terminate
875 				 * since timed out cmds are removed from
876 				 * the list.
877 				 */
878 				goto rescan;
879 			}
880 		}
881 		c = next_c;
882 	}
883 
884 	d->pd_timedout += timed_out_cnt;
885 	mutex_exit(&d->pd_mutex);
886 }
887 
888 static void
889 cmd_timeout_scan(void *v)
890 {
891 	pqi_state_t		*s = v;
892 	pqi_device_t		*d;
893 
894 	mutex_enter(&s->s_mutex);
895 
896 	for (d = list_head(&s->s_devnodes); d != NULL;
897 	    d = list_next(&s->s_devnodes, d)) {
898 		cmd_timeout_drive(d);
899 	}
900 	cmd_timeout_drive(&s->s_special_device);
901 
902 	mutex_exit(&s->s_mutex);
903 	s->s_cmd_timeout = timeout(cmd_timeout_scan, s,
904 	    CMD_TIMEOUT_SCAN_SECS * drv_usectohz(MICROSEC));
905 }
906 
907 static void
908 abort_all(struct scsi_address *ap, pqi_state_t *s __unused)
909 {
910 	pqi_device_t	*devp;
911 
912 	if ((devp = scsi_device_hba_private_get(ap->a.a_sd)) == NULL)
913 		return;
914 
915 	pqi_fail_drive_cmds(devp, CMD_ABORTED);
916 }
917 
918 static boolean_t
919 create_phys_lun(pqi_state_t *s, pqi_device_t *d,
920     struct scsi_inquiry *inq, dev_info_t **childp)
921 {
922 	char		**compatible	= NULL;
923 	char		*nodename	= NULL;
924 	int		ncompatible	= 0;
925 	dev_info_t	*dip;
926 
927 	/* ---- At this point we have a new device not in our list ---- */
928 	scsi_hba_nodename_compatible_get(inq, NULL,
929 	    inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
930 	if (nodename == NULL)
931 		return (B_FALSE);
932 
933 	if (ndi_devi_alloc(s->s_dip, nodename, DEVI_SID_NODEID, &dip) !=
934 	    NDI_SUCCESS) {
935 		dev_err(s->s_dip, CE_WARN, "failed to alloc device instance");
936 		goto free_nodename;
937 	}
938 
939 	d->pd_dip = dip;
940 	d->pd_pip = NULL;
941 
942 	if (ndi_prop_update_int64(DDI_DEV_T_NONE, dip, LUN64_PROP,
943 	    d->pd_lun) != DDI_PROP_SUCCESS) {
944 		goto free_devi;
945 	}
946 
947 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, COMPAT_PROP,
948 	    compatible, ncompatible) != DDI_PROP_SUCCESS) {
949 		goto free_devi;
950 	}
951 
952 	if (d->pd_wwid != 0) {
953 		char		wwn_str[20];
954 		(void) snprintf(wwn_str, 20, "w%016" PRIx64, d->pd_wwid);
955 		if (ndi_prop_update_string(DDI_DEV_T_NONE, dip,
956 		    SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS) {
957 			goto free_devi;
958 		}
959 	} else {
960 		if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, TARGET_PROP,
961 		    d->pd_target) != DDI_PROP_SUCCESS) {
962 			goto free_devi;
963 		}
964 	}
965 
966 	if (d->pd_guid != NULL) {
967 		if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, NDI_GUID,
968 		    d->pd_guid) != DDI_PROP_SUCCESS) {
969 			goto free_devi;
970 		}
971 	}
972 
973 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, "pm-capable", 1) !=
974 	    DDI_PROP_SUCCESS) {
975 		goto free_devi;
976 	}
977 
978 	if (ndi_devi_online(dip, NDI_ONLINE_ATTACH) != NDI_SUCCESS)
979 		goto free_devi;
980 
981 	if (childp != NULL)
982 		*childp = dip;
983 
984 	scsi_hba_nodename_compatible_free(nodename, compatible);
985 
986 	return (B_TRUE);
987 
988 free_devi:
989 	ndi_prop_remove_all(dip);
990 	(void) ndi_devi_free(dip);
991 	d->pd_dip = NULL;
992 free_nodename:
993 	scsi_hba_nodename_compatible_free(nodename, compatible);
994 	return (B_FALSE);
995 }
996 
997 static boolean_t
998 create_virt_lun(pqi_state_t *s, pqi_device_t *d, struct scsi_inquiry *inq,
999     dev_info_t **childp)
1000 {
1001 	char		*nodename;
1002 	char		**compatible;
1003 	int		ncompatible;
1004 	int		rval;
1005 	mdi_pathinfo_t	*pip		= NULL;
1006 	char		*guid_ptr;
1007 	char		wwid_str[17];
1008 	dev_info_t	*lun_dip;
1009 	char		*old_guid;
1010 
1011 	if (d->pd_pip_offlined != NULL) {
1012 		lun_dip = mdi_pi_get_client(d->pd_pip_offlined);
1013 		ASSERT(lun_dip != NULL);
1014 
1015 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
1016 		    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
1017 		    MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
1018 			if (strncmp(d->pd_guid, old_guid,
1019 			    strlen(d->pd_guid)) == 0) {
1020 				/* ---- Same path came back online ---- */
1021 				(void) ddi_prop_free(old_guid);
1022 				if (mdi_pi_online(d->pd_pip_offlined, 0) ==
1023 				    DDI_SUCCESS) {
1024 					d->pd_pip = d->pd_pip_offlined;
1025 					d->pd_pip_offlined = NULL;
1026 					return (B_TRUE);
1027 				} else {
1028 					return (B_FALSE);
1029 				}
1030 			} else {
1031 				/* ---- Different device in slot ---- */
1032 				(void) ddi_prop_free(old_guid);
1033 				if (mdi_pi_offline(d->pd_pip_offlined, 0) !=
1034 				    DDI_SUCCESS) {
1035 					return (B_FALSE);
1036 				}
1037 				if (mdi_pi_free(d->pd_pip_offlined, 0) !=
1038 				    MDI_SUCCESS) {
1039 					return (B_FALSE);
1040 				}
1041 				d->pd_pip_offlined = NULL;
1042 			}
1043 		} else {
1044 			dev_err(s->s_dip, CE_WARN, "Can't get client-guid "
1045 			    "property for lun %lx", d->pd_wwid);
1046 			return (B_FALSE);
1047 		}
1048 	}
1049 
1050 	scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
1051 	    &nodename, &compatible, &ncompatible);
1052 	if (nodename == NULL)
1053 		return (B_FALSE);
1054 
1055 	if (d->pd_guid != NULL) {
1056 		guid_ptr = d->pd_guid;
1057 	} else {
1058 		(void) snprintf(wwid_str, sizeof (wwid_str), "%" PRIx64,
1059 		    d->pd_wwid);
1060 		guid_ptr = wwid_str;
1061 	}
1062 	rval = mdi_pi_alloc_compatible(s->s_dip, nodename, guid_ptr,
1063 	    d->pd_unit_address, compatible, ncompatible, 0, &pip);
1064 	if (rval == MDI_SUCCESS) {
1065 		mdi_pi_set_phci_private(pip, (caddr_t)d);
1066 
1067 		if (mdi_prop_update_string(pip, MDI_GUID, guid_ptr) !=
1068 		    DDI_SUCCESS) {
1069 			dev_err(s->s_dip, CE_WARN,
1070 			    "unable to create property (MDI_GUID) for %s",
1071 			    guid_ptr);
1072 			goto cleanup;
1073 		}
1074 
1075 		/*
1076 		 * For MPxIO, we actually don't really need to care
1077 		 * about the LUN or target property, because nothing
1078 		 * really uses them.
1079 		 */
1080 		if (mdi_prop_update_int64(pip, LUN64_PROP, d->pd_lun) !=
1081 		    DDI_SUCCESS) {
1082 			dev_err(s->s_dip, CE_WARN,
1083 			    "unable to create property (%s) for %s",
1084 			    LUN64_PROP, guid_ptr);
1085 			goto cleanup;
1086 		}
1087 
1088 		if (mdi_prop_update_string_array(pip, COMPAT_PROP,
1089 		    compatible, ncompatible) != DDI_SUCCESS) {
1090 			dev_err(s->s_dip, CE_WARN,
1091 			    "unable to create property (%s) for %s",
1092 			    COMPAT_PROP, guid_ptr);
1093 			goto cleanup;
1094 		}
1095 
1096 		if (mdi_pi_online(pip, 0) == MDI_NOT_SUPPORTED)
1097 			goto cleanup;
1098 
1099 		d->pd_dip = NULL;
1100 		d->pd_pip = pip;
1101 	}
1102 
1103 	scsi_hba_nodename_compatible_free(nodename, compatible);
1104 	if (childp != NULL)
1105 		*childp = mdi_pi_get_client(pip);
1106 	return (B_TRUE);
1107 cleanup:
1108 	scsi_hba_nodename_compatible_free(nodename, compatible);
1109 	d->pd_pip = NULL;
1110 	d->pd_dip = NULL;
1111 	(void) mdi_prop_remove(pip, NULL);
1112 	(void) mdi_pi_free(pip, 0);
1113 	return (B_FALSE);
1114 }
1115 
1116 static int
1117 config_one(dev_info_t *pdip, pqi_state_t *s, pqi_device_t *d,
1118     dev_info_t **childp)
1119 {
1120 	struct scsi_inquiry	inq;
1121 	boolean_t		rval = B_FALSE;
1122 
1123 	/* ---- Inquiry target ---- */
1124 	if (!d->pd_online ||
1125 	    pqi_scsi_inquiry(s, d, 0, &inq, sizeof (inq)) == B_FALSE) {
1126 		pqi_fail_drive_cmds(d, CMD_DEV_GONE);
1127 
1128 		if (d->pd_dip != NULL) {
1129 			(void) ndi_devi_offline(d->pd_dip,
1130 			    NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
1131 			d->pd_dip = NULL;
1132 		} else if (d->pd_pip != NULL) {
1133 			(void) mdi_pi_offline(d->pd_pip, 0);
1134 			d->pd_pip_offlined = d->pd_pip;
1135 			d->pd_pip = NULL;
1136 		}
1137 		return (NDI_FAILURE);
1138 	} else if (d->pd_dip != NULL) {
1139 		if (childp != NULL)
1140 			*childp = d->pd_dip;
1141 		return (NDI_SUCCESS);
1142 	} else if (d->pd_pip != NULL) {
1143 		if (childp != NULL)
1144 			*childp = mdi_pi_get_client(d->pd_pip);
1145 		return (NDI_SUCCESS);
1146 	}
1147 
1148 	d->pd_parent = pdip;
1149 	if ((!s->s_disable_mpxio) && is_physical_dev(d))
1150 		rval = create_virt_lun(s, d, &inq, childp);
1151 
1152 	if (rval == B_FALSE)
1153 		rval = create_phys_lun(s, d, &inq, childp);
1154 
1155 	return ((rval == B_TRUE) ? NDI_SUCCESS : NDI_FAILURE);
1156 }
1157 
1158 static void
1159 cmd_ext_free(pqi_cmd_t *cmd)
1160 {
1161 	struct scsi_pkt *pkt = CMD2PKT(cmd);
1162 
1163 	if ((cmd->pc_flags & PQI_FLAG_CDB_EXT) != 0) {
1164 		kmem_free(pkt->pkt_cdbp, cmd->pc_cmdlen);
1165 		cmd->pc_flags &= ~PQI_FLAG_CDB_EXT;
1166 	}
1167 	if ((cmd->pc_flags & PQI_FLAG_SCB_EXT) != 0) {
1168 		kmem_free(pkt->pkt_scbp, cmd->pc_statuslen);
1169 		cmd->pc_flags &= ~PQI_FLAG_SCB_EXT;
1170 	}
1171 	if ((cmd->pc_flags & PQI_FLAG_PRIV_EXT) != 0) {
1172 		kmem_free(pkt->pkt_private, cmd->pc_tgtlen);
1173 		cmd->pc_flags &= ~PQI_FLAG_PRIV_EXT;
1174 	}
1175 }
1176 
1177 static int
1178 cmd_ext_alloc(pqi_cmd_t *cmd, int kf)
1179 {
1180 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
1181 	void			*buf;
1182 
1183 	if (cmd->pc_cmdlen > sizeof (cmd->pc_cdb)) {
1184 		if ((buf = kmem_zalloc(cmd->pc_cmdlen, kf)) == NULL)
1185 			return (DDI_FAILURE);
1186 		pkt->pkt_cdbp = buf;
1187 		cmd->pc_flags |= PQI_FLAG_CDB_EXT;
1188 	}
1189 
1190 	if (cmd->pc_statuslen > sizeof (cmd->pc_cmd_scb)) {
1191 		if ((buf = kmem_zalloc(cmd->pc_statuslen, kf)) == NULL)
1192 			goto out;
1193 		pkt->pkt_scbp = buf;
1194 		cmd->pc_flags |= PQI_FLAG_SCB_EXT;
1195 	}
1196 
1197 	if (cmd->pc_tgtlen > sizeof (cmd->pc_tgt_priv)) {
1198 		if ((buf = kmem_zalloc(cmd->pc_tgtlen, kf)) == NULL)
1199 			goto out;
1200 		pkt->pkt_private = buf;
1201 		cmd->pc_flags |= PQI_FLAG_PRIV_EXT;
1202 	}
1203 
1204 	return (DDI_SUCCESS);
1205 
1206 out:
1207 	cmd_ext_free(cmd);
1208 
1209 	return (DDI_FAILURE);
1210 }
1211 
1212 static boolean_t
1213 is_physical_dev(pqi_device_t *d)
1214 {
1215 	return (d->pd_phys_dev ? B_TRUE : B_FALSE);
1216 }
1217