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