565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * This file and its contents are supplied under the terms of the
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Common Development and Distribution License ("CDDL"), version 1.0.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * You may only use this file in accordance with the terms of version
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * 1.0 of the CDDL.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * A full copy of the text of the CDDL should have accompanied this
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * source. A copy of the CDDL is also available via the Internet at
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * http://www.illumos.org/license/CDDL.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Copyright 2016 Nexenta Systems, Inc.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/atomic.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/cmn_err.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/conf.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/cpuvar.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/ddi.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/errno.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/fs/dv_node.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/kmem.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/kmem_impl.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/list.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/modctl.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/pci.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/scsi/scsi.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/sunddi.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/sysmacros.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/time.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include <sys/types.h>
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include "pvscsi.h"
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#include "pvscsi_var.h"
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovint pvscsi_enable_msi = 1;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovint pvscsi_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_PER_RING;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovint pvscsi_msg_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_MSG_RING;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int pvscsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void *pvscsi_sstate;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* HBA DMA attributes */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic ddi_dma_attr_t pvscsi_hba_dma_attr = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_version = DMA_ATTR_V0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_addr_lo = 0x0000000000000000ull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_count_max = 0x000000007FFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_align = 0x0000000000000001ull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_burstsizes = 0x7ff,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_minxfer = 0x00000001u,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_maxxfer = 0x00000000FFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_seg = 0x00000000FFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_sgllen = 1,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_granular = 0x00000200u,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_flags = 0
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* DMA attributes for req/comp rings */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic ddi_dma_attr_t pvscsi_ring_dma_attr = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_version = DMA_ATTR_V0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_addr_lo = 0x0000000000000000ull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_count_max = 0x000000007FFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_align = 0x0000000000000001ull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_burstsizes = 0x7ff,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_minxfer = 0x00000001u,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_maxxfer = 0x00000000FFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_seg = 0x00000000FFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_sgllen = 1,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_granular = 0x00000001u,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_flags = 0
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* DMA attributes for buffer I/O */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic ddi_dma_attr_t pvscsi_io_dma_attr = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_version = DMA_ATTR_V0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_addr_lo = 0x0000000000000000ull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_count_max = 0x000000007FFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_align = 0x0000000000000001ull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_burstsizes = 0x7ff,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_minxfer = 0x00000001u,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_maxxfer = 0x00000000FFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_seg = 0x00000000FFFFFFFFull,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_sgllen = PVSCSI_MAX_SG_SIZE,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_granular = 0x00000200u,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .dma_attr_flags = 0
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic ddi_device_acc_attr_t pvscsi_mmio_attr = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DEVICE_ATTR_V1,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_STRUCTURE_LE_ACC,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_STRICTORDER_ACC,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DEFAULT_ACC
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic ddi_device_acc_attr_t pvscsi_dma_attrs = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DEVICE_ATTR_V0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_STRUCTURE_LE_ACC,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_STRICTORDER_ACC,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DEFAULT_ACC,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_add_to_queue(pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cmd->cmd_pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(!list_link_active(&(cmd)->cmd_queue_node));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_insert_tail(&pvs->cmd_queue, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->cmd_queue_len++;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_remove_from_queue(pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cmd->cmd_pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(list_link_active(&cmd->cmd_queue_node));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs->cmd_queue_len > 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (list_link_active(&cmd->cmd_queue_node)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_remove(&pvs->cmd_queue, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->cmd_queue_len--;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic uint64_t
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_map_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_ctx_t *io_ctx)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (io_ctx - pvs->cmd_ctx + 1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic pvscsi_cmd_ctx_t *
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_lookup_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ctx_t *ctx, *end;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov end = &pvs->cmd_ctx[pvs->req_depth];
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (ctx = pvs->cmd_ctx; ctx < end; ctx++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ctx->cmd == cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic pvscsi_cmd_ctx_t *
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_resolve_ctx(pvscsi_softc_t *pvs, uint64_t ctx)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ctx > 0 && ctx <= pvs->req_depth)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (&pvs->cmd_ctx[ctx - 1]);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov else
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic boolean_t
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_acquire_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ctx_t *ctx;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (list_is_empty(&pvs->cmd_ctx_pool))
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (B_FALSE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ctx = (pvscsi_cmd_ctx_t *)list_remove_head(&pvs->cmd_ctx_pool);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(ctx != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ctx->cmd = cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->ctx = ctx;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (B_TRUE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_release_ctx(pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cmd->cmd_pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->ctx->cmd = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_insert_tail(&pvs->cmd_ctx_pool, cmd->ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->ctx = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic uint32_t
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reg_read(pvscsi_softc_t *pvs, uint32_t offset)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t ret;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT((offset & (sizeof (uint32_t) - 1)) == 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ret = ddi_get32(pvs->mmio_handle,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (uint32_t *)(pvs->mmio_base + offset));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reg_write(pvscsi_softc_t *pvs, uint32_t offset, uint32_t value)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT((offset & (sizeof (uint32_t) - 1)) == 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_put32(pvs->mmio_handle, (uint32_t *)(pvs->mmio_base + offset),
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov value);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_write_cmd_desc(pvscsi_softc_t *pvs, uint32_t cmd, void *desc, size_t len)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov len /= sizeof (uint32_t);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_COMMAND, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_rep_put32(pvs->mmio_handle, (uint32_t *)desc,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (uint32_t *)(pvs->mmio_base + PVSCSI_REG_OFFSET_COMMAND_DATA),
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov len, DDI_DEV_NO_AUTOINCR);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic uint32_t
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_read_intr_status(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (pvscsi_reg_read(pvs, PVSCSI_REG_OFFSET_INTR_STATUS));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_write_intr_status(pvscsi_softc_t *pvs, uint32_t val)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_STATUS, val);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_mask_intr(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov VERIFY(pvs->intr_lock_counter >= 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (++pvs->intr_lock_counter == 1)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_MASK, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_unmask_intr(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov VERIFY(pvs->intr_lock_counter > 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (--pvs->intr_lock_counter == 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_MASK,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov PVSCSI_INTR_CMPL_MASK | PVSCSI_INTR_MSG_MASK);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reset_hba(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reset_bus(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_RESET_BUS, NULL, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_submit_nonrw_io(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_KICK_NON_RW_IO, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_submit_rw_io(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_inquiry_target(pvscsi_softc_t *pvs, int target, struct scsi_inquiry *inq)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int len = sizeof (struct scsi_inquiry);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ret = -1;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct buf *b;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_address ap;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint8_t cdb[CDB_GROUP0];
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ap.a_hba_tran = pvs->tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ap.a_target = (ushort_t)target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ap.a_lun = (uchar_t)0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((b = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL, len,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov B_READ, NULL_FUNC, NULL)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pkt = scsi_init_pkt(&ap, (struct scsi_pkt *)NULL, b,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov CDB_GROUP0, sizeof (struct scsi_arq_status), 0, 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov NULL_FUNC, NULL)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdb[0] = SCMD_INQUIRY;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdb[1] = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdb[2] = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdb[3] = (len & 0xff00) >> 8;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdb[4] = (len & 0x00ff);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdb[5] = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (inq != NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(inq, sizeof (*inq));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bcopy(cdb, pkt->pkt_cdbp, CDB_GROUP0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero((struct scsi_inquiry *)b->b_un.b_addr, sizeof (*inq));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ret = scsi_poll(pkt)) == 0 && inq != NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bcopy(b->b_un.b_addr, inq, sizeof (*inq));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_destroy_pkt(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_buf:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_free_consistent_buf(b);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_config_one(dev_info_t *pdip, pvscsi_softc_t *pvs, int target,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_info_t **childp)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov char **compatible = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov char *nodename = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_info_t *dip;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int inqrc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ncompatible = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_device_t *devnode;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_inquiry inq;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov ASSERT(DEVI_BUSY_OWNED(pdip));
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Inquiry target */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov inqrc = pvscsi_inquiry_target(pvs, target, &inq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Find devnode */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (devnode = list_head(&pvs->devnodes); devnode != NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov devnode = list_next(&pvs->devnodes, devnode)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (devnode->target == target)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (devnode != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (inqrc != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Target disappeared, drop devnode */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (i_ddi_devi_attached(devnode->pdip)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov char *devname;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Get full devname */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov devname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_deviname(devnode->pdip, devname);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Clean cache and name */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) devfs_clean(devnode->parent, devname + 1,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DV_CLEAN_FORCE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(devname, MAXPATHLEN);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ndi_devi_offline(devnode->pdip, NDI_DEVI_REMOVE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_remove(&pvs->devnodes, devnode);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(devnode, sizeof (*devnode));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if (childp != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Target exists */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *childp = devnode->pdip;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if (inqrc != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Target doesn't exist */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_nodename_compatible_get(&inq, NULL, inq.inq_dtype, NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &nodename, &compatible, &ncompatible);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (nodename == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_nodename;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ndi_devi_alloc(pdip, nodename, DEVI_SID_NODEID,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &dip) != NDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to alloc device instance");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_nodename;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ndi_prop_update_string(DDI_DEV_T_NONE, dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "device-type", "scsi") != DDI_PROP_SUCCESS ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_prop_update_int(DDI_DEV_T_NONE, dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "target", target) != DDI_PROP_SUCCESS ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_prop_update_int(DDI_DEV_T_NONE, dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "lun", 0) != DDI_PROP_SUCCESS ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_prop_update_int(DDI_DEV_T_NONE, dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "pm-capable", 1) != DDI_PROP_SUCCESS ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to update props for target %d", target);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_devi;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((devnode = kmem_zalloc(sizeof (*devnode), KM_NOSLEEP)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_devi;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ndi_devi_online(dip, NDI_ONLINE_ATTACH) != NDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to online target %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov target);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(devnode, sizeof (*devnode));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_devi;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov devnode->target = target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov devnode->pdip = dip;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov devnode->parent = pdip;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_insert_tail(&pvs->devnodes, devnode);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (childp != NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *childp = dip;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_nodename_compatible_free(nodename, compatible);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_devi:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_prop_remove_all(dip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ndi_devi_free(dip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_nodename:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_nodename_compatible_free(nodename, compatible);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_config_all(dev_info_t *pdip, pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov for (target = 0; target < PVSCSI_MAXTGTS; target++) {
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov /* ndi_devi_enter is done in pvscsi_bus_config */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) pvscsi_config_one(pdip, pvs, target, NULL);
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic pvscsi_cmd_t *
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_process_comp_ring(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t **pnext_cmd = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *head = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIRingsState *sdesc = RINGS_STATE(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t cmp_ne = sdesc->cmpNumEntriesLog2;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->rx_mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov while (sdesc->cmpConsIdx != sdesc->cmpProdIdx) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ctx_t *ctx;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIRingCmpDesc *cdesc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cdesc = CMP_RING(pvs) + (sdesc->cmpConsIdx & MASK(cmp_ne));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov membar_consumer();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ctx = pvscsi_resolve_ctx(pvs, cdesc->context);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(ctx != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd = ctx->cmd) != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->next_cmd = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Save command status for further processing */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmp_stat.host_status = cdesc->hostStatus;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmp_stat.scsi_status = cdesc->scsiStatus;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmp_stat.data_len = cdesc->dataLen;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Mark this command as arrived from hardware */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_HW_STATUS;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (head == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov head = cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov head->tail_cmd = cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov head->tail_cmd = cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pnext_cmd == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pnext_cmd = &cmd->next_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pnext_cmd = cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pnext_cmd = &cmd->next_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov membar_consumer();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sdesc->cmpConsIdx++;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (head);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic pvscsi_msg_t *
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_process_msg_ring(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_msg_t *msg;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIRingsState *sdesc = RINGS_STATE(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIRingMsgDesc *mdesc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIMsgDescDevStatusChanged *desc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t msg_ne = sdesc->msgNumEntriesLog2;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->rx_mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (sdesc->msgProdIdx == sdesc->msgConsIdx)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mdesc = MSG_RING(pvs) + (sdesc->msgConsIdx & MASK(msg_ne));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov membar_consumer();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (mdesc->type) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case PVSCSI_MSG_DEV_ADDED:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case PVSCSI_MSG_DEV_REMOVED:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov desc = (struct PVSCSIMsgDescDevStatusChanged *)mdesc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov msg = kmem_alloc(sizeof (pvscsi_msg_t), KM_NOSLEEP);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (msg == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov msg->msg_pvs = pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov msg->type = mdesc->type;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov msg->target = desc->target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!unknown msg type: %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mdesc->type);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov membar_consumer();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sdesc->msgConsIdx++;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (msg);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_handle_msg(void *arg)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_msg_t *msg = (pvscsi_msg_t *)arg;
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov dev_info_t *dip = msg->msg_pvs->dip;
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov int circ;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov ndi_devi_enter(dip, &circ);
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov (void) pvscsi_config_one(dip, msg->msg_pvs, msg->target, NULL);
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov ndi_devi_exit(dip, circ);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(msg, sizeof (pvscsi_msg_t));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_abort_cmd(pvscsi_cmd_t *cmd, pvscsi_cmd_t **pending)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cmd->cmd_pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *c;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *done;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSICmdDescAbortCmd acmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!aborting command %p", (void *)cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->rx_mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->tx_mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Check if the cmd was already completed by the HBA */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pending = done = pvscsi_process_comp_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (c = done; c != NULL; c = c->next_cmd) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (c == cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (CMD_CMPLT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Check if cmd was really scheduled by the HBA */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_lookup_ctx(pvs, cmd) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (CMD_CMPLT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Abort cmd in the HBA */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(&acmd, sizeof (acmd));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov acmd.target = cmd->cmd_target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov acmd.context = pvscsi_map_ctx(pvs, cmd->ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_ABORT_CMD, &acmd, sizeof (acmd));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Check if cmd was completed by the HBA before it could be aborted */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((done = pvscsi_process_comp_ring(pvs)) != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov done->tail_cmd->next_cmd = *pending;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pending = done;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (c = done; c != NULL; c = c->next_cmd) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (c == cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (CMD_CMPLT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Release I/O ctx */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->ctx != NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_release_ctx(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Remove cmd from the queue */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_remove_from_queue(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Insert cmd at the beginning of the list */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->next_cmd = *pending;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pending = cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!command %p aborted", (void *)cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (CMD_ABORTED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_map_buffers(pvscsi_cmd_t *cmd, struct PVSCSIRingReqDesc *rdesc)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->cmd_dmaccount > 0 && cmd->cmd_dmaccount <=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov PVSCSI_MAX_SG_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->dataLen = cmd->cmd_dma_count;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->dataAddr = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmd_dma_count == 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmd_dmaccount > 1) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSISGElement *sgl = CMD_CTX_SGLIST_VA(cmd->ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < cmd->cmd_dmaccount; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sgl[i].addr = cmd->cached_cookies[i].dmac_laddress;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sgl[i].length = cmd->cached_cookies[i].dmac_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sgl[i].flags = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->flags |= PVSCSI_FLAG_CMD_WITH_SG_LIST;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->dataAddr = (uint64_t)CMD_CTX_SGLIST_PA(cmd->ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->dataAddr = cmd->cached_cookies[0].dmac_laddress;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_comp_cmd(pvscsi_cmd_t *cmd, uint8_t status)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_DMA_VALID) != 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= STATE_XFERRED_DATA;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_CMPLT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_resid = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *(pkt->pkt_scbp) = status;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_set_status(pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cmd->cmd_pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uchar_t scsi_status = cmd->cmp_stat.scsi_status;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t host_status = cmd->cmp_stat.host_status;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (scsi_status != STATUS_GOOD &&
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (host_status == BTSTAT_SUCCESS ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (host_status == BTSTAT_LINKED_COMMAND_COMPLETED) ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (host_status == BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG))) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (scsi_status == STATUS_CHECK) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_arq_status *astat = (void*)(pkt->pkt_scbp);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint8_t *sensedata;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int arq_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pkt->pkt_scbp = scsi_status;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= STATE_ARQ_DONE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_XARQ) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov arq_size = (cmd->cmd_rqslen >=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov SENSE_BUFFER_SIZE) ? SENSE_BUFFER_SIZE :
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_rqslen;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov astat->sts_rqpkt_resid = SENSE_BUFFER_SIZE -
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov arq_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sensedata = (uint8_t *)&astat->sts_sensedata;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bcopy(cmd->arqbuf->b_un.b_addr, sensedata,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov arq_size);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= STATE_XARQ_DONE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov astat->sts_rqpkt_resid = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov astat->sts_rqpkt_statistics = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov astat->sts_rqpkt_reason = CMD_CMPLT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (*(uint8_t *)&astat->sts_rqpkt_status) = STATUS_GOOD;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov astat->sts_rqpkt_state = STATE_GOT_BUS |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_GOT_TARGET | STATE_SENT_CMD |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_XFERRED_DATA | STATE_GOT_STATUS;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_comp_cmd(cmd, scsi_status);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (host_status) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_SUCCESS:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_LINKED_COMMAND_COMPLETED:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_comp_cmd(cmd, STATUS_GOOD);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_DATARUN:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_DATA_OVR;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_XFERRED_DATA);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_resid = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_DATA_UNDERRUN:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = pkt->pkt_state |= (STATE_GOT_BUS |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_GOT_TARGET | STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_resid = cmd->dma_count - cmd->cmp_stat.data_len;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pkt->pkt_resid != cmd->dma_count)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= STATE_XFERRED_DATA;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_SELTIMEO:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_DEV_GONE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= STATE_GOT_BUS;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_TAGREJECT:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_TAG_REJECT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_BADMSG:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_BADMSG;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_SENTRST:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_RECVRST:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_BUSRESET:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_RESET;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_ABORTQUEUE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_ABORTED;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_HAHARDWARE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_INVPHASE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_HATIMEOUT:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_NORESPONSE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_DISCONNECT:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_HASOFTWARE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_BUSFREE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BTSTAT_SENSFAILED:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_TRAN_ERR;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!unknown host status code: %d", host_status);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_TRAN_ERR;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STATE_SENT_CMD | STATE_GOT_STATUS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_complete_chained(void *arg)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = (pvscsi_cmd_t *)arg;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *c;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov while (cmd != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cmd->cmd_pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov c = cmd->next_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->next_cmd = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pkt == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_IO_IOPB) != 0 &&
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (cmd->flags & PVSCSI_FLAG_IO_READ) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_sync(cmd->cmd_dmahdl, 0, 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DMA_SYNC_FORCPU);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Release I/O ctx */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->ctx != NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_release_ctx(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Remove command from queue */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_remove_from_queue(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_HW_STATUS) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_set_status(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT((cmd->flags & PVSCSI_FLAGS_NON_HW_COMPLETION) !=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_TIMED_OUT) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_reason = CMD_TIMEOUT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_statistics |=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (STAT_TIMEOUT | STAT_ABORTED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if ((cmd->flags & PVSCSI_FLAG_ABORTED) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_reason = CMD_ABORTED;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_statistics |=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (STAT_TIMEOUT | STAT_ABORTED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if ((cmd->flags & PVSCSI_FLAGS_RESET) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_reason = CMD_RESET;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_RESET_BUS) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_statistics |=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STAT_BUS_RESET;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt->pkt_statistics |=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STAT_DEV_RESET;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_DONE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_TRANSPORT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pkt->pkt_flags & FLAG_NOINTR) == 0 &&
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_comp != NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (*pkt->pkt_comp)(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd = c;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_dev_reset(pvscsi_softc_t *pvs, int target)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSICmdDescResetDevice cmd = { 0 };
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd.target = target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_RESET_DEVICE, &cmd, sizeof (cmd));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_poll_cmd(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t seen_intr;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int cycles = (cmd->pkt->pkt_time * 1000000) / USECS_TO_WAIT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *dcmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Make sure we're not missing any commands completed
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * concurrently before we have actually disabled interrupts.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dcmd = pvscsi_process_comp_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(dcmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov while ((cmd->flags & PVSCSI_FLAG_DONE) == 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov seen_intr = B_FALSE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Disable interrupts from H/W */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_mask_intr(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Wait for interrupt to arrive */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < cycles; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t status;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov status = pvscsi_read_intr_status(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((status & PVSCSI_INTR_ALL_SUPPORTED) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Check completion ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dcmd = pvscsi_process_comp_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov seen_intr = B_TRUE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov drv_usecwait(USECS_TO_WAIT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Enable interrupts from H/W */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_unmask_intr(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (!seen_intr) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* No interrupts seen from device during the timeout */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAGS_COMPLETION) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Command was cancelled asynchronously */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dcmd = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if ((pvscsi_abort_cmd(cmd,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &dcmd)) == CMD_ABORTED) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Command was cancelled in hardware */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STAT_TIMEOUT | STAT_ABORTED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_statistics |= (STAT_TIMEOUT |
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov STAT_ABORTED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_TIMEOUT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Complete commands that might be on completion list.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Target command can also be on the list in case it was
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * completed before it could be actually cancelled.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(dcmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (!seen_intr)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (TRAN_ACCEPT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_abort_all(struct scsi_address *ap, pvscsi_softc_t *pvs,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t **pending, int marker_flag)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int qlen = pvs->cmd_queue_len;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd, *pcmd, *phead = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->rx_mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(mutex_owned(&pvs->tx_mutex));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Try to abort all queued commands, merging commands waiting
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * for completion into a single list to complete them at one
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * time when mutex is released.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov while (qlen > 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd = list_remove_head(&pvs->cmd_queue);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov qlen--;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ap == NULL || ap->a_target == cmd->cmd_target) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int c = --pvs->cmd_queue_len;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_abort_cmd(cmd, &pcmd) == CMD_ABORTED) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Assume command is completely cancelled now,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * so mark it as requested.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= marker_flag;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov qlen -= (c - pvs->cmd_queue_len);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Now merge current pending commands with
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * previous ones.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (phead == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov phead = pcmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if (pcmd != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov phead->tail_cmd->next_cmd = pcmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov phead->tail_cmd = pcmd->tail_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_insert_tail(&pvs->cmd_queue, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pending = phead;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_quiesce_notify(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvs->cmd_queue_len == 0 &&
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (pvs->flags & PVSCSI_HBA_QUIESCE_PENDING) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags &= ~PVSCSI_HBA_QUIESCE_PENDING;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_broadcast(&pvs->quiescevar);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_transport_command(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIRingReqDesc *rdesc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSIRingsState *sdesc = RINGS_STATE(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t req_ne = sdesc->reqNumEntriesLog2;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (!pvscsi_acquire_ctx(pvs, cmd)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!no free ctx available");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (TRAN_BUSY);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((sdesc->reqProdIdx - sdesc->cmpConsIdx) >= (1 << req_ne)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_release_ctx(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!no free I/O slots available");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (TRAN_BUSY);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_TRANSPORT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc = REQ_RING(pvs) + (sdesc->reqProdIdx & MASK(req_ne));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(&rdesc->lun, sizeof (rdesc->lun));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->bus = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->target = cmd->cmd_target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_XARQ) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero((void*)cmd->arqbuf->b_un.b_addr, SENSE_BUFFER_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->senseLen = SENSE_BUFFER_SIZE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->senseAddr = cmd->arqc.dmac_laddress;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->senseLen = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->senseAddr = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->vcpuHint = CPU->cpu_id;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->cdbLen = cmd->cmdlen;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bcopy(cmd->cmd_cdb, rdesc->cdb, cmd->cmdlen);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup tag info */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_TAG) != 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->tag = cmd->tag;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov else
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->tag = MSG_SIMPLE_QTAG;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup I/O direction and map data buffers */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_DMA_VALID) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_IO_READ) != 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->flags = PVSCSI_FLAG_CMD_DIR_TOHOST;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov else
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->flags = PVSCSI_FLAG_CMD_DIR_TODEVICE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_map_buffers(cmd, rdesc);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->flags = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rdesc->context = pvscsi_map_ctx(pvs, cmd->ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov membar_producer();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sdesc->reqProdIdx++;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov membar_producer();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->timeout_lbolt = ddi_get_lbolt() + SEC_TO_TICK(pkt->pkt_time);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_add_to_queue(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (cmd->pkt->pkt_cdbp[0]) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_READ:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_WRITE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_READ_G1:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_WRITE_G1:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_READ_G4:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_WRITE_G4:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_READ_G5:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCMD_WRITE_G5:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT((cmd->flags & PVSCSI_FLAG_DMA_VALID) != 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_submit_rw_io(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_submit_nonrw_io(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (TRAN_ACCEPT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reset_generic(pvscsi_softc_t *pvs, struct scsi_address *ap)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t bus_reset = (ap == NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int flags;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *done, *aborted;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov flags = bus_reset ? PVSCSI_FLAG_RESET_BUS : PVSCSI_FLAG_RESET_DEV;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Try to process pending requests */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov done = pvscsi_process_comp_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Abort all pending requests */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_abort_all(ap, pvs, &aborted, flags);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Reset at hardware level */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (bus_reset) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reset_bus(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Should never happen after bus reset */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvscsi_process_comp_ring(pvs) == NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_dev_reset(pvs, ap->a_target);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(done);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(aborted);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_cmd_ext_free(pvscsi_cmd_t *cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_CDB_EXT) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pkt->pkt_cdbp, cmd->cmdlen);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_CDB_EXT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_SCB_EXT) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pkt->pkt_scbp, cmd->statuslen);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_SCB_EXT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_PRIV_EXT) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pkt->pkt_private, cmd->tgtlen);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_PRIV_EXT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED pvs */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_cmd_ext_alloc(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd, int kf)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_pkt *pkt = CMD2PKT(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov void *buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmdlen > sizeof (cmd->cmd_cdb)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((buf = kmem_zalloc(cmd->cmdlen, kf)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_cdbp = buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_CDB_EXT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->statuslen > sizeof (cmd->cmd_scb)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((buf = kmem_zalloc(cmd->statuslen, kf)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_scbp = buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_SCB_EXT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_rqslen = (cmd->statuslen - sizeof (cmd->cmd_scb));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->tgtlen > sizeof (cmd->tgt_priv)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((buf = kmem_zalloc(cmd->tgtlen, kf)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_private = buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_PRIV_EXT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovout:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ext_free(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_setup_dma_buffer(pvscsi_softc_t *pvs, size_t length,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_dma_buf_t *buf)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_cookie_t cookie;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint_t ccount;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ddi_dma_alloc_handle(pvs->dip, &pvscsi_ring_dma_attr,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DMA_SLEEP, NULL, &buf->dma_handle)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to allocate DMA handle");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ddi_dma_mem_alloc(buf->dma_handle, length, &pvscsi_dma_attrs,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &buf->addr,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &buf->real_length, &buf->acc_handle)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to allocate %ld bytes for DMA buffer", length);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&buf->dma_handle);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ddi_dma_addr_bind_handle(buf->dma_handle, NULL, buf->addr,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov buf->real_length, DDI_DMA_CONSISTENT | DDI_DMA_RDWR, DDI_DMA_SLEEP,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov NULL, &cookie, &ccount)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to bind DMA buffer");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&buf->dma_handle);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_mem_free(&buf->acc_handle);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* TODO Support multipart SG regions */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(ccount == 1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov buf->pa = cookie.dmac_laddress;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_free_dma_buffer(pvscsi_dma_buf_t *buf)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&buf->dma_handle);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_mem_free(&buf->acc_handle);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_setup_sg(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ctx_t *ctx;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov size_t size = pvs->req_depth * sizeof (pvscsi_cmd_ctx_t);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ctx = pvs->cmd_ctx = kmem_zalloc(size, KM_SLEEP);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->req_depth; ++i, ++ctx) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_insert_tail(&pvs->cmd_ctx_pool, ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_dma_buffer(pvs, PAGE_SIZE,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &ctx->dma_buf) != DDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto cleanup;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovcleanup:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (; i >= 0; --i, --ctx) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_remove(&pvs->cmd_ctx_pool, ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&ctx->dma_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pvs->cmd_ctx, size);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_free_sg(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ctx_t *ctx = pvs->cmd_ctx;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->req_depth; ++i, ++ctx) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_remove(&pvs->cmd_ctx_pool, ctx);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&ctx->dma_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pvs->cmd_ctx, pvs->req_pages << PAGE_SHIFT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_allocate_rings(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate DMA buffer for rings state */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_dma_buffer(pvs, PAGE_SIZE,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvs->rings_state_buf) != DDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate DMA buffer for request ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->req_pages = MIN(pvscsi_ring_pages, PVSCSI_MAX_NUM_PAGES_REQ_RING);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->req_depth = pvs->req_pages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_dma_buffer(pvs, pvs->req_pages * PAGE_SIZE,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvs->req_ring_buf) != DDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_rings_state;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate completion ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->cmp_pages = MIN(pvscsi_ring_pages, PVSCSI_MAX_NUM_PAGES_CMP_RING);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_dma_buffer(pvs, pvs->cmp_pages * PAGE_SIZE,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvs->cmp_ring_buf) != DDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_req_buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate message ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->msg_pages = MIN(pvscsi_msg_ring_pages,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov PVSCSI_MAX_NUM_PAGES_MSG_RING);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_dma_buffer(pvs, pvs->msg_pages * PAGE_SIZE,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvs->msg_ring_buf) != DDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_cmp_buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_cmp_buf:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->cmp_ring_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_req_buf:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->req_ring_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_rings_state:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->rings_state_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_free_rings(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->msg_ring_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->cmp_ring_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->req_ring_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_dma_buffer(&pvs->rings_state_buf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_setup_rings(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSICmdDescSetupMsgRing cmd_msg = { 0 };
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct PVSCSICmdDescSetupRings cmd = { 0 };
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint64_t base;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd.ringsStatePPN = pvs->rings_state_buf.pa >> PAGE_SHIFT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd.reqRingNumPages = pvs->req_pages;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd.cmpRingNumPages = pvs->cmp_pages;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup request ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov base = pvs->req_ring_buf.pa;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->req_pages; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd.reqRingPPNs[i] = base >> PAGE_SHIFT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov base += PAGE_SIZE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup completion ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov base = pvs->cmp_ring_buf.pa;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->cmp_pages; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd.cmpRingPPNs[i] = base >> PAGE_SHIFT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov base += PAGE_SIZE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(RINGS_STATE(pvs), PAGE_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(REQ_RING(pvs), pvs->req_pages * PAGE_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(CMP_RING(pvs), pvs->cmp_pages * PAGE_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Issue SETUP command */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_SETUP_RINGS, &cmd, sizeof (cmd));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup message ring */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd_msg.numPages = pvs->msg_pages;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov base = pvs->msg_ring_buf.pa;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->msg_pages; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd_msg.ringPPNs[i] = base >> PAGE_SHIFT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov base += PAGE_SIZE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(MSG_RING(pvs), pvs->msg_pages * PAGE_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_SETUP_MSG_RING, &cmd_msg,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sizeof (cmd_msg));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_setup_io(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int offset, rcount, rn, type;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ret = DDI_FAILURE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov off_t regsize;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pci_regspec_t *regs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint_t regs_length;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pvs->dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_PROP_DONTPASS, "reg", (int **)&regs,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &regs_length) != DDI_PROP_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to lookup 'reg' property");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rcount = regs_length * sizeof (int) / sizeof (pci_regspec_t);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (offset = PCI_CONF_BASE0; offset <= PCI_CONF_BASE5; offset += 4) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (rn = 0; rn < rcount; ++rn) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (PCI_REG_REG_G(regs[rn].pci_phys_hi) == offset) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov type = regs[rn].pci_phys_hi & PCI_ADDR_MASK;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (rn >= rcount)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov continue;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (type != PCI_ADDR_IO) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_dev_regsize(pvs->dip, rn,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &regsize) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to get size of reg %d", rn);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (regsize == PVSCSI_MEM_SPACE_SIZE) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_regs_map_setup(pvs->dip, rn,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvs->mmio_base, 0, 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvscsi_mmio_attr,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvs->mmio_handle) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to map MMIO BAR");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ret = DDI_SUCCESS;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovout:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_prop_free(regs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_free_io(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_regs_map_free(&pvs->mmio_handle);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_enable_intrs(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i, rc, intr_caps;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((rc = ddi_intr_get_cap(pvs->intr_htable[0], &intr_caps)) !=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to get interrupt caps");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((intr_caps & DDI_INTR_FLAG_BLOCK) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((rc = ddi_intr_block_enable(pvs->intr_htable,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_cnt)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to enable interrupt block");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->intr_cnt; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((rc = ddi_intr_enable(pvs->intr_htable[i])) ==
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov continue;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to enable interrupt");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov while (--i >= 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_intr_disable(pvs->intr_htable[i]);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Unmask interrupts */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (rc == DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_MASK,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov PVSCSI_INTR_CMPL_MASK | PVSCSI_INTR_MSG_MASK);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (rc);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED arg2 */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic uint32_t
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_intr_handler(caddr_t arg1, caddr_t arg2)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t handled;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = (pvscsi_softc_t *)arg1;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint32_t status;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvs->num_pollers > 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_INTR_CLAIMED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_enable_msi) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov handled = B_TRUE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov status = pvscsi_read_intr_status(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov handled = (status & PVSCSI_INTR_ALL_SUPPORTED) != 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (handled)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_write_intr_status(pvs, status);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (handled) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t qnotify;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *pending;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_msg_t *msg;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pending = pvscsi_process_comp_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov msg = pvscsi_process_msg_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov qnotify = HBA_QUIESCE_PENDING(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pending != NULL && ddi_taskq_dispatch(pvs->comp_tq,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained, pending,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_NOSLEEP) == DDI_FAILURE)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(pending);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (msg != NULL && ddi_taskq_dispatch(pvs->msg_tq,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_handle_msg, msg, DDI_NOSLEEP) == DDI_FAILURE) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to process msg type %d for target %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov msg->type, msg->target);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(msg, sizeof (pvscsi_msg_t));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (qnotify)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_quiesce_notify(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (handled ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_register_isr(pvscsi_softc_t *pvs, int type)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int navail, nactual;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_intr_get_navail(pvs->dip, type, &navail) != DDI_SUCCESS ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov navail == 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to get number of available interrupts of type %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov type);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov navail = MIN(navail, PVSCSI_MAX_INTRS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_size = navail * sizeof (ddi_intr_handle_t);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs->intr_htable = kmem_alloc(pvs->intr_size, KM_SLEEP)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to allocate %d bytes for interrupt hashtable",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_size);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_intr_alloc(pvs->dip, pvs->intr_htable, type, 0, navail,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &nactual, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS || nactual == 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to allocate %d interrupts",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov navail);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_htable;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_cnt = nactual;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_intr_get_pri(pvs->intr_htable[0],
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (uint_t *)&pvs->intr_pri) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to get interrupt priority");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_intrs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < nactual; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_intr_add_handler(pvs->intr_htable[i],
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_intr_handler, (caddr_t)pvs, NULL) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to add interrupt handler");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_intrs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_intrs:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < nactual; i++)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_intr_free(pvs->intr_htable[i]);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_htable:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pvs->intr_htable, pvs->intr_size);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_free_intr_resources(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 0; i < pvs->intr_cnt; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_intr_disable(pvs->intr_htable[i]);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_intr_remove_handler(pvs->intr_htable[i]);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_intr_free(pvs->intr_htable[i]);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_free(pvs->intr_htable, pvs->intr_size);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_setup_isr(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int intr_types;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_intr_get_supported_types(pvs->dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &intr_types) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to get supported interrupt types");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((intr_types & DDI_INTR_TYPE_MSIX) != 0 && pvscsi_enable_msi) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_register_isr(pvs,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_INTR_TYPE_MSIX) == DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_type = DDI_INTR_TYPE_MSIX;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to install MSI-X interrupt handler");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if ((intr_types & DDI_INTR_TYPE_MSI) != 0 && pvscsi_enable_msi) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_register_isr(pvs,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_type = DDI_INTR_TYPE_MSI;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to install MSI interrupt handler");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if ((intr_types & DDI_INTR_TYPE_FIXED) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_register_isr(pvs,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->intr_type = DDI_INTR_TYPE_FIXED;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to install FIXED interrupt handler");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (pvs->intr_type == 0 ? DDI_FAILURE : DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_wd_thread(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov clock_t now;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *expired, *c, *cn, **pnext;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (;;) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov expired = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pnext = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov now = ddi_get_lbolt();
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (c = list_head(&pvs->cmd_queue); c != NULL; ) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cn = list_next(&pvs->cmd_queue, c);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Commands with 'FLAG_NOINTR' are watched using their
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * own timeouts, so we should not touch them.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((c->pkt->pkt_flags & FLAG_NOINTR) == 0 &&
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov now > c->timeout_lbolt) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!expired command: %p (%ld > %ld)",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void *)c, now, c->timeout_lbolt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_remove_from_queue(c);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (expired == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov expired = c;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pnext == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pnext = &c->next_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *pnext = c;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pnext = &c->next_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov c = cn;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Now cancel all expired commands */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (expired != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_address sa = {0};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Build a fake SCSI address */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sa.a_hba_tran = pvs->tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov while (expired != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov c = expired->next_cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sa.a_target = expired->cmd_target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sa.a_lun = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) pvscsi_abort(&sa, CMD2PKT(expired));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov expired = c;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs->flags & PVSCSI_DRIVER_SHUTDOWN) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Finish job */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cv_reltimedwait(&pvs->wd_condvar, &pvs->mutex,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov SEC_TO_TICK(1), TR_CLOCK_TICK) > 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Explicitly woken up, finish job */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Confirm thread termination */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_signal(&pvs->syncvar);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_ccache_constructor(void *buf, void *cdrarg, int kmflags)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int (*callback)(caddr_t);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov uint_t cookiec;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = (pvscsi_cmd_t *)buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = cdrarg;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct scsi_address ap;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov callback = (kmflags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ap.a_hba_tran = pvs->tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ap.a_target = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ap.a_lun = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate a DMA handle for data transfers */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ddi_dma_alloc_handle(pvs->dip, &pvs->io_dma_attr, callback,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov NULL, &cmd->cmd_dmahdl)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to allocate DMA handle");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup ARQ buffer */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->arqbuf = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov SENSE_BUFFER_SIZE, B_READ, callback, NULL)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to allocate ARQ buffer");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_handle;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_dma_alloc_handle(pvs->dip, &pvs->hba_dma_attr,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov callback, NULL, &cmd->arqhdl) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to allocate DMA handle for ARQ buffer");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_arqbuf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_dma_buf_bind_handle(cmd->arqhdl, cmd->arqbuf,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (DDI_DMA_READ | DDI_DMA_CONSISTENT), callback, NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->arqc, &cookiec) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to bind ARQ buffer");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_arqhdl;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_arqhdl:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&cmd->arqhdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_arqbuf:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_free_consistent_buf(cmd->arqbuf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_handle:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&cmd->cmd_dmahdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED cdrarg */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_ccache_destructor(void *buf, void *cdrarg)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = (pvscsi_cmd_t *)buf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmd_dmahdl != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_unbind_handle(cmd->cmd_dmahdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&cmd->cmd_dmahdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_dmahdl = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->arqhdl != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_unbind_handle(cmd->arqhdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_free_handle(&cmd->arqhdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->arqhdl = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->arqbuf != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_free_consistent_buf(cmd->arqbuf);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->arqbuf = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* tran_* entry points and setup */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED hba_dip tgt_dip hba_tran */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = SDEV2PRIV(sd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (sd->sd_address.a_target >= PVSCSI_MAXTGTS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t poll = ((pkt->pkt_flags & FLAG_NOINTR) != 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int rc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = PKT2CMD(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = ap->a_hba_tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->pkt == pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->cmd_pvs == pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Reinitialize some fields because the packet may
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * have been resubmitted.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_reason = CMD_CMPLT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_state = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_statistics = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Zero status byte */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov *(pkt->pkt_scbp) = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_DMA_VALID) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->cmd_dma_count != 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_resid = cmd->cmd_dma_count;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Consistent packets need to be synced first
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * (only for data going out).
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_IO_IOPB) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_sync(cmd->cmd_dmahdl, 0, 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DMA_SYNC_FORDEV);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_target = ap->a_target;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (HBA_IS_QUIESCED(pvs) && !poll) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (TRAN_BUSY);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rc = pvscsi_transport_command(pvs, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (poll) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *dcmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t qnotify;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (rc == TRAN_ACCEPT)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rc = pvscsi_poll_cmd(pvs, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dcmd = pvscsi_process_comp_ring(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov qnotify = HBA_QUIESCE_PENDING(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(dcmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (qnotify)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_quiesce_notify(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (rc);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reset(struct scsi_address *ap, int level)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = AP2PRIV(ap);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (level) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case RESET_ALL:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (pvscsi_reset_generic(pvs, NULL));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case RESET_TARGET:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(ap != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (pvscsi_reset_generic(pvs, ap));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t qnotify = B_FALSE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *pending;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = ap->a_hba_tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pkt != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Abort single command */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = PKT2CMD(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_abort_cmd(cmd, &pending) == CMD_ABORTED) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Assume command is completely cancelled now */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_ABORTED;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Abort all commands on the bus */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_abort_all(ap, pvs, &pending, PVSCSI_FLAG_ABORTED);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov qnotify = HBA_QUIESCE_PENDING(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->tx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_complete_chained(pending);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (qnotify)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_quiesce_notify(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED tgtonly */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = ap->a_hba_tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cap == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (scsi_hba_lookup_capstr(cap)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCSI_CAP_ARQ:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return ((pvs->flags & PVSCSI_HBA_AUTO_REQUEST_SENSE) != 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCSI_CAP_UNTAGGED_QING:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED tgtonly */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = ap->a_hba_tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cap == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (scsi_hba_lookup_capstr(cap)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case SCSI_CAP_ARQ:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (value == 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags &= ~PVSCSI_HBA_AUTO_REQUEST_SENSE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov else
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags |= PVSCSI_HBA_AUTO_REQUEST_SENSE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = PKT2CMD(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs = ap->a_hba_tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->cmd_pvs == pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_DMA_VALID) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_DMA_VALID;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_unbind_handle(cmd->cmd_dmahdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->ctx != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_release_ctx(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAGS_EXT) != 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_ext_free(cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_cache_free(pvs->cmd_cache, cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic struct scsi_pkt *
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, struct buf *bp,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int cmdlen, int statuslen, int tgtlen, int flags, int (*callback)(),
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov caddr_t arg)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov boolean_t is_new;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int rc, i;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs = ap->a_hba_tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate a new SCSI packet */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pkt == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_handle_t saved_dmahdl, saved_arqhdl;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov struct buf *saved_arqbuf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_cookie_t saved_arqc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov is_new = B_TRUE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd = kmem_cache_alloc(pvs->cmd_cache, kf)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov saved_dmahdl = cmd->cmd_dmahdl;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov saved_arqhdl = cmd->arqhdl;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov saved_arqbuf = cmd->arqbuf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov saved_arqc = cmd->arqc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bzero(cmd, sizeof (pvscsi_cmd_t) -
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sizeof (cmd->cached_cookies));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_pvs = pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_dmahdl = saved_dmahdl;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->arqhdl = saved_arqhdl;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->arqbuf = saved_arqbuf;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->arqc = saved_arqc;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt = &cmd->cached_pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_ha_private = (opaque_t)cmd;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_address = *ap;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_scbp = (uint8_t *)&cmd->cmd_scb;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_cdbp = (uint8_t *)&cmd->cmd_cdb;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_private = (opaque_t)&cmd->tgt_priv;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->tgtlen = tgtlen;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->statuslen = statuslen;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmdlen = cmdlen;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->pkt = pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->ctx = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate extended buffers */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmdlen > sizeof (cmd->cmd_cdb)) ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (statuslen > sizeof (cmd->cmd_scb)) ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (tgtlen > sizeof (cmd->tgt_priv))) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_cmd_ext_alloc(pvs, cmd, kf) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!extent allocation failed");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov is_new = B_FALSE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd = PKT2CMD(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= PVSCSI_FLAGS_PERSISTENT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT((cmd->flags & PVSCSI_FLAG_TRANSPORT) == 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((flags & PKT_XARQ) != 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_XARQ;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Handle partial DMA transfers */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmd_nwin > 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (++cmd->cmd_winindex >= cmd->cmd_nwin)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_dma_getwin(cmd->cmd_dmahdl, cmd->cmd_winindex,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->cmd_dmac, &cmd->cmd_dmaccount) == DDI_FAILURE)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto handle_dma_cookies;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup data buffer */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (bp != NULL && bp->b_bcount > 0 &&
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (cmd->flags & PVSCSI_FLAG_DMA_VALID) == 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int dma_flags;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->cmd_dmahdl != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((bp->b_flags & B_READ) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_IO_READ;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dma_flags = DDI_DMA_READ;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_IO_READ;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dma_flags = DDI_DMA_WRITE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((flags & PKT_CONSISTENT) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_IO_IOPB;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dma_flags |= DDI_DMA_CONSISTENT;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((flags & PKT_DMA_PARTIAL) != 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dma_flags |= DDI_DMA_PARTIAL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov rc = ddi_dma_buf_bind_handle(cmd->cmd_dmahdl, bp,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dma_flags, callback, arg, &cmd->cmd_dmac,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->cmd_dmaccount);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (rc == DDI_DMA_PARTIAL_MAP) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_numwin(cmd->cmd_dmahdl,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->cmd_nwin);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_winindex = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_getwin(cmd->cmd_dmahdl,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_winindex, &cmd->cmd_dma_offset,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->cmd_dma_len, &cmd->cmd_dmac,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &cmd->cmd_dmaccount);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov } else if (rc != 0 && rc != DDI_DMA_MAPPED) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (rc) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_DMA_NORESOURCES:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bioerror(bp, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_DMA_BADATTR:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_DMA_NOMAPPING:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bioerror(bp, EFAULT);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_DMA_TOOBIG:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bioerror(bp, EINVAL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_DMA_VALID;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovhandle_dma_cookies:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(cmd->cmd_dmaccount > 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmd_dmaccount > PVSCSI_MAX_SG_SIZE) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!invalid cookie count: %d (max %d)",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_dmaccount, PVSCSI_MAX_SG_SIZE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov bioerror(bp, EINVAL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto out;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags |= PVSCSI_FLAG_DMA_VALID;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_dma_count = cmd->cmd_dmac.dmac_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_total_dma_count += cmd->cmd_dmac.dmac_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cached_cookies[0] = cmd->cmd_dmac;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Calculate total amount of bytes for this I/O and
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * store cookies for further processing.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov for (i = 1; i < cmd->cmd_dmaccount; i++) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_dma_nextcookie(cmd->cmd_dmahdl, &cmd->cmd_dmac);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cached_cookies[i] = cmd->cmd_dmac;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_dma_count += cmd->cmd_dmac.dmac_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->cmd_total_dma_count += cmd->cmd_dmac.dmac_size;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pkt->pkt_resid = (bp->b_bcount - cmd->cmd_total_dma_count);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovout:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (is_new)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_destroy_pkt(ap, pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED ap */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = PKT2CMD(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((cmd->flags & PVSCSI_FLAG_DMA_VALID) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_unbind_handle(cmd->cmd_dmahdl);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmd->flags &= ~PVSCSI_FLAG_DMA_VALID;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED ap */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic void
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_cmd_t *cmd = PKT2CMD(pkt);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (cmd->cmd_dmahdl != NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) ddi_dma_sync(cmd->cmd_dmahdl, 0, 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (cmd->flags & PVSCSI_FLAG_IO_READ) ?
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_DMA_SYNC_FORCPU : DDI_DMA_SYNC_FORDEV);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* ARGSUSED ap flag callback arg */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_reset_notify(struct scsi_address *ap, int flag,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov void (*callback)(caddr_t), caddr_t arg)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_quiesce_hba(dev_info_t *dip)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_t *tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((tran = ddi_get_driver_private(dip)) == NULL ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (pvs = TRAN2PRIV(tran)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (!HBA_IS_QUIESCED(pvs))
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags |= PVSCSI_HBA_QUIESCED;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvs->cmd_queue_len != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Outstanding commands present, wait */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags |= PVSCSI_HBA_QUIESCE_PENDING;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_wait(&pvs->quiescevar, &pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs->cmd_queue_len == 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Suspend taskq delivery and complete all scheduled tasks */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_suspend(pvs->msg_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_wait(pvs->msg_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_suspend(pvs->comp_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_wait(pvs->comp_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_unquiesce_hba(dev_info_t *dip)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_t *tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((tran = ddi_get_driver_private(dip)) == NULL ||
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (pvs = TRAN2PRIV(tran)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (!HBA_IS_QUIESCED(pvs)) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs->cmd_queue_len == 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags &= ~PVSCSI_HBA_QUIESCED;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Resume taskq delivery */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_resume(pvs->msg_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_resume(pvs->comp_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_bus_config(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov void *arg, dev_info_t **childp)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov char *p;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int circ;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ret = NDI_FAILURE;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov long target = 0;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_t *tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov tran = ddi_get_driver_private(pdip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs = tran->tran_hba_private;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_devi_enter(pdip, &circ);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (op) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BUS_CONFIG_ONE:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((p = strrchr((char *)arg, '@')) != NULL &&
6bd8a07093bddc0edfc07bfda4ca600e31c02c03Yuri Pankov ddi_strtol(p + 1, NULL, 16, &target) == 0)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ret = pvscsi_config_one(pdip, pvs, (int)target, childp);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BUS_CONFIG_DRIVER:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case BUS_CONFIG_ALL:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ret = pvscsi_config_all(pdip, pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ret == NDI_SUCCESS)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ret = ndi_busop_bus_config(pdip, flags, op, arg, childp, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ndi_devi_exit(pdip, circ);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_hba_setup(pvscsi_softc_t *pvs)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_t *hba_tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran = pvs->tran = scsi_hba_tran_alloc(pvs->dip,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov SCSI_HBA_CANSLEEP);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(pvs->tran != NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_hba_private = pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_tgt_private = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_tgt_init = pvscsi_tgt_init;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_tgt_free = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_tgt_probe = scsi_hba_probe;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_start = pvscsi_start;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_reset = pvscsi_reset;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_abort = pvscsi_abort;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_getcap = pvscsi_getcap;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_setcap = pvscsi_setcap;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_init_pkt = pvscsi_init_pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_destroy_pkt = pvscsi_destroy_pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_dmafree = pvscsi_dmafree;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_sync_pkt = pvscsi_sync_pkt;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_reset_notify = pvscsi_reset_notify;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_quiesce = pvscsi_quiesce_hba;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_unquiesce = pvscsi_unquiesce_hba;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_bus_reset = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_add_eventcall = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_get_eventcookie = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_post_event = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_remove_eventcall = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_bus_config = pvscsi_bus_config;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (scsi_hba_attach_setup(pvs->dip, &pvs->hba_dma_attr, hba_tran,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov SCSI_HBA_TRAN_CDB | SCSI_HBA_TRAN_SCB | SCSI_HBA_TRAN_CLONE) !=
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to attach HBA");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_free(hba_tran);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->tran = NULL;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (-1);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int instance;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov char buf[32];
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ASSERT(scsi_hba_iport_unit_address(dip) == NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (cmd) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_ATTACH:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_RESUME:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov instance = ddi_get_instance(dip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Allocate softstate information */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_soft_state_zalloc(pvscsi_sstate, instance) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!ddi_soft_state_zalloc() failed for instance %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov instance);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs = ddi_get_soft_state(pvscsi_sstate, instance)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!failed to get soft state for instance %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov instance);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto fail;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /*
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * Indicate that we are 'sizeof (scsi_*(9S))' clean, we use
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov * scsi_pkt_size() instead.
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_size_clean(dip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Setup HBA instance */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->instance = instance;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->dip = dip;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->hba_dma_attr = pvscsi_hba_dma_attr;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->ring_dma_attr = pvscsi_ring_dma_attr;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->io_dma_attr = pvscsi_io_dma_attr;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_init(&pvs->mutex, "pvscsi instance mutex", MUTEX_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_init(&pvs->intr_mutex, "pvscsi instance interrupt mutex",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov MUTEX_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_init(&pvs->rx_mutex, "pvscsi rx ring mutex", MUTEX_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_init(&pvs->tx_mutex, "pvscsi tx ring mutex", MUTEX_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_create(&pvs->cmd_ctx_pool, sizeof (pvscsi_cmd_ctx_t),
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov offsetof(pvscsi_cmd_ctx_t, list));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_create(&pvs->devnodes, sizeof (pvscsi_device_t),
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov offsetof(pvscsi_device_t, list));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov list_create(&pvs->cmd_queue, sizeof (pvscsi_cmd_t),
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov offsetof(pvscsi_cmd_t, cmd_queue_node));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_init(&pvs->syncvar, "pvscsi synchronization cv", CV_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_init(&pvs->wd_condvar, "pvscsi watchdog cv", CV_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_init(&pvs->quiescevar, "pvscsi quiesce cv", CV_DRIVER, NULL);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void) sprintf(buf, "pvscsi%d_cache", instance);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->cmd_cache = kmem_cache_create(buf, sizeof (pvscsi_cmd_t), 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_ccache_constructor, pvscsi_ccache_destructor, NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov (void *)pvs, NULL, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvs->cmd_cache == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to create a cache for SCSI commands");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto fail;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvscsi_setup_io(pvs)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to setup I/O region");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_cache;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reset_hba(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvscsi_allocate_rings(pvs)) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to allocate DMA rings");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_io;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_setup_rings(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_isr(pvs) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to setup ISR");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_rings;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_setup_sg(pvs) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to setup S/G");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_intr;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_hba_setup(pvs) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to setup HBA");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_sg;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs->comp_tq = ddi_taskq_create(pvs->dip, "comp_tq",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov MIN(UINT16_MAX, ncpus), TASKQ_DEFAULTPRI, 0)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to create completion taskq");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_sg;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs->msg_tq = ddi_taskq_create(pvs->dip, "msg_tq",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov "!failed to create message taskq");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_comp_tq;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (pvscsi_enable_intrs(pvs) != DDI_SUCCESS) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov dev_err(pvs->dip, CE_WARN, "!failed to enable interrupts");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov goto free_msg_tq;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Launch watchdog thread */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->wd_thread = thread_create(NULL, 0, pvscsi_wd_thread, pvs, 0, &p0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov TS_RUN, minclsyspri);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_msg_tq:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_destroy(pvs->msg_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_comp_tq:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_destroy(pvs->comp_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_sg:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_sg(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_intr:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_intr_resources(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_rings:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reset_hba(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_rings(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_io:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_io(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfree_cache:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_cache_destroy(pvs->cmd_cache);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovfail:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_soft_state_free(pvscsi_sstate, instance);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int instance;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov switch (cmd) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov case DDI_DETACH:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov break;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov default:
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov instance = ddi_get_instance(dip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs = ddi_get_soft_state(pvscsi_sstate, instance)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!failed to get soft state for instance %d",
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov instance);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_FAILURE);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reset_hba(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_intr_resources(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Shutdown message taskq */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_wait(pvs->msg_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_destroy(pvs->msg_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Shutdown completion taskq */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_wait(pvs->comp_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_taskq_destroy(pvs->comp_tq);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Shutdown watchdog thread */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_enter(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvs->flags |= PVSCSI_DRIVER_SHUTDOWN;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_signal(&pvs->wd_condvar);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_wait(&pvs->syncvar, &pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_exit(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_sg(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_rings(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_free_io(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov kmem_cache_destroy(pvs->cmd_cache);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_destroy(&pvs->mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_destroy(&pvs->intr_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov mutex_destroy(&pvs->rx_mutex);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_destroy(&pvs->syncvar);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_destroy(&pvs->wd_condvar);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cv_destroy(&pvs->quiescevar);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_soft_state_free(pvscsi_sstate, instance);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_prop_remove_all(dip);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int *rval)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ret;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if (ddi_get_soft_state(pvscsi_sstate, getminor(dev)) == NULL) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!invalid device instance: %d", getminor(dev));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ENXIO);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Try to handle command in a common way */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ret = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval)) != ENOTTY)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!unsupported IOCTL command: 0x%X", cmd);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ENXIO);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic int
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovpvscsi_quiesce(dev_info_t *devi)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_tran_t *tran;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_softc_t *pvs;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((tran = ddi_get_driver_private(devi)) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((pvs = tran->tran_hba_private) == NULL)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Mask all interrupts from device */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_MASK, 0);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov /* Reset the HBA */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov pvscsi_reset_hba(pvs);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (DDI_SUCCESS);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov/* module */
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic struct cb_ops pvscsi_cb_ops = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_open = scsi_hba_open,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_close = scsi_hba_close,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_strategy = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_print = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_dump = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_read = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_write = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_ioctl = pvscsi_ioctl,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_devmap = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_mmap = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_segmap = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_chpoll = nochpoll,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_prop_op = ddi_prop_op,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_str = NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_flag = D_MP,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_rev = CB_REV,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_aread = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .cb_awrite = nodev
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic struct dev_ops pvscsi_ops = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_rev = DEVO_REV,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_refcnt = 0,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_getinfo = ddi_no_info,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_identify = nulldev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_probe = nulldev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_attach = pvscsi_attach,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_detach = pvscsi_detach,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_reset = nodev,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_cb_ops = &pvscsi_cb_ops,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_bus_ops = NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_power = NULL,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov .devo_quiesce = pvscsi_quiesce
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov#define PVSCSI_IDENT "VMware PVSCSI"
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic struct modldrv modldrv = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &mod_driverops,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov PVSCSI_IDENT,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &pvscsi_ops,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovstatic struct modlinkage modlinkage = {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov MODREV_1,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov &modldrv,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov NULL
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov};
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovint
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov_init(void)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ret;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ret = ddi_soft_state_init(&pvscsi_sstate,
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov sizeof (struct pvscsi_softc), PVSCSI_INITIAL_SSTATE_ITEMS)) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!ddi_soft_state_init() failed");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ret = scsi_hba_init(&modlinkage)) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!scsi_hba_init() failed");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_soft_state_fini(&pvscsi_sstate);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ret = mod_install(&modlinkage)) != 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov cmn_err(CE_WARN, "!mod_install() failed");
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_soft_state_fini(&pvscsi_sstate);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_fini(&modlinkage);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovint
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov_info(struct modinfo *modinfop)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (mod_info(&modlinkage, modinfop));
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankovint
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov_fini(void)
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov{
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov int ret;
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov if ((ret = mod_remove(&modlinkage)) == 0) {
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov ddi_soft_state_fini(&pvscsi_sstate);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov scsi_hba_fini(&modlinkage);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov }
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov return (ret);
565657ca18725b8f8dbe5b93704cc1d173be9d65Yuri Pankov}