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
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.
13 * Copyright 2016 Nexenta Systems, Inc.
16 #include <sys/atomic.h>
17 #include <sys/cmn_err.h>
19 #include <sys/cpuvar.h>
21 #include <sys/errno.h>
22 #include <sys/fs/dv_node.h>
24 #include <sys/kmem_impl.h>
26 #include <sys/modctl.h>
28 #include <sys/scsi/scsi.h>
29 #include <sys/sunddi.h>
30 #include <sys/sysmacros.h>
32 #include <sys/types.h>
35 #include "pvscsi_var.h"
37 int pvscsi_enable_msi
= 1;
38 int pvscsi_ring_pages
= PVSCSI_DEFAULT_NUM_PAGES_PER_RING
;
39 int pvscsi_msg_ring_pages
= PVSCSI_DEFAULT_NUM_PAGES_MSG_RING
;
41 static int pvscsi_abort(struct scsi_address
*ap
, struct scsi_pkt
*pkt
);
43 static void *pvscsi_sstate
;
45 /* HBA DMA attributes */
46 static ddi_dma_attr_t pvscsi_hba_dma_attr
= {
47 .dma_attr_version
= DMA_ATTR_V0
,
48 .dma_attr_addr_lo
= 0x0000000000000000ull
,
49 .dma_attr_addr_hi
= 0xFFFFFFFFFFFFFFFFull
,
50 .dma_attr_count_max
= 0x000000007FFFFFFFull
,
51 .dma_attr_align
= 0x0000000000000001ull
,
52 .dma_attr_burstsizes
= 0x7ff,
53 .dma_attr_minxfer
= 0x00000001u
,
54 .dma_attr_maxxfer
= 0x00000000FFFFFFFFull
,
55 .dma_attr_seg
= 0x00000000FFFFFFFFull
,
57 .dma_attr_granular
= 0x00000200u
,
61 /* DMA attributes for req/comp rings */
62 static ddi_dma_attr_t pvscsi_ring_dma_attr
= {
63 .dma_attr_version
= DMA_ATTR_V0
,
64 .dma_attr_addr_lo
= 0x0000000000000000ull
,
65 .dma_attr_addr_hi
= 0xFFFFFFFFFFFFFFFFull
,
66 .dma_attr_count_max
= 0x000000007FFFFFFFull
,
67 .dma_attr_align
= 0x0000000000000001ull
,
68 .dma_attr_burstsizes
= 0x7ff,
69 .dma_attr_minxfer
= 0x00000001u
,
70 .dma_attr_maxxfer
= 0x00000000FFFFFFFFull
,
71 .dma_attr_seg
= 0x00000000FFFFFFFFull
,
73 .dma_attr_granular
= 0x00000001u
,
77 /* DMA attributes for buffer I/O */
78 static ddi_dma_attr_t pvscsi_io_dma_attr
= {
79 .dma_attr_version
= DMA_ATTR_V0
,
80 .dma_attr_addr_lo
= 0x0000000000000000ull
,
81 .dma_attr_addr_hi
= 0xFFFFFFFFFFFFFFFFull
,
82 .dma_attr_count_max
= 0x000000007FFFFFFFull
,
83 .dma_attr_align
= 0x0000000000000001ull
,
84 .dma_attr_burstsizes
= 0x7ff,
85 .dma_attr_minxfer
= 0x00000001u
,
86 .dma_attr_maxxfer
= 0x00000000FFFFFFFFull
,
87 .dma_attr_seg
= 0x00000000FFFFFFFFull
,
88 .dma_attr_sgllen
= PVSCSI_MAX_SG_SIZE
,
89 .dma_attr_granular
= 0x00000200u
,
93 static ddi_device_acc_attr_t pvscsi_mmio_attr
= {
100 static ddi_device_acc_attr_t pvscsi_dma_attrs
= {
102 DDI_STRUCTURE_LE_ACC
,
108 pvscsi_add_to_queue(pvscsi_cmd_t
*cmd
)
110 pvscsi_softc_t
*pvs
= cmd
->cmd_pvs
;
113 ASSERT(mutex_owned(&pvs
->mutex
));
114 ASSERT(!list_link_active(&(cmd
)->cmd_queue_node
));
116 list_insert_tail(&pvs
->cmd_queue
, cmd
);
117 pvs
->cmd_queue_len
++;
121 pvscsi_remove_from_queue(pvscsi_cmd_t
*cmd
)
123 pvscsi_softc_t
*pvs
= cmd
->cmd_pvs
;
126 ASSERT(mutex_owned(&pvs
->mutex
));
127 ASSERT(list_link_active(&cmd
->cmd_queue_node
));
128 ASSERT(pvs
->cmd_queue_len
> 0);
130 if (list_link_active(&cmd
->cmd_queue_node
)) {
131 list_remove(&pvs
->cmd_queue
, cmd
);
132 pvs
->cmd_queue_len
--;
137 pvscsi_map_ctx(pvscsi_softc_t
*pvs
, pvscsi_cmd_ctx_t
*io_ctx
)
139 return (io_ctx
- pvs
->cmd_ctx
+ 1);
142 static pvscsi_cmd_ctx_t
*
143 pvscsi_lookup_ctx(pvscsi_softc_t
*pvs
, pvscsi_cmd_t
*cmd
)
145 pvscsi_cmd_ctx_t
*ctx
, *end
;
147 end
= &pvs
->cmd_ctx
[pvs
->req_depth
];
148 for (ctx
= pvs
->cmd_ctx
; ctx
< end
; ctx
++) {
156 static pvscsi_cmd_ctx_t
*
157 pvscsi_resolve_ctx(pvscsi_softc_t
*pvs
, uint64_t ctx
)
159 if (ctx
> 0 && ctx
<= pvs
->req_depth
)
160 return (&pvs
->cmd_ctx
[ctx
- 1]);
166 pvscsi_acquire_ctx(pvscsi_softc_t
*pvs
, pvscsi_cmd_t
*cmd
)
168 pvscsi_cmd_ctx_t
*ctx
;
170 if (list_is_empty(&pvs
->cmd_ctx_pool
))
173 ctx
= (pvscsi_cmd_ctx_t
*)list_remove_head(&pvs
->cmd_ctx_pool
);
183 pvscsi_release_ctx(pvscsi_cmd_t
*cmd
)
185 pvscsi_softc_t
*pvs
= cmd
->cmd_pvs
;
187 ASSERT(mutex_owned(&pvs
->mutex
));
189 cmd
->ctx
->cmd
= NULL
;
190 list_insert_tail(&pvs
->cmd_ctx_pool
, cmd
->ctx
);
195 pvscsi_reg_read(pvscsi_softc_t
*pvs
, uint32_t offset
)
199 ASSERT((offset
& (sizeof (uint32_t) - 1)) == 0);
201 ret
= ddi_get32(pvs
->mmio_handle
,
202 (uint32_t *)(pvs
->mmio_base
+ offset
));
208 pvscsi_reg_write(pvscsi_softc_t
*pvs
, uint32_t offset
, uint32_t value
)
210 ASSERT((offset
& (sizeof (uint32_t) - 1)) == 0);
212 ddi_put32(pvs
->mmio_handle
, (uint32_t *)(pvs
->mmio_base
+ offset
),
217 pvscsi_write_cmd_desc(pvscsi_softc_t
*pvs
, uint32_t cmd
, void *desc
, size_t len
)
219 len
/= sizeof (uint32_t);
220 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_COMMAND
, cmd
);
221 ddi_rep_put32(pvs
->mmio_handle
, (uint32_t *)desc
,
222 (uint32_t *)(pvs
->mmio_base
+ PVSCSI_REG_OFFSET_COMMAND_DATA
),
223 len
, DDI_DEV_NO_AUTOINCR
);
227 pvscsi_read_intr_status(pvscsi_softc_t
*pvs
)
229 return (pvscsi_reg_read(pvs
, PVSCSI_REG_OFFSET_INTR_STATUS
));
233 pvscsi_write_intr_status(pvscsi_softc_t
*pvs
, uint32_t val
)
235 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_INTR_STATUS
, val
);
239 pvscsi_mask_intr(pvscsi_softc_t
*pvs
)
241 mutex_enter(&pvs
->intr_mutex
);
243 VERIFY(pvs
->intr_lock_counter
>= 0);
245 if (++pvs
->intr_lock_counter
== 1)
246 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_INTR_MASK
, 0);
248 mutex_exit(&pvs
->intr_mutex
);
252 pvscsi_unmask_intr(pvscsi_softc_t
*pvs
)
254 mutex_enter(&pvs
->intr_mutex
);
256 VERIFY(pvs
->intr_lock_counter
> 0);
258 if (--pvs
->intr_lock_counter
== 0) {
259 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_INTR_MASK
,
260 PVSCSI_INTR_CMPL_MASK
| PVSCSI_INTR_MSG_MASK
);
263 mutex_exit(&pvs
->intr_mutex
);
267 pvscsi_reset_hba(pvscsi_softc_t
*pvs
)
269 pvscsi_write_cmd_desc(pvs
, PVSCSI_CMD_ADAPTER_RESET
, NULL
, 0);
273 pvscsi_reset_bus(pvscsi_softc_t
*pvs
)
275 pvscsi_write_cmd_desc(pvs
, PVSCSI_CMD_RESET_BUS
, NULL
, 0);
279 pvscsi_submit_nonrw_io(pvscsi_softc_t
*pvs
)
281 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_KICK_NON_RW_IO
, 0);
285 pvscsi_submit_rw_io(pvscsi_softc_t
*pvs
)
287 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_KICK_RW_IO
, 0);
292 pvscsi_inquiry_target(pvscsi_softc_t
*pvs
, int target
, struct scsi_inquiry
*inq
)
294 int len
= sizeof (struct scsi_inquiry
);
297 struct scsi_address ap
;
298 struct scsi_pkt
*pkt
;
299 uint8_t cdb
[CDB_GROUP0
];
301 ap
.a_hba_tran
= pvs
->tran
;
302 ap
.a_target
= (ushort_t
)target
;
303 ap
.a_lun
= (uchar_t
)0;
305 if ((b
= scsi_alloc_consistent_buf(&ap
, (struct buf
*)NULL
, len
,
306 B_READ
, NULL_FUNC
, NULL
)) == NULL
)
309 if ((pkt
= scsi_init_pkt(&ap
, (struct scsi_pkt
*)NULL
, b
,
310 CDB_GROUP0
, sizeof (struct scsi_arq_status
), 0, 0,
311 NULL_FUNC
, NULL
)) == NULL
)
314 cdb
[0] = SCMD_INQUIRY
;
317 cdb
[3] = (len
& 0xff00) >> 8;
318 cdb
[4] = (len
& 0x00ff);
322 bzero(inq
, sizeof (*inq
));
323 bcopy(cdb
, pkt
->pkt_cdbp
, CDB_GROUP0
);
324 bzero((struct scsi_inquiry
*)b
->b_un
.b_addr
, sizeof (*inq
));
326 if ((ret
= scsi_poll(pkt
)) == 0 && inq
!= NULL
)
327 bcopy(b
->b_un
.b_addr
, inq
, sizeof (*inq
));
329 scsi_destroy_pkt(pkt
);
332 scsi_free_consistent_buf(b
);
338 pvscsi_config_one(dev_info_t
*pdip
, pvscsi_softc_t
*pvs
, int target
,
341 char **compatible
= NULL
;
342 char *nodename
= NULL
;
346 pvscsi_device_t
*devnode
;
347 struct scsi_inquiry inq
;
350 inqrc
= pvscsi_inquiry_target(pvs
, target
, &inq
);
353 for (devnode
= list_head(&pvs
->devnodes
); devnode
!= NULL
;
354 devnode
= list_next(&pvs
->devnodes
, devnode
)) {
355 if (devnode
->target
== target
)
359 if (devnode
!= NULL
) {
361 /* Target disappeared, drop devnode */
362 if (i_ddi_devi_attached(devnode
->pdip
)) {
364 /* Get full devname */
365 devname
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
366 (void) ddi_deviname(devnode
->pdip
, devname
);
367 /* Clean cache and name */
368 (void) devfs_clean(devnode
->parent
, devname
+ 1,
370 kmem_free(devname
, MAXPATHLEN
);
373 (void) ndi_devi_offline(devnode
->pdip
, NDI_DEVI_REMOVE
);
375 list_remove(&pvs
->devnodes
, devnode
);
376 kmem_free(devnode
, sizeof (*devnode
));
377 } else if (childp
!= NULL
) {
379 *childp
= devnode
->pdip
;
381 return (NDI_SUCCESS
);
382 } else if (inqrc
!= 0) {
383 /* Target doesn't exist */
384 return (NDI_FAILURE
);
387 scsi_hba_nodename_compatible_get(&inq
, NULL
, inq
.inq_dtype
, NULL
,
388 &nodename
, &compatible
, &ncompatible
);
389 if (nodename
== NULL
)
392 if (ndi_devi_alloc(pdip
, nodename
, DEVI_SID_NODEID
,
393 &dip
) != NDI_SUCCESS
) {
394 dev_err(pvs
->dip
, CE_WARN
, "!failed to alloc device instance");
398 if (ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
399 "device-type", "scsi") != DDI_PROP_SUCCESS
||
400 ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
401 "target", target
) != DDI_PROP_SUCCESS
||
402 ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
403 "lun", 0) != DDI_PROP_SUCCESS
||
404 ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
405 "pm-capable", 1) != DDI_PROP_SUCCESS
||
406 ndi_prop_update_string_array(DDI_DEV_T_NONE
, dip
,
407 "compatible", compatible
, ncompatible
) != DDI_PROP_SUCCESS
) {
408 dev_err(pvs
->dip
, CE_WARN
,
409 "!failed to update props for target %d", target
);
413 if ((devnode
= kmem_zalloc(sizeof (*devnode
), KM_NOSLEEP
)) == NULL
)
416 if (ndi_devi_online(dip
, NDI_ONLINE_ATTACH
) != NDI_SUCCESS
) {
417 dev_err(pvs
->dip
, CE_WARN
, "!failed to online target %d",
419 kmem_free(devnode
, sizeof (*devnode
));
423 devnode
->target
= target
;
425 devnode
->parent
= pdip
;
426 list_insert_tail(&pvs
->devnodes
, devnode
);
431 scsi_hba_nodename_compatible_free(nodename
, compatible
);
433 return (NDI_SUCCESS
);
436 ndi_prop_remove_all(dip
);
437 (void) ndi_devi_free(dip
);
439 scsi_hba_nodename_compatible_free(nodename
, compatible
);
441 return (NDI_FAILURE
);
445 pvscsi_config_all(dev_info_t
*pdip
, pvscsi_softc_t
*pvs
)
449 for (target
= 0; target
< PVSCSI_MAXTGTS
; target
++)
450 (void) pvscsi_config_one(pdip
, pvs
, target
, NULL
);
452 return (NDI_SUCCESS
);
455 static pvscsi_cmd_t
*
456 pvscsi_process_comp_ring(pvscsi_softc_t
*pvs
)
458 pvscsi_cmd_t
**pnext_cmd
= NULL
;
460 pvscsi_cmd_t
*head
= NULL
;
461 struct PVSCSIRingsState
*sdesc
= RINGS_STATE(pvs
);
462 uint32_t cmp_ne
= sdesc
->cmpNumEntriesLog2
;
464 ASSERT(mutex_owned(&pvs
->rx_mutex
));
466 while (sdesc
->cmpConsIdx
!= sdesc
->cmpProdIdx
) {
467 pvscsi_cmd_ctx_t
*ctx
;
468 struct PVSCSIRingCmpDesc
*cdesc
;
470 cdesc
= CMP_RING(pvs
) + (sdesc
->cmpConsIdx
& MASK(cmp_ne
));
473 ctx
= pvscsi_resolve_ctx(pvs
, cdesc
->context
);
476 if ((cmd
= ctx
->cmd
) != NULL
) {
477 cmd
->next_cmd
= NULL
;
479 /* Save command status for further processing */
480 cmd
->cmp_stat
.host_status
= cdesc
->hostStatus
;
481 cmd
->cmp_stat
.scsi_status
= cdesc
->scsiStatus
;
482 cmd
->cmp_stat
.data_len
= cdesc
->dataLen
;
484 /* Mark this command as arrived from hardware */
485 cmd
->flags
|= PVSCSI_FLAG_HW_STATUS
;
489 head
->tail_cmd
= cmd
;
491 head
->tail_cmd
= cmd
;
494 if (pnext_cmd
== NULL
) {
495 pnext_cmd
= &cmd
->next_cmd
;
498 pnext_cmd
= &cmd
->next_cmd
;
509 static pvscsi_msg_t
*
510 pvscsi_process_msg_ring(pvscsi_softc_t
*pvs
)
513 struct PVSCSIRingsState
*sdesc
= RINGS_STATE(pvs
);
514 struct PVSCSIRingMsgDesc
*mdesc
;
515 struct PVSCSIMsgDescDevStatusChanged
*desc
;
516 uint32_t msg_ne
= sdesc
->msgNumEntriesLog2
;
518 ASSERT(mutex_owned(&pvs
->rx_mutex
));
520 if (sdesc
->msgProdIdx
== sdesc
->msgConsIdx
)
523 mdesc
= MSG_RING(pvs
) + (sdesc
->msgConsIdx
& MASK(msg_ne
));
526 switch (mdesc
->type
) {
527 case PVSCSI_MSG_DEV_ADDED
:
528 case PVSCSI_MSG_DEV_REMOVED
:
529 desc
= (struct PVSCSIMsgDescDevStatusChanged
*)mdesc
;
530 msg
= kmem_alloc(sizeof (pvscsi_msg_t
), KM_NOSLEEP
);
534 msg
->type
= mdesc
->type
;
535 msg
->target
= desc
->target
;
538 dev_err(pvs
->dip
, CE_WARN
, "!unknown msg type: %d",
550 pvscsi_handle_msg(void *arg
)
552 pvscsi_msg_t
*msg
= (pvscsi_msg_t
*)arg
;
554 (void) pvscsi_config_one(msg
->msg_pvs
->dip
, msg
->msg_pvs
, msg
->target
,
557 kmem_free(msg
, sizeof (pvscsi_msg_t
));
561 pvscsi_abort_cmd(pvscsi_cmd_t
*cmd
, pvscsi_cmd_t
**pending
)
563 pvscsi_softc_t
*pvs
= cmd
->cmd_pvs
;
566 struct PVSCSICmdDescAbortCmd acmd
;
568 dev_err(pvs
->dip
, CE_WARN
, "!aborting command %p", (void *)cmd
);
570 ASSERT(mutex_owned(&pvs
->rx_mutex
));
571 ASSERT(mutex_owned(&pvs
->tx_mutex
));
573 /* Check if the cmd was already completed by the HBA */
574 *pending
= done
= pvscsi_process_comp_ring(pvs
);
575 for (c
= done
; c
!= NULL
; c
= c
->next_cmd
) {
580 /* Check if cmd was really scheduled by the HBA */
581 if (pvscsi_lookup_ctx(pvs
, cmd
) == NULL
)
584 /* Abort cmd in the HBA */
585 bzero(&acmd
, sizeof (acmd
));
586 acmd
.target
= cmd
->cmd_target
;
587 acmd
.context
= pvscsi_map_ctx(pvs
, cmd
->ctx
);
588 pvscsi_write_cmd_desc(pvs
, PVSCSI_CMD_ABORT_CMD
, &acmd
, sizeof (acmd
));
590 /* Check if cmd was completed by the HBA before it could be aborted */
591 if ((done
= pvscsi_process_comp_ring(pvs
)) != NULL
) {
592 done
->tail_cmd
->next_cmd
= *pending
;
594 for (c
= done
; c
!= NULL
; c
= c
->next_cmd
) {
600 /* Release I/O ctx */
601 mutex_enter(&pvs
->mutex
);
602 if (cmd
->ctx
!= NULL
)
603 pvscsi_release_ctx(cmd
);
604 /* Remove cmd from the queue */
605 pvscsi_remove_from_queue(cmd
);
606 mutex_exit(&pvs
->mutex
);
608 /* Insert cmd at the beginning of the list */
609 cmd
->next_cmd
= *pending
;
612 dev_err(pvs
->dip
, CE_WARN
, "!command %p aborted", (void *)cmd
);
614 return (CMD_ABORTED
);
618 pvscsi_map_buffers(pvscsi_cmd_t
*cmd
, struct PVSCSIRingReqDesc
*rdesc
)
623 ASSERT(cmd
->cmd_dmaccount
> 0 && cmd
->cmd_dmaccount
<=
626 rdesc
->dataLen
= cmd
->cmd_dma_count
;
629 if (cmd
->cmd_dma_count
== 0)
632 if (cmd
->cmd_dmaccount
> 1) {
633 struct PVSCSISGElement
*sgl
= CMD_CTX_SGLIST_VA(cmd
->ctx
);
635 for (i
= 0; i
< cmd
->cmd_dmaccount
; i
++) {
636 sgl
[i
].addr
= cmd
->cached_cookies
[i
].dmac_laddress
;
637 sgl
[i
].length
= cmd
->cached_cookies
[i
].dmac_size
;
640 rdesc
->flags
|= PVSCSI_FLAG_CMD_WITH_SG_LIST
;
641 rdesc
->dataAddr
= (uint64_t)CMD_CTX_SGLIST_PA(cmd
->ctx
);
643 rdesc
->dataAddr
= cmd
->cached_cookies
[0].dmac_laddress
;
648 pvscsi_comp_cmd(pvscsi_cmd_t
*cmd
, uint8_t status
)
650 struct scsi_pkt
*pkt
= CMD2PKT(cmd
);
652 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
| STATE_SENT_CMD
|
654 if ((cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) != 0)
655 pkt
->pkt_state
|= STATE_XFERRED_DATA
;
656 pkt
->pkt_reason
= CMD_CMPLT
;
658 *(pkt
->pkt_scbp
) = status
;
662 pvscsi_set_status(pvscsi_cmd_t
*cmd
)
664 pvscsi_softc_t
*pvs
= cmd
->cmd_pvs
;
665 struct scsi_pkt
*pkt
= CMD2PKT(cmd
);
666 uchar_t scsi_status
= cmd
->cmp_stat
.scsi_status
;
667 uint32_t host_status
= cmd
->cmp_stat
.host_status
;
669 if (scsi_status
!= STATUS_GOOD
&&
670 (host_status
== BTSTAT_SUCCESS
||
671 (host_status
== BTSTAT_LINKED_COMMAND_COMPLETED
) ||
672 (host_status
== BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG
))) {
673 if (scsi_status
== STATUS_CHECK
) {
674 struct scsi_arq_status
*astat
= (void*)(pkt
->pkt_scbp
);
678 *pkt
->pkt_scbp
= scsi_status
;
679 pkt
->pkt_state
|= STATE_ARQ_DONE
;
681 if ((cmd
->flags
& PVSCSI_FLAG_XARQ
) != 0) {
682 arq_size
= (cmd
->cmd_rqslen
>=
683 SENSE_BUFFER_SIZE
) ? SENSE_BUFFER_SIZE
:
686 astat
->sts_rqpkt_resid
= SENSE_BUFFER_SIZE
-
688 sensedata
= (uint8_t *)&astat
->sts_sensedata
;
689 bcopy(cmd
->arqbuf
->b_un
.b_addr
, sensedata
,
692 pkt
->pkt_state
|= STATE_XARQ_DONE
;
694 astat
->sts_rqpkt_resid
= 0;
697 astat
->sts_rqpkt_statistics
= 0;
698 astat
->sts_rqpkt_reason
= CMD_CMPLT
;
699 (*(uint8_t *)&astat
->sts_rqpkt_status
) = STATUS_GOOD
;
700 astat
->sts_rqpkt_state
= STATE_GOT_BUS
|
701 STATE_GOT_TARGET
| STATE_SENT_CMD
|
702 STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
704 pvscsi_comp_cmd(cmd
, scsi_status
);
709 switch (host_status
) {
711 case BTSTAT_LINKED_COMMAND_COMPLETED
:
712 case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG
:
713 pvscsi_comp_cmd(cmd
, STATUS_GOOD
);
716 pkt
->pkt_reason
= CMD_DATA_OVR
;
717 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
718 STATE_SENT_CMD
| STATE_GOT_STATUS
|
722 case BTSTAT_DATA_UNDERRUN
:
723 pkt
->pkt_reason
= pkt
->pkt_state
|= (STATE_GOT_BUS
|
724 STATE_GOT_TARGET
| STATE_SENT_CMD
| STATE_GOT_STATUS
);
725 pkt
->pkt_resid
= cmd
->dma_count
- cmd
->cmp_stat
.data_len
;
726 if (pkt
->pkt_resid
!= cmd
->dma_count
)
727 pkt
->pkt_state
|= STATE_XFERRED_DATA
;
729 case BTSTAT_SELTIMEO
:
730 pkt
->pkt_reason
= CMD_DEV_GONE
;
731 pkt
->pkt_state
|= STATE_GOT_BUS
;
733 case BTSTAT_TAGREJECT
:
734 pkt
->pkt_reason
= CMD_TAG_REJECT
;
735 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
736 STATE_SENT_CMD
| STATE_GOT_STATUS
);
739 pkt
->pkt_reason
= CMD_BADMSG
;
740 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
741 STATE_SENT_CMD
| STATE_GOT_STATUS
);
745 case BTSTAT_BUSRESET
:
746 pkt
->pkt_reason
= CMD_RESET
;
747 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
748 STATE_SENT_CMD
| STATE_GOT_STATUS
);
750 case BTSTAT_ABORTQUEUE
:
751 pkt
->pkt_reason
= CMD_ABORTED
;
752 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
753 STATE_SENT_CMD
| STATE_GOT_STATUS
);
755 case BTSTAT_HAHARDWARE
:
756 case BTSTAT_INVPHASE
:
757 case BTSTAT_HATIMEOUT
:
758 case BTSTAT_NORESPONSE
:
759 case BTSTAT_DISCONNECT
:
760 case BTSTAT_HASOFTWARE
:
762 case BTSTAT_SENSFAILED
:
763 pkt
->pkt_reason
= CMD_TRAN_ERR
;
764 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
765 STATE_SENT_CMD
| STATE_GOT_STATUS
);
768 dev_err(pvs
->dip
, CE_WARN
,
769 "!unknown host status code: %d", host_status
);
770 pkt
->pkt_reason
= CMD_TRAN_ERR
;
771 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
|
772 STATE_SENT_CMD
| STATE_GOT_STATUS
);
778 pvscsi_complete_chained(void *arg
)
780 pvscsi_cmd_t
*cmd
= (pvscsi_cmd_t
*)arg
;
782 struct scsi_pkt
*pkt
;
784 while (cmd
!= NULL
) {
785 pvscsi_softc_t
*pvs
= cmd
->cmd_pvs
;
788 cmd
->next_cmd
= NULL
;
794 if ((cmd
->flags
& PVSCSI_FLAG_IO_IOPB
) != 0 &&
795 (cmd
->flags
& PVSCSI_FLAG_IO_READ
) != 0) {
796 (void) ddi_dma_sync(cmd
->cmd_dmahdl
, 0, 0,
797 DDI_DMA_SYNC_FORCPU
);
800 mutex_enter(&pvs
->mutex
);
801 /* Release I/O ctx */
802 if (cmd
->ctx
!= NULL
)
803 pvscsi_release_ctx(cmd
);
804 /* Remove command from queue */
805 pvscsi_remove_from_queue(cmd
);
806 mutex_exit(&pvs
->mutex
);
808 if ((cmd
->flags
& PVSCSI_FLAG_HW_STATUS
) != 0) {
809 pvscsi_set_status(cmd
);
811 ASSERT((cmd
->flags
& PVSCSI_FLAGS_NON_HW_COMPLETION
) !=
814 if ((cmd
->flags
& PVSCSI_FLAG_TIMED_OUT
) != 0) {
815 cmd
->pkt
->pkt_reason
= CMD_TIMEOUT
;
816 cmd
->pkt
->pkt_statistics
|=
817 (STAT_TIMEOUT
| STAT_ABORTED
);
818 } else if ((cmd
->flags
& PVSCSI_FLAG_ABORTED
) != 0) {
819 cmd
->pkt
->pkt_reason
= CMD_ABORTED
;
820 cmd
->pkt
->pkt_statistics
|=
821 (STAT_TIMEOUT
| STAT_ABORTED
);
822 } else if ((cmd
->flags
& PVSCSI_FLAGS_RESET
) != 0) {
823 cmd
->pkt
->pkt_reason
= CMD_RESET
;
824 if ((cmd
->flags
& PVSCSI_FLAG_RESET_BUS
) != 0) {
825 cmd
->pkt
->pkt_statistics
|=
828 cmd
->pkt
->pkt_statistics
|=
834 cmd
->flags
|= PVSCSI_FLAG_DONE
;
835 cmd
->flags
&= ~PVSCSI_FLAG_TRANSPORT
;
837 if ((pkt
->pkt_flags
& FLAG_NOINTR
) == 0 &&
838 pkt
->pkt_comp
!= NULL
)
839 (*pkt
->pkt_comp
)(pkt
);
846 pvscsi_dev_reset(pvscsi_softc_t
*pvs
, int target
)
848 struct PVSCSICmdDescResetDevice cmd
= { 0 };
851 pvscsi_write_cmd_desc(pvs
, PVSCSI_CMD_RESET_DEVICE
, &cmd
, sizeof (cmd
));
855 pvscsi_poll_cmd(pvscsi_softc_t
*pvs
, pvscsi_cmd_t
*cmd
)
858 int cycles
= (cmd
->pkt
->pkt_time
* 1000000) / USECS_TO_WAIT
;
861 struct scsi_pkt
*pkt
= CMD2PKT(cmd
);
864 * Make sure we're not missing any commands completed
865 * concurrently before we have actually disabled interrupts.
867 mutex_enter(&pvs
->rx_mutex
);
868 dcmd
= pvscsi_process_comp_ring(pvs
);
869 mutex_exit(&pvs
->rx_mutex
);
871 pvscsi_complete_chained(dcmd
);
873 while ((cmd
->flags
& PVSCSI_FLAG_DONE
) == 0) {
876 /* Disable interrupts from H/W */
877 pvscsi_mask_intr(pvs
);
879 /* Wait for interrupt to arrive */
880 for (i
= 0; i
< cycles
; i
++) {
883 mutex_enter(&pvs
->rx_mutex
);
884 mutex_enter(&pvs
->intr_mutex
);
885 status
= pvscsi_read_intr_status(pvs
);
886 if ((status
& PVSCSI_INTR_ALL_SUPPORTED
) != 0) {
887 /* Check completion ring */
888 mutex_exit(&pvs
->intr_mutex
);
889 dcmd
= pvscsi_process_comp_ring(pvs
);
890 mutex_exit(&pvs
->rx_mutex
);
894 mutex_exit(&pvs
->intr_mutex
);
895 mutex_exit(&pvs
->rx_mutex
);
896 drv_usecwait(USECS_TO_WAIT
);
900 /* Enable interrupts from H/W */
901 pvscsi_unmask_intr(pvs
);
904 /* No interrupts seen from device during the timeout */
905 mutex_enter(&pvs
->tx_mutex
);
906 mutex_enter(&pvs
->rx_mutex
);
907 if ((cmd
->flags
& PVSCSI_FLAGS_COMPLETION
) != 0) {
908 /* Command was cancelled asynchronously */
910 } else if ((pvscsi_abort_cmd(cmd
,
911 &dcmd
)) == CMD_ABORTED
) {
912 /* Command was cancelled in hardware */
913 pkt
->pkt_state
|= (STAT_TIMEOUT
| STAT_ABORTED
);
914 pkt
->pkt_statistics
|= (STAT_TIMEOUT
|
916 pkt
->pkt_reason
= CMD_TIMEOUT
;
918 mutex_exit(&pvs
->rx_mutex
);
919 mutex_exit(&pvs
->tx_mutex
);
922 * Complete commands that might be on completion list.
923 * Target command can also be on the list in case it was
924 * completed before it could be actually cancelled.
929 pvscsi_complete_chained(dcmd
);
935 return (TRAN_ACCEPT
);
939 pvscsi_abort_all(struct scsi_address
*ap
, pvscsi_softc_t
*pvs
,
940 pvscsi_cmd_t
**pending
, int marker_flag
)
942 int qlen
= pvs
->cmd_queue_len
;
943 pvscsi_cmd_t
*cmd
, *pcmd
, *phead
= NULL
;
945 ASSERT(mutex_owned(&pvs
->rx_mutex
));
946 ASSERT(mutex_owned(&pvs
->tx_mutex
));
949 * Try to abort all queued commands, merging commands waiting
950 * for completion into a single list to complete them at one
951 * time when mutex is released.
954 mutex_enter(&pvs
->mutex
);
955 cmd
= list_remove_head(&pvs
->cmd_queue
);
960 if (ap
== NULL
|| ap
->a_target
== cmd
->cmd_target
) {
961 int c
= --pvs
->cmd_queue_len
;
963 mutex_exit(&pvs
->mutex
);
965 if (pvscsi_abort_cmd(cmd
, &pcmd
) == CMD_ABORTED
) {
967 * Assume command is completely cancelled now,
968 * so mark it as requested.
970 cmd
->flags
|= marker_flag
;
973 qlen
-= (c
- pvs
->cmd_queue_len
);
976 * Now merge current pending commands with
981 } else if (pcmd
!= NULL
) {
982 phead
->tail_cmd
->next_cmd
= pcmd
;
983 phead
->tail_cmd
= pcmd
->tail_cmd
;
986 list_insert_tail(&pvs
->cmd_queue
, cmd
);
987 mutex_exit(&pvs
->mutex
);
995 pvscsi_quiesce_notify(pvscsi_softc_t
*pvs
)
997 mutex_enter(&pvs
->mutex
);
998 if (pvs
->cmd_queue_len
== 0 &&
999 (pvs
->flags
& PVSCSI_HBA_QUIESCE_PENDING
) != 0) {
1000 pvs
->flags
&= ~PVSCSI_HBA_QUIESCE_PENDING
;
1001 cv_broadcast(&pvs
->quiescevar
);
1003 mutex_exit(&pvs
->mutex
);
1007 pvscsi_transport_command(pvscsi_softc_t
*pvs
, pvscsi_cmd_t
*cmd
)
1009 struct PVSCSIRingReqDesc
*rdesc
;
1010 struct PVSCSIRingsState
*sdesc
= RINGS_STATE(pvs
);
1011 struct scsi_pkt
*pkt
= CMD2PKT(cmd
);
1012 uint32_t req_ne
= sdesc
->reqNumEntriesLog2
;
1014 mutex_enter(&pvs
->tx_mutex
);
1015 mutex_enter(&pvs
->mutex
);
1016 if (!pvscsi_acquire_ctx(pvs
, cmd
)) {
1017 mutex_exit(&pvs
->mutex
);
1018 mutex_exit(&pvs
->tx_mutex
);
1019 dev_err(pvs
->dip
, CE_WARN
, "!no free ctx available");
1023 if ((sdesc
->reqProdIdx
- sdesc
->cmpConsIdx
) >= (1 << req_ne
)) {
1024 pvscsi_release_ctx(cmd
);
1025 mutex_exit(&pvs
->mutex
);
1026 mutex_exit(&pvs
->tx_mutex
);
1027 dev_err(pvs
->dip
, CE_WARN
, "!no free I/O slots available");
1030 mutex_exit(&pvs
->mutex
);
1032 cmd
->flags
|= PVSCSI_FLAG_TRANSPORT
;
1034 rdesc
= REQ_RING(pvs
) + (sdesc
->reqProdIdx
& MASK(req_ne
));
1036 bzero(&rdesc
->lun
, sizeof (rdesc
->lun
));
1039 rdesc
->target
= cmd
->cmd_target
;
1041 if ((cmd
->flags
& PVSCSI_FLAG_XARQ
) != 0) {
1042 bzero((void*)cmd
->arqbuf
->b_un
.b_addr
, SENSE_BUFFER_SIZE
);
1043 rdesc
->senseLen
= SENSE_BUFFER_SIZE
;
1044 rdesc
->senseAddr
= cmd
->arqc
.dmac_laddress
;
1046 rdesc
->senseLen
= 0;
1047 rdesc
->senseAddr
= 0;
1050 rdesc
->vcpuHint
= CPU
->cpu_id
;
1051 rdesc
->cdbLen
= cmd
->cmdlen
;
1052 bcopy(cmd
->cmd_cdb
, rdesc
->cdb
, cmd
->cmdlen
);
1054 /* Setup tag info */
1055 if ((cmd
->flags
& PVSCSI_FLAG_TAG
) != 0)
1056 rdesc
->tag
= cmd
->tag
;
1058 rdesc
->tag
= MSG_SIMPLE_QTAG
;
1060 /* Setup I/O direction and map data buffers */
1061 if ((cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) != 0) {
1062 if ((cmd
->flags
& PVSCSI_FLAG_IO_READ
) != 0)
1063 rdesc
->flags
= PVSCSI_FLAG_CMD_DIR_TOHOST
;
1065 rdesc
->flags
= PVSCSI_FLAG_CMD_DIR_TODEVICE
;
1066 pvscsi_map_buffers(cmd
, rdesc
);
1071 rdesc
->context
= pvscsi_map_ctx(pvs
, cmd
->ctx
);
1074 sdesc
->reqProdIdx
++;
1077 mutex_enter(&pvs
->mutex
);
1078 cmd
->timeout_lbolt
= ddi_get_lbolt() + SEC_TO_TICK(pkt
->pkt_time
);
1079 pkt
->pkt_state
|= (STATE_GOT_BUS
| STATE_GOT_TARGET
| STATE_SENT_CMD
);
1080 pvscsi_add_to_queue(cmd
);
1082 switch (cmd
->pkt
->pkt_cdbp
[0]) {
1091 ASSERT((cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) != 0);
1092 pvscsi_submit_rw_io(pvs
);
1095 pvscsi_submit_nonrw_io(pvs
);
1098 mutex_exit(&pvs
->mutex
);
1099 mutex_exit(&pvs
->tx_mutex
);
1101 return (TRAN_ACCEPT
);
1105 pvscsi_reset_generic(pvscsi_softc_t
*pvs
, struct scsi_address
*ap
)
1107 boolean_t bus_reset
= (ap
== NULL
);
1109 pvscsi_cmd_t
*done
, *aborted
;
1111 flags
= bus_reset
? PVSCSI_FLAG_RESET_BUS
: PVSCSI_FLAG_RESET_DEV
;
1113 mutex_enter(&pvs
->tx_mutex
);
1114 mutex_enter(&pvs
->rx_mutex
);
1115 /* Try to process pending requests */
1116 done
= pvscsi_process_comp_ring(pvs
);
1118 /* Abort all pending requests */
1119 pvscsi_abort_all(ap
, pvs
, &aborted
, flags
);
1121 /* Reset at hardware level */
1123 pvscsi_reset_bus(pvs
);
1124 /* Should never happen after bus reset */
1125 ASSERT(pvscsi_process_comp_ring(pvs
) == NULL
);
1127 pvscsi_dev_reset(pvs
, ap
->a_target
);
1129 mutex_exit(&pvs
->rx_mutex
);
1130 mutex_exit(&pvs
->tx_mutex
);
1132 pvscsi_complete_chained(done
);
1133 pvscsi_complete_chained(aborted
);
1139 pvscsi_cmd_ext_free(pvscsi_cmd_t
*cmd
)
1141 struct scsi_pkt
*pkt
= CMD2PKT(cmd
);
1143 if ((cmd
->flags
& PVSCSI_FLAG_CDB_EXT
) != 0) {
1144 kmem_free(pkt
->pkt_cdbp
, cmd
->cmdlen
);
1145 cmd
->flags
&= ~PVSCSI_FLAG_CDB_EXT
;
1147 if ((cmd
->flags
& PVSCSI_FLAG_SCB_EXT
) != 0) {
1148 kmem_free(pkt
->pkt_scbp
, cmd
->statuslen
);
1149 cmd
->flags
&= ~PVSCSI_FLAG_SCB_EXT
;
1151 if ((cmd
->flags
& PVSCSI_FLAG_PRIV_EXT
) != 0) {
1152 kmem_free(pkt
->pkt_private
, cmd
->tgtlen
);
1153 cmd
->flags
&= ~PVSCSI_FLAG_PRIV_EXT
;
1159 pvscsi_cmd_ext_alloc(pvscsi_softc_t
*pvs
, pvscsi_cmd_t
*cmd
, int kf
)
1161 struct scsi_pkt
*pkt
= CMD2PKT(cmd
);
1164 if (cmd
->cmdlen
> sizeof (cmd
->cmd_cdb
)) {
1165 if ((buf
= kmem_zalloc(cmd
->cmdlen
, kf
)) == NULL
)
1167 pkt
->pkt_cdbp
= buf
;
1168 cmd
->flags
|= PVSCSI_FLAG_CDB_EXT
;
1171 if (cmd
->statuslen
> sizeof (cmd
->cmd_scb
)) {
1172 if ((buf
= kmem_zalloc(cmd
->statuslen
, kf
)) == NULL
)
1174 pkt
->pkt_scbp
= buf
;
1175 cmd
->flags
|= PVSCSI_FLAG_SCB_EXT
;
1176 cmd
->cmd_rqslen
= (cmd
->statuslen
- sizeof (cmd
->cmd_scb
));
1179 if (cmd
->tgtlen
> sizeof (cmd
->tgt_priv
)) {
1180 if ((buf
= kmem_zalloc(cmd
->tgtlen
, kf
)) == NULL
)
1182 pkt
->pkt_private
= buf
;
1183 cmd
->flags
|= PVSCSI_FLAG_PRIV_EXT
;
1186 return (DDI_SUCCESS
);
1189 pvscsi_cmd_ext_free(cmd
);
1195 pvscsi_setup_dma_buffer(pvscsi_softc_t
*pvs
, size_t length
,
1196 pvscsi_dma_buf_t
*buf
)
1198 ddi_dma_cookie_t cookie
;
1201 if ((ddi_dma_alloc_handle(pvs
->dip
, &pvscsi_ring_dma_attr
,
1202 DDI_DMA_SLEEP
, NULL
, &buf
->dma_handle
)) != DDI_SUCCESS
) {
1203 dev_err(pvs
->dip
, CE_WARN
, "!failed to allocate DMA handle");
1204 return (DDI_FAILURE
);
1207 if ((ddi_dma_mem_alloc(buf
->dma_handle
, length
, &pvscsi_dma_attrs
,
1208 DDI_DMA_CONSISTENT
, DDI_DMA_SLEEP
, NULL
, &buf
->addr
,
1209 &buf
->real_length
, &buf
->acc_handle
)) != DDI_SUCCESS
) {
1210 dev_err(pvs
->dip
, CE_WARN
,
1211 "!failed to allocate %ld bytes for DMA buffer", length
);
1212 ddi_dma_free_handle(&buf
->dma_handle
);
1213 return (DDI_FAILURE
);
1216 if ((ddi_dma_addr_bind_handle(buf
->dma_handle
, NULL
, buf
->addr
,
1217 buf
->real_length
, DDI_DMA_CONSISTENT
| DDI_DMA_RDWR
, DDI_DMA_SLEEP
,
1218 NULL
, &cookie
, &ccount
)) != DDI_SUCCESS
) {
1219 dev_err(pvs
->dip
, CE_WARN
, "!failed to bind DMA buffer");
1220 ddi_dma_free_handle(&buf
->dma_handle
);
1221 ddi_dma_mem_free(&buf
->acc_handle
);
1222 return (DDI_FAILURE
);
1225 /* TODO Support multipart SG regions */
1226 ASSERT(ccount
== 1);
1228 buf
->pa
= cookie
.dmac_laddress
;
1230 return (DDI_SUCCESS
);
1234 pvscsi_free_dma_buffer(pvscsi_dma_buf_t
*buf
)
1236 ddi_dma_free_handle(&buf
->dma_handle
);
1237 ddi_dma_mem_free(&buf
->acc_handle
);
1241 pvscsi_setup_sg(pvscsi_softc_t
*pvs
)
1244 pvscsi_cmd_ctx_t
*ctx
;
1245 size_t size
= pvs
->req_depth
* sizeof (pvscsi_cmd_ctx_t
);
1247 ctx
= pvs
->cmd_ctx
= kmem_zalloc(size
, KM_SLEEP
);
1249 for (i
= 0; i
< pvs
->req_depth
; ++i
, ++ctx
) {
1250 list_insert_tail(&pvs
->cmd_ctx_pool
, ctx
);
1251 if (pvscsi_setup_dma_buffer(pvs
, PAGE_SIZE
,
1252 &ctx
->dma_buf
) != DDI_SUCCESS
)
1256 return (DDI_SUCCESS
);
1259 for (; i
>= 0; --i
, --ctx
) {
1260 list_remove(&pvs
->cmd_ctx_pool
, ctx
);
1261 pvscsi_free_dma_buffer(&ctx
->dma_buf
);
1263 kmem_free(pvs
->cmd_ctx
, size
);
1265 return (DDI_FAILURE
);
1269 pvscsi_free_sg(pvscsi_softc_t
*pvs
)
1272 pvscsi_cmd_ctx_t
*ctx
= pvs
->cmd_ctx
;
1274 for (i
= 0; i
< pvs
->req_depth
; ++i
, ++ctx
) {
1275 list_remove(&pvs
->cmd_ctx_pool
, ctx
);
1276 pvscsi_free_dma_buffer(&ctx
->dma_buf
);
1279 kmem_free(pvs
->cmd_ctx
, pvs
->req_pages
<< PAGE_SHIFT
);
1283 pvscsi_allocate_rings(pvscsi_softc_t
*pvs
)
1285 /* Allocate DMA buffer for rings state */
1286 if (pvscsi_setup_dma_buffer(pvs
, PAGE_SIZE
,
1287 &pvs
->rings_state_buf
) != DDI_SUCCESS
)
1288 return (DDI_FAILURE
);
1290 /* Allocate DMA buffer for request ring */
1291 pvs
->req_pages
= MIN(pvscsi_ring_pages
, PVSCSI_MAX_NUM_PAGES_REQ_RING
);
1292 pvs
->req_depth
= pvs
->req_pages
* PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE
;
1293 if (pvscsi_setup_dma_buffer(pvs
, pvs
->req_pages
* PAGE_SIZE
,
1294 &pvs
->req_ring_buf
) != DDI_SUCCESS
)
1295 goto free_rings_state
;
1297 /* Allocate completion ring */
1298 pvs
->cmp_pages
= MIN(pvscsi_ring_pages
, PVSCSI_MAX_NUM_PAGES_CMP_RING
);
1299 if (pvscsi_setup_dma_buffer(pvs
, pvs
->cmp_pages
* PAGE_SIZE
,
1300 &pvs
->cmp_ring_buf
) != DDI_SUCCESS
)
1303 /* Allocate message ring */
1304 pvs
->msg_pages
= MIN(pvscsi_msg_ring_pages
,
1305 PVSCSI_MAX_NUM_PAGES_MSG_RING
);
1306 if (pvscsi_setup_dma_buffer(pvs
, pvs
->msg_pages
* PAGE_SIZE
,
1307 &pvs
->msg_ring_buf
) != DDI_SUCCESS
)
1310 return (DDI_SUCCESS
);
1313 pvscsi_free_dma_buffer(&pvs
->cmp_ring_buf
);
1315 pvscsi_free_dma_buffer(&pvs
->req_ring_buf
);
1317 pvscsi_free_dma_buffer(&pvs
->rings_state_buf
);
1319 return (DDI_FAILURE
);
1323 pvscsi_free_rings(pvscsi_softc_t
*pvs
)
1325 pvscsi_free_dma_buffer(&pvs
->msg_ring_buf
);
1326 pvscsi_free_dma_buffer(&pvs
->cmp_ring_buf
);
1327 pvscsi_free_dma_buffer(&pvs
->req_ring_buf
);
1328 pvscsi_free_dma_buffer(&pvs
->rings_state_buf
);
1332 pvscsi_setup_rings(pvscsi_softc_t
*pvs
)
1335 struct PVSCSICmdDescSetupMsgRing cmd_msg
= { 0 };
1336 struct PVSCSICmdDescSetupRings cmd
= { 0 };
1339 cmd
.ringsStatePPN
= pvs
->rings_state_buf
.pa
>> PAGE_SHIFT
;
1340 cmd
.reqRingNumPages
= pvs
->req_pages
;
1341 cmd
.cmpRingNumPages
= pvs
->cmp_pages
;
1343 /* Setup request ring */
1344 base
= pvs
->req_ring_buf
.pa
;
1345 for (i
= 0; i
< pvs
->req_pages
; i
++) {
1346 cmd
.reqRingPPNs
[i
] = base
>> PAGE_SHIFT
;
1350 /* Setup completion ring */
1351 base
= pvs
->cmp_ring_buf
.pa
;
1352 for (i
= 0; i
< pvs
->cmp_pages
; i
++) {
1353 cmd
.cmpRingPPNs
[i
] = base
>> PAGE_SHIFT
;
1357 bzero(RINGS_STATE(pvs
), PAGE_SIZE
);
1358 bzero(REQ_RING(pvs
), pvs
->req_pages
* PAGE_SIZE
);
1359 bzero(CMP_RING(pvs
), pvs
->cmp_pages
* PAGE_SIZE
);
1361 /* Issue SETUP command */
1362 pvscsi_write_cmd_desc(pvs
, PVSCSI_CMD_SETUP_RINGS
, &cmd
, sizeof (cmd
));
1364 /* Setup message ring */
1365 cmd_msg
.numPages
= pvs
->msg_pages
;
1366 base
= pvs
->msg_ring_buf
.pa
;
1368 for (i
= 0; i
< pvs
->msg_pages
; i
++) {
1369 cmd_msg
.ringPPNs
[i
] = base
>> PAGE_SHIFT
;
1372 bzero(MSG_RING(pvs
), pvs
->msg_pages
* PAGE_SIZE
);
1374 pvscsi_write_cmd_desc(pvs
, PVSCSI_CMD_SETUP_MSG_RING
, &cmd_msg
,
1379 pvscsi_setup_io(pvscsi_softc_t
*pvs
)
1381 int offset
, rcount
, rn
, type
;
1382 int ret
= DDI_FAILURE
;
1384 pci_regspec_t
*regs
;
1387 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, pvs
->dip
,
1388 DDI_PROP_DONTPASS
, "reg", (int **)®s
,
1389 ®s_length
) != DDI_PROP_SUCCESS
) {
1390 dev_err(pvs
->dip
, CE_WARN
, "!failed to lookup 'reg' property");
1391 return (DDI_FAILURE
);
1394 rcount
= regs_length
* sizeof (int) / sizeof (pci_regspec_t
);
1396 for (offset
= PCI_CONF_BASE0
; offset
<= PCI_CONF_BASE5
; offset
+= 4) {
1397 for (rn
= 0; rn
< rcount
; ++rn
) {
1398 if (PCI_REG_REG_G(regs
[rn
].pci_phys_hi
) == offset
) {
1399 type
= regs
[rn
].pci_phys_hi
& PCI_ADDR_MASK
;
1407 if (type
!= PCI_ADDR_IO
) {
1408 if (ddi_dev_regsize(pvs
->dip
, rn
,
1409 ®size
) != DDI_SUCCESS
) {
1410 dev_err(pvs
->dip
, CE_WARN
,
1411 "!failed to get size of reg %d", rn
);
1414 if (regsize
== PVSCSI_MEM_SPACE_SIZE
) {
1415 if (ddi_regs_map_setup(pvs
->dip
, rn
,
1416 &pvs
->mmio_base
, 0, 0,
1418 &pvs
->mmio_handle
) != DDI_SUCCESS
) {
1419 dev_err(pvs
->dip
, CE_WARN
,
1420 "!failed to map MMIO BAR");
1430 ddi_prop_free(regs
);
1436 pvscsi_free_io(pvscsi_softc_t
*pvs
)
1438 ddi_regs_map_free(&pvs
->mmio_handle
);
1442 pvscsi_enable_intrs(pvscsi_softc_t
*pvs
)
1444 int i
, rc
, intr_caps
;
1446 if ((rc
= ddi_intr_get_cap(pvs
->intr_htable
[0], &intr_caps
)) !=
1448 dev_err(pvs
->dip
, CE_WARN
, "!failed to get interrupt caps");
1449 return (DDI_FAILURE
);
1452 if ((intr_caps
& DDI_INTR_FLAG_BLOCK
) != 0) {
1453 if ((rc
= ddi_intr_block_enable(pvs
->intr_htable
,
1454 pvs
->intr_cnt
)) != DDI_SUCCESS
) {
1455 dev_err(pvs
->dip
, CE_WARN
,
1456 "!failed to enable interrupt block");
1459 for (i
= 0; i
< pvs
->intr_cnt
; i
++) {
1460 if ((rc
= ddi_intr_enable(pvs
->intr_htable
[i
])) ==
1463 dev_err(pvs
->dip
, CE_WARN
,
1464 "!failed to enable interrupt");
1466 (void) ddi_intr_disable(pvs
->intr_htable
[i
]);
1471 /* Unmask interrupts */
1472 if (rc
== DDI_SUCCESS
) {
1473 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_INTR_MASK
,
1474 PVSCSI_INTR_CMPL_MASK
| PVSCSI_INTR_MSG_MASK
);
1482 pvscsi_intr_handler(caddr_t arg1
, caddr_t arg2
)
1485 pvscsi_softc_t
*pvs
= (pvscsi_softc_t
*)arg1
;
1488 mutex_enter(&pvs
->intr_mutex
);
1489 if (pvs
->num_pollers
> 0) {
1490 mutex_exit(&pvs
->intr_mutex
);
1491 return (DDI_INTR_CLAIMED
);
1494 if (pvscsi_enable_msi
) {
1497 status
= pvscsi_read_intr_status(pvs
);
1498 handled
= (status
& PVSCSI_INTR_ALL_SUPPORTED
) != 0;
1500 pvscsi_write_intr_status(pvs
, status
);
1502 mutex_exit(&pvs
->intr_mutex
);
1506 pvscsi_cmd_t
*pending
;
1509 mutex_enter(&pvs
->rx_mutex
);
1510 pending
= pvscsi_process_comp_ring(pvs
);
1511 msg
= pvscsi_process_msg_ring(pvs
);
1512 mutex_exit(&pvs
->rx_mutex
);
1514 mutex_enter(&pvs
->mutex
);
1515 qnotify
= HBA_QUIESCE_PENDING(pvs
);
1516 mutex_exit(&pvs
->mutex
);
1518 if (pending
!= NULL
&& ddi_taskq_dispatch(pvs
->comp_tq
,
1519 pvscsi_complete_chained
, pending
,
1520 DDI_NOSLEEP
) == DDI_FAILURE
)
1521 pvscsi_complete_chained(pending
);
1523 if (msg
!= NULL
&& ddi_taskq_dispatch(pvs
->msg_tq
,
1524 pvscsi_handle_msg
, msg
, DDI_NOSLEEP
) == DDI_FAILURE
) {
1525 dev_err(pvs
->dip
, CE_WARN
,
1526 "!failed to process msg type %d for target %d",
1527 msg
->type
, msg
->target
);
1528 kmem_free(msg
, sizeof (pvscsi_msg_t
));
1532 pvscsi_quiesce_notify(pvs
);
1535 return (handled
? DDI_INTR_CLAIMED
: DDI_INTR_UNCLAIMED
);
1539 pvscsi_register_isr(pvscsi_softc_t
*pvs
, int type
)
1541 int navail
, nactual
;
1544 if (ddi_intr_get_navail(pvs
->dip
, type
, &navail
) != DDI_SUCCESS
||
1546 dev_err(pvs
->dip
, CE_WARN
,
1547 "!failed to get number of available interrupts of type %d",
1549 return (DDI_FAILURE
);
1551 navail
= MIN(navail
, PVSCSI_MAX_INTRS
);
1553 pvs
->intr_size
= navail
* sizeof (ddi_intr_handle_t
);
1554 if ((pvs
->intr_htable
= kmem_alloc(pvs
->intr_size
, KM_SLEEP
)) == NULL
) {
1555 dev_err(pvs
->dip
, CE_WARN
,
1556 "!failed to allocate %d bytes for interrupt hashtable",
1558 return (DDI_FAILURE
);
1561 if (ddi_intr_alloc(pvs
->dip
, pvs
->intr_htable
, type
, 0, navail
,
1562 &nactual
, DDI_INTR_ALLOC_NORMAL
) != DDI_SUCCESS
|| nactual
== 0) {
1563 dev_err(pvs
->dip
, CE_WARN
, "!failed to allocate %d interrupts",
1568 pvs
->intr_cnt
= nactual
;
1570 if (ddi_intr_get_pri(pvs
->intr_htable
[0],
1571 (uint_t
*)&pvs
->intr_pri
) != DDI_SUCCESS
) {
1572 dev_err(pvs
->dip
, CE_WARN
, "!failed to get interrupt priority");
1576 for (i
= 0; i
< nactual
; i
++) {
1577 if (ddi_intr_add_handler(pvs
->intr_htable
[i
],
1578 pvscsi_intr_handler
, (caddr_t
)pvs
, NULL
) != DDI_SUCCESS
) {
1579 dev_err(pvs
->dip
, CE_WARN
,
1580 "!failed to add interrupt handler");
1585 return (DDI_SUCCESS
);
1588 for (i
= 0; i
< nactual
; i
++)
1589 (void) ddi_intr_free(pvs
->intr_htable
[i
]);
1591 kmem_free(pvs
->intr_htable
, pvs
->intr_size
);
1593 return (DDI_FAILURE
);
1597 pvscsi_free_intr_resources(pvscsi_softc_t
*pvs
)
1601 for (i
= 0; i
< pvs
->intr_cnt
; i
++) {
1602 (void) ddi_intr_disable(pvs
->intr_htable
[i
]);
1603 (void) ddi_intr_remove_handler(pvs
->intr_htable
[i
]);
1604 (void) ddi_intr_free(pvs
->intr_htable
[i
]);
1606 kmem_free(pvs
->intr_htable
, pvs
->intr_size
);
1610 pvscsi_setup_isr(pvscsi_softc_t
*pvs
)
1614 if (ddi_intr_get_supported_types(pvs
->dip
,
1615 &intr_types
) != DDI_SUCCESS
) {
1616 dev_err(pvs
->dip
, CE_WARN
,
1617 "!failed to get supported interrupt types");
1618 return (DDI_FAILURE
);
1621 if ((intr_types
& DDI_INTR_TYPE_MSIX
) != 0 && pvscsi_enable_msi
) {
1622 if (pvscsi_register_isr(pvs
,
1623 DDI_INTR_TYPE_MSIX
) == DDI_SUCCESS
) {
1624 pvs
->intr_type
= DDI_INTR_TYPE_MSIX
;
1626 dev_err(pvs
->dip
, CE_WARN
,
1627 "!failed to install MSI-X interrupt handler");
1629 } else if ((intr_types
& DDI_INTR_TYPE_MSI
) != 0 && pvscsi_enable_msi
) {
1630 if (pvscsi_register_isr(pvs
,
1631 DDI_INTR_TYPE_MSI
) == DDI_SUCCESS
) {
1632 pvs
->intr_type
= DDI_INTR_TYPE_MSI
;
1634 dev_err(pvs
->dip
, CE_WARN
,
1635 "!failed to install MSI interrupt handler");
1637 } else if ((intr_types
& DDI_INTR_TYPE_FIXED
) != 0) {
1638 if (pvscsi_register_isr(pvs
,
1639 DDI_INTR_TYPE_FIXED
) == DDI_SUCCESS
) {
1640 pvs
->intr_type
= DDI_INTR_TYPE_FIXED
;
1642 dev_err(pvs
->dip
, CE_WARN
,
1643 "!failed to install FIXED interrupt handler");
1647 return (pvs
->intr_type
== 0 ? DDI_FAILURE
: DDI_SUCCESS
);
1651 pvscsi_wd_thread(pvscsi_softc_t
*pvs
)
1654 pvscsi_cmd_t
*expired
, *c
, *cn
, **pnext
;
1656 mutex_enter(&pvs
->mutex
);
1660 now
= ddi_get_lbolt();
1662 for (c
= list_head(&pvs
->cmd_queue
); c
!= NULL
; ) {
1663 cn
= list_next(&pvs
->cmd_queue
, c
);
1666 * Commands with 'FLAG_NOINTR' are watched using their
1667 * own timeouts, so we should not touch them.
1669 if ((c
->pkt
->pkt_flags
& FLAG_NOINTR
) == 0 &&
1670 now
> c
->timeout_lbolt
) {
1671 dev_err(pvs
->dip
, CE_WARN
,
1672 "!expired command: %p (%ld > %ld)",
1673 (void *)c
, now
, c
->timeout_lbolt
);
1674 pvscsi_remove_from_queue(c
);
1675 if (expired
== NULL
)
1677 if (pnext
== NULL
) {
1678 pnext
= &c
->next_cmd
;
1681 pnext
= &c
->next_cmd
;
1686 mutex_exit(&pvs
->mutex
);
1688 /* Now cancel all expired commands */
1689 if (expired
!= NULL
) {
1690 struct scsi_address sa
= {0};
1691 /* Build a fake SCSI address */
1692 sa
.a_hba_tran
= pvs
->tran
;
1693 while (expired
!= NULL
) {
1694 c
= expired
->next_cmd
;
1695 sa
.a_target
= expired
->cmd_target
;
1697 (void) pvscsi_abort(&sa
, CMD2PKT(expired
));
1702 mutex_enter(&pvs
->mutex
);
1703 if ((pvs
->flags
& PVSCSI_DRIVER_SHUTDOWN
) != 0) {
1707 if (cv_reltimedwait(&pvs
->wd_condvar
, &pvs
->mutex
,
1708 SEC_TO_TICK(1), TR_CLOCK_TICK
) > 0) {
1709 /* Explicitly woken up, finish job */
1714 /* Confirm thread termination */
1715 cv_signal(&pvs
->syncvar
);
1716 mutex_exit(&pvs
->mutex
);
1720 pvscsi_ccache_constructor(void *buf
, void *cdrarg
, int kmflags
)
1722 int (*callback
)(caddr_t
);
1724 pvscsi_cmd_t
*cmd
= (pvscsi_cmd_t
*)buf
;
1725 pvscsi_softc_t
*pvs
= cdrarg
;
1726 struct scsi_address ap
;
1728 callback
= (kmflags
== KM_SLEEP
) ? DDI_DMA_SLEEP
: DDI_DMA_DONTWAIT
;
1729 ap
.a_hba_tran
= pvs
->tran
;
1733 /* Allocate a DMA handle for data transfers */
1734 if ((ddi_dma_alloc_handle(pvs
->dip
, &pvs
->io_dma_attr
, callback
,
1735 NULL
, &cmd
->cmd_dmahdl
)) != DDI_SUCCESS
) {
1736 dev_err(pvs
->dip
, CE_WARN
, "!failed to allocate DMA handle");
1740 /* Setup ARQ buffer */
1741 if ((cmd
->arqbuf
= scsi_alloc_consistent_buf(&ap
, (struct buf
*)NULL
,
1742 SENSE_BUFFER_SIZE
, B_READ
, callback
, NULL
)) == NULL
) {
1743 dev_err(pvs
->dip
, CE_WARN
, "!failed to allocate ARQ buffer");
1747 if (ddi_dma_alloc_handle(pvs
->dip
, &pvs
->hba_dma_attr
,
1748 callback
, NULL
, &cmd
->arqhdl
) != DDI_SUCCESS
) {
1749 dev_err(pvs
->dip
, CE_WARN
,
1750 "!failed to allocate DMA handle for ARQ buffer");
1754 if (ddi_dma_buf_bind_handle(cmd
->arqhdl
, cmd
->arqbuf
,
1755 (DDI_DMA_READ
| DDI_DMA_CONSISTENT
), callback
, NULL
,
1756 &cmd
->arqc
, &cookiec
) != DDI_SUCCESS
) {
1757 dev_err(pvs
->dip
, CE_WARN
, "!failed to bind ARQ buffer");
1764 ddi_dma_free_handle(&cmd
->arqhdl
);
1766 scsi_free_consistent_buf(cmd
->arqbuf
);
1768 ddi_dma_free_handle(&cmd
->cmd_dmahdl
);
1773 /* ARGSUSED cdrarg */
1775 pvscsi_ccache_destructor(void *buf
, void *cdrarg
)
1777 pvscsi_cmd_t
*cmd
= (pvscsi_cmd_t
*)buf
;
1779 if (cmd
->cmd_dmahdl
!= NULL
) {
1780 (void) ddi_dma_unbind_handle(cmd
->cmd_dmahdl
);
1781 ddi_dma_free_handle(&cmd
->cmd_dmahdl
);
1782 cmd
->cmd_dmahdl
= NULL
;
1785 if (cmd
->arqhdl
!= NULL
) {
1786 (void) ddi_dma_unbind_handle(cmd
->arqhdl
);
1787 ddi_dma_free_handle(&cmd
->arqhdl
);
1791 if (cmd
->arqbuf
!= NULL
) {
1792 scsi_free_consistent_buf(cmd
->arqbuf
);
1797 /* tran_* entry points and setup */
1798 /* ARGSUSED hba_dip tgt_dip hba_tran */
1800 pvscsi_tgt_init(dev_info_t
*hba_dip
, dev_info_t
*tgt_dip
,
1801 scsi_hba_tran_t
*hba_tran
, struct scsi_device
*sd
)
1803 pvscsi_softc_t
*pvs
= SDEV2PRIV(sd
);
1805 ASSERT(pvs
!= NULL
);
1807 if (sd
->sd_address
.a_target
>= PVSCSI_MAXTGTS
)
1808 return (DDI_FAILURE
);
1810 return (DDI_SUCCESS
);
1814 pvscsi_start(struct scsi_address
*ap
, struct scsi_pkt
*pkt
)
1816 boolean_t poll
= ((pkt
->pkt_flags
& FLAG_NOINTR
) != 0);
1818 pvscsi_cmd_t
*cmd
= PKT2CMD(pkt
);
1819 pvscsi_softc_t
*pvs
= ap
->a_hba_tran
->tran_hba_private
;
1821 ASSERT(cmd
->pkt
== pkt
);
1822 ASSERT(cmd
->cmd_pvs
== pvs
);
1825 * Reinitialize some fields because the packet may
1826 * have been resubmitted.
1828 pkt
->pkt_reason
= CMD_CMPLT
;
1830 pkt
->pkt_statistics
= 0;
1832 /* Zero status byte */
1833 *(pkt
->pkt_scbp
) = 0;
1835 if ((cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) != 0) {
1836 ASSERT(cmd
->cmd_dma_count
!= 0);
1837 pkt
->pkt_resid
= cmd
->cmd_dma_count
;
1840 * Consistent packets need to be synced first
1841 * (only for data going out).
1843 if ((cmd
->flags
& PVSCSI_FLAG_IO_IOPB
) != 0) {
1844 (void) ddi_dma_sync(cmd
->cmd_dmahdl
, 0, 0,
1845 DDI_DMA_SYNC_FORDEV
);
1849 cmd
->cmd_target
= ap
->a_target
;
1851 mutex_enter(&pvs
->mutex
);
1852 if (HBA_IS_QUIESCED(pvs
) && !poll
) {
1853 mutex_exit(&pvs
->mutex
);
1856 mutex_exit(&pvs
->mutex
);
1858 rc
= pvscsi_transport_command(pvs
, cmd
);
1864 if (rc
== TRAN_ACCEPT
)
1865 rc
= pvscsi_poll_cmd(pvs
, cmd
);
1867 mutex_enter(&pvs
->rx_mutex
);
1868 dcmd
= pvscsi_process_comp_ring(pvs
);
1869 mutex_exit(&pvs
->rx_mutex
);
1871 mutex_enter(&pvs
->mutex
);
1872 qnotify
= HBA_QUIESCE_PENDING(pvs
);
1873 mutex_exit(&pvs
->mutex
);
1875 pvscsi_complete_chained(dcmd
);
1878 pvscsi_quiesce_notify(pvs
);
1885 pvscsi_reset(struct scsi_address
*ap
, int level
)
1887 pvscsi_softc_t
*pvs
= AP2PRIV(ap
);
1891 return (pvscsi_reset_generic(pvs
, NULL
));
1894 return (pvscsi_reset_generic(pvs
, ap
));
1901 pvscsi_abort(struct scsi_address
*ap
, struct scsi_pkt
*pkt
)
1903 boolean_t qnotify
= B_FALSE
;
1904 pvscsi_cmd_t
*pending
;
1905 pvscsi_softc_t
*pvs
= ap
->a_hba_tran
->tran_hba_private
;
1907 mutex_enter(&pvs
->tx_mutex
);
1908 mutex_enter(&pvs
->rx_mutex
);
1910 /* Abort single command */
1911 pvscsi_cmd_t
*cmd
= PKT2CMD(pkt
);
1913 if (pvscsi_abort_cmd(cmd
, &pending
) == CMD_ABORTED
) {
1914 /* Assume command is completely cancelled now */
1915 cmd
->flags
|= PVSCSI_FLAG_ABORTED
;
1918 /* Abort all commands on the bus */
1919 pvscsi_abort_all(ap
, pvs
, &pending
, PVSCSI_FLAG_ABORTED
);
1921 qnotify
= HBA_QUIESCE_PENDING(pvs
);
1922 mutex_exit(&pvs
->rx_mutex
);
1923 mutex_exit(&pvs
->tx_mutex
);
1925 pvscsi_complete_chained(pending
);
1928 pvscsi_quiesce_notify(pvs
);
1933 /* ARGSUSED tgtonly */
1935 pvscsi_getcap(struct scsi_address
*ap
, char *cap
, int tgtonly
)
1937 pvscsi_softc_t
*pvs
= ap
->a_hba_tran
->tran_hba_private
;
1942 switch (scsi_hba_lookup_capstr(cap
)) {
1944 return ((pvs
->flags
& PVSCSI_HBA_AUTO_REQUEST_SENSE
) != 0);
1945 case SCSI_CAP_UNTAGGED_QING
:
1952 /* ARGSUSED tgtonly */
1954 pvscsi_setcap(struct scsi_address
*ap
, char *cap
, int value
, int tgtonly
)
1956 pvscsi_softc_t
*pvs
= ap
->a_hba_tran
->tran_hba_private
;
1961 switch (scsi_hba_lookup_capstr(cap
)) {
1963 mutex_enter(&pvs
->mutex
);
1965 pvs
->flags
&= ~PVSCSI_HBA_AUTO_REQUEST_SENSE
;
1967 pvs
->flags
|= PVSCSI_HBA_AUTO_REQUEST_SENSE
;
1968 mutex_exit(&pvs
->mutex
);
1976 pvscsi_destroy_pkt(struct scsi_address
*ap
, struct scsi_pkt
*pkt
)
1978 pvscsi_cmd_t
*cmd
= PKT2CMD(pkt
);
1979 pvscsi_softc_t
*pvs
= ap
->a_hba_tran
->tran_hba_private
;
1981 ASSERT(cmd
->cmd_pvs
== pvs
);
1983 if ((cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) != 0) {
1984 cmd
->flags
&= ~PVSCSI_FLAG_DMA_VALID
;
1985 (void) ddi_dma_unbind_handle(cmd
->cmd_dmahdl
);
1988 if (cmd
->ctx
!= NULL
) {
1989 mutex_enter(&pvs
->mutex
);
1990 pvscsi_release_ctx(cmd
);
1991 mutex_exit(&pvs
->mutex
);
1994 if ((cmd
->flags
& PVSCSI_FLAGS_EXT
) != 0)
1995 pvscsi_cmd_ext_free(cmd
);
1997 kmem_cache_free(pvs
->cmd_cache
, cmd
);
2000 static struct scsi_pkt
*
2001 pvscsi_init_pkt(struct scsi_address
*ap
, struct scsi_pkt
*pkt
, struct buf
*bp
,
2002 int cmdlen
, int statuslen
, int tgtlen
, int flags
, int (*callback
)(),
2006 int kf
= (callback
== SLEEP_FUNC
) ? KM_SLEEP
: KM_NOSLEEP
;
2009 pvscsi_softc_t
*pvs
;
2011 pvs
= ap
->a_hba_tran
->tran_hba_private
;
2012 ASSERT(pvs
!= NULL
);
2014 /* Allocate a new SCSI packet */
2016 ddi_dma_handle_t saved_dmahdl
, saved_arqhdl
;
2017 struct buf
*saved_arqbuf
;
2018 ddi_dma_cookie_t saved_arqc
;
2022 if ((cmd
= kmem_cache_alloc(pvs
->cmd_cache
, kf
)) == NULL
)
2025 saved_dmahdl
= cmd
->cmd_dmahdl
;
2026 saved_arqhdl
= cmd
->arqhdl
;
2027 saved_arqbuf
= cmd
->arqbuf
;
2028 saved_arqc
= cmd
->arqc
;
2030 bzero(cmd
, sizeof (pvscsi_cmd_t
) -
2031 sizeof (cmd
->cached_cookies
));
2034 cmd
->cmd_dmahdl
= saved_dmahdl
;
2035 cmd
->arqhdl
= saved_arqhdl
;
2036 cmd
->arqbuf
= saved_arqbuf
;
2037 cmd
->arqc
= saved_arqc
;
2039 pkt
= &cmd
->cached_pkt
;
2040 pkt
->pkt_ha_private
= (opaque_t
)cmd
;
2041 pkt
->pkt_address
= *ap
;
2042 pkt
->pkt_scbp
= (uint8_t *)&cmd
->cmd_scb
;
2043 pkt
->pkt_cdbp
= (uint8_t *)&cmd
->cmd_cdb
;
2044 pkt
->pkt_private
= (opaque_t
)&cmd
->tgt_priv
;
2046 cmd
->tgtlen
= tgtlen
;
2047 cmd
->statuslen
= statuslen
;
2048 cmd
->cmdlen
= cmdlen
;
2052 /* Allocate extended buffers */
2053 if ((cmdlen
> sizeof (cmd
->cmd_cdb
)) ||
2054 (statuslen
> sizeof (cmd
->cmd_scb
)) ||
2055 (tgtlen
> sizeof (cmd
->tgt_priv
))) {
2056 if (pvscsi_cmd_ext_alloc(pvs
, cmd
, kf
) != DDI_SUCCESS
) {
2057 dev_err(pvs
->dip
, CE_WARN
,
2058 "!extent allocation failed");
2066 cmd
->flags
&= PVSCSI_FLAGS_PERSISTENT
;
2069 ASSERT((cmd
->flags
& PVSCSI_FLAG_TRANSPORT
) == 0);
2071 if ((flags
& PKT_XARQ
) != 0)
2072 cmd
->flags
|= PVSCSI_FLAG_XARQ
;
2074 /* Handle partial DMA transfers */
2075 if (cmd
->cmd_nwin
> 0) {
2076 if (++cmd
->cmd_winindex
>= cmd
->cmd_nwin
)
2078 if (ddi_dma_getwin(cmd
->cmd_dmahdl
, cmd
->cmd_winindex
,
2079 &cmd
->cmd_dma_offset
, &cmd
->cmd_dma_len
,
2080 &cmd
->cmd_dmac
, &cmd
->cmd_dmaccount
) == DDI_FAILURE
)
2082 goto handle_dma_cookies
;
2085 /* Setup data buffer */
2086 if (bp
!= NULL
&& bp
->b_bcount
> 0 &&
2087 (cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) == 0) {
2090 ASSERT(cmd
->cmd_dmahdl
!= NULL
);
2092 if ((bp
->b_flags
& B_READ
) != 0) {
2093 cmd
->flags
|= PVSCSI_FLAG_IO_READ
;
2094 dma_flags
= DDI_DMA_READ
;
2096 cmd
->flags
&= ~PVSCSI_FLAG_IO_READ
;
2097 dma_flags
= DDI_DMA_WRITE
;
2099 if ((flags
& PKT_CONSISTENT
) != 0) {
2100 cmd
->flags
|= PVSCSI_FLAG_IO_IOPB
;
2101 dma_flags
|= DDI_DMA_CONSISTENT
;
2103 if ((flags
& PKT_DMA_PARTIAL
) != 0)
2104 dma_flags
|= DDI_DMA_PARTIAL
;
2106 rc
= ddi_dma_buf_bind_handle(cmd
->cmd_dmahdl
, bp
,
2107 dma_flags
, callback
, arg
, &cmd
->cmd_dmac
,
2108 &cmd
->cmd_dmaccount
);
2109 if (rc
== DDI_DMA_PARTIAL_MAP
) {
2110 (void) ddi_dma_numwin(cmd
->cmd_dmahdl
,
2112 cmd
->cmd_winindex
= 0;
2113 (void) ddi_dma_getwin(cmd
->cmd_dmahdl
,
2114 cmd
->cmd_winindex
, &cmd
->cmd_dma_offset
,
2115 &cmd
->cmd_dma_len
, &cmd
->cmd_dmac
,
2116 &cmd
->cmd_dmaccount
);
2117 } else if (rc
!= 0 && rc
!= DDI_DMA_MAPPED
) {
2119 case DDI_DMA_NORESOURCES
:
2122 case DDI_DMA_BADATTR
:
2123 case DDI_DMA_NOMAPPING
:
2124 bioerror(bp
, EFAULT
);
2126 case DDI_DMA_TOOBIG
:
2128 bioerror(bp
, EINVAL
);
2131 cmd
->flags
&= ~PVSCSI_FLAG_DMA_VALID
;
2136 ASSERT(cmd
->cmd_dmaccount
> 0);
2137 if (cmd
->cmd_dmaccount
> PVSCSI_MAX_SG_SIZE
) {
2138 dev_err(pvs
->dip
, CE_WARN
,
2139 "!invalid cookie count: %d (max %d)",
2140 cmd
->cmd_dmaccount
, PVSCSI_MAX_SG_SIZE
);
2141 bioerror(bp
, EINVAL
);
2145 cmd
->flags
|= PVSCSI_FLAG_DMA_VALID
;
2146 cmd
->cmd_dma_count
= cmd
->cmd_dmac
.dmac_size
;
2147 cmd
->cmd_total_dma_count
+= cmd
->cmd_dmac
.dmac_size
;
2149 cmd
->cached_cookies
[0] = cmd
->cmd_dmac
;
2152 * Calculate total amount of bytes for this I/O and
2153 * store cookies for further processing.
2155 for (i
= 1; i
< cmd
->cmd_dmaccount
; i
++) {
2156 ddi_dma_nextcookie(cmd
->cmd_dmahdl
, &cmd
->cmd_dmac
);
2157 cmd
->cached_cookies
[i
] = cmd
->cmd_dmac
;
2158 cmd
->cmd_dma_count
+= cmd
->cmd_dmac
.dmac_size
;
2159 cmd
->cmd_total_dma_count
+= cmd
->cmd_dmac
.dmac_size
;
2162 pkt
->pkt_resid
= (bp
->b_bcount
- cmd
->cmd_total_dma_count
);
2169 pvscsi_destroy_pkt(ap
, pkt
);
2176 pvscsi_dmafree(struct scsi_address
*ap
, struct scsi_pkt
*pkt
)
2178 pvscsi_cmd_t
*cmd
= PKT2CMD(pkt
);
2180 if ((cmd
->flags
& PVSCSI_FLAG_DMA_VALID
) != 0) {
2181 (void) ddi_dma_unbind_handle(cmd
->cmd_dmahdl
);
2182 cmd
->flags
&= ~PVSCSI_FLAG_DMA_VALID
;
2188 pvscsi_sync_pkt(struct scsi_address
*ap
, struct scsi_pkt
*pkt
)
2190 pvscsi_cmd_t
*cmd
= PKT2CMD(pkt
);
2192 if (cmd
->cmd_dmahdl
!= NULL
) {
2193 (void) ddi_dma_sync(cmd
->cmd_dmahdl
, 0, 0,
2194 (cmd
->flags
& PVSCSI_FLAG_IO_READ
) ?
2195 DDI_DMA_SYNC_FORCPU
: DDI_DMA_SYNC_FORDEV
);
2200 /* ARGSUSED ap flag callback arg */
2202 pvscsi_reset_notify(struct scsi_address
*ap
, int flag
,
2203 void (*callback
)(caddr_t
), caddr_t arg
)
2205 return (DDI_FAILURE
);
2209 pvscsi_quiesce_hba(dev_info_t
*dip
)
2211 pvscsi_softc_t
*pvs
;
2212 scsi_hba_tran_t
*tran
;
2214 if ((tran
= ddi_get_driver_private(dip
)) == NULL
||
2215 (pvs
= TRAN2PRIV(tran
)) == NULL
)
2218 mutex_enter(&pvs
->mutex
);
2219 if (!HBA_IS_QUIESCED(pvs
))
2220 pvs
->flags
|= PVSCSI_HBA_QUIESCED
;
2222 if (pvs
->cmd_queue_len
!= 0) {
2223 /* Outstanding commands present, wait */
2224 pvs
->flags
|= PVSCSI_HBA_QUIESCE_PENDING
;
2225 cv_wait(&pvs
->quiescevar
, &pvs
->mutex
);
2226 ASSERT(pvs
->cmd_queue_len
== 0);
2228 mutex_exit(&pvs
->mutex
);
2230 /* Suspend taskq delivery and complete all scheduled tasks */
2231 ddi_taskq_suspend(pvs
->msg_tq
);
2232 ddi_taskq_wait(pvs
->msg_tq
);
2233 ddi_taskq_suspend(pvs
->comp_tq
);
2234 ddi_taskq_wait(pvs
->comp_tq
);
2240 pvscsi_unquiesce_hba(dev_info_t
*dip
)
2242 pvscsi_softc_t
*pvs
;
2243 scsi_hba_tran_t
*tran
;
2245 if ((tran
= ddi_get_driver_private(dip
)) == NULL
||
2246 (pvs
= TRAN2PRIV(tran
)) == NULL
)
2249 mutex_enter(&pvs
->mutex
);
2250 if (!HBA_IS_QUIESCED(pvs
)) {
2251 mutex_exit(&pvs
->mutex
);
2254 ASSERT(pvs
->cmd_queue_len
== 0);
2255 pvs
->flags
&= ~PVSCSI_HBA_QUIESCED
;
2256 mutex_exit(&pvs
->mutex
);
2258 /* Resume taskq delivery */
2259 ddi_taskq_resume(pvs
->msg_tq
);
2260 ddi_taskq_resume(pvs
->comp_tq
);
2266 pvscsi_bus_config(dev_info_t
*pdip
, uint_t flags
, ddi_bus_config_op_t op
,
2267 void *arg
, dev_info_t
**childp
)
2271 int ret
= NDI_FAILURE
;
2273 pvscsi_softc_t
*pvs
;
2274 scsi_hba_tran_t
*tran
;
2276 tran
= ddi_get_driver_private(pdip
);
2277 pvs
= tran
->tran_hba_private
;
2279 ndi_devi_enter(pdip
, &circ
);
2281 case BUS_CONFIG_ONE
:
2282 if ((p
= strrchr((char *)arg
, '@')) != NULL
&&
2283 ddi_strtol(p
+ 1, NULL
, 10, &target
) == 0)
2284 ret
= pvscsi_config_one(pdip
, pvs
, (int)target
, childp
);
2286 case BUS_CONFIG_DRIVER
:
2287 case BUS_CONFIG_ALL
:
2288 ret
= pvscsi_config_all(pdip
, pvs
);
2294 if (ret
== NDI_SUCCESS
)
2295 ret
= ndi_busop_bus_config(pdip
, flags
, op
, arg
, childp
, 0);
2296 ndi_devi_exit(pdip
, circ
);
2302 pvscsi_hba_setup(pvscsi_softc_t
*pvs
)
2304 scsi_hba_tran_t
*hba_tran
;
2306 hba_tran
= pvs
->tran
= scsi_hba_tran_alloc(pvs
->dip
,
2308 ASSERT(pvs
->tran
!= NULL
);
2310 hba_tran
->tran_hba_private
= pvs
;
2311 hba_tran
->tran_tgt_private
= NULL
;
2313 hba_tran
->tran_tgt_init
= pvscsi_tgt_init
;
2314 hba_tran
->tran_tgt_free
= NULL
;
2315 hba_tran
->tran_tgt_probe
= scsi_hba_probe
;
2317 hba_tran
->tran_start
= pvscsi_start
;
2318 hba_tran
->tran_reset
= pvscsi_reset
;
2319 hba_tran
->tran_abort
= pvscsi_abort
;
2320 hba_tran
->tran_getcap
= pvscsi_getcap
;
2321 hba_tran
->tran_setcap
= pvscsi_setcap
;
2322 hba_tran
->tran_init_pkt
= pvscsi_init_pkt
;
2323 hba_tran
->tran_destroy_pkt
= pvscsi_destroy_pkt
;
2325 hba_tran
->tran_dmafree
= pvscsi_dmafree
;
2326 hba_tran
->tran_sync_pkt
= pvscsi_sync_pkt
;
2327 hba_tran
->tran_reset_notify
= pvscsi_reset_notify
;
2329 hba_tran
->tran_quiesce
= pvscsi_quiesce_hba
;
2330 hba_tran
->tran_unquiesce
= pvscsi_unquiesce_hba
;
2331 hba_tran
->tran_bus_reset
= NULL
;
2333 hba_tran
->tran_add_eventcall
= NULL
;
2334 hba_tran
->tran_get_eventcookie
= NULL
;
2335 hba_tran
->tran_post_event
= NULL
;
2336 hba_tran
->tran_remove_eventcall
= NULL
;
2338 hba_tran
->tran_bus_config
= pvscsi_bus_config
;
2340 hba_tran
->tran_interconnect_type
= INTERCONNECT_SAS
;
2342 if (scsi_hba_attach_setup(pvs
->dip
, &pvs
->hba_dma_attr
, hba_tran
,
2343 SCSI_HBA_TRAN_CDB
| SCSI_HBA_TRAN_SCB
| SCSI_HBA_TRAN_CLONE
) !=
2345 dev_err(pvs
->dip
, CE_WARN
, "!failed to attach HBA");
2346 scsi_hba_tran_free(hba_tran
);
2355 pvscsi_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
2358 pvscsi_softc_t
*pvs
;
2361 ASSERT(scsi_hba_iport_unit_address(dip
) == NULL
);
2368 return (DDI_FAILURE
);
2371 instance
= ddi_get_instance(dip
);
2373 /* Allocate softstate information */
2374 if (ddi_soft_state_zalloc(pvscsi_sstate
, instance
) != DDI_SUCCESS
) {
2376 "!ddi_soft_state_zalloc() failed for instance %d",
2378 return (DDI_FAILURE
);
2381 if ((pvs
= ddi_get_soft_state(pvscsi_sstate
, instance
)) == NULL
) {
2382 cmn_err(CE_WARN
, "!failed to get soft state for instance %d",
2388 * Indicate that we are 'sizeof (scsi_*(9S))' clean, we use
2389 * scsi_pkt_size() instead.
2391 scsi_size_clean(dip
);
2393 /* Setup HBA instance */
2394 pvs
->instance
= instance
;
2396 pvs
->hba_dma_attr
= pvscsi_hba_dma_attr
;
2397 pvs
->ring_dma_attr
= pvscsi_ring_dma_attr
;
2398 pvs
->io_dma_attr
= pvscsi_io_dma_attr
;
2399 mutex_init(&pvs
->mutex
, "pvscsi instance mutex", MUTEX_DRIVER
, NULL
);
2400 mutex_init(&pvs
->intr_mutex
, "pvscsi instance interrupt mutex",
2401 MUTEX_DRIVER
, NULL
);
2402 mutex_init(&pvs
->rx_mutex
, "pvscsi rx ring mutex", MUTEX_DRIVER
, NULL
);
2403 mutex_init(&pvs
->tx_mutex
, "pvscsi tx ring mutex", MUTEX_DRIVER
, NULL
);
2404 list_create(&pvs
->cmd_ctx_pool
, sizeof (pvscsi_cmd_ctx_t
),
2405 offsetof(pvscsi_cmd_ctx_t
, list
));
2406 list_create(&pvs
->devnodes
, sizeof (pvscsi_device_t
),
2407 offsetof(pvscsi_device_t
, list
));
2408 list_create(&pvs
->cmd_queue
, sizeof (pvscsi_cmd_t
),
2409 offsetof(pvscsi_cmd_t
, cmd_queue_node
));
2410 cv_init(&pvs
->syncvar
, "pvscsi synchronization cv", CV_DRIVER
, NULL
);
2411 cv_init(&pvs
->wd_condvar
, "pvscsi watchdog cv", CV_DRIVER
, NULL
);
2412 cv_init(&pvs
->quiescevar
, "pvscsi quiesce cv", CV_DRIVER
, NULL
);
2414 (void) sprintf(buf
, "pvscsi%d_cache", instance
);
2415 pvs
->cmd_cache
= kmem_cache_create(buf
, sizeof (pvscsi_cmd_t
), 0,
2416 pvscsi_ccache_constructor
, pvscsi_ccache_destructor
, NULL
,
2417 (void *)pvs
, NULL
, 0);
2418 if (pvs
->cmd_cache
== NULL
) {
2419 dev_err(pvs
->dip
, CE_WARN
,
2420 "!failed to create a cache for SCSI commands");
2424 if ((pvscsi_setup_io(pvs
)) != DDI_SUCCESS
) {
2425 dev_err(pvs
->dip
, CE_WARN
, "!failed to setup I/O region");
2429 pvscsi_reset_hba(pvs
);
2431 if ((pvscsi_allocate_rings(pvs
)) != DDI_SUCCESS
) {
2432 dev_err(pvs
->dip
, CE_WARN
, "!failed to allocate DMA rings");
2436 pvscsi_setup_rings(pvs
);
2438 if (pvscsi_setup_isr(pvs
) != DDI_SUCCESS
) {
2439 dev_err(pvs
->dip
, CE_WARN
, "!failed to setup ISR");
2443 if (pvscsi_setup_sg(pvs
) != DDI_SUCCESS
) {
2444 dev_err(pvs
->dip
, CE_WARN
, "!failed to setup S/G");
2448 if (pvscsi_hba_setup(pvs
) != 0) {
2449 dev_err(pvs
->dip
, CE_WARN
, "!failed to setup HBA");
2453 if ((pvs
->comp_tq
= ddi_taskq_create(pvs
->dip
, "comp_tq",
2454 MIN(UINT16_MAX
, ncpus
), TASKQ_DEFAULTPRI
, 0)) == NULL
) {
2455 dev_err(pvs
->dip
, CE_WARN
,
2456 "!failed to create completion taskq");
2460 if ((pvs
->msg_tq
= ddi_taskq_create(pvs
->dip
, "msg_tq",
2461 1, TASKQ_DEFAULTPRI
, 0)) == NULL
) {
2462 dev_err(pvs
->dip
, CE_WARN
,
2463 "!failed to create message taskq");
2467 if (pvscsi_enable_intrs(pvs
) != DDI_SUCCESS
) {
2468 dev_err(pvs
->dip
, CE_WARN
, "!failed to enable interrupts");
2472 /* Launch watchdog thread */
2473 pvs
->wd_thread
= thread_create(NULL
, 0, pvscsi_wd_thread
, pvs
, 0, &p0
,
2474 TS_RUN
, minclsyspri
);
2476 return (DDI_SUCCESS
);
2479 ddi_taskq_destroy(pvs
->msg_tq
);
2481 ddi_taskq_destroy(pvs
->comp_tq
);
2483 pvscsi_free_sg(pvs
);
2485 pvscsi_free_intr_resources(pvs
);
2487 pvscsi_reset_hba(pvs
);
2488 pvscsi_free_rings(pvs
);
2490 pvscsi_free_io(pvs
);
2492 kmem_cache_destroy(pvs
->cmd_cache
);
2494 ddi_soft_state_free(pvscsi_sstate
, instance
);
2496 return (DDI_FAILURE
);
2500 pvscsi_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
2503 pvscsi_softc_t
*pvs
;
2509 return (DDI_FAILURE
);
2512 instance
= ddi_get_instance(dip
);
2513 if ((pvs
= ddi_get_soft_state(pvscsi_sstate
, instance
)) == NULL
) {
2514 cmn_err(CE_WARN
, "!failed to get soft state for instance %d",
2516 return (DDI_FAILURE
);
2519 pvscsi_reset_hba(pvs
);
2520 pvscsi_free_intr_resources(pvs
);
2522 /* Shutdown message taskq */
2523 ddi_taskq_wait(pvs
->msg_tq
);
2524 ddi_taskq_destroy(pvs
->msg_tq
);
2526 /* Shutdown completion taskq */
2527 ddi_taskq_wait(pvs
->comp_tq
);
2528 ddi_taskq_destroy(pvs
->comp_tq
);
2530 /* Shutdown watchdog thread */
2531 mutex_enter(&pvs
->mutex
);
2532 pvs
->flags
|= PVSCSI_DRIVER_SHUTDOWN
;
2533 cv_signal(&pvs
->wd_condvar
);
2534 cv_wait(&pvs
->syncvar
, &pvs
->mutex
);
2535 mutex_exit(&pvs
->mutex
);
2537 pvscsi_free_sg(pvs
);
2538 pvscsi_free_rings(pvs
);
2539 pvscsi_free_io(pvs
);
2541 kmem_cache_destroy(pvs
->cmd_cache
);
2543 mutex_destroy(&pvs
->mutex
);
2544 mutex_destroy(&pvs
->intr_mutex
);
2545 mutex_destroy(&pvs
->rx_mutex
);
2547 cv_destroy(&pvs
->syncvar
);
2548 cv_destroy(&pvs
->wd_condvar
);
2549 cv_destroy(&pvs
->quiescevar
);
2551 ddi_soft_state_free(pvscsi_sstate
, instance
);
2552 ddi_prop_remove_all(dip
);
2554 return (DDI_SUCCESS
);
2558 pvscsi_ioctl(dev_t dev
, int cmd
, intptr_t data
, int mode
, cred_t
*credp
,
2563 if (ddi_get_soft_state(pvscsi_sstate
, getminor(dev
)) == NULL
) {
2564 cmn_err(CE_WARN
, "!invalid device instance: %d", getminor(dev
));
2568 /* Try to handle command in a common way */
2569 if ((ret
= scsi_hba_ioctl(dev
, cmd
, data
, mode
, credp
, rval
)) != ENOTTY
)
2572 cmn_err(CE_WARN
, "!unsupported IOCTL command: 0x%X", cmd
);
2578 pvscsi_quiesce(dev_info_t
*devi
)
2580 scsi_hba_tran_t
*tran
;
2581 pvscsi_softc_t
*pvs
;
2583 if ((tran
= ddi_get_driver_private(devi
)) == NULL
)
2584 return (DDI_SUCCESS
);
2586 if ((pvs
= tran
->tran_hba_private
) == NULL
)
2587 return (DDI_SUCCESS
);
2589 /* Mask all interrupts from device */
2590 pvscsi_reg_write(pvs
, PVSCSI_REG_OFFSET_INTR_MASK
, 0);
2593 pvscsi_reset_hba(pvs
);
2595 return (DDI_SUCCESS
);
2600 static struct cb_ops pvscsi_cb_ops
= {
2601 .cb_open
= scsi_hba_open
,
2602 .cb_close
= scsi_hba_close
,
2603 .cb_strategy
= nodev
,
2608 .cb_ioctl
= pvscsi_ioctl
,
2612 .cb_chpoll
= nochpoll
,
2613 .cb_prop_op
= ddi_prop_op
,
2621 static struct dev_ops pvscsi_ops
= {
2622 .devo_rev
= DEVO_REV
,
2624 .devo_getinfo
= ddi_no_info
,
2625 .devo_identify
= nulldev
,
2626 .devo_probe
= nulldev
,
2627 .devo_attach
= pvscsi_attach
,
2628 .devo_detach
= pvscsi_detach
,
2629 .devo_reset
= nodev
,
2630 .devo_cb_ops
= &pvscsi_cb_ops
,
2631 .devo_bus_ops
= NULL
,
2633 .devo_quiesce
= pvscsi_quiesce
2636 #define PVSCSI_IDENT "VMware PVSCSI"
2638 static struct modldrv modldrv
= {
2644 static struct modlinkage modlinkage
= {
2655 if ((ret
= ddi_soft_state_init(&pvscsi_sstate
,
2656 sizeof (struct pvscsi_softc
), PVSCSI_INITIAL_SSTATE_ITEMS
)) != 0) {
2657 cmn_err(CE_WARN
, "!ddi_soft_state_init() failed");
2661 if ((ret
= scsi_hba_init(&modlinkage
)) != 0) {
2662 cmn_err(CE_WARN
, "!scsi_hba_init() failed");
2663 ddi_soft_state_fini(&pvscsi_sstate
);
2667 if ((ret
= mod_install(&modlinkage
)) != 0) {
2668 cmn_err(CE_WARN
, "!mod_install() failed");
2669 ddi_soft_state_fini(&pvscsi_sstate
);
2670 scsi_hba_fini(&modlinkage
);
2677 _info(struct modinfo
*modinfop
)
2679 return (mod_info(&modlinkage
, modinfop
));
2687 if ((ret
= mod_remove(&modlinkage
)) == 0) {
2688 ddi_soft_state_fini(&pvscsi_sstate
);
2689 scsi_hba_fini(&modlinkage
);