a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER START
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The contents of this file are subject to the terms of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Common Development and Distribution License (the "License").
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You may not use this file except in compliance with the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * or http://www.opensolaris.org/os/licensing.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * See the License for the specific language governing permissions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and limitations under the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If applicable, add the following below this CDDL HEADER, with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER END
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
c2b2c94b55bdcff203640921e4879b4b968d8183Peter Gill * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/conf.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/file.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sunddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/cpuvar.h>
a668b114487acbb725f522170849c39f8e844673Priya Krishnan#include <sys/sdt.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/socket.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/strsubr.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/socketvar.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sysmacros.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm_so.h>
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng#include <hd_crc.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapextern idm_transport_t idm_transport_list[];
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng/*
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng * -1 - uninitialized
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng * 0 - applicable
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng * others - NA
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng */
d4b0f84707225327c617c6838361d3cfb7762b34Jack Mengstatic int iscsi_crc32_hd = -1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_async_evt_hdr_t *async_evt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If we are in full-featured mode then route SCSI-related
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * commands to the appropriate function vector
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_timestamp = ddi_get_lbolt();
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_state_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ic->ic_ffp && ic->ic_pdu_events == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_state_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idm_pdu_rx_forward_ffp(ic, pdu) == B_TRUE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Forwarded SCSI-related commands */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_state_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If we get here with a SCSI-related PDU then we are not in
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * full-feature mode and the PDU is a protocol error (SCSI command
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * PDU's may sometimes be an exception, see below). All
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * non-SCSI PDU's get treated them the same regardless of whether
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * we are in full-feature mode.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Look at the opcode and in some cases the PDU status and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * determine the appropriate event to send to the connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * state machine. Generate the event, passing the PDU as data.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If the current connection state allows reception of the event
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the PDU will be submitted to the IDM client for processing,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * otherwise the PDU will be dropped.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (IDM_PDU_OPCODE(pdu)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_LOGIN_CMD:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(login__command, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_login_hdr_t *, (iscsi_login_hdr_t *)pdu->isp_hdr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, CE_LOGIN_RCV, (uintptr_t)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_LOGIN_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_parse_login_rsp(ic, pdu, /* RX */ B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_LOGOUT_CMD:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(logout__command, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_logout_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_logout_hdr_t *)pdu->isp_hdr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_parse_logout_req(ic, pdu, /* RX */ B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_LOGOUT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_parse_logout_rsp(ic, pdu, /* RX */ B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_ASYNC_EVENT:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap async_evt = (iscsi_async_evt_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap switch (async_evt->async_event) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, CE_ASYNC_LOGOUT_RCV,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uintptr_t)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, CE_ASYNC_DROP_CONN_RCV,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uintptr_t)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, CE_ASYNC_DROP_ALL_CONN_RCV,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uintptr_t)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_ASYNC_EVENT_SCSI_EVENT:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, CE_MISC_RX,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uintptr_t)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_CMD:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Consider this scenario: We are a target connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in "in login" state and a "login success sent" event has
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * been generated but not yet handled. Since we've sent
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the login response but we haven't actually transitioned
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to FFP mode we might conceivably receive a SCSI command
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * from the initiator before we are ready. We are actually
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in FFP we just don't know it yet -- to address this we
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * can generate an event corresponding to the SCSI command.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * At the point when the event is handled by the state
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * machine the login request will have been handled and we
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * should be in FFP. If we are not in FFP by that time
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * we can reject the SCSI command with a protocol error.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This scenario only applies to the target.
a668b114487acbb725f522170849c39f8e844673Priya Krishnan *
a668b114487acbb725f522170849c39f8e844673Priya Krishnan * Handle dtrace probe in iscsit so we can find all the
a668b114487acbb725f522170849c39f8e844673Priya Krishnan * pieces of the CDB
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_DATA:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(data__receive, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_data_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_data_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan break;
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_SCSI_TASK_MGT_MSG:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(task__command, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_scsi_task_mgt_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_scsi_task_mgt_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan break;
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_NOOP_OUT:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(nop__receive, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_nop_out_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_nop_out_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan break;
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_TEXT_CMD:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(text__command, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_text_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_text_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan break;
a668b114487acbb725f522170849c39f8e844673Priya Krishnan /* Initiator PDU's */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_DATA_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_RTT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SNACK_CMD:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_NOOP_IN:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_TEXT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_REJECT_MSG:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Validate received PDU against current state */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, CE_MISC_RX,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uintptr_t)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_state_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_transport_ops->it_tx_pdu)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapboolean_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If this is an FFP request, call the appropriate handler
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and return B_TRUE, otherwise return B_FALSE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (IDM_PDU_OPCODE(pdu)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_CMD:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_conn_ops.icb_rx_scsi_cmd)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_DATA:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(data__receive, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_data_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_data_hdr_t *)pdu->isp_hdr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_transport_ops->it_rx_dataout)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_SCSI_TASK_MGT_MSG:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(task__command, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_scsi_task_mgt_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_scsi_task_mgt_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan return (B_TRUE);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_NOOP_OUT:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(nop__receive, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_nop_out_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_nop_out_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan return (B_TRUE);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_TEXT_CMD:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(text__command, idm_conn_t *, ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_text_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_text_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan return (B_TRUE);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan /* Initiator only */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan case ISCSI_OP_SCSI_RSP:
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (*ic->ic_conn_ops.icb_rx_scsi_rsp)(ic, pdu);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_DATA_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_transport_ops->it_rx_datain)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_RTT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_transport_ops->it_rx_rtt)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_TEXT_RSP:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case ISCSI_OP_NOOP_IN:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_FALSE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*NOTREACHED*/
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Some PDU's specific to FFP get special handling. This function
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * will normally never be called in FFP with an FFP PDU since this
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * is a slow path but in can happen on the target side during
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the transition to FFP. We primarily call
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_pdu_rx_forward_ffp here to avoid code duplication.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idm_pdu_rx_forward_ffp(ic, pdu) == B_FALSE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Non-FFP PDU, use generic RC handler
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu, boolean_t rx)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_login_rsp_hdr_t *login_rsp =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (iscsi_login_rsp_hdr_t *)login_rsp_pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_event_t new_event;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (login_rsp->status_class == ISCSI_STATUS_CLASS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!(login_rsp->flags & ISCSI_FLAG_LOGIN_CONTINUE) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (ISCSI_LOGIN_NEXT_STAGE(login_rsp->flags) ==
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ISCSI_FULL_FEATURE_PHASE)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = (rx ? CE_LOGIN_SUCCESS_RCV :
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap CE_LOGIN_SUCCESS_SND);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = (rx ? CE_MISC_RX : CE_MISC_TX);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = (rx ? CE_LOGIN_FAIL_RCV : CE_LOGIN_FAIL_SND);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rx) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, new_event, (uintptr_t)login_rsp_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_tx_pdu_event(ic, new_event, (uintptr_t)login_rsp_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, boolean_t rx)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_logout_hdr_t *logout_req =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (iscsi_logout_hdr_t *)logout_req_pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_event_t new_event;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t reason =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (logout_req->flags & ISCSI_FLAG_LOGOUT_REASON_MASK);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * For a normal logout (close connection or close session) IDM
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * will terminate processing of all tasks completing the tasks
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * back to the client with a status indicating the connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * was logged out. These tasks do not get completed.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * For a "close connection for recovery logout) IDM suspends
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * processing of all tasks and completes them back to the client
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * with a status indicating connection was logged out for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * recovery. Both initiator and target hang onto these tasks.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * When we add ERL2 support IDM will need to provide mechanisms
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to change the task and buffer associations to a new connection.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This code doesn't address the possibility of MC/S. We'll
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * need to decide how the separate connections get handled
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in that case. One simple option is to make the client
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * generate the events for the other connections.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (rx ? CE_LOGOUT_SESSION_RCV : CE_LOGOUT_SESSION_SND);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else if ((reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (reason == ISCSI_LOGOUT_REASON_RECOVERY)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Check logout CID against this connection's CID */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ntohs(logout_req->cid) == ic->ic_login_cid) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Logout is for this connection */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = (rx ? CE_LOGOUT_THIS_CONN_RCV :
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap CE_LOGOUT_THIS_CONN_SND);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Logout affects another connection. This is not
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * a relevant event for this connection so we'll
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * just treat it as a normal PDU event. Client
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * will need to lookup the other connection and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * generate the event.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = (rx ? CE_MISC_RX : CE_MISC_TX);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Invalid reason code */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = (rx ? CE_RX_PROTOCOL_ERROR : CE_TX_PROTOCOL_ERROR);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rx) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, new_event, (uintptr_t)logout_req_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_tx_pdu_event(ic, new_event, (uintptr_t)logout_req_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *logout_rsp_pdu, boolean_t rx)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_event_t new_event;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_logout_rsp_hdr_t *logout_rsp =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (iscsi_logout_rsp_hdr_t *)logout_rsp_pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (logout_rsp->response == ISCSI_STATUS_CLASS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = rx ? CE_LOGOUT_SUCCESS_RCV : CE_LOGOUT_SUCCESS_SND;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_event = rx ? CE_LOGOUT_FAIL_RCV : CE_LOGOUT_FAIL_SND;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rx) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rx_pdu_event(ic, new_event, (uintptr_t)logout_rsp_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_tx_pdu_event(ic, new_event, (uintptr_t)logout_rsp_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_svc_conn_create()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Transport-agnostic service connection creation, invoked from the transport
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * layer.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_svc_conn_create(idm_svc_t *is, idm_transport_type_t tt,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t **ic_result)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States /*
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * Skip some work if we can already tell we are going offline.
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * Otherwise we will destroy this connection later as part of
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * shutting down the svc.
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&is->is_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (!is->is_online) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&is->is_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&is->is_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic = idm_conn_create_common(CONN_TYPE_TGT, tt,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &is->is_svc_req.sr_conn_ops);
e97fb1537da57d70dafde456e25bbd6bcc839475Peter Cudhea - Sun Microsystems - Burlington, MA United States if (ic == NULL) {
e97fb1537da57d70dafde456e25bbd6bcc839475Peter Cudhea - Sun Microsystems - Burlington, MA United States return (IDM_STATUS_FAIL);
e97fb1537da57d70dafde456e25bbd6bcc839475Peter Cudhea - Sun Microsystems - Burlington, MA United States }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_svc_binding = is;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Prepare connection state machine
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((rc = idm_conn_sm_init(ic)) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_destroy_common(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (rc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *ic_result = ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idm.idm_global_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_insert_tail(&idm.idm_tgt_conn_list, ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_tgt_conn_count++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idm.idm_global_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_svc_conn_destroy(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idm.idm_global_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_remove(&idm.idm_tgt_conn_list, ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_tgt_conn_count--;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idm.idm_global_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ic->ic_transport_private != NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_ops->it_tgt_conn_destroy(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_destroy_common(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_conn_create_common()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Allocate and initialize IDM connection context
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_conn_t *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_conn_create_common(idm_conn_type_t conn_type, idm_transport_type_t tt,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_ops_t *conn_ops)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_t *it;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_type_t type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it = &idm_transport_list[type];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((it->it_ops != NULL) && (it->it_type == tt))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(it->it_type == tt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (it->it_type != tt)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic = kmem_zalloc(sizeof (idm_conn_t), KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Initialize data */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan ic->ic_target_name[0] = '\0';
a668b114487acbb725f522170849c39f8e844673Priya Krishnan ic->ic_initiator_name[0] = '\0';
a668b114487acbb725f522170849c39f8e844673Priya Krishnan ic->ic_isid[0] = '\0';
a668b114487acbb725f522170849c39f8e844673Priya Krishnan ic->ic_tsih[0] = '\0';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_conn_type = conn_type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_conn_ops = *conn_ops;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_ops = it->it_ops;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_type = tt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_private = NULL; /* Set by transport service */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_internal_cid = idm_cid_alloc();
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ic->ic_internal_cid == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(ic, sizeof (idm_conn_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_init(&ic->ic_mutex, NULL, MUTEX_DEFAULT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_init(&ic->ic_cv, NULL, CV_DEFAULT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_refcnt_init(&ic->ic_refcnt, ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_conn_destroy_common(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_conn_sm_fini(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_refcnt_destroy(&ic->ic_refcnt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_destroy(&ic->ic_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_destroy(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_cid_free(ic->ic_internal_cid);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(ic, sizeof (idm_conn_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Invoked from the SM as a result of client's invocation of
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_ini_conn_connect()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_ini_conn_finish(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* invoke transport-specific connection */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (ic->ic_transport_ops->it_ini_conn_connect(ic));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_tgt_conn_finish(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = idm_notify_client(ic, CN_CONNECT_ACCEPT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc != IDM_STATUS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_REJECT);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Target client is ready to receive a login, start connection */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (ic->ic_transport_ops->it_tgt_conn_connect(ic));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_transport_t *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_transport_lookup(idm_conn_req_t *cr)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_type_t type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_t *it;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_caps_t caps;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Make sure all available transports are setup. We call this now
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * instead of at initialization time in case IB has become available
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * since we started (hotplug, etc).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng idm_transport_setup(cr->cr_li, cr->cr_boot_conn);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Determine the transport for this connection */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it = &idm_transport_list[type];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (it->it_ops == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* transport is not registered */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (it->it_ops->it_conn_is_capable(cr, &caps)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (it);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (NULL); /* Make gcc happy */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Mengidm_transport_setup(ldi_ident_t li, boolean_t boot_conn)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_type_t type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_t *it;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it = &idm_transport_list[type];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * We may want to store the LDI handle in the idm_svc_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and then allow multiple calls to ldi_open_by_name. This
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * would enable the LDI code to track who has the device open
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * which could be useful in the case where we have multiple
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * services and perhaps also have initiator and target opening
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the transport simultaneously. For now we stick with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * plan.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (it->it_ops == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* transport is not ready, try to initialize it */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (it->it_type == IDM_TRANSPORT_TYPE_SOCKETS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_init(it);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng if (boot_conn == B_TRUE) {
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng /*
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng * iSCSI boot doesn't need iSER.
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng * Open iSER here may drive IO to
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng * a failed session and cause
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng * deadlock
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng */
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng continue;
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = ldi_open_by_name(it->it_device_path,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap FREAD | FWRITE, kcred, &it->it_ldi_hdl, li);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If the open is successful we will have
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * filled in the LDI handle in the transport
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * table and we expect that the transport
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * registered itself.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it->it_ldi_hdl = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_transport_teardown()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_transport_type_t type;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_transport_t *it;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mutex_owned(&idm.idm_global_mutex));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Caller holds the IDM global mutex */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap it = &idm_transport_list[type];
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* If we have an open LDI handle on this driver, close it */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (it->it_ldi_hdl != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) ldi_close(it->it_ldi_hdl, FNDELAY, kcred);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap it->it_ldi_hdl = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * ID pool code. We use this to generate unique structure identifiers without
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * searching the existing structures. This avoids the need to lock entire
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * sets of structures at inopportune times. Adapted from the CIFS server code.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * A pool of IDs is a pool of 16 bit numbers. It is implemented as a bitmap.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * A bit set to '1' indicates that that particular value has been allocated.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The allocation process is done shifting a bit through the whole bitmap.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The current position of that index bit is kept in the idm_idpool_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * structure and represented by a byte index (0 to buffer size minus 1) and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * a bit index (0 to 7).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The pools start with a size of 8 bytes or 64 IDs. Each time the pool runs
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * out of IDs its current size is doubled until it reaches its maximum size
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * (8192 bytes or 65536 IDs). The IDs 0 and 65535 are never given out which
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * means that a pool can have a maximum number of 65534 IDs available.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_idpool_increment(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_idpool_t *pool)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t *new_pool;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t new_size;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_size = pool->id_size * 2;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (new_size <= IDM_IDPOOL_MAX_SIZE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (new_pool) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(new_pool, new_size / 8);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bcopy(pool->id_pool, new_pool, pool->id_size / 8);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(pool->id_pool, pool->id_size / 8);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_pool = new_pool;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_free_counter += new_size - pool->id_size;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_max_free_counter += new_size - pool->id_size;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_size = new_size;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_idx_msk = (new_size / 8) - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (new_size >= IDM_IDPOOL_MAX_SIZE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* id -1 made unavailable */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_pool[pool->id_idx_msk] = 0x80;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_free_counter--;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_max_free_counter--;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_idpool_constructor
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function initializes the pool structure provided.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_idpool_create(idm_idpool_t *pool)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_magic != IDM_IDPOOL_MAGIC);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_size = IDM_IDPOOL_MIN_SIZE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_idx_msk = (IDM_IDPOOL_MIN_SIZE / 8) - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_free_counter = IDM_IDPOOL_MIN_SIZE - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_max_free_counter = IDM_IDPOOL_MIN_SIZE - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_bit = 0x02;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_bit_idx = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_idx = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_pool = (uint8_t *)kmem_alloc((IDM_IDPOOL_MIN_SIZE / 8),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(pool->id_pool, (IDM_IDPOOL_MIN_SIZE / 8));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* -1 id made unavailable */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_pool[0] = 0x01; /* id 0 made unavailable */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_magic = IDM_IDPOOL_MAGIC;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_idpool_destructor
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function tears down and frees the resources associated with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * pool provided.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_idpool_destroy(idm_idpool_t *pool)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_free_counter == pool->id_max_free_counter);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_magic = (uint32_t)~IDM_IDPOOL_MAGIC;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_destroy(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(pool->id_pool, (size_t)(pool->id_size / 8));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_idpool_alloc
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function allocates an ID from the pool provided.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_idpool_alloc(idm_idpool_t *pool, uint16_t *id)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t i;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t bit;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t bit_idx;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t byte;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((pool->id_free_counter == 0) && idm_idpool_increment(pool)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i = pool->id_size;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (i) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bit = pool->id_bit;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bit_idx = pool->id_bit_idx;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte = pool->id_pool[pool->id_idx];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (bit) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (byte & bit) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bit = bit << 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bit_idx++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_pool[pool->id_idx] |= bit;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_free_counter--;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_bit = bit;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_bit_idx = bit_idx;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_bit = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_bit_idx = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_idx++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_idx &= pool->id_idx_msk;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap --i;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This section of code shouldn't be reached. If there are IDs
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * available and none could be found there's a problem.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_idpool_free
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function frees the ID provided.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_idpool_free(idm_idpool_t *pool, uint16_t id)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(id != 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(id != 0xFFFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pool->id_pool[id >> 3] & (1 << (id & 7))) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_pool[id >> 3] &= ~(1 << (id & 7));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pool->id_free_counter++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pool->id_free_counter <= pool->id_max_free_counter);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Freeing a free ID. */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&pool->id_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapuint32_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_cid_alloc(void)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * ID pool works with 16-bit identifiers right now. That should
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * be plenty since we will probably never have more than 2^16
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * connections simultaneously.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint16_t cid16;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idm_idpool_alloc(&idm.idm_conn_id_pool, &cid16) == -1) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0); /* Fail */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return ((uint32_t)cid16);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_cid_free(uint32_t cid)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_idpool_free(&idm.idm_conn_id_pool, (uint16_t)cid);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Code for generating the header and data digests
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This is the CRC-32C table
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Generated with:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * width = 32 bits
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * poly = 0x1EDC6F41
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * reflect input bytes = true
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * reflect output bytes = true
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapuint32_t idm_crc32c_table[256] =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * iscsi_crc32c - Steps through buffer one byte at at time, calculates
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * reflected crc using table.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapuint32_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_crc32c(void *address, unsigned long length)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t *buffer = address;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t crc = 0xffffffff, result;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _BIG_ENDIAN
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t byte0, byte1, byte2, byte3;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(address != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng if (iscsi_crc32_hd == -1) {
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng if (hd_crc32_avail((uint32_t *)idm_crc32c_table) == B_TRUE) {
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng iscsi_crc32_hd = 0;
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng } else {
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng iscsi_crc32_hd = 1;
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng }
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng }
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng if (iscsi_crc32_hd == 0)
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng return (HW_CRC32(buffer, length, crc));
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (length--) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc = idm_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (crc >> 8);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap result = crc ^ 0xffffffff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _BIG_ENDIAN
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte0 = (uint8_t)(result & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte1 = (uint8_t)((result >> 8) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte2 = (uint8_t)((result >> 16) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte3 = (uint8_t)((result >> 24) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif /* _BIG_ENDIAN */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (result);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_crc32c_continued - Continues stepping through buffer one
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * byte at at time, calculates reflected crc using table.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapuint32_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_crc32c_continued(void *address, unsigned long length, uint32_t crc)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t *buffer = address;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t result;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _BIG_ENDIAN
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t byte0, byte1, byte2, byte3;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(address != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng if (iscsi_crc32_hd == -1) {
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng if (hd_crc32_avail((uint32_t *)idm_crc32c_table) == B_TRUE) {
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng iscsi_crc32_hd = 0;
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng } else {
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng iscsi_crc32_hd = 1;
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng }
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng }
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng if (iscsi_crc32_hd == 0)
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng return (HW_CRC32_CONT(buffer, length, crc));
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng
d4b0f84707225327c617c6838361d3cfb7762b34Jack Meng
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _BIG_ENDIAN
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte0 = (uint8_t)((crc >> 24) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte1 = (uint8_t)((crc >> 16) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte2 = (uint8_t)((crc >> 8) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte3 = (uint8_t)(crc & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc = crc ^ 0xffffffff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (length--) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc = idm_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (crc >> 8);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap result = crc ^ 0xffffffff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _BIG_ENDIAN
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte0 = (uint8_t)(result & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte1 = (uint8_t)((result >> 8) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte2 = (uint8_t)((result >> 16) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap byte3 = (uint8_t)((result >> 24) & 0xFF);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (result);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_task_constructor(void *hdl, void *arg, int flags)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt = (idm_task_t *)hdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t next_task;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_init(&idt->idt_mutex, NULL, MUTEX_DEFAULT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Find the next free task ID */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rw_enter(&idm.idm_taskid_table_lock, RW_WRITER);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap next_task = idm.idm_taskid_next;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (idm.idm_taskid_table[next_task]) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap next_task++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (next_task == idm.idm_taskid_max)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap next_task = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (next_task == idm.idm_taskid_next) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rw_exit(&idm.idm_taskid_table_lock);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_taskid_table[next_task] = idt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_taskid_next = (next_task + 1) % idm.idm_taskid_max;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rw_exit(&idm.idm_taskid_table_lock);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt->idt_tt = next_task;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_create(&idt->idt_inbufv, sizeof (idm_buf_t),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offsetof(idm_buf_t, idb_buflink));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_create(&idt->idt_outbufv, sizeof (idm_buf_t),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offsetof(idm_buf_t, idb_buflink));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_refcnt_init(&idt->idt_refcnt, idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Set the transport header pointer explicitly. This removes the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * need for per-transport header allocation, which simplifies cache
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * init considerably. If at a later date we have an additional IDM
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * transport that requires a different size, we'll revisit this.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt->idt_transport_hdr = (void *)(idt + 1); /* pointer arithmetic */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan idt->idt_flags = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_task_destructor(void *hdl, void *arg)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt = (idm_task_t *)hdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Remove the task from the ID table */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rw_enter(&idm.idm_taskid_table_lock, RW_WRITER);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_taskid_table[idt->idt_tt] = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rw_exit(&idm.idm_taskid_table_lock);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* free the inbuf and outbuf */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_refcnt_destroy(&idt->idt_refcnt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_destroy(&idt->idt_inbufv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_destroy(&idt->idt_outbufv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The final call to idm_task_rele may happen with the task
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * mutex held which may invoke this destructor immediately.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Stall here until the task mutex owner lets go.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_destroy(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_listbuf_insert searches from the back of the list looking for the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * insertion point.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_listbuf_insert(list_t *lst, idm_buf_t *buf)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* iterate through the list to find the insertion point */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (idb = list_tail(lst); idb != NULL; idb = list_prev(lst, idb)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb->idb_bufoffset < buf->idb_bufoffset) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_insert_after(lst, idb, buf);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* add the buf to the head of the list */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_insert_head(lst, buf);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*ARGSUSED*/
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_wd_thread(void *arg)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t wake_time = SEC_TO_TICK(IDM_WD_INTERVAL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap clock_t idle_time;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a41f981938219ee4d436d2bb22dddcefa57a1a4fJames Moore /* Record the thread id for thread_join() */
a41f981938219ee4d436d2bb22dddcefa57a1a4fJames Moore idm.idm_wd_thread_did = curthread->t_did;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idm.idm_global_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_wd_thread_running = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&idm.idm_wd_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (idm.idm_wd_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (ic = list_head(&idm.idm_tgt_conn_list);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic != NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic = list_next(&idm.idm_tgt_conn_list, ic)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idle_time = ddi_get_lbolt() - ic->ic_timestamp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * If this connection is in FFP then grab a hold
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * and check the various timeout thresholds. Otherwise
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * the connection is closing and we should just
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * move on to the next one.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_enter(&ic->ic_state_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (ic->ic_ffp) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap idm_conn_hold(ic);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap } else {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_exit(&ic->ic_state_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap continue;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If there hasn't been any activity on this
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * connection for the keepalive timeout period
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * and if the client has provided a keepalive
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * callback then call the keepalive callback.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * This allows the client to take action to keep
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * the link alive (like send a nop PDU).
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if ((TICK_TO_SEC(idle_time) >=
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT) &&
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap !ic->ic_keepalive) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap ic->ic_keepalive = B_TRUE;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (ic->ic_conn_ops.icb_keepalive) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_exit(&ic->ic_state_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_exit(&idm.idm_global_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap (*ic->ic_conn_ops.icb_keepalive)(ic);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_enter(&idm.idm_global_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_enter(&ic->ic_state_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap } else if ((TICK_TO_SEC(idle_time) <
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT)) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /* Reset keepalive */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap ic->ic_keepalive = B_FALSE;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * If there hasn't been any activity on this
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * connection for the failure timeout period then
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * drop the connection. We expect the initiator
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to keep the connection alive if it wants the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * connection to stay open.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If it turns out to be desireable to take a
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * more active role in maintaining the connect
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * we could add a client callback to send
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * a "keepalive" kind of message (no doubt a nop)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and fire that on a shorter timer.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (TICK_TO_SEC(idle_time) >
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_TRANSPORT_FAIL_IDLE_TIMEOUT) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_exit(&ic->ic_state_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_exit(&idm.idm_global_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap IDM_SM_LOG(CE_WARN, "idm_wd_thread: "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "conn %p idle for %d seconds, "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "sending CE_TRANSPORT_FAIL",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap (void *)ic, (int)idle_time);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_enter(&idm.idm_global_mutex);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_enter(&ic->ic_state_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap idm_conn_rele(ic);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mutex_exit(&ic->ic_state_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&idm.idm_wd_cv, &idm.idm_global_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni wake_time, TR_CLOCK_TICK);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idm.idm_global_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_exit();
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}