1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * CDDL HEADER START
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The contents of this file are subject to the terms of the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Common Development and Distribution License (the "License").
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * You may not use this file except in compliance with the License.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * or http://www.opensolaris.org/os/licensing.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * See the License for the specific language governing permissions
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and limitations under the License.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * When distributing Covered Code, include this CDDL HEADER in each
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If applicable, add the following below this CDDL HEADER, with the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * fields enclosed by brackets "[]" replaced with your own identifying
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * information: Portions Copyright [yyyy] [name of copyright owner]
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * CDDL HEADER END
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * RDMA channel interface for Solaris SCSI RDMA Protocol Target (SRP)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * transport port provider module for the COMSTAR framework.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/cpuvar.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/types.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/conf.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/stat.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/file.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/ddi.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/sunddi.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/modctl.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/sysmacros.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/sdt.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/taskq.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/scsi/scsi.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include <sys/ib/ibtl/ibti.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/stmf.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/stmf_ioctl.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/portif.h>
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include "srp.h"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include "srpt_impl.h"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include "srpt_ioc.h"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include "srpt_stp.h"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#include "srpt_ch.h"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonextern srpt_ctxt_t *srpt_ctxt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonextern uint16_t srpt_send_msg_depth;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Prototypes.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_ch_scq_hdlr(ibt_cq_hdl_t cq_dhl, void *arg);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_ch_rcq_hdlr(ibt_cq_hdl_t cq_dhl, void *arg);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void srpt_ch_process_iu(srpt_channel_t *ch, srpt_iu_t *iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_alloc()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_channel_t *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_alloc(srpt_target_port_t *tgt, uint8_t port)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_channel_t *ch;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_cq_attr_t cq_attr;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_rc_chan_alloc_args_t ch_args;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint32_t cq_real_size;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ioc_t *ioc;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(tgt != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ioc = tgt->tp_ioc;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(ioc != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch = kmem_zalloc(sizeof (*ch), KM_SLEEP);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_init(&ch->ch_rwlock, NULL, RW_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_init(&ch->ch_reflock, NULL, MUTEX_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_init(&ch->ch_cv_complete, NULL, CV_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_refcnt = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_cv_waiters = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_state = SRPT_CHANNEL_CONNECTING;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_tgt = tgt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_req_lim_delta = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_ti_iu_len = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_attr.cq_size = srpt_send_msg_depth * 2;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_attr.cq_sched = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_attr.cq_flags = IBT_CQ_NO_FLAGS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_alloc_cq(ioc->ioc_ibt_hdl, &cq_attr, &ch->ch_scq_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson &cq_real_size);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L1("ch_alloc, send CQ alloc error (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto scq_alloc_err;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_attr.cq_size = srpt_send_msg_depth + 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_attr.cq_sched = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_attr.cq_flags = IBT_CQ_NO_FLAGS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_alloc_cq(ioc->ioc_ibt_hdl, &cq_attr, &ch->ch_rcq_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson &cq_real_size);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_alloc, receive CQ alloc error (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto rcq_alloc_err;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_set_cq_handler(ch->ch_scq_hdl, srpt_ch_scq_hdlr, ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_set_cq_handler(ch->ch_rcq_hdl, srpt_ch_rcq_hdlr, ch);
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_enable_cq_notify(ch->ch_scq_hdl, IBT_NEXT_COMPLETION);
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_enable_cq_notify(ch->ch_rcq_hdl, IBT_NEXT_COMPLETION);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_flags = IBT_WR_SIGNALED;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* Maker certain initiator can not read/write our memory */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_control = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_hca_port_num = port;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Any SRP IU can result in a number of STMF data buffer transfers
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and those transfers themselves could span multiple initiator
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * buffers. Therefore, the number of send WQE's actually required
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * can vary. Here we assume that on average an I/O will require
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * no more than SRPT_MAX_OUT_IO_PER_CMD send WQE's. In practice
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * this will prevent send work queue overrun, but we will also
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * inform STMF to throttle I/O should the work queue become full.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If the HCA tells us the max outstanding WRs for a channel is
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * lower than our default, use the HCA value.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_sizes.cs_sq = min(ioc->ioc_attr.hca_max_chan_sz,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (srpt_send_msg_depth * SRPT_MAX_OUT_IO_PER_CMD));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_sizes.cs_rq = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_sizes.cs_sq_sgl = 2;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_sizes.cs_rq_sgl = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_scq = ch->ch_scq_hdl;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_rcq = ch->ch_rcq_hdl;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_pd = ioc->ioc_pd_hdl;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_clone_chan = NULL;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch_args.rc_srq = ioc->ioc_srq_hdl;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_alloc_rc_channel(ioc->ioc_ibt_hdl, IBT_ACHAN_USES_SRQ,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson &ch_args, &ch->ch_chan_hdl, &ch->ch_sizes);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_alloc, IBT channel alloc error (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto qp_alloc_err;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Create pool of send WQE entries to map send wqe work IDs
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * to various types (specifically in error cases where OP
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * is not known).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_num_swqe = ch->ch_sizes.cs_sq;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_alloc, number of SWQEs = %u", ch->ch_num_swqe);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe = kmem_zalloc(sizeof (srpt_swqe_t) * ch->ch_num_swqe,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson KM_SLEEP);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_swqe == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_alloc, SWQE alloc error");
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_free_channel(ch->ch_chan_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto qp_alloc_err;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_init(&ch->ch_swqe_lock, NULL, MUTEX_DRIVER, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_head = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (ch->ch_tail = 1; ch->ch_tail < ch->ch_num_swqe -1; ch->ch_tail++) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe[ch->ch_tail].sw_next = ch->ch_tail + 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe[ch->ch_tail].sw_next = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_set_chan_private(ch->ch_chan_hdl, ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonqp_alloc_err:
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_free_cq(ch->ch_rcq_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonrcq_alloc_err:
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_free_cq(ch->ch_scq_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonscq_alloc_err:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_destroy(&ch->ch_cv_complete);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_destroy(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_destroy(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson kmem_free(ch, sizeof (*ch));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_add_ref()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonvoid
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_add_ref(srpt_channel_t *ch)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_refcnt++;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_add_ref, ch (%p), refcnt (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)ch, ch->ch_refcnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(ch->ch_refcnt != 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_release_ref()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * A non-zero value for wait causes thread to block until all references
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * to channel are released.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonvoid
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_release_ref(srpt_channel_t *ch, uint_t wait)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_release_ref, ch (%p), refcnt (%d), wait (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)ch, ch->ch_refcnt, wait);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(ch->ch_refcnt != 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_refcnt--;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_refcnt != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wait) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_cv_waiters++;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while (ch->ch_refcnt != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_wait(&ch->ch_cv_complete, &ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_cv_waiters--;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Last thread out frees the IB resources, locks/conditions and memory
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_cv_waiters > 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* we're not last, wake someone else up */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cv_signal(&ch->ch_cv_complete);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_release_ref - release resources");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_chan_hdl) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_release_ref - free channel");
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_free_channel(ch->ch_chan_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_scq_hdl) {
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_free_cq(ch->ch_scq_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_rcq_hdl) {
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_free_cq(ch->ch_rcq_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * There should be no IU's associated with this
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * channel on the SCSI session.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_session != NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(list_is_empty(&ch->ch_session->ss_task_list));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Currently only have one channel per session, we will
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * need to release a reference when support is added
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * for multi-channel target login.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_free_session(ch->ch_session);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_session = NULL;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson kmem_free(ch->ch_swqe, sizeof (srpt_swqe_t) * ch->ch_num_swqe);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_destroy(&ch->ch_swqe_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_destroy(&ch->ch_reflock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_destroy(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson kmem_free(ch, sizeof (srpt_channel_t));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_disconnect()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonvoid
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_disconnect(srpt_channel_t *ch)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_disconnect, invoked for ch (%p)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_WRITER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If we are already in the process of disconnecting then
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * nothing need be done, CM will call-back into us when done.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_disconnect, called when"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " disconnect in progress");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_state = SRPT_CHANNEL_DISCONNECTING;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Initiate the sending of the CM DREQ message, the private data
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * should be the SRP Target logout IU. We don't really care about
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the remote CM DREP message returned. We issue this in an
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * asynchronous manner and will cleanup when called back by CM.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_close_rc_channel(ch->ch_chan_hdl, IBT_NONBLOCKING,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson NULL, 0, NULL, NULL, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_disconnect, close RC channel"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " err(%d)", status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_cleanup()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonvoid
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_cleanup(srpt_channel_t *ch)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_iu_t *iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_iu_t *next;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_t wc;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_target_port_t *tgt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_channel_t *tgt_ch;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson scsi_task_t *iutask;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_cleanup, invoked for ch(%p), state(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)ch, ch->ch_state);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* add a ref for the channel until we're done */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_add_ref(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tgt = ch->ch_tgt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(tgt != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Make certain the channel is in the target ports list of
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * known channels and remove it (releasing the target
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * ports reference to the channel).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&tgt->tp_ch_list_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tgt_ch = list_head(&tgt->tp_ch_list);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while (tgt_ch != NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (tgt_ch == ch) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson list_remove(&tgt->tp_ch_list, tgt_ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(tgt_ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tgt_ch = list_next(&tgt->tp_ch_list, tgt_ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&tgt->tp_ch_list_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (tgt_ch == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_cleanup, target channel no"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "longer known to target");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_WRITER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_state = SRPT_CHANNEL_DISCONNECTING;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * Don't accept any further incoming requests, and clean
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * up the receive queue. The send queue is left alone
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * so tasks can finish and clean up (whether normally
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * or via abort).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_rcq_hdl) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_set_cq_handler(ch->ch_rcq_hdl, NULL, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while (ibt_poll_cq(ch->ch_rcq_hdl, &wc, 1, NULL) ==
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu = (srpt_iu_t *)(uintptr_t)wc.wc_id;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_cleanup, recovering"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " outstanding RX iu(%p)", (void *)iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ioc_repost_recv_iu(iu->iu_ioc, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Channel reference has not yet been added for this
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * IU, so do not decrement.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Go through the list of outstanding IU for the channel's SCSI
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * session and for each either abort or complete an abort.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_session != NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_session->ss_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu = list_head(&ch->ch_session->ss_task_list);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while (iu != NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson next = list_next(&ch->ch_session->ss_task_list, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch == iu->iu_ch) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (iu->iu_stmf_task == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cmn_err(CE_NOTE,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "ch_cleanup, NULL stmf task");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iutask = iu->iu_stmf_task;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iutask = NULL;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (iutask != NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_cleanup, aborting "
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "task(%p)", (void *)iutask);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_abort(STMF_QUEUE_TASK_ABORT, iutask,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson STMF_ABORTED, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu = next;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_session->ss_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_rsp_comp()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Process a completion for an IB SEND message. A SEND completion
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * is for a SRP response packet sent back to the initiator. It
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * will not have a STMF SCSI task associated with it if it was
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * sent for a rejected IU, or was a task management abort response.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_rsp_comp(srpt_channel_t *ch, srpt_iu_t *iu,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_status_t wc_status)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson stmf_status_t st = STMF_SUCCESS;
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(iu->iu_ch == ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson * Process the completion regardless whether it's a failure or
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson * success. At this point, we've processed as far as we can and
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson * just need to complete the associated task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wc_status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_rsp_comp, WC status err(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wc_status);
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson st = STMF_FAILURE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wc_status != IBT_WC_WR_FLUSHED_ERR) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_disconnect(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If the IU response completion is not associated with
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * with a SCSI task, release the IU to return the resource
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and the reference to the channel it holds.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson atomic_dec_32(&iu->iu_sq_posted_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (iu->iu_stmf_task == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ioc_repost_recv_iu(iu->iu_ioc, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We should not get a SEND completion where the task has already
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * completed aborting and STMF has been informed.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT((iu->iu_flags & SRPT_IU_ABORTED) == 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Let STMF know we are done.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
6527ba5141349c7745f5bbd93541fc251914bffaSue Gleeson stmf_send_status_done(iu->iu_stmf_task, st, STMF_IOF_LPORT_DONE);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_data_comp()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Process an IB completion for a RDMA operation. This completion
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * should be associated with the last RDMA operation for any
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * data buffer transfer.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_data_comp(srpt_channel_t *ch, stmf_data_buf_t *stmf_dbuf,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_status_t wc_status)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ds_dbuf_t *dbuf;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_iu_t *iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(stmf_dbuf != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson dbuf = (srpt_ds_dbuf_t *)stmf_dbuf->db_port_private;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(dbuf != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu = dbuf->db_iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(iu != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(iu->iu_ch == ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If work completion indicates non-flush failure, then
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * start a channel disconnect (asynchronous) and release
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the reference to the IU. The task will be cleaned
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * up with STMF during channel shutdown processing.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wc_status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_data_comp, WC status err(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wc_status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wc_status != IBT_WC_WR_FLUSHED_ERR) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_disconnect(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson atomic_dec_32(&iu->iu_sq_posted_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If STMF has requested this task be aborted, then if this is the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * last I/O operation outstanding, notify STMF the task has been
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * aborted and ignore the completion.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson atomic_dec_32(&iu->iu_sq_posted_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if ((iu->iu_flags & SRPT_IU_STMF_ABORTING) != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson scsi_task_t *abort_task = iu->iu_stmf_task;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_abort(STMF_REQUEUE_TASK_ABORT_LPORT, abort_task,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson STMF_ABORTED, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We should not get an RDMA completion where the task has already
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * completed aborting and STMF has been informed.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT((iu->iu_flags & SRPT_IU_ABORTED) == 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Good completion for last RDMA op associated with a data buffer
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * I/O, if specified initiate status otherwise let STMF know we are
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * done.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_dbuf->db_xfer_status = STMF_SUCCESS;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting DTRACE_SRP_8(xfer__done, srpt_channel_t, ch,
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting ibt_wr_ds_t, &(dbuf->db_sge), srpt_iu_t, iu,
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting ibt_send_wr_t, 0, uint32_t, stmf_dbuf->db_data_size,
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting uint32_t, 0, uint32_t, 0,
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting uint32_t, (stmf_dbuf->db_flags & DB_DIRECTION_TO_RPORT) ? 1 : 0);
7830165bb404e703a4653a49ad9fe110003bde03Charles Ting
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if ((stmf_dbuf->db_flags & DB_SEND_STATUS_GOOD) != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_stp_send_status(dbuf->db_iu->iu_stmf_task, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status == STMF_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_dbuf->db_xfer_status = STMF_FAILURE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_data_xfer_done(dbuf->db_iu->iu_stmf_task, stmf_dbuf, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_scq_hdlr()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_scq_hdlr(ibt_cq_hdl_t cq_hdl, void *arg)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_channel_t *ch = arg;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_t wc[SRPT_SEND_WC_POLL_SIZE];
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_t *wcp;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson int i;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint32_t cq_rearmed = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint32_t entries;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_swqe_t *swqe;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(ch != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* Reference channel for the duration of this call */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_add_ref(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (;;) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_poll_cq(cq_hdl, &wc[0], SRPT_SEND_WC_POLL_SIZE,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson &entries);
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson if (status != IBT_SUCCESS) {
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson if (status != IBT_CQ_EMPTY) {
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson /*
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * This error should not happen. It indicates
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * something abnormal has gone wrong and means
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * either a hardware or programming logic error.
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson */
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson SRPT_DPRINTF_L2(
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson "ch_scq_hdlr, unexpected CQ err(%d)",
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson status);
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson srpt_ch_disconnect(ch);
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson }
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * If we have not rearmed the CQ do so now and poll to
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * eliminate race; otherwise we are done.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (cq_rearmed == 0) {
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_enable_cq_notify(ch->ch_scq_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson IBT_NEXT_COMPLETION);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_rearmed = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson continue;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (wcp = wc, i = 0; i < entries; i++, wcp++) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * A zero work ID indicates this CQE is associated
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * with an intermediate post of a RDMA data transfer
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * operation. Since intermediate data requests are
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * unsignaled, we should only get these if there was
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * an error. No action is required.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wcp->wc_id == 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson continue;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson swqe = ch->ch_swqe + wcp->wc_id;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson switch (swqe->sw_type) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRPT_SWQE_TYPE_RESP:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_rsp_comp(ch, (srpt_iu_t *)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson swqe->sw_addr, wcp->wc_status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRPT_SWQE_TYPE_DATA:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_data_comp(ch, (stmf_data_buf_t *)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson swqe->sw_addr, wcp->wc_status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson default:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_scq_hdlr, bad type(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson swqe->sw_type);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_free_swqe_wrid(ch, wcp->wc_id);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_rcq_hdlr()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_rcq_hdlr(ibt_cq_hdl_t cq_hdl, void *arg)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_channel_t *ch = arg;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_t wc[SRPT_RECV_WC_POLL_SIZE];
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wc_t *wcp;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson int i;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint32_t entries;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_iu_t *iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint_t cq_rearmed = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The channel object will exists while the CQ handler call-back
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * is installed.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(ch != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_add_ref(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * If we know a channel disconnect has started do nothing
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * and let channel cleanup code recover resources from the CQ.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We are not concerned about races with the state transition
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * since the code will do the correct thing either way. This
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * is simply to circumvent rearming the CQ, and it will
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * catch the state next time.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_rcq_hdlr, channel disconnecting");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (;;) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_poll_cq(cq_hdl, &wc[0], SRPT_RECV_WC_POLL_SIZE,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson &entries);
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson if (status != IBT_SUCCESS) {
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson if (status != IBT_CQ_EMPTY) {
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson /*
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * This error should not happen. It indicates
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * something abnormal has gone wrong and means
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * either a hardware or programming logic error.
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson */
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson SRPT_DPRINTF_L2(
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson "ch_rcq_hdlr, unexpected CQ err(%d)",
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson status);
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson srpt_ch_disconnect(ch);
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson break;
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson }
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * If we have not rearmed the CQ do so now and poll to
2840660841c53ef1e1ae476579be5839d1127eabSue Gleeson * eliminate race; otherwise we are done.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (cq_rearmed == 0) {
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_enable_cq_notify(ch->ch_rcq_hdl,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson IBT_NEXT_COMPLETION);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cq_rearmed = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson continue;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (wcp = wc, i = 0; i < entries; i++, wcp++) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Check wc_status before proceeding. If the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * status indicates a channel problem, stop processing.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wcp->wc_status != IBT_WC_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wcp->wc_status == IBT_WC_WR_FLUSHED_ERR) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2(
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "ch_rcq, unexpected"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " wc_status err(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wcp->wc_status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_disconnect(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto done;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* skip IUs with errors */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2(
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "ch_rcq, ERROR comp(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wcp->wc_status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* XXX - verify not leaking IUs */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson continue;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu = (srpt_iu_t *)(uintptr_t)wcp->wc_id;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(iu != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Process the IU.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(wcp->wc_type == IBT_WRC_RECV);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_process_iu(ch, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesondone:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_srp_cmd()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic int
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_srp_cmd(srpt_channel_t *ch, srpt_iu_t *iu)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srp_cmd_req_t *cmd = (srp_cmd_req_t *)iu->iu_buf;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srp_indirect_desc_t *i_desc;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint_t i_di_cnt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint_t i_do_cnt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint8_t do_fmt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint8_t di_fmt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint32_t *cur_desc_off;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson int i;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint8_t addlen;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
191c289b86668766245f78ec1f87557319bc46a1Charles Ting
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_2(task__command, srpt_channel_t, ch, srp_cmd_req_t, cmd);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_ch = ch;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_tag = cmd->cr_tag;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The SRP specification and SAM require support for bi-directional
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * data transfer, so we create a single buffer descriptor list that
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * in the IU buffer that covers the data-in and data-out buffers.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * In practice we will just see unidirectional transfers with either
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * data-in or data out descriptors. If we were to take that as fact,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * we could reduce overhead slightly.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * additional length is a 6-bit number in 4-byte words, so multiply by 4
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * to get bytes.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson addlen = cmd->cr_add_cdb_len & 0x3f; /* mask off 6 bits */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cur_desc_off = (uint32_t *)(void *)&cmd->cr_add_data;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cur_desc_off += addlen; /* 32-bit arithmetic */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_num_rdescs = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_rdescs = (srp_direct_desc_t *)(void *)cur_desc_off;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Examine buffer description for Data In (i.e. data flows
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * to the initiator).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_do_cnt = i_di_cnt = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson di_fmt = cmd->cr_buf_fmt >> 4;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (di_fmt == SRP_DATA_DESC_DIRECT) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_num_rdescs = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cur_desc_off = (uint32_t *)(void *)&iu->iu_rdescs[1];
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else if (di_fmt == SRP_DATA_DESC_INDIRECT) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_desc = (srp_indirect_desc_t *)iu->iu_rdescs;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_di_cnt = b2h32(i_desc->id_table.dd_len) /
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson sizeof (srp_direct_desc_t);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Some initiators like OFED occasionally use the wrong counts,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * so check total to allow for this. NOTE: we do not support
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * reading of the descriptor table from the initiator, so if
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * not all descriptors are in the IU we drop the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (i_di_cnt > (cmd->cr_dicnt + cmd->cr_docnt)) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, remote RDMA of"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " descriptors not supported");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, sizeof entry (%d),"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " i_di_cnt(%d), cr_dicnt(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (uint_t)sizeof (srp_direct_desc_t),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_di_cnt, cmd->cr_dicnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_rdescs = NULL;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson bcopy(&i_desc->id_desc[0], iu->iu_rdescs,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson sizeof (srp_direct_desc_t) * i_di_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_num_rdescs += i_di_cnt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cur_desc_off = (uint32_t *)(void *)&i_desc->id_desc[i_di_cnt];
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Examine buffer description for Data Out (i.e. data flows
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * from the initiator).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson do_fmt = cmd->cr_buf_fmt & 0x0F;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (do_fmt == SRP_DATA_DESC_DIRECT) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (di_fmt == SRP_DATA_DESC_DIRECT) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson bcopy(cur_desc_off, &iu->iu_rdescs[iu->iu_num_rdescs],
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson sizeof (srp_direct_desc_t));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_num_rdescs++;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else if (do_fmt == SRP_DATA_DESC_INDIRECT) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_desc = (srp_indirect_desc_t *)cur_desc_off;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_do_cnt = b2h32(i_desc->id_table.dd_len) /
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson sizeof (srp_direct_desc_t);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Some initiators like OFED occasionally use the wrong counts,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * so check total to allow for this. NOTE: we do not support
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * reading of the descriptor table from the initiator, so if
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * not all descriptors are in the IU we drop the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if ((i_di_cnt + i_do_cnt) > (cmd->cr_dicnt + cmd->cr_docnt)) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, remote RDMA of"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " descriptors not supported");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, sizeof entry (%d),"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " i_do_cnt(%d), cr_docnt(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (uint_t)sizeof (srp_direct_desc_t),
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i_do_cnt, cmd->cr_docnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_rdescs = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson bcopy(&i_desc->id_desc[0], &iu->iu_rdescs[iu->iu_num_rdescs],
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson sizeof (srp_direct_desc_t) * i_do_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_num_rdescs += i_do_cnt;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_tot_xfer_len = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (i = 0; i < iu->iu_num_rdescs; i++) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_rdescs[i].dd_vaddr = b2h64(iu->iu_rdescs[i].dd_vaddr);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_rdescs[i].dd_hdl = b2h32(iu->iu_rdescs[i].dd_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_rdescs[i].dd_len = b2h32(iu->iu_rdescs[i].dd_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_tot_xfer_len += iu->iu_rdescs[i].dd_len;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#ifdef DEBUG
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (srpt_errlevel >= SRPT_LOG_L4) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_srp_cmd, iu->iu_tot_xfer_len (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_tot_xfer_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson for (i = 0; i < iu->iu_num_rdescs; i++) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_srp_cmd, rdescs[%d].dd_vaddr"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " (0x%08llx)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i, (u_longlong_t)iu->iu_rdescs[i].dd_vaddr);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_srp_cmd, rdescs[%d].dd_hdl"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " (0x%08x)", i, iu->iu_rdescs[i].dd_hdl);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_srp_cmd, rdescs[%d].dd_len (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson i, iu->iu_rdescs[i].dd_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_srp_cmd, LUN (0x%08lx)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (unsigned long int) *((uint64_t *)(void *) cmd->cr_lun));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson#endif
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The channel has begun disconnecting, so ignore the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the command returning the IU resources.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Once a SCSI task is allocated and assigned to the IU, it
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * owns those IU resources, which will be held until STMF
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * is notified the task is done (from a lport perspective).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task = stmf_task_alloc(ch->ch_tgt->tp_lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_session->ss_ss, cmd->cr_lun,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRP_CDB_SIZE + (addlen * 4), 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (iu->iu_stmf_task == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Could not allocate, return status to the initiator
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * indicating that we are temporarily unable to process
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * commands. If unable to send, immediately return IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * resource.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, SCSI task allocation failure");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_stp_send_response(iu, STATUS_BUSY, 0, 0, 0,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson NULL, SRPT_NO_FENCE_SEND);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, error(%d) posting error"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " response", status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_port_private = iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (di_fmt != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_WRITE_DATA;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (do_fmt != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_READ_DATA;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson switch (cmd->cr_task_attr) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_ATTR_QTYPE_SIMPLE:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_ATTR_SIMPLE_QUEUE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_ATTR_QTYPE_HEAD_OF_Q:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_ATTR_HEAD_OF_QUEUE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_ATTR_QTYPE_ORDERED:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_ATTR_ORDERED_QUEUE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_ATTR_QTYPE_ACA_Q_TAG:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_ATTR_ACA;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson default:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_cmd, reserved task attr (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson cmd->cr_task_attr);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags |= TF_ATTR_ORDERED_QUEUE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_additional_flags = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_priority = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_mgmt_function = TM_NONE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_max_nbufs = STMF_BUFS_MAX;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_expected_xfer_length = iu->iu_tot_xfer_len;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_csn_size = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson bcopy(cmd->cr_cdb, iu->iu_stmf_task->task_cdb,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRP_CDB_SIZE);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (addlen != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson bcopy(&cmd->cr_add_data,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_cdb + SRP_CDB_SIZE,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson addlen * 4);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Add the IU/task to the session and post to STMF. The task will
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * remain in the session's list until STMF is informed by SRP that
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * it is done with the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_3(scsi__command, srpt_channel_t, iu->iu_ch,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting scsi_task_t, iu->iu_stmf_task, srp_cmd_req_t, cmd);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_add_task(ch->ch_session, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_srp_cmd, new task (%p) posted",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)iu->iu_stmf_task);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_post_task(iu->iu_stmf_task, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_task_mgmt_abort()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson *
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Returns 0 on success, indicating we've sent a management response.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Returns !0 to indicate failure; the IU should be reposted.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic ibt_status_t
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_task_mgmt_abort(srpt_channel_t *ch, srpt_iu_t *iu,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint64_t tag_to_abort)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_session_t *session = ch->ch_session;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_iu_t *ss_iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Locate the associated task (tag_to_abort) in the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * session's active task list.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&session->ss_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ss_iu = list_head(&session->ss_task_list);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson while (ss_iu != NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&ss_iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if ((tag_to_abort == ss_iu->iu_tag)) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ss_iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ss_iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ss_iu = list_next(&session->ss_task_list, ss_iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&session->ss_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Take appropriate action based on state of task
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * to be aborted:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * 1) No longer exists - do nothing.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * 2) Previously aborted or status queued - do nothing.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * 3) Otherwise - initiate abort.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ss_iu == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto send_mgmt_resp;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&ss_iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if ((ss_iu->iu_flags & (SRPT_IU_STMF_ABORTING |
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_IU_ABORTED | SRPT_IU_RESP_SENT)) != 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ss_iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto send_mgmt_resp;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Set aborting flag and notify STMF of abort request. No
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * additional I/O will be queued for this IU.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_task_mgmt_abort, task found");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ss_iu->iu_flags |= SRPT_IU_SRP_ABORTING;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ss_iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_abort(STMF_QUEUE_TASK_ABORT,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ss_iu->iu_stmf_task, STMF_ABORTED, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsend_mgmt_resp:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_stp_send_mgmt_response(iu, SRP_TM_SUCCESS,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_FENCE_SEND);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_task_mgmt_abort, err(%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " posting abort response", status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_srp_task_mgmt()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic int
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_srp_task_mgmt(srpt_channel_t *ch, srpt_iu_t *iu)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srp_tsk_mgmt_t *tsk = (srp_tsk_mgmt_t *)iu->iu_buf;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint8_t tm_fn;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_srp_task_mgmt, SRP TASK MGMT func(%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tsk->tm_function);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
191c289b86668766245f78ec1f87557319bc46a1Charles Ting /*
191c289b86668766245f78ec1f87557319bc46a1Charles Ting * Both tag and lun fileds have the same corresponding offsets
191c289b86668766245f78ec1f87557319bc46a1Charles Ting * in both srp_tsk_mgmt_t and srp_cmd_req_t structures. The
191c289b86668766245f78ec1f87557319bc46a1Charles Ting * casting will allow us to use the same dtrace translator.
191c289b86668766245f78ec1f87557319bc46a1Charles Ting */
191c289b86668766245f78ec1f87557319bc46a1Charles Ting DTRACE_SRP_2(task__command, srpt_channel_t, ch,
191c289b86668766245f78ec1f87557319bc46a1Charles Ting srp_cmd_req_t, (srp_cmd_req_t *)tsk);
191c289b86668766245f78ec1f87557319bc46a1Charles Ting
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_ch = ch;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_tag = tsk->tm_tag;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Task management aborts are processed directly by the SRP driver;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * all other task management requests are handed off to STMF.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson switch (tsk->tm_function) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_MGMT_ABORT_TASK:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Initiate SCSI transport protocol specific task abort
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * logic.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_ch_task_mgmt_abort(ch, iu, tsk->tm_task_tag);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* repost this IU */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson } else {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_MGMT_ABORT_TASK_SET:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tm_fn = TM_ABORT_TASK_SET;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_MGMT_CLEAR_TASK_SET:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tm_fn = TM_CLEAR_TASK_SET;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_MGMT_LUN_RESET:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tm_fn = TM_LUN_RESET;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_TSK_MGMT_CLEAR_ACA:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson tm_fn = TM_CLEAR_ACA;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson default:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * SRP does not support the requested task management
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * function; return a not supported status in the response.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_task_mgmt, SRP task mgmt fn(%d)"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " not supported", tsk->tm_function);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_stp_send_mgmt_response(iu,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRP_TM_NOT_SUPPORTED, SRPT_NO_FENCE_SEND);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_task_mgmt, err(%d) posting"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " response", status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * The channel has begun disconnecting, so ignore the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * the command returning the IU resources.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Once a SCSI mgmt task is allocated and assigned to the IU, it
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * owns those IU resources, which will be held until we inform
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * STMF that we are done with the task (from an lports perspective).
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task = stmf_task_alloc(ch->ch_tgt->tp_lport,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_session->ss_ss, tsk->tm_lun, 0, STMF_TASK_EXT_NONE);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (iu->iu_stmf_task == NULL) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Could not allocate, return status to the initiator
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * indicating that we are temporarily unable to process
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * commands. If unable to send, immediately return IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * resource.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_task_mgmt, SCSI task allocation"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " failure");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_stp_send_response(iu, STATUS_BUSY, 0, 0, 0,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson NULL, SRPT_NO_FENCE_SEND);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_srp_task_mgmt, err(%d) posting"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson "busy response", status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /* repost the IU */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (1);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_port_private = iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_flags = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_additional_flags =
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson TASK_AF_NO_EXPECTED_XFER_LENGTH;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_priority = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_mgmt_function = tm_fn;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_max_nbufs = STMF_BUFS_MAX;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_expected_xfer_length = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iu->iu_stmf_task->task_csn_size = 0;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Add the IU/task to the session and post to STMF. The task will
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * remain in the session's list until STMF is informed by SRP that
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * it is done with the task.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_add_task(ch->ch_session, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_srp_task_mgmt, new mgmt task(%p) posted",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)iu->iu_stmf_task);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson stmf_post_task(iu->iu_stmf_task, NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_process_iu()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonstatic void
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_process_iu(srpt_channel_t *ch, srpt_iu_t *iu)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_iu_data_t *iud;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson int status = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * IU adds reference to channel which will represent a
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * a reference by STMF. If for whatever reason the IU
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * is not handed off to STMF, then this reference will be
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * released. Otherwise, the reference will be released when
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * SRP informs STMF that the associated SCSI task is done.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_add_ref(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Validate login RC channel state. Normally active, if
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * not active then we need to handle a possible race between the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * receipt of a implied RTU and CM calling back to notify of the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * state transition.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson goto repost_iu;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson iud = iu->iu_buf;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson switch (iud->rx_iu.srp_op) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_IU_CMD:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_ch_srp_cmd(ch, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_IU_TASK_MGMT:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = srpt_ch_srp_task_mgmt(ch, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_IU_I_LOGOUT:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L3("ch_process_iu, SRP INITIATOR LOGOUT");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Initiators should logout by issuing a CM disconnect
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * request (DREQ) with the logout IU in the private data;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * however some initiators have been known to send the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * IU in-band, if this happens just initiate the logout.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * Note that we do not return a response as per the
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * specification.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_stp_logout(ch);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_IU_AER_RSP:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson case SRP_IU_CRED_RSP:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson default:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson /*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * We don't send asynchronous events or ask for credit
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * adjustments, so nothing need be done. Log we got an
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * unexpected IU but then just repost the IU to the SRQ.
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_process_iu, invalid IU from initiator,"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " IU opcode(%d)", iud->rx_iu.srp_op);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson break;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status == 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonrepost_iu:
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("process_iu: reposting iu %p", (void *)iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ioc_repost_recv_iu(iu->iu_ioc, iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&iu->iu_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_release_ref(ch, 0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_post_send
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonibt_status_t
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_post_send(srpt_channel_t *ch, srpt_iu_t *iu, uint32_t len,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint_t fence)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_status_t status;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_send_wr_t wr;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wr_ds_t ds;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson uint_t posted;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(ch != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(iu != NULL);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ASSERT(mutex_owned(&iu->iu_lock));
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_enter(&ch->ch_rwlock, RW_READER);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_state == SRPT_CHANNEL_DISCONNECTING) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_post_send, bad ch state (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_state);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (IBT_FAILURE);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson rw_exit(&ch->ch_rwlock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_id = srpt_ch_alloc_swqe_wrid(ch, SRPT_SWQE_TYPE_RESP,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (void *)iu);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (wr.wr_id == 0) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_post_send, queue full");
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (IBT_FAILURE);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson atomic_inc_32(&iu->iu_sq_posted_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_flags = IBT_WR_SEND_SIGNAL;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (fence == SRPT_FENCE_SEND) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_flags |= IBT_WR_SEND_FENCE;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_opcode = IBT_WRC_SEND;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_trans = IBT_RC_SRV;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_nds = 1;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wr.wr_sgl = &ds;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ds.ds_va = iu->iu_sge.ds_va;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ds.ds_key = iu->iu_sge.ds_key;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ds.ds_len = len;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L4("ch_post_send, posting SRP response to channel"
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " ds.ds_va (0x%16llx), ds.ds_key (0x%08x), "
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson " ds.ds_len (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson (u_longlong_t)ds.ds_va, ds.ds_key, ds.ds_len);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status = ibt_post_send(ch->ch_chan_hdl, &wr, 1, &posted);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (status != IBT_SUCCESS) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson SRPT_DPRINTF_L2("ch_post_send, post_send failed (%d)",
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson atomic_dec_32(&iu->iu_sq_posted_cnt);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_ch_free_swqe_wrid(ch, wr.wr_id);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (status);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (IBT_SUCCESS);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_alloc_swqe_wrid()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonibt_wrid_t
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_alloc_swqe_wrid(srpt_channel_t *ch,
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson srpt_swqe_type_t wqe_type, void *addr)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ibt_wrid_t wrid;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&ch->ch_swqe_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson if (ch->ch_head == ch->ch_tail) {
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_swqe_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return ((ibt_wrid_t)0);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson }
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson wrid = (ibt_wrid_t)ch->ch_head;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe[ch->ch_head].sw_type = wqe_type;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe[ch->ch_head].sw_addr = addr;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_head = ch->ch_swqe[ch->ch_head].sw_next;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe_posted++;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_swqe_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson return (wrid);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson/*
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson * srpt_ch_free_swqe_wrid()
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson */
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonvoid
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleesonsrpt_ch_free_swqe_wrid(srpt_channel_t *ch, ibt_wrid_t id)
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson{
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_enter(&ch->ch_swqe_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe[ch->ch_tail].sw_next = id;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_tail = (uint32_t)id;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson ch->ch_swqe_posted--;
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson mutex_exit(&ch->ch_swqe_lock);
1bdd6c0e3710e91cb1f31aa78de33cb638494480Sue Gleeson}